Hello all, it has been to long again. This is a project I wrote and finished up about a year ago. I was getting ready for a trip and I was still having problems with low voltage at my radio once in a while so I wanted something I could monitor from the Drivers seat to see when the voltage was getting low. So was born the idea of using my cell phone and a blue tooth transmitter to monitor my Battery system in the rear of my car(2009 Volkswagen Jetta TDI).

I decided on an Arduino Mega 2560 ($11.00 at the time), DH11($2.55) for Temperature and threw in Humidity, 2 each N103 Voltage Sensors ($2.79 for both) , case ($7.98) and a breadboard ($2.00), Blue Tooth transmitter HC06 ($7.00). So for far less than $50.00 I could transmit my Voltages at the battery, and the humidity plus Temperature from the Trunk of my car all the while being able to watch it from the Drivers Seat.

Now I make no mention that I invented any of this code nor did I steal it, most of what I did was use public domain and modified it for my usage. For the Cell Phone I just used a Blue Tooth Terminal Program. I have left in the notes from the original authors in the code. If i removed their name or credits, I apologize.

Her we will start with some of the code and perhaps some explanations Some may be out of order.

I plan on using the HC06 on Serial3.

\***********************************************************/

String MY_TDI_VOLTAGE_MONITOR_VERSION = “1.04”;

// Setup to blink Pin 13 has an LED connected on most Arduino
// boards. Then give it a name:
int led = 13;
int state;
int flag = 0; // makes sure that the Serial3 only prints
// once the state is set HIGH.
int pass = 0; // keep count of pass and displays it.

\***********************************************************/

Now for the Blue Tooth stuff.

/***********************************************************
dht11
************************************************************

Board              int.0      int.1      int.2      int.3      int.4      int.5
Uno, Ethernet      2      3
Mega2560      2      3      21      20      19      18
Leonardo      3      2      0      1
Due              (any pin, more info http://arduino.cc/en/Reference/AttachInterrupt)

This example, as difference to the other, make use of the
new method acquireAndWait()
*************************************************************/

DTH11 Humidity and Temperature sensor.

/* SFE_BMP180 library example sketch

This sketch shows how to use the SFE_BMP180 library to read
the Bosch BMP180 barometric pressure sensor.
https://www.sparkfun.com/products/11824
Like most pressure sensors, the BMP180 measures absolute
pressure. This is the actual ambient pressure seen by the
device, which will vary with both altitude and weather.

Before taking a pressure reading you must take a temperature
reading. This is done with startTemperature() and
getTemperature(). The result is in degrees C.

Once you have a temperature reading, you can take a pressure
reading. This is done with startPressure() and getPressure().
The result is in millibar (mb) aka hectopascals (hPa).

If you’ll be monitoring weather patterns, you will probably
want to remove the effects of altitude. This will produce
readings that can be compared to the published pressure
readings from other locations. To do this, use the sealevel()
function. You will need to provide the known altitude at
which the pressure was measured.

If you want to measure altitude, you will need to know the
pressure at a baseline altitude. This can be average
sealevel pressure, or a previous pressure reading at your
altitude, in which case subsequent altitude readings will
be + or – the initial baseline. This is done with the
altitude() function.

Hardware connections:

– (GND) to GND
+ (VDD) to 3.3V

(WARNING: do not connect + to 5V or the sensor will be
damaged!)

You will also need to connect the I2C pins (SCL and SDA)
to your Arduino. The pins are different on different
Arduinos:

Any Arduino pins labeled:  SDA  SCL
Uno, Redboard, Pro:        A4   A5
Mega2560, Due:             20   21
Leonardo:                   2    3

Leave the IO (VDDIO) pin unconnected. This pin is for
connecting the BMP180 to systems with lower logic levels
such as 1.8V

Have fun! -Your friends at SparkFun.

The SFE_BMP180 library uses floating-point equations
developed by the Weather Station Data Logger
project: http://wmrx00.sourceforge.net/

Our example code uses the “beerware” license. You can do
anything you like with this code. No really, anything. If
you find it useful, buy me a beer someday.

V10 Mike Grusin, SparkFun Electronics 10/24/2013
V1.1.2 Updates for Arduino 1.6.4 5/2015
\***************************************************/

