kizniche / Mycodo

An environmental monitoring and regulation system
http://kylegabriel.com/projects/
GNU General Public License v3.0
2.96k stars 494 forks source link

MH-Z19 not working #446

Closed riverfreeloader closed 6 years ago

riverfreeloader commented 6 years ago

Have added a MH-Z19 to a RP3B and added enable_uart=1 to /boot/config.txt but still cannot get data from it. Pins (MH <> RP3) are 2 (RXD) to 8 (TXD), 3 (TXD) to 10 (RXD), 7 (GND) to , 6 (VIN) to 3 (5V). Any other changes I need to make in order to get the serial port working correctly?

kizniche commented 6 years ago

Are you able to obtain measurements with any other scripts/software?

Theoi-Meteoroi commented 6 years ago

On the RPi-3, the bluetooth device gets the UART and the serial port presented is a less capable (buggy) interface that doesn't work for the MH-Z CO2 sensors.

See this discussion: https://www.raspberrypi.org/forums/viewtopic.php?t=142112

I usually just use the disable-bt overlay. Or I use a USB serial adaptor.

Kattihatt commented 6 years ago

I have the same issue. Can't use the sensor in the software. I use a script for it.

kizniche commented 6 years ago

Can you link me to the code you use? I'll update the input module.

Kattihatt commented 6 years ago
#!/usr/bin/python
import serial
import time

def mh_z19():
  ser = serial.Serial('/dev/ttyAMA0',
                      baudrate=9600,
                      bytesize=serial.EIGHTBITS,
                      parity=serial.PARITY_NONE,
                      stopbits=serial.STOPBITS_ONE,
                      timeout=1.0)
  while 1:
    result=ser.write("\xff\x01\x86\x00\x00\x00\x00\x00\x79")
    s=ser.read(9)
    if s[0] == "\xff" and s[1] == "\x86":
      return {'co2': ord(s[2])*256 + ord(s[3])}
    break

if __name__ == '__main__':
    value = int(mh_z19()['co2'])
    print(value)
kizniche commented 6 years ago

I have a suspicion that this code will not work with Python 3. Can you please test it with the python3 installed in the Mycodo virtualenv?

~/Mycodo/env/bin/python3 ~/path/to/script.py
kizniche commented 6 years ago

I just pushed a fix for the upcoming 6.0.0 release, that incorporates the fixes we discovered in #359 for the MH-Z16 to work with Python 3. You can make the manual edits and restart the daemon if you want to test if it works:

https://github.com/kizniche/Mycodo/commit/ec94d8eef3795c778aa19c5c0f02f90743e5c6fa#diff-bcc5b3aca316822cc771e508d540261d

Than, sudo service mycodo restart

kizniche commented 6 years ago

Interestingly, the edits from pull request 361 don't appear to be with the current version. The MH-Z16 and MH-Z19 modules are also slightly different from @Theoi-Meteoroi's edits, with struct.unpack() being used in the MH-Z16 module, but not in the MH-Z19 module.

So, you may need to test either of these changes in the MH-Z19 module:

Change this:

self.ser.write("\xff\x01\x86\x00\x00\x00\x00\x00\x79".encode())

to this:

self.ser.write(bytearray([0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79]))

And change this:

                high = ord(resp[2])
                low = ord(resp[3])

to this:

                high = resp[2]
                low = resp[3]

or this:

                high = struct.unpack('B', resp[2])[0]
                low = struct.unpack('B', resp[3])[0]
Theoi-Meteoroi commented 6 years ago

I tested the first changed line in Mycodo v5.7.2 with a MH-Z19 on a USB serial adapter. It's working again with the newest version and I'm getting comparable readings to the MH-Z16 sensor that is using the ttyAMA0 port. That one change seems to be enough for that version. I found the second change (dropping the ord() function) was already like your suggestion.

kizniche commented 6 years ago

I found the second change (dropping the ord() function) was already like your suggestion.

What do you mean "was already like your suggestion"?

So, without ord() or struct.unpack() it will work?

stminm commented 6 years ago

