I’m trying to add analog data from gas sensors using the LPP format
Data I’m sending (serial debug output):
CO2 407.00 TVOC 1.00
MQ135 41 MQ009 74
On TTN console it’s showing as:
So it seems the larger value is somehow converted wrongly. Where do I look further for debugging this?
The library’s code shows that value 407.00 is sent as a 16 bits signed integer, using
int16_t val = value * 100, hence as 40,700. That’s too large to fit in a 16 bits signed integer which ranges from -32,768 through 32,767.
In hexadecimal, 40,700 is 0x9EFC† which when interpreted as a signed integer is indeed -24,836, which divided by 100 indeed yields -248.36.
It’s quite weird LPP does not provide some generic methods for larger values. Some options:
You could (ab)use
addTemperature which uses
int16_t val = celsius * 10, hence sends 4,070 which fits just fine. Same goes for
Or, as you know CO2 values are always positive, you could use
addLuminosity which expects an unsigned 16 bits integer, which ranges from 0 through 65,535. If you need the two decimals then you’d have to multiply the float by 100 yourself before adding it to LPP, and divide by 100 after receiving it.
Or, just forget about LPP and dive into Working with Bytes and payload functions in TTN Console.
Thanks, I can see now it’s just the library way of encoding the payload.
The actual LPP definition looks normal, 2 bytes signed
I’ll play around defining my own addAnalog.
I was confused by the AnalogInput conversion but after seeing the post from @arjanvanb I suspect that the Cayenne coders weren’t thinking 10 bit arduino analog inputs when they created the function. So a possible workaround is to save the analogRead value as a float, then divide by 100. Therefore the 10 bit range of (0 to 1023) is converted to (0 to 10.23) which is perfectly fine to work with.
// Prepare upstream data transmission at the next possible time.
float x = analogRead(A0); // cast to float but don't divide the integer by 100 here or the number will be rounded off
x = x / 100; // divide by 100
LMIC_setTxData2(1, lpp.getBuffer(), lpp.getSize(), 0);
In this case the analogRead function read 451 and 507
In my opinion the problem is that addAnalogInput accepts floats, but in the implementation they are binary-converted in signed int, divided by 100 and sent. So if from my ESP32 i send the following values:
// Send our data
for (int i=0;i<numdati;i++)
Serial.printf(“Invio in LoRaWAN su port %i Valore: %f\n”,i,f[i]);
in my application server I’m getting:
In other words, AddAnalogRead can only send values between -327,67 and +327,67 with 2 decimals.