flyte / mqtt-io

Expose GPIO modules (Raspberry Pi, Beaglebone, PCF8754, PiFace2 etc.) and digital sensors (LM75 etc.) to an MQTT server for remote control and monitoring.
MIT License
469 stars 159 forks source link

Problem with ads1x15 - readings messed up #254

Closed pakagi closed 2 years ago

pakagi commented 2 years ago

I observe this problem when trying to read voltages using the ads1x15 module, with ADS1115 A/D connected via I2C.

It has four input channels for measuring voltage. When I use just one channel, config like this:

sensor_modules:
  - name: ads_ch0
    module: ads1x15
    type: ADS1115
    pin: 0
sensor_inputs:
  - name: voltage_0
    module: ads_ch0
    interval: 10
    type: voltage

it is working fine, I get correct readings like:

2022-02-06 13:57:41 mqtt_io.server [INFO] Read sensor 'voltage_0' value of 3.3
2022-02-06 13:57:51 mqtt_io.server [INFO] Read sensor 'voltage_0' value of 3.3

But as soon as I try to use more than one channel, it seems to randomly report either correct value or the value from the other channel. Config is like:

sensor_modules:
  - name: ads_ch0
    module: ads1x15
    type: ADS1115
    pin: 0
  - name: ads_ch1
    module: ads1x15
    type: ADS1115
    pin: 1
sensor_inputs:
  - name: voltage_0
    module: ads_ch0
    interval: 10
    type: voltage
  - name: voltage_1
    module: ads_ch1
    interval: 10
    type: voltage

and instead of reporting 3.3V on channel 0 and 0.56V on channel 1 (what is really on inputs...), it randomly mixes those:

2022-02-06 14:04:47 mqtt_io.server [INFO] Read sensor 'voltage_1' value of 0.56
2022-02-06 14:04:47 mqtt_io.server [INFO] Read sensor 'voltage_0' value of 0.56
2022-02-06 14:04:57 mqtt_io.server [INFO] Read sensor 'voltage_0' value of 0.56
2022-02-06 14:04:57 mqtt_io.server [INFO] Read sensor 'voltage_1' value of 0.56
2022-02-06 14:05:07 mqtt_io.server [INFO] Read sensor 'voltage_1' value of 3.3
2022-02-06 14:05:07 mqtt_io.server [INFO] Read sensor 'voltage_0' value of 3.3
2022-02-06 14:05:17 mqtt_io.server [INFO] Read sensor 'voltage_0' value of 0.56
2022-02-06 14:05:17 mqtt_io.server [INFO] Read sensor 'voltage_1' value of 0.56
2022-02-06 14:05:27 mqtt_io.server [INFO] Read sensor 'voltage_1' value of 3.3
2022-02-06 14:05:27 mqtt_io.server [INFO] Read sensor 'voltage_0' value of 3.3
2022-02-06 14:05:37 mqtt_io.server [INFO] Read sensor 'voltage_0' value of 0.56
2022-02-06 14:05:37 mqtt_io.server [INFO] Read sensor 'voltage_1' value of 0.56

The problem seems to be, that (as the poll interval is equal for all those 4 sensor_inputs) it tries to get the values for the sensor_modules instances mostly in parallel, and something like mixing requests and responses happens (maybe on I2C level ?) causing wrong value read. If the intervals are e.g. 5 and 7, the returned values are ok - at least seems to be the case at the moments the intervals do not meet.

So looks like fix would be: for one particular sensor, serialize the operations to read the values from sensor.

Observing on Raspberry Pi, the module connected via I2C via GPIO, OS Raspian.

BenjiU commented 2 years ago

@flyte: do you think we need to change the poll threads? Meaning that for different channels on a single sensor, only one poll thread should be started and handle all request sequentiell. Maybe even if there are different polling intervals.

xNiux commented 2 years ago

I have the same problem. I'm using only channel 0 and 1 .. And the results is mixing between the too channel ... I get the channels with 600s interval.

shbatm commented 2 years ago

Also having the same issue. Just starting to look into this, but it looks like a potential issue with having two (or more) instances of the ADS1x15 defined and it's confusing which pin is being read when using SINGLE mode.

jcsouthworth commented 2 years ago

I reinstalled branch 3bfa1b7d5f which has #286 implemented. I updated the config to add "pins" to the module and "pin" to the sensor. I still see the "mixed up" behavior between my two inputs on my ADS1015. I had one sensor polling at 5 seconds and one at 180 seconds. I changed them to 5 and 181 which substantially reduced the collisions, but they still happen from time to time.

shbatm commented 2 years ago

@jcsouthworth did you consolidate the two module sections into one? (ref: the example in the PR linked above).

jcsouthworth commented 2 years ago

Yes.

# original config
#  - name: ads1015_pin0
#    module: ads1x15
#    type: ADS1015
#    pin: 0

#  - name: ads1015_pin1
#    module: ads1x15
#    type: ADS1015
#    pin: 1

# new config
- name: ads1015_01
    module: ads1x15
    type: ADS1015
    pins:
      - 0
      - 1

The program runs fine, but after a couple of hours I did start to see the occasional mixing of the signals again on the new config/new version. I have one ADS1015 and several DS18B20 sensors in my config.

I'm confused because your edits should have resolved this! I'm happy to help debug if you can think of anything else to try. I am on an old old old school original RPi B from 2012, so I might be an outlier. (but otherwise fully updated on RPi OS).

jcsouthworth commented 2 years ago

I think I found the problem! I was looking over the code last night and realized it might be spawning a separate instance for each "type". I was doing one of the conversions within mqtt-io and the other on another system with mqtt-io just outputting the raw bit values. My original sensor_inputs config:

  - name: sensor1_a2d
    module: ads1015_01
    interval: 180
#    type: voltage
    pin: 0
    digits: 2

  - name: sensor2_a2d
    module: ads1015_01
    type: voltage
    pin: 1
    interval: 5
    digits: 2

I removed the comment and made both sensors "type: voltage" and it appears to fix the issue - no more collisions in the output data stream.

shbatm commented 2 years ago

That's still strange--the voltage and value are read every time from a channel regardless of output.

I've gone a different direction and reverted back to using an ESP32 because I needed a flow counter input, so I'm afraid I won't be able to debug further.