PMS5003 传感器未返回数据。 “设备报告已准备好读取,但未返回任何数据(设备已断开连接或端口上有多个访问)

问题描述 投票:0回答:1

在 biginning 中,我得到了读数,并且偶尔会在读数之间出现此错误。从那以后,我收到的这条消息的数量开始多于我收到的读数。我现在对代码进行了很多更改,但我仍然明白。我将得到 2 个读数,并且将得到 3 个“未返回数据消息”,这种情况会一遍又一遍地发生,这是一种模式,所以我相信我的代码有问题。有些部分未对齐和错误识别,但这是由于此文本框造成的,请忽略它。

这是我的代码:

import json
import paho.mqtt.client as mqtt
import serial
import time




class PMSensor:
    
    # Constructor for the PMSensor class, initializes the class variables
    def __init__(self, serial_port, baud_rate, bytesize, parity, stopbits, mqtt_broker, mqtt_port, mqtt_username, mqtt_password, mqtt_topic):
        
        
        """ Serial port variables """
        # Initialize the PM sensor object with the specified serial port, baud rate, bytesize, parity, and stopbits
        self.serial_port = serial_port
        self.baud_rate = baud_rate
        self.bytesize = bytesize
        self.stopbits = stopbits
        self.parity = parity
        
        """ MQTT variables """
        # Initialize the MQTT client with the specified broker, port, username, and password
        self.mqtt_broker = mqtt_broker
        self.mqtt_port = mqtt_port
        self.mqtt_username = mqtt_username
        self.mqtt_password = mqtt_password
        self.mqtt_topic = mqtt_topic
        self.ser = None
        
        
    # Callback function for MQTT client connection event
    def on_connect(self, client, userdata, flags, rc):
        # If connection is successful the rc code should be 0, if not successfult rc code will return a 5
        # if code returns 5, check broker address, port and userdata.
        if rc == 0:
            print('Connected to MQTT broker.')
            print("--------------------------------------")
            client.subscribe(self.mqtt_topic)
        else:
            print('Failed to connect to MQTT broker with error code:', rc)
            
    
    def on_disconnect(self, client, userdata, rc):
        print("Ddisconnected from MQTT broker with result code: " + str(rc))
        
    
    
    def connect_mqtt(self):
        # Function to connect to the MQTT broker with the specified username and password
        self.client.username_pw_set(self.mqtt_username, self.mqtt_password)
        self.client.connect(self.mqtt_broker, self.mqtt_port)

    
    
    
    # Using the PM constructor variables we stablish the serial connection  
    def establish_serial_connection(self):
        try:
            self.ser = serial.Serial(self.serial_port, self.baud_rate, self.bytesize, self.parity, self.stopbits)
            if self.ser.is_open:
                print('Serial connection established:', self.ser.portstr)
            else:
                print('Failed to establish serial connection.')
                return False
            return True
        except Exception as e:
            print('Error while establishing serial connection:', e)
            return False
        
        
        
    # This function checks that the serial connection is open, once we stablish connection
    # we flush the buffer and proceed to read 32 bytes. The first two bytes are fixed as
    # /x42 and /x4d, in order to read the data we need to check for this to match with the sensor.
    # Once the first two bytes are a match, we proceed to read the rest of the data and assign them
    # to their proper variables. 
    def read_pm25(self):
        try:
            """ check for serial connection """
            if self.ser.is_open:
                """ Clear buffer """
                self.ser.flushInput()
                """ Proceed to read 32 bytes """
                data = self.ser.read(32)
                """ Check that the first two fixed bytes of data match that of the sensor """
                if data[:2] == b'\x42\x4d':
                    
                    
                    # This part of the code is taking each piece of the serial stream
                    # (16 byte stream) and converting it from the hexadecimal values to the output values.
                    
                    # The first high 8 bit reading can be multiplied by 256 to shift the bit
                    # value over by 8 places to the left in order to add it to the lower 8
                    # bit value reading. This is also the same as << 8.
                    
                    # The apm10, 25, and 100 are the factory calibration settings.
                    apm1 = (data[4] << 8) + data[5]
                    apm25 = (data[6] << 8) + data[7]
                    apm10 = (data[8] << 8) + data[9]
                    
                    # PM10, 25, and 100 are the generic atmospheric conditions for calibration.
                    pm1 = (data[10] << 8) + data[11]
                    pm25 = (data[12] << 8) + data[13]
                    pm10 = (data[14] << 8) + data[15]
                    
                    # The gt03, 05, 10, 25, 50, 100 are the number of particles with
                    # certain diameter readings. (all units are unit ug/m3
                    gt03um = (data[16] << 8) + data[17]
                    gt05um = (data[18] << 8) + data[19]
                    gt10um = (data[20] << 8) + data[21]
                    gt25um = (data[22] << 8) + data[23]
                    gt50um = (data[24] << 8) + data[25]
                    gt100um = (data[26] << 8) + data[27]
                     
                    return apm1, apm25, apm10, pm1, pm25, pm10, gt03um, gt05um, gt10um, gt25um, gt50um, gt100um
            return None
        except Exception as e:
            print('Error while reading PM sensor:', e)
            return None
        
        
    # Format the data to display in shell.
    def display_in_shell(self, apm1, apm25, apm10, pm1, pm25, pm10, gt03um, gt05um, gt10um, gt25um, gt50um, gt100um):
        
        print("--------------------------------------")
        print("Concentration Units (Standard)")
        print(f'\n PM1.0 (ug/m3): {apm1} \t\t PM2.5 (ug/m3): {apm25} \t\t PM10 (ug/m3): {apm10}')
        print("--------------------------------------")
        print("Concentration Units (Enviromental)")
        print(f'\nPM1.0 (ug/m3): {pm1} \t\t PM2.5 (ug/m3): {pm25} \t\t PM10 (ug/m3): {pm10}')
        print("--------------------------------------")
        print("Particle Count\n")
        print(f' >0.3um in 0.1L air: {gt03um}')
        print(f' >0.5um in 0.1L air: {gt05um}')
        print(f' >1.0um in 0.1L air: {gt10um}')
        print(f' >2.5um in 0.1L air: {gt25um}')
        print(f' >5.0um in 0.1L air: {gt50um}')
        print(f' >10um in 0.1L air: {gt100um}')
        print("--------------------------------------")



    def start(self):
        # if serial connection is established proceed to connect to mqtt
        if self.establish_serial_connection():
            try:
                # Function to start the PM sensor data reading and sending process
                # Connect to MQTT broker
                self.connect_mqtt()

                # Set the MQTT callback functions
                self.client.on_connect = self.on_connect
                self.client.on_disconnect = self.on_disconnect

                # Start the MQTT loop in the background
                self.client.loop_start()
            except Exception as e:
                print("Could not establish connection with broker -->", e)

            while True:
                # Function to start the PM sensor data reading and sending process
                pm_data = self.read_pm25()
                # if no data is returned by the sensor, display else statement.
                if pm_data is not None:
                    
                    apm1, apm25, apm10, pm1, pm25, pm10, gt03um, gt05um, gt10um, gt25um, gt50um, gt100um = pm_data
                    
                    self.display_in_shell(apm1, apm25, apm10, pm1, pm25, pm10, gt03um, gt05um, gt10um, gt25um, gt50um, gt100um)
                    
                    payload = json.dumps({'apm1': apm1, 'apm25': apm25, 'apm10': apm10, 'pm1': pm1, 'pm25': pm25, 'pm10': pm10,
                                          'gt03um': gt03um, 'gt05um': gt05um, 'gt10um': gt10um, 'gt25um': gt25um, 'gt50um': gt50um, 'gt100um': gt100um})
                    
                    mqtt_client.publish(self.mqtt_topic, payload)
                    
                else:
                    print('Failed to read PM sensor data.')
                    
                time.sleep(1)
            
        
        
    def stop(self):
        # Function to stop the PM sensor data reading and sending process
        # Stop the MQTT loop
        self.client.loop_stop()
        # Disconnect from the MQTT broker
        self.client.disconnect()
        

