insufficient accuracy for internal Vcc measurement
-
Hi,
I'm working on a battery operated node doing motion + temp, and I use Yveaux's Arduino_Vcc library to measure battery voltage.
I've tested the voltage from the 2 AAs and it's 2.99v, but the internal measurement gives 2.22v. I have a 25% difference where we should expect max 10%, shouldn't we ?
I'll try to debug that tomorrow with a dedicated sketch, but maybe someone can easily spot the error in the following code ?
/** * DESCRIPTION * Motion Sensor (HC-SR501) + Temp sensor (MCP9700 analog sensor) * inspired by : * mysensors PIR example created by Henrik Ekblad : http://www.mysensors.org/build/motion * Slim Node as a Mini 2AA Battery PIR Motion Sensor : http://forum.mysensors.org/topic/2715/slim-node-as-a-mini-2aa-battery-pir-motion-sensor * Kevin Kessler's blog for reading MCP9700 temperature sensor : http://blog.kkessler.com/2012/06/20/mcp9700/ */ #include <MySensor.h> #include <SPI.h> #include <Vcc.h> #define NODE_ID 30 #define MOTION_INPUT_PIN 3 // The digital input you attached your motion sensor. (Only 2 and 3 generates interrupt!) #define CHILD_ID_MOTION 1 #define CHILD_ID_TEMP 2 #define CHILD_ID_BATT 3 #define DOMOTICZ_OFF_DELAY 10000 #define MINIMUM_SEND_INTERVAL 86400000 // once a day #define TEMP_SEND_FREQ 300000 // every 5min #define TEMP_SEND_THRESHOLD 0.3 // do not send temp if variation is below delta #define VCC_MIN 1.9 #define VCC_MAX 3.3 float lastTemperature = 0;; float lastVoltage = 0; int loopCounter = 0; bool interruptReturn = false; // "false" will make the first loop disregard high output from HC-SR501 (from start-up) and make a battery+temp report instead. Vcc vcc(1.34); // 2.98/2.22=1.3423 . Can this be ok ??? MySensor gw; MyMessage msgMotion(CHILD_ID_MOTION, V_TRIPPED); MyMessage msgTemp(CHILD_ID_TEMP,V_TEMP); MyMessage msgBattery(CHILD_ID_BATT, V_VOLTAGE); void setup() { delay(100); // to settle power for radio gw.begin(NULL, NODE_ID); // Send the sketch version information to the gateway and Controller gw.sendSketchInfo("Motion & Temp Sensor", "1.0"); pinMode(MOTION_INPUT_PIN, INPUT); // sets the motion sensor digital pin as input // Register all sensors to gw (they will be created as child devices) gw.present(CHILD_ID_MOTION, S_MOTION); gw.present(CHILD_ID_TEMP, S_TEMP); gw.present(CHILD_ID_BATT, S_MULTIMETER); gw.sleep(20000); // Wait until motion sensor warmed-up and output returned low. } void loop() { int sleeptime = 0; if (interruptReturn) { // Woke up by rising pin gw.send(msgMotion.set("1")); // Domoticz will take care of setting the node off after some delay sleeptime = DOMOTICZ_OFF_DELAY; // sleep until domoticz sets the sensor off on its side } else { float voltage = vcc.Read_Volts(); float temperature = readMCP9700(4,0); // send if variation is enough or if delay was reached if (abs(temperature - lastTemperature) >= TEMP_SEND_THRESHOLD) { lastTemperature = temperature; sleeptime = 3000; loopCounter = 0; gw.send(msgTemp.set(temperature, 1)); } // send on first iteration, then if variation is enough or if delay was reached if (abs(voltage - lastVoltage) >= 0.1) { sendBatteryReport(voltage); sleeptime = 3000; loopCounter = 0; lastVoltage = voltage; } if (loopCounter++ * TEMP_SEND_FREQ >= MINIMUM_SEND_INTERVAL) { loopCounter = 0; sleeptime = 3000; gw.send(msgTemp.set(temperature, 1)); sendBatteryReport(voltage); } } if (sleeptime) { gw.sleep(sleeptime); // Make sure everything is stable before start to sleep with interrupts. (don't use "gw.wait()" here). Tests shows false trip ~2s after battery report otherwise. } interruptReturn = gw.sleep(MOTION_INPUT_PIN-2, RISING, TEMP_SEND_FREQ); } void sendBatteryReport(float voltage) { float perc = 100.0 * (voltage-VCC_MIN) / (VCC_MAX-VCC_MIN); gw.send(msgBattery.set(voltage, 2)); gw.sendBatteryLevel(static_cast<int>(perc)); } // this function comes from Kevin Kessler's blog : http://blog.kkessler.com/2012/06/20/mcp9700/ float readMCP9700(int pin,float offset) { analogReference(INTERNAL); for (int n=0;n<5;n++) analogRead(pin); int adc=analogRead(pin); float tSensor=((adc*(1.1/1024.0))-0.5+offset)*100; float error=244e-6*(125-tSensor)*(tSensor - -40.0) + 2E-12*(tSensor - -40.0)-2.0; float temp=tSensor-error; return temp; }
Regards
Mikael