Lux sensor (BH1750) sending battery level (V)
-
Hi,
I really enjoy using MySensors!
Got a small general question though: I'm using a BH1750 light sensor, powered by a 3V battery and I'd like to keep an eye on the battery status.
I have added a line to the existing BH1750 scetch:
#define CHILD_ID_VCC = 1 MyMessage msgVcc(CHILD_ID_VCC, V_VOLTAGE); .. void Presentation() { sendSketchInfo("Light Lux Sensor", "1.1"); present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); present(CHILD_ID_VCC, S_MULTIMETER); } Loop() { uint16_t lux = lightSensor.readLightLevel(); float Vcc = ReadVcc(); send(msgLux.set(Lux)); send(msgVcc.set(Vcc)); }
Domoticz recieves the data now, but the Voltage is reading 2968V because readVcc delivers mV
If I change the code to:float Vcc = readVcc()/1000;
I get an error message "call of overloaded 'set(float&)'is ambiguous"
How can I send decimal values to the Domoticz controller from MySensors?Regards, Frank
-
@frankvk No programming skills, but is it correct trying to calculate in a procedure call rather than insert an intermediate step?
If the ReadVcc() procedure call returns millivolts, suggest preceding the "float Vcc = ReadVcc();" with "int Voltage= ReadVcc();" and change the "float Vcc = ReadVcc();" to "float Vcc = Voltage/1000;", it should then do as you want.
-
Hi Zboblamont,
Thanks for your response, but the error occurs in the line, obviously because Vcc is of the type 'float'
send(msgVcc.set(Vcc));
-
@frankvk I'm no expert on this, but do know all my nodes send battery as a float for the last 2 years, excerpt as follows:
// Call for battery reading, send in every 12th RTC call? if(halfday==12){ digitalWrite(BatteryOn, HIGH); voltread = analogRead(BatteryIn); float voltage = (7.272 * voltread) / 1024; sleep(5); digitalWrite(BatteryOn, LOW); send(msg3.set(voltage,2)); sleep(50); voltread=0; sleep(50); halfday=0;//Reset for 12 hourly cycle } halfday++;//Increment hourly cycle
That is based on the internal value defined without any complications, but note that the message is sent to 2 decimal places, whether that truncation is essential for the MySensors environment I do not know, it was all I required.
-
Is there a typo in your message or in your code?
First you used ReadVcc(), then readVcc()
-
@frankvk could you post the entire sketch, including where readVcc comes from? Seeing the code will make it much easier to help you.
-
The line
float Vcc = readVcc()/1000;
should be:
float Vcc = readVcc()/1000.;
to start with. Note the decimal point! If read Vcc() returns a float, you cannot divide by an integer.
-
@bgunnarb
But readVcc returns longlong 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 = 1126400L / result; // Back-calculate AVcc in mV return result; }```
-
A float can be divided by an integer. The result will be a float.
A long can be divided by an integer or a float. The result will differ though.
2968/1000 will give the integer 2
2968/1000.0 will give the float 2.968See "Integer and floating point division" at https://www.learncpp.com/cpp-tutorial/32-arithmetic-operators/
-
@mfalkvidd @bgunnarb Something new learned from that, hadn't realised a procedure call could be mathematically manipulated like that, nor the subtle differences in the outputs...
-
Actually, I needed to change 2 things: first one was dividing by 1000.0 rather than 1000 and the other one was calling send(msgVcc.set(Vcc, 2)); rather than send(msgVcc.set(Vcc)); Now the log reads 2.95V.
Thanks Mikael (@mfalkvidd) & everyone! Happy coding!
-
@mfalkvidd
Yep, this is a great way of introducing errors that will be nearly impossible to find!