本帖最后由 roc634 于 2018-3-28 15:10 编辑
先说明一下我现在的情况,我买了一个串口的声音传感器模块,通过修改内置的二氧化碳插件co2sensor.py实现了读取数据,但是由于这个声音传感器模块是每秒发送两次数据,加上声音的特性,使得表现出来的曲线初看起来就像一把锯子,基本不能直接看出声音变化的趋势,见下图,我希望取一定时间或者若干个数据的平均值(10个,20个或者10秒,20秒等,这个需要实验后才能确定),这样表现出来的声音曲线能够像下面的气压曲线那么一目也然,我估计出来的效果应该差不多是我在噪声曲线上手工画的那个蓝色的线。
我修改后能够正常读取数据的文件是这样的:
def read_mh_z19_with_temperature(serial_device):
""" Read the CO2 PPM concenration and temperature from a MH-Z19 sensor"""
logger = logging.getLogger(__name__)
ser = serial.Serial(port=serial_device,
baudrate=115200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS)
sbuf = bytearray()
starttime = time.time()
finished = False
timeout = 2
res = None
while not finished:
mytime = time.time()
if mytime - starttime > timeout:
logger.error("read timeout after %s seconds, read %s bytes",
timeout, len(sbuf))
return None
if ser.inWaiting() > 0:
sbuf += ser.read(1)
if len(sbuf) == MHZ19_SIZE and sbuf[:3] == MZH19_READ:
# TODO: check checksum
res = round((sbuf[4]*256 + sbuf[3])*0.1, 1)
logger.debug("Finished reading data %s", sbuf)
finished = True
else:
time.sleep(.1)
logger.debug("Serial waiting for data, buffer length=%s",
len(sbuf))
return (res,0)
复制代码
我试过了将读取的数据先存到一个数组中,然后再计算平均值。也试过了将数据直接相加,然后取平均值的方法,但是都没有成功,后果就是噪声的数值不再显示,见下图。
后来我发现,只要在while的循环外定义一个空列表,或者为了在外面加一个嵌套的循环而定义一个变量的初始值为0,其他一切都不变,程序就出错。见下图:
而在函数之外定义的全局变量,则不会出错,噪声数据依然可以显示:
由于本人也是python的初学者,自己折腾了一个多星期也没搞明白,不得已麻烦大神们,希望能得到你们的指导。
由于只是添加一个列表或者一个参数就出错,实在不能继续下去,因此下面的代码也不知道对不对,请大神们帮看一下,不胜感激!!
我希望用列表来保存10个数据,然后取平均值的代码:
""""
Read data from CO2 sensor
"""
import time
import logging
import serial
MHZ19_SIZE = 6
MZH19_READ = bytes([0xBB, 0xAA, 0x01])
#sound = []
def read_mh_z19(serial_device):
""" Read the CO2 PPM concenration from a MH-Z19 sensor"""
result = read_mh_z19_with_temperature(serial_device)
if result is None:
return None
ppm = result
return ppm
def read_mh_z19_with_temperature(serial_device):
""" Read the CO2 PPM concenration and temperature from a MH-Z19 sensor"""
logger = logging.getLogger(__name__)
ser = serial.Serial(port=serial_device,
baudrate=115200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS)
sbuf = bytearray()
starttime = time.time()
finished = False
timeout = 2
res = None
sound = []
while len(sound) < 10:
while not finished:
mytime = time.time()
if mytime - starttime > timeout:
logger.error("read timeout after %s seconds, read %s bytes",
timeout, len(sbuf))
return None
if ser.inWaiting() > 0:
sbuf += ser.read(1)
if len(sbuf) == MHZ19_SIZE and sbuf[:3] == MZH19_READ:
# TODO: check checksum
res = round((sbuf[4]*256 + sbuf[3])*0.1, 1)
logger.debug("Finished reading data %s", sbuf)
finished = True
else:
time.sleep(.1)
logger.debug("Serial waiting for data, buffer length=%s",
len(sbuf))
sound.append(res)
ave = round(sum(sound)/len(sound), 1)
return (ave, 0)
复制代码
需要说明的是,这个插件返回的数据格式是元组,即(50,30)这样的格式,第一个数据是原插件的co2浓度,第二个数据是温度。所以我最后也加0将其变为元组,以符合原插件的要求。我知道直接改原来系统插件是不好的,但是在我有能力自己写之前,能通过借用来实现就已经很有成就感了。希望以后可以自己写吧。