I'm working on a sketch / circuit to tell me when the source voltage has dropped below some value. The source voltage will be in the range of 10v DC to 15v DC. The circuit runs the source voltage through a voltage divider (two resistors, R1=3.3 MOhms, R2=1.5 MOhms) which yields an output voltage from the voltage divider in the range of 2.75v to 4.43v when the source is from my bench power supply.
The output from the voltage divider is being fed into analog pin A0 on a Arduino Pro Mini.
When reading pin A0 these are the results I'm seeing:
Source Voltage Divider Output A0 Reading
11v 2.75v 444 - 454
12v 3.05v 492 - 503
13v 3.60v 578 - 592
14v 3.86v 624 - 638
16v 4.43v 713 - 729
The source voltage is constant, the Divider Output voltage doesn't vary, either. However, the reading on pin A0 varies quite a bit.
The sketch itself should read analog pin A0 every couple of seconds and calculate the source voltage (in the sketch as currently written, that calculation isn't working correctly). It should also read a reference voltage from analog pin A2 which is fed by a 10k linear potentiometer (this part of the sketch hasn't been worked and at the moment, pin A2 is grounded). If the source voltage falls below the reference voltage, then an LED should light and a buzzer sound.
The part of the sketch that's concerning me is where the sketch reads analog pin A0 (about line 55) and even though the voltage to the pin is constant, the analogRead varies quite a bit. Further, I'd expect as the source voltage approaches 16v (and the voltage divider output approaches 5v) that the reading from analog pin A0 should approach 1023. It doesn't.
Is this what should be happening? Or (more likely) what am I doing wrong?
Here's the source code for the sketch as currently written.
#include <SPI.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Define LCD pinout
const int en = 2, rw = 1, rs = 0, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 3;
// Define I2C Address - change if reqiuired
const int i2c_addr = 0x27;
LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);
int LEDPin = 9;
int BUZZERPin = 7;
int LEDOk = 13;
// int vIn = 16;
// float r1 = 3294.0;
// float r2 = 1482.0;
// float voltConvert = r2/(r1+r2);
// calibrating voltage (Start at 5v because that is the arduino pro mini base voltage)
int readDelay = 10;
int voltagePin = A0;
int triggerPin = A2;
void setup() {
Serial.begin(9600);
while (!Serial)
{
}
lcd.begin(16,2);
delay(2000);
// setup the pin for the low voltage alert
pinMode(LEDPin, OUTPUT);
pinMode(BUZZERPin, OUTPUT);
// Clear the buffer
lcd.clear();
digitalWrite(LEDOk, HIGH);
}
void loop() {
float limitValue = analogRead(triggerPin);
// Serial.print("limitValue: ");
// Serial.println(limitValue);
float limitVoltage = convertSlope(0.0,16.0,0.0,1023.0,limitValue);
// Serial.print("calcLimit: ");
// Serial.println(limitVoltage);
float voltageValue = analogRead(voltagePin);
Serial.print("voltageValue: ");
Serial.println(voltageValue);
float realVolts = convertSlope(0.0,17.5,0.0,1023.0,voltageValue);
Serial.print("realVolts: ");
Serial.println(realVolts);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Voltage: ");
lcd.print(realVolts);
lcd.setCursor(0,1);
lcd.print("Trigger: ");
lcd.print(limitVoltage);
if (realVolts <= limitVoltage) {
LowVoltageAlert();
}
delay(2000);
}
void LowVoltageAlert(){
digitalWrite(LEDPin, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(BUZZERPin, HIGH);
digitalWrite(LEDOk, LOW);
delay(250);
digitalWrite(BUZZERPin, LOW);
delay(1000); // wait for a second
digitalWrite(LEDPin, LOW); // turn the LED off by making the voltage LOW
digitalWrite(LEDOk, HIGH);
delay(1000); // wait for a second
}
// Convert a float range from 0-1023 to 0-16
float convertSlope(float outputStart,float outputEnd,float inputStart,float inputEnd,float inputValue) {
float slope = (outputEnd-outputStart) / (inputEnd - inputStart);
float outputValue = outputStart + slope * (inputValue - inputStart);
return outputValue;
}