[Solved] UART for a PMS7003 sensor gives weird output.

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
Post Reply
mcabra
Posts: 4
Joined: Sun Mar 25, 2018 8:46 pm

[Solved] UART for a PMS7003 sensor gives weird output.

Post by mcabra » Sun Mar 25, 2018 9:04 pm

Hello,

The problem:
I'm trying to read data from a device that connects through UART. The device is PMS7003 and it runs on a 9600 baud rate, has no check bit, stop bit is 1 and provides 32 bytes in one air quality reading.

The symptoms:
When I connect the sensor to my PC via a USB-UART cable I can read the data with ease - it starts with `BM` and follows with 30 bytes

Code: Select all

BM\x00\x1c\x00\x15\x00)\x00/\x00\x15\x00)\x00/\n5\x02\xe9\x00\xb4\x00&\x00\x06\x00\x02\x91\x00\x04"

But when I connect it to a UART0 in ESP8266 (which makes debugging a nightmare) or to UART2 on ESP32 (much easier) I get loads of

Code: Select all

\x00\xfe\x00\xfe\x00\xff\x00\xfe\x00\xfe\x00\xfe\x00\xfe\x00\xfe\x00\xff\x00\x00\x00@\x00\x00\x00\xfc\x00\xfe\x00\xfe\x00\xfe
The ask:
Please help me understand and maybe fix the issue so that I can have a proper reading from my UART on one of the ESPs.

A bonus help would be if someone could help me with the

Code: Select all

W (436295) uart: UART event queue full
...
W (436375) uart: UART event queue full
... I'd like to disable/hide those warnings.
Last edited by mcabra on Tue Mar 27, 2018 8:38 pm, edited 2 times in total.

User avatar
pythoncoder
Posts: 4023
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: UART for a PMS7003 sensor gves weird output.

Post by pythoncoder » Mon Mar 26, 2018 6:28 am

Does the sensor provide 0-3.3V on its UART output? If it's 0-5V you need a logic level converter.
Peter Hinch

mcabra
Posts: 4
Joined: Sun Mar 25, 2018 8:46 pm

Re: UART for a PMS7003 sensor gves weird output.

Post by mcabra » Mon Mar 26, 2018 7:30 am

The data sheet provides the following information:

Circuit Attentions
1) DC 5V power supply is needed because the FAN should be driven by 5V. But the high level of data pin is 3.3V. Level conversion unit should be used if the power of host MCU is 5V.

So I'm powering it with 5V but the TX pin of the sensor is connected straight to the ESP. It also worked when the sensor was running entirely from 3.3V.

mcabra
Posts: 4
Joined: Sun Mar 25, 2018 8:46 pm

Re: UART for a PMS7003 sensor gves weird output.

Post by mcabra » Mon Mar 26, 2018 9:30 pm

Ok, so despite what I quoted, I have the sensor now powered on 3.3V and I'm reading UART with no problem. I could swear that I tried powering it with 3.3V but it apparently was not the case. Lesson learned - if your UART is weird, check the power...

I still need to figure out how can I reset the serial buffer but that's another topic.

Thank you very much.

If someone will be interested here's my code (adapted from here) working on an ESP-WROOM-32 DevKitC:

Code: Select all

import machine
import ustruct as struct


class PMS7003:
    PMS_FRAME_LENGTH = 0
    PMS_PM1_0 = 1
    PMS_PM2_5 = 2
    PMS_PM10_0 = 3
    PMS_PM1_0_ATM = 4
    PMS_PM2_5_ATM = 5
    PMS_PM10_0_ATM = 6
    PMS_PCNT_0_3 = 7
    PMS_PCNT_0_5 = 8
    PMS_PCNT_1_0 = 9
    PMS_PCNT_2_5 = 10
    PMS_PCNT_5_0 = 11
    PMS_PCNT_10_0 = 12
    PMS_VERSION = 13
    PMS_ERROR = 14
    PMS_CHECKSUM = 15

    def get_uart(self):
        uart = machine.UART(2, 9600)
        uart.init(9600, bits=8, parity=None, stop=1)
        return uart

    def _assert_byte(self, byte, expected):
        if byte is None or len(byte) < 1 or ord(byte) != expected:
            return False
        return True

    def read(self):
        uart = self.get_uart()
        while True:
            if not self._assert_byte(uart.read(1), 0x42):
                print('bad first')
                continue
            if not self._assert_byte(uart.read(1), 0x4D):
                print('bad second')
                continue

            read_buffer = uart.read(30)
            if len(read_buffer) < 30:
                continue

            data = struct.unpack('!HHHHHHHHHHHHHBBH', read_buffer)

            checksum = 0x42 + 0x4D
            for c in read_buffer[0:28]:
                checksum += c
            if checksum != data[self.PMS_CHECKSUM]:
                print('bad checksum')
                continue

            return {
                'FRAME_LENGTH': data[self.PMS_FRAME_LENGTH],
                'PM1_0': data[self.PMS_PM1_0],
                'PM2_5': data[self.PMS_PM2_5],
                'PM10_0': data[self.PMS_PM10_0],
                'PM1_0_ATM': data[self.PMS_PM1_0_ATM],
                'PM2_5_ATM': data[self.PMS_PM2_5_ATM],
                'PM10_0_ATM': data[self.PMS_PM10_0_ATM],
                'PCNT_0_3': data[self.PMS_PCNT_0_3],
                'PCNT_0_5': data[self.PMS_PCNT_0_5],
                'PCNT_1_0': data[self.PMS_PCNT_1_0],
                'PCNT_2_5': data[self.PMS_PCNT_2_5],
                'PCNT_5_0': data[self.PMS_PCNT_5_0],
                'PCNT_10_0': data[self.PMS_PCNT_10_0],
                'VERSION': data[self.PMS_VERSION],
                'ERROR': data[self.PMS_ERROR],
                'CHECKSUM': data[self.PMS_CHECKSUM],
            }

pms = PMS7003()
while True:
    pms_data = pms.read()


guye1296
Posts: 2
Joined: Sat Apr 07, 2018 5:50 pm

Re: [Solved] UART for a PMS7003 sensor gives weird output.

Post by guye1296 » Sun Apr 08, 2018 8:53 pm

How did you make UART2 work? Did you make any change to the official MicroPython build?

mcabra
Posts: 4
Joined: Sun Mar 25, 2018 8:46 pm

Re: [Solved] UART for a PMS7003 sensor gives weird output.

Post by mcabra » Mon Apr 09, 2018 5:07 pm

Not at all, but please note I'm using ESP32 here, if you are using an ESP8266 you have only UART0 and UART1 (last one having only a TX).

User avatar
tve
Posts: 97
Joined: Wed Jan 01, 2020 10:12 pm
Location: Santa Barbara, CA
Contact:

Re: [Solved] UART for a PMS7003 sensor gives weird output.

Post by tve » Wed Jan 01, 2020 10:14 pm

FYI, if you're powering the device from 3.3V the fan will run at a lower speed, which will reduce the airflow, which will impact the accuracy of the measurements.

Post Reply