# Create an instance of the PMSensor class
pms5003_sensor = PMSensor(serial_port = '/dev/ttyUSB0',
                     baud_rate = 9600,
                     bytesize = serial.EIGHTBITS,
                     parity = serial.PARITY_NONE,
                     stopbits = serial.STOPBITS_ONE,
                     timeout = 2.0
                     
                     mqtt_broker="192.168.21.201",
                     mqtt_port=1883,
                     mqtt_username='WLED',
                     mqtt_password='Toyota',
                     mqtt_topic='TMNA/PEMC/FirstFloor/LivingWall/reTerminal/ParticulateSensor/Enviromental')


# Start the PM sensor data reading and sending process
pms5003_sensor.start()

# To stop the PM sensor data reading and sending process, call the stop() method
# pms5003_sensor.stop()

就像我提到的那样。我获得了传感器的 2 个读数,然后 3 个读数在 else 语句中没有返回任何数据消息。我已经换过两次传感器了。和电缆,串行连接良好。我认为这是我读取和返回数据的方式,但我不知道如何去做。

debugging syntax-error thonny
1个回答
0
投票

我刚刚看到这个问题。我用 C 语言编写了 ESP32 代码,但遇到了非常相似的问题。就我而言,我在被动模式下使用 PMS5003。在这种模式下,您发送 requestRead(),等待(我有 1 秒),然后处理读取的数据。我注意到有时接收缓冲区中存在错误数据,导致校验和和读取长度错误。我不记得在哪里 - 对不起原作者,但我找到了一个在发出 readRequest() 之前清除读取缓冲区的示例。这意味着 PMS5003 数据被读入干净的缓冲区并解决了我的“无数据”问题。我知道你正在用 Python 编写你的项目,而我的项目是用 C 编写的,但这可能是一个类似的问题。我正在使用 pms.h 和 SoftwareSerial.h,并且在从 PMS5003 请求数据之前,我通过以下方式清除读取缓冲区:

while (pmsSerial.available()) 
{ 
    pmsSerial.read(); // read any residual buffer data
}

希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.