Hi all,
I've got an Arduino Uno V3 equivalent running a 20x4 I2C LCD, and am gradually building a vehicle monitor for my 4WD, starting with monitoring my two batteries and my solar panels, plus two DS18B20 temp sensors, before I move on to greater things on my Arduino Mega 2560 and KS0108B screen.
I've had these 2 years but in the past fortnight have really been getting in to wanting to finalise something and get it mounted in my car. Below is a schematic of my current circuit, and my code. I'm a Mechanical & Mechatronic Engineer, so covered much of this in my university education, but we never really got in to circuit design, and am coming a bit unstuck. I finally got a couple DC-DC buck converters (LM2596) to run off my car batteries, and I've got it running off my auxiliary battery (to avoid alternator and starter motor spikes), which should vary from 11.5 to 14.5v with the Buck outputting 9v. The trouble is, I'm finding that with the Buck converter, my voltages are down by approximately 3-4% compared to my Digital Multimeter, so the batteries show about 0.4v lower when the car is off. If I connect the USB cable for power and disconnect the Buck, the voltages are much more accurate, within about 0.5% of my DMM, which is fine with me. If I disconnect the car inputs but leave the USB and the Buck, the Buck converter seems to backfeed and show a battery voltage of 3.6V (which is why I've tentatively put Diodes on the positive lines of it in my schematic. If i disconnect the USB, and instead use a 9v cell battery (reading 8.4v OCV), with the car inputs connected, they are about 3-4% over what my DMM reads.
I've tried searching for similar experiences of others and haven't been able to find what I'm looking for. I found some code for checking Vcc and calculating based on that, so I've implemented that in my code, and it's a bit better than it was before, but still not right. I don't want the USB powering the unit, so trying to work out if it's a software or hardware issue. any advice would be so appreciated, hope I've covered all bases.
The code included the start of implementing a pushbutton and current measurement, but that's sidelined til I re-learn op amps. It's sort of been hacked together from a bunch of other examples, but I hope it's succinct enough. Thank you!
//load libraries
#include <Wire.h>
#include <OneWire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <DallasTemperature.h>
//Define variables
//LCD I2C
#define I2C_ADDR 0x27 //Define I2C Address where the PCF8574A is
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
//Temp Sensors DS18B20
#define ONE_WIRE_BUS 7
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
//Initialise the LCD
LiquidCrystal_I2C lcd(I2C_ADDR, En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
//Pushbutton
int button = 0; //button off state
int oldButton = 0; //last state read
//Voltages
int batt_voltage_alarm = 11; //min voltage before alarm is tripped
int pri_battPin = 0; // Input from primary Battery
int aux_battPin = 1; // Input from auxiliaryy Battery
int solar_Pin = 2; // Input from solar Battery
int primaryVal = 0; //temporarily store the primary input
int auxVal = 0; //temporarily store the secondary input
int solarVal = 0; //temporarily store the solar input
float pri_pinVolt = 0; // variable to hold the calculated voltage
float aux_pinVolt = 0; // variable to hold the calculated voltage
float solar_pinVoltage = 0; // variable to hold the calculated voltage
float priBattVolt = 0; //Temporarily store the primary Voltage
float auxBattVolt = 0; //Temporarily store the secondary Voltage
float solar_chargeVoltage = 0; //Temporarily store the secondary Voltage
float ratio = 5.5334; // The multiplier depending on which resistors used
// I used 68K and 15K 1/2 watt resistors.
//Screen Update
long previousMillis = 0;
long interval = 500;
//Temperatures
float tempC1 = 0;
float tempC2 = 0;
//reading Vcc for accurate ADC values
long readVcc() {
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1125300L / result; // Back-calculate AVcc in mV
return result;
}
void setup()
{
//Define the LCD as 20 column by 4 rows
lcd.begin (20,4);
sensors.begin();
//Switch on the backlight
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
pinMode(2, INPUT); //pushbutton input
pinMode(3, OUTPUT);
analogWrite(3, 0); //pwm output to pin, duty cycle out of 255
lcd.setCursor(3, 0);// Place the Cursor on the Fist line first character position on the LCD screen
lcd.print("WELCOME LEWIS"); // First Line
lcd.setCursor(3, 2);// Place the Cursor on the Fist line first character position on the LCD screen
lcd.print("NISSAN PATROL"); // First Line
lcd.setCursor(4, 3);// Place the Cursor on the Fist line first character position on the LCD screen
lcd.print("GUIV TD42TI"); // First Line
delay(2000); //Pause for two seconds
lcd.clear();
}
void loop()
{
unsigned long currentMillis = millis();
double Vcc = readVcc()/1000.0;
float ADCratio = Vcc / 1024;
//VOLTAGES
primaryVal = analogRead(pri_battPin); //Read the primary Battery input per loop
auxVal = analogRead(aux_battPin); //Read the secondary Battery input per loop
solarVal = analogRead(solar_Pin); //Read the primary Battery input per loop
pri_pinVolt = primaryVal * ADCratio; //ADCratiomV per 1024 steps for 5 Volts (ie; 5 / 1024 = ADCratio)
aux_pinVolt = auxVal * ADCratio;
solar_pinVoltage = solarVal * ADCratio; //ADCratiomV per 1024 steps for 5 Volts (ie; 5 / 1024 = ADCratio)
priBattVolt = pri_pinVolt * ratio; //grab the calculated under 5Volt input and multiply it by the ratio to ..........
priBattVolt = round(priBattVolt * 10)/10.0;
auxBattVolt = aux_pinVolt * ratio; // .............take it back to the 11~12~13Volt Range.
auxBattVolt = round(auxBattVolt*10)/10.0;
solar_chargeVoltage = solar_pinVoltage * ratio; //grab the calculated under 5Volt input and multiply it by the ratio to ..........
solar_chargeVoltage = round(solar_chargeVoltage*10)/10.0;
//TEMPS
sensors.requestTemperatures();
tempC1 = sensors.getTempCByIndex(0);
tempC2 = sensors.getTempCByIndex(1);
if (digitalRead(2) == HIGH){ //If Pin 2 is high (at 5V)
button = 1 - button; //inverts value
}
if(button == 1 && oldButton ==0){
//enter functions for with button on, such as swap backlight
delay(500);
}
if(button == 0 && oldButton ==1){
//enter functions for with button off, such as swap backlight
delay(500);
}
if (currentMillis - previousMillis > interval)
{
//lcd.clear();
lcd.setCursor(0, 0);// Place the Cursor on the Fist line first character position on the LCD screen
lcd.print("MAIN:"); // First Line
if (priBattVolt < 10.0){
lcd.print(" ");
}
lcd.print(priBattVolt,1); //The Voltage of Primary Battery.. Still on the first Line
lcd.print("V"); // First Line
lcd.setCursor(11, 0);
lcd.print("AUX:"); // Second Line
if (auxBattVolt < 10.0){
lcd.print(" ");
}
lcd.print(auxBattVolt,1); //The Voltage of Secondary Battery..
lcd.print("V");
lcd.setCursor(4, 1);
lcd.print("SOLAR:"); // 2nd Line
if (solar_chargeVoltage < 10.0){
lcd.print(" ");
}
lcd.print(solar_chargeVoltage,1);
lcd.print("V");
lcd.setCursor(1, 3);
lcd.print("IN:");
if (tempC1 < 10.0){
lcd.print(" ");
}
lcd.print(tempC1,0);
lcd.print("'C");
lcd.setCursor(11, 3);
lcd.print("OUT:");
if (tempC2 < 10.0){
lcd.print(" ");
}
lcd.print(tempC2,0);
lcd.print("'C");
}
oldButton = button; //data is now old
}