I had the same problem. After I applied ec94d8e in mycodo/inputs/mh_z19.py the issue was fixed. Thanks!

Theoi-Meteoroi commented 6 years ago
 You had suggested three edits:

The first is the fix for the Python3 compatible version.

self.ser.write(bytearray([0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79]))

The second is existing code in 5.7.2 mh_z19.py

high = resp[2] low = resp[3] The third suggestion is un-necessary.

We had to change the python2 string handling into python3 byte objects when you did the Python3 port for both devices when using UART interface.

The MH-Z16 and the MH-Z19 are somewhat different in design and interfacing. I haven’t looked at combining the code modules, mostly since Winsen doesn’t really document reading module type, if I recall.

My MH-Z19 sensor had stopped working at some point and I didn’t debug the reason. I assumed a problem on my side and didn’t suspect a code regression.

tl,dr: the fix is only the one line. In the Python3 version the data is stored as a byte-array and can be used directly.

BTW: Really good work on Mycodo! The interface and functional improvements continue to be impressive. Upgrade has been stable for me.

On Apr 13, 2018, at 12:35 PM, Kyle Gabriel notifications@github.com wrote:

I found the second change (dropping the ord() function) was already like your suggestion.

What do you mean "was already like your suggestion"?

So, without ord() or struct.unpack() it will work?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/kizniche/Mycodo/issues/446#issuecomment-381240329, or mute the thread https://github.com/notifications/unsubscribe-auth/APsXKhUJc78i6chW9Uz-yzzC-GGWuG2Pks5toP39gaJpZM4TOAzR.

kizniche commented 6 years ago

Thanks for testing that. Again, I'm not sure how your edits didn't get incorporated into the latest version.

Kattihatt commented 6 years ago

My MH-Z19 is still not working by the way. Is it supposed to work now?

kizniche commented 6 years ago

It should be working. Are you receiving any errors in the daemon log?

Kattihatt commented 6 years ago
2018-05-09 14:49:09,258 - mycodo.input_24 - ERROR - Could not acquire input lock. Breaking for future locking.
2018-05-09 14:49:09,266 - mycodo.input_8 - ERROR - Could not acquire input lock. Breaking for future locking.
2018-05-09 14:49:09,267 - mycodo.input_8 - ERROR - Can't delete lock file: Lock file doesn't exist.
2018-05-09 14:49:13,636 - mycodo.input_25 - ERROR - StopIteration raised. Possibly could not read input. Ensure it's connected properly and detected.
2018-05-09 14:49:57,053 - mycodo.input_25 - ERROR - StopIteration raised. Possibly could not read input. Ensure it's connected properly and detected.
2018-05-09 14:50:42,060 - mycodo.input_25 - ERROR - StopIteration raised. Possibly could not read input. Ensure it's connected properly and detected.
2018-05-09 14:51:27,073 - mycodo.input_25 - ERROR - StopIteration raised. Possibly could not read input. Ensure it's connected properly and detected.
2018-05-09 14:52:11,990 - mycodo.input_25 - ERROR - StopIteration raised. Possibly could not read input. Ensure it's connected properly and detected.
kizniche commented 6 years ago

I see several inputs. Which input is the MH-Z19? Also, can you provide a screenshot of the input settings?

Kattihatt commented 6 years ago

I didn't even realise. Number 8 and 24 are the ADC inputs, but I haven't noticed any issues apart from some taking a long time to get a correct value when they start. I will start working on the triggers some day soon, and hopefully it's not just the live values but the values shown in the chart that you can use. So that it doesn't matter that it's without a reading for a while and starts watering.

Number 25 is the MH-Z19 and here is the image of the settings: https://imgur.com/a/kWbfQgv

I put /dev/ttyAMA0 just as in the script I'm using that returns the correct values. I tried the default as well but that didn't return anything.

kizniche commented 6 years ago

I don't have this sensor, so can't test code changes. Could you provide ssh access so I could test new code on your system? It would probably only require a few restarts of the daemon to figure out what part of the module isn't working.