[SOLVED] UART and MH-Z16 CO2 sensor



  • Hello there! :)

    I am having some trouble communicating with this CO2 sensor.
    This it's wiki with sample code, and this is the datasheet.

    Okay so I think my issue is related to byte conversion but not sure.

    from machine import UART
    uart = UART(1, 9600) 
    uart.write(b'\xFF\x01\x86\x00\x00\x00\x00\x00\x79') # This is what should trigger the measure 
    uart.read(9) #b'\xff\x86\x01\xecF\x00\x00\x00G' #This is the answer
    

    I am not sure how to process the read value.. The first 2 number is always ff and 86 the next is always small, then the 4th is something weird.. then always 2 zero, and zero with a letter in the and.
    So do you have any idea how can I get proper measurment out of it? Thank you!



  • @robert-hh Yep, Thank You! :)



  • @tttadam It looks like the x type code is not supported by MicroPython. Use:

    d1, cmd, concentration, d2, check = unpack(">bBhiB", s)
    

    d1 and d2 are dummy values, which can be ignored.



  • @robert-hh said in [SOLVED] UART and MH-Z16 CO2 sensor:

    @tttadam Using struct.unpack, you can also use:

    from machine import UART
    from struct import unpack
    uart = UART(1, 9600) 
    uart.write(b'\xFF\x01\x86\x00\x00\x00\x00\x00\x79') # This is what should trigger the measure 
    response = uart.read(9)
    cmd, concentration, check = unpack(">xBh4xB", response)
    checksum = (256 - sum(response[1:-1])) % 256
    print(concentration, checksum == check)
    

    FYI, nowadays when I try this code I got ValueError: bad typecode error. I am not sure if this was the case back in May.



  • @robert-hh Thank you! :)
    I got it now. It's work like it's should.
    Maybe I should to open the window :D



  • @tttadam Using struct.unpack, you can also use:

    from machine import UART
    from struct import unpack
    uart = UART(1, 9600) 
    uart.write(b'\xFF\x01\x86\x00\x00\x00\x00\x00\x79') # This is what should trigger the measure 
    response = uart.read(9)
    cmd, concentration, check = unpack(">xBh4xB", response)
    checksum = (256 - sum(response[1:-1])) % 256
    print(concentration, checksum == check)
    


  • @tttadam The checksum is just to be used to verify, that the data was received correctly. The calculated value should be identical to response[8]. Note that I changed the code, such that the checksum is always positive.



  • @robert-hh Thank you. The code is working, but the values seems to be off, and I am not sure how should I understood the checksum. Should I calibrate the sensor somehow?
    response: 586
    checksum: -29

    response: 590
    checksum: -33

    response: 667
    checksum: -112



  • @tttadam Look at the struct module. It allows to unpack a bytearray into individual data elements. You can also make it simpler,. just following the manual:

    from machine import UART
    uart = UART(1, 9600) 
    uart.write(b'\xFF\x01\x86\x00\x00\x00\x00\x00\x79') # This is what should trigger the measure 
    response = bytearray(uart.read(9)) #
    concentration = response[2] * 256 + response[3]
    checksum = (256 - sum(response[1:-1])) % 256
    print(concentration)
    

    The last byte is the checksum. It looks as if the sample C code in the data sheet is wrong. The variable checksum is not initialized to 0.
    Edit: Checksum simplified



Pycom on Twitter