Necessary Libraries needed.

/************************************************************
Your sketch must #include the following libraries.
Wire.h is a standard library included with Arduino.):
***********************************************************/

#include <idDHT11.h>
#include <SFE_BMP180.h>
#include <Wire.h>
#include <String.h>

int idDHT11pin = 2; //Digital pin for comunications
int idDHT11intNumber = 0; //interrupt number (must be the one that use the previus defined pin (see table above)

// must be declared before the lib initialization

void dht11_wrapper();
// Lib instantiate
idDHT11 DHT11(idDHT11pin,idDHT11intNumber,dht11_wrapper);

// This wrapper is in charge of calling the DHT11
// and must be defined like this for the lib work

void dht11_wrapper() {
DHT11.isrCallback();
}

/******************** SFE_BMP180 ***************************
You will need to create an SFE_BMP180 object, here called
“pressure”:
************************************************************/

SFE_BMP180 pressure;

float ALTITUDE = 0.0;

// #define ALTITUDE 28.9559907340803 Fern Park, FL.

/********************** voltage setup **********************/

// voltage setup.
float val;    // value for voltage monitor
float val_1;  // value for voltage monitor

int analogInput_0 = 1; // analog input pin 1
int analogInput_1 = 2; // analog input pin 2
float vin  = 0.0;
float vout = 0.0;
float R1 = 30000.0; // resistor R1.
float R2 = 7500.0;  // resister R2.
int value = 0;
int FistTimeFlag = HIGH;

 

 Now setup to clear the screen on the Android.

