Miceuz / rs485-moist-sensor

Digital (RS485 - based) soil moisture and temperature sensor
Apache License 2.0
63 stars 23 forks source link

Sensor readings incorrect when temp below zero #9

Closed chris-b-tanner closed 3 years ago

chris-b-tanner commented 3 years ago

I have a range of sensors based on the schematic and layout of this project, which work brilliantly - apart from when the temperature goes negative. I get a reading from the registers of 65515, or close to (it's not exactly the same each read). Does anyone get this from the original RS485 sensors which are shipped via Tindie?

The firmware is from this project, up to date.

cheeeeee commented 3 years ago

It's most likely going to be an integer overflow error where an unsigned value should be signed. Since it's used for watering I actually haven't bothered testing values below freezing. My best guess is that the union declaration may be converting a signed value to unsigned when it's pair in an array but I'm not 100% sure. If you can mix and match signed/unsigned values in a array then it may be in the thermistor programming where things get more granular.

chris-b-tanner commented 3 years ago

@cheeeeee we use our sensors for controlling heaters as well as pumping water, and also to prevent pumping cycles when the water might be frozen. I suspect it's in the firmware too but my knowledge of the code isn't up to this level of debug. Is there anything in the firmware that looks suspicious to you? The fact that it's exactly at the zero crossover suggests that is is a signed/unsigned problem. There's no problem with the i2c version of this sensor which reads nicely below zero.

Miceuz commented 3 years ago

I am not at my pc now, cant investigate, but i guess this is just receiving library thing. If you subtract 65535 you will get a correct negative number

On April 17, 2021 11:03:49 PM GMT+03:00, Chris Tanner @.> wrote: @. we use our sensors for controlling heaters as well as pumping

water, and also to prevent pumping cycles when the water might be frozen. I suspect it's in the firmware too but my knowledge of the code isn't up to this level of debug. Is there anything in the firmware that looks suspicious to you? The fact that it's exactly at the zero crossover suggests that is is a signed/unsigned problem. There's no problem with the i2c version of this sensor which reads nicely below zero.

-- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/Miceuz/rs485-moist-sensor/issues/9#issuecomment-821879724

-- Sent from my Android device with K-9 Mail. Please excuse my brevity.

cheeeeee commented 3 years ago

It'll be lines 27-35 of main.c then most likely if the ic2 read correctly below zero where int16 is mismatched from uint16. The array declaration probably has type conversion of the contents.

chris-b-tanner commented 3 years ago

@cheeeeee if you have time to fix on your fork, I'm happy to run some hardware tests below zero. I believe your fork also has a fix for issue with reading interval resetting which isn't yet in this repo?

Miceuz commented 3 years ago

Guys, I don't get what are you talking about - both in main.c and in measurement.c (where actual measurement is performed) and in thermistor code - everywhere I see signed type used.

What are you using to read the sensor? If it's python library provided by me, then update it, I have fixed this in the library more than a year ago. And I am seeing negative temperatures - I have done environmental chamber tests a year ago.

Also note that at modbus master side you have to decide (or inform your modbus driver to do so) if you will interpret the reading as unsigned or a signed number. Have a look, minimalmodbus has a separete argument to specify that:

https://github.com/Miceuz/rs485-moist-sensor/blob/6bc4947f385b5dd4cc75266e2c948ae950f28cb6/utils/lib/chirp_modbus.py#L33

cheeeeee commented 3 years ago

Oh no I'm referring to main.c not the .py files

volatile union{ uint16_t asArray[3]; struct { uint16_t moisture; int16_t temperature; uint16_t fwVersion; } asStruct; } inputRegisters;

This would be the firmware for the attiny441. Best guess is that since you have an array that's declared as unsigned the compiler may say that all things inside the array need to be unsigned and convert them. Maybe. I've sort of abandoned working with the modbus as of now since the cabling is really to expensive to deploy at scale so I just haven't looked at these sensors as of late.

https://github.com/Miceuz/rs485-moist-sensor/blob/master/src/main.c

Miceuz commented 3 years ago

Ok, got it. This really does nothing to the negative value. Both -12 and 65524 have the same binary representation: 0b1111111111110100

As I have said, the problem is in decoding at the masters side. @chris-b-tanner can you give more details on what do you use to read sensors?

BTW 65515 is -21 really, were you testing sensors in a freezer?

cheeeeee commented 3 years ago

Correct it would effect the sign bit on the binary so no matter what a positive would be returned. It would just drop the sign bit assuming that it wouldn't be used.

Miceuz commented 3 years ago

No, it wouldn't affect the sign bit as unsigned numbers use this bit to store information. You can store 0-65535 or -32767-32768 in two bytes.

chris-b-tanner commented 3 years ago

As I have said, the problem is in decoding at the masters side. @chris-b-tanner can you give more details on what do you use to read sensors? BTW 65515 is -21 really, were you testing sensors in a freezer?

Yes, I've been testing in a freezer. I've been using a ModbusMaster package with an ESP32/Arduino IDE to read the value, and can easily subtract 65535 when appropriate. My minsuderstanding here - thank you for input! Great pieces of kit.

Miceuz commented 3 years ago

@chris-b-tanner you don't have to do any arithmetics, you can simply cast the result to signed type:

temperature = (int16_t) node.getResponseBuffer(j);