/******************* clearAndHomeScr() ***********************/
void clearAndHomeScr() {
Serial3.write(27); // ESC
Serial3.print(“[2J”); // clear screen
Serial3.write(27); // ESC
Serial3.print(“[H”); // cursor to home
delay(250);
}

 Some serial stuff.

/***************** getSerialString() ***********************/
void getSerialString() {
String string=””;
int count = 0;
while(-1) { // loop for input.
delay(500); // delay 500 ms for input timer.
count++;  //increase timer by 1.
if(count>120) {
ALTITUDE = 28.9559907340803; // house Fern Park, FL.
return; // if timer reaches 1 minute exit input.
}
while(Serial3.available() > 0) {
string = Serial3.readString();
Serial3.print(string);
ALTITUDE = (string.toFloat()/3.2808);
string = “”; // Clear string.
return;      // force nothing to return.
}
}
}

Now to do the setup()

void setup() {
// sets the pins as outputs:
pinMode(led,OUTPUT);
pinMode(analogInput_0,INPUT);
pinMode(analogInput_1,INPUT);

digitalWrite(led,LOW);
delay(1000);
digitalWrite(led,HIGH);

// initialize Serial32 communication at 9600 bps:
Serial3.begin(9600);
clearAndHomeScr(); // clear BlueTooth Term 2 program.
Serial3.println(“\nW4QED’s bluetooth voltage monitor.”);
Serial3.print(” Ver”);
Serial3.println(MY_TDI_VOLTAGE_MONITOR_VERSION);

Serial3.print(“\nusing DHT11 LIB version: “);
Serial3.println(IDDHT11LIB_VERSION);
Serial3.println();

Serial3.print(“Enter current Altitude in feet: “);
getSerialString();

// Initialize the sensor (it is important to get
// calibration values stored on the device).

if (pressure.begin()) {
Serial3.println(“BMP180 init success”);
} else {
// Oops, something went wrong, this is usually a
// connection problem,
// see the comments at the top of this sketch for
// the proper connections.

Serial3.println(“BMP180 init fail\n\n”);
while(-1); // Pause forever.
}

// dht11
Serial3.println(“\nRetrieving information from sensor:”);
Serial3.print(“Read DHT11 sensor: “);

int result = DHT11.acquireAndWait();

switch (result) {
case IDDHTLIB_OK:
Serial3.println(“OK”);
break;
case IDDHTLIB_ERROR_CHECKSUM:
Serial3.println(“Error\n\r\tChecksum error”);
break;
case IDDHTLIB_ERROR_ISR_TIMEOUT:
Serial3.println(“Error\n\r\tISR time out error”);
break;
case IDDHTLIB_ERROR_RESPONSE_TIMEOUT:
Serial3.println(“Error\n\r\tResponse time out error”);
break;
case IDDHTLIB_ERROR_DATA_TIMEOUT:
Serial3.println(“Error\n\r\tData time out error”);
break;
case IDDHTLIB_ERROR_ACQUIRING:
Serial3.println(“Error\n\r\tAcquiring”);
break;
case IDDHTLIB_ERROR_DELTA:
Serial3.println(“Error\n\r\tDelta time to small”);
break;
case IDDHTLIB_ERROR_NOTSTARTED:
Serial3.println(“Error\n\r\tNot started”);
break;
default:
Serial3.println(“Unknown error”);
break;
}
}

Last but not least the proverbial loop()

void loop() {
char status;
double T,P,p0,a;

if (FistTimeFlag==LOW) {
clearAndHomeScr();
}
// Loop here getting pressure readings every 10 seconds.

// If you want sea-level-compensated pressure, as used
// in weather reports, you will need to know the altitude
// at which your measurements are taken.
// We’re using a constant called ALTITUDE in this sketch:
Serial3.print(“\nprovided altitude: “);
Serial3.print(ALTITUDE,0);
Serial3.print(” meters, “);
Serial3.print(ALTITUDE*3.28084,0);
Serial3.println(” feet”);
if (FistTimeFlag==HIGH) {
delay(3000); // delay 3 sec.
}

// If you want to measure altitude, and not pressure,
// you will instead need to provide a known baseline
// pressure. This is shown at the end of the sketch.

// You must first get a temperature measurement to perform
// a pressure reading.

// Start a temperature measurement:
// If request is successful, the number of ms to wait is
// returned.
// If request is unsuccessful, 0 is returned.

status = pressure.startTemperature();
if (status != 0) {
// Wait for the measurement to complete:
delay(status);

// Retrieve the completed temperature measurement:
// Note that the measurement is stored in the variable
// T.
// Function returns 1 if successful, 0 if failure.

status = pressure.getTemperature(T);
if (status != 0) {
// Print out the measurement:
Serial3.print(“temperature: “);
Serial3.print(T,2);
Serial3.print(“C, “);
Serial3.print((9.0/5.0)*T+32.0,2);
Serial3.println(“F”);

// Start a pressure measurement:
// The parameter is the oversampling setting, from 0
// to 3 (highest res, longest wait).
// If request is successful, the number of ms to wait
// is returned.
// If request is unsuccessful, 0 is returned.

status = pressure.startPressure(3);
if (status != 0) {
// Wait for the measurement to complete:
delay(status);

// Retrieve the completed pressure measurement:
// Note that the measurement is stored in the
// variable P.
// Note also that the function requires the previous
// temperature measurement (T).
// (If temperature is stable, you can do one
// temperature measurement for a number of pressure
// measurements.)
// Function returns 1 if successful, 0 if failure.

status = pressure.getPressure(P,T);
if (status != 0) {
// Print out the measurement:
Serial3.print(“abs pressure: “);
Serial3.print(P,2);
Serial3.print(” mb, “);
Serial3.print(P*0.0295333727,2);
Serial3.println(” inHg”);

// The pressure sensor returns abolute pressure,
// which varies with altitude.
// To remove the effects of altitude, use the
// sealevel function and your current altitude.
// This number is commonly used in weather reports.
// Parameters: P = absolute pressure in mb,
// ALTITUDE = current altitude in meters.
// Result: p0 = sea-level compensated pressure in
// mb
// we’re at 1655 meters (Boulder, CO)
p0 = pressure.sealevel(P,ALTITUDE);
Serial3.println(“relative (sea-level)”);
Serial3.print(” pressure: “);
Serial3.print(p0,2);
Serial3.print(” mb, “);
Serial3.print(p0*0.0295333727,2);
Serial3.println(” inHg”);

// On the other hand, if you want to determine
// your altitude from the pressure reading,
// use the altitude function along with a baseline.
// pressure (sea-level or other).
// Parameters: P = absolute pressure in mb,
// p0 = baseline pressure in mb.
// Result: a = altitude in m.

a = pressure.altitude(P,p0);
Serial3.print(“computed altitude: “);
Serial3.print(a,0);
Serial3.print(” meters, “);
Serial3.print(a*3.28084,0);
Serial3.println(” feet”);
} else {
Serial3.println(“ERROR:retrieving pressure.\n”);
}
} else {
Serial3.println(“ERROR:starting pressure.\n”);
}
} else {
Serial3.println(“ERROR:retrieving temperature.\n”);
}
} else {
Serial3.println(“ERROR:starting temperature.\n”);
}
Serial3.print(“\nHumidity: “);
Serial3.print(DHT11.getHumidity(),0);
Serial3.println(“%.”);
Serial3.print(“Temp : “);
Serial3.print(DHT11.getCelsius(),2);
Serial3.print(“C : “);
Serial3.print(DHT11.getFahrenheit(),2);
Serial3.print(“F : “);
Serial3.print(DHT11.getKelvin(),2);
Serial3.println(“K.”);

Serial3.print(“DewPoint: “);
Serial3.print(DHT11.getDewPoint());
Serial3.print(“C : “);
Serial3.print(DHT11.getDewPoint()*(9.0/5.0)+32);
Serial3.println(“F.”);

Serial3.print(“DewPoint Slow: “);
Serial3.print(DHT11.getDewPointSlow());
Serial3.print(“C : “);
Serial3.print(DHT11.getDewPointSlow()*(9.0/5.0)+32);
Serial3.println(“F.”);

Voltage is simular to:

resistor_divider

Now if Voltage_In = 13.8

then R1 = 3000 R2 = 7500 then the R2/(R1+R2) =  0.714

V_IN = val * Volts.

Now if you want to scale then

13.8V would be read at V_OUT as 9.85 Volts

Now if you want your readings to be close, but not entirely 100% accurate then use

the 0.714 as a multiplier to the voltage at V_OUT.

I display the actual readings. but could be Serial3.print((val_1 * 0.714),3);

// 1st voltage sensor here.

value = analogRead(analogInput_0);
vout = (value * 5.0)/1024.0;
vin = (vout/(R2/(R1+R2)));
if (vin < 0.09) {
vin = 0.0; // just amke it Zero volts.
}
Serial3.print(“\nVoltage Supply: “);
Serial3.print(vin,3);
Serial3.print(“V. “);

// next voltage sensor
value = 0.0;
value = analogRead(analogInput_1);
vout = (value * 5.0)/1024.0;
vin = (vout/(R2/(R1+R2)));
if (vin < 0.09) {
vin = 0.0; // force to Zero volts.
}
Serial3.print(” Bat: “);
Serial3.print(vin,3);
Serial3.println(“V.”);

// Alternative reading
/*

value = 0.0;
value = analogRead(analogInput_1;

// where 9.857 volts at V_OUT is across the 7500 Ohm resistor and 0.714 the value of V_IN.
vin = (vout/(1/(R2/(R1+R2))); // or vin = (vout / 0.714)
if (vin < 0.09) {
vin = 0.0; // force to Zero volts.
}
Serial3.print(” Bat: “);
Serial3.print(vin,3);
Serial3.println(“V.”);
*/
Serial3.print(“\n\n pass: “);
Serial3.println(pass);
pass++;

if (FistTimeFlag) {
delay(60000); // delay 60 seconds on 1st pass.
FistTimeFlag = LOW;
} else {
delay(20000); // delay 20 seconds on all other passes.
}
}

/* end of code */

Reference:

Voltage divider circuit from:

http://forums.trossenrobotics.com/tutorials/how-to-diy-128/cheap-battery-monitor-using-resistive-voltage-divider-3264/

I’m either sure you will have questions or just give up and do your own. I hope the prior, but best of luck, enjoy and learn.

/* end of code.*/

 

Advertisements