简介
甲醛是一种有特殊刺激气味的气体,对人的眼睛有强烈的刺激作用。若空气中甲醛浓度过高,比如新装修的房子、新买的汽车等,可引起中毒反应,严重的可致癌。家去拿时空气中的杀手之一,需要时刻提防。本案例的核心在于准确测量家庭中的甲醛浓度。
电化学甲醛模组
产品型号 | CJSH20-CH2O |
---|
检测气体 | 甲醛 | 干扰气体 | 酒精,一氧化碳等气体 | 输出数据 | UART 输出(3.3V 电平) | 工作电压 | 3.7V~5.5V | 预热时间 | ≤3 分钟 | 响应时间 | ≤60 秒 | 恢复时间 | ≤60 秒 | 量程 | 0~5ppm | 分辨率 | ≤0.010 mg/m3 | 工作温度 | -20℃~50℃ | 工作湿度 | 15%RH-90%RH(无凝结) | 存储温度 | 0~25℃ | 使用寿命 | 2 年(空气中 0℃~35℃) | 模组尺寸 | 长17.7mm×宽17.8mm |
1、管脚定义 2、通讯协议
3、通讯命令 通信分为主动上传式和问答式,出厂默认主动上传,每间隔1S发送一次浓度值。 如果用户切换到问答模式下,需要重新切换为主动上传时,发送如下命令行格式即可: 数据显示格式如下: 气 体 浓 度 值 (PPB)=( 气 体 浓 度 高 位 *256+ 气 体 浓 度 低 位 ). 当转换为 PPM 时: PPM= PPB/1000,1PPM甲醛相当于1.34mg/m3. 1mg/m3甲醛相当于0.746PPM.
准备
本案例需要的硬件
器材 | 数量 |
---|
HaaS506开发板 | 1 | 电化学甲醛模组 | 1 | SIM卡 | 1 | 杜邦线 | 若干 |
硬件连接图
- 使用TTL口下载完成后,用TTL口连接甲醛传感器进行数据读取。
代码流程
1、连接阿里云平台。 2、上传云端报警状态,重复读取传感器数据,并上传云端。
1、物联网平台开发
第一次使用物联网平台的读者,需要开通实例后使用物联网平台功能。也可以使用免费的公共实例进行开发,在阿里云物联网平台中,左上角选择‘华东2-上海’,点击‘公共实例’,即可开通。
1、平台产品创建可参考haas506 2.0开发教程-aliyunIoT 2、创建产品属性(添加物模型)
-
选择产品功能定义–编辑草稿 -
添加自定义功能 -
添加标识符与数据类型(标识符要与代码一致) -
点击发布上线 -
点击确定
2、设备端开发
- 第一次使用开发板的读者可以按照haas5062.0开发教程-导学篇搭建开发环境。
- 搭建完后复制以下代码到Visual Studio Code,复制产品证书到代码相应位置。
- main.py
import network
import ujson
import utime as time
import modem
from aliyunIoT import Device
import kv
from driver import UART
def on_connect(data):
global module_name,default_ver,productKey,deviceName,deviceSecret,on_trigger,on_download,on_verify,on_upgrade
print('***** connect lp succeed****')
data_handle = {}
data_handle['device_handle'] = device.getDeviceHandle()
def on_disconnect():
print('linkkit is disconnected')
def on_props(request):
print('clound req data is {}'.format(request))
def on_service(id,request):
print('clound req id is {} , req is {}'.format(id,request))
def on_error(err):
print('err msg is {} '.format(err))
def on_4g_cb(args):
global g_connect_status
pdp = args[0]
netwk_sta = args[1]
if netwk_sta == 1:
g_connect_status = True
else:
g_connect_status = False
def connect_network():
global net,on_4g_cb,g_connect_status
net = network.NetWorkClient()
g_register_network = False
if net._stagecode is not None and net._stagecode == 3 and net._subcode == 1:
g_register_network = True
else:
g_register_network = False
if g_register_network:
net.on(1,on_4g_cb)
net.connect(None)
else:
print('网络注册失败')
while True:
if g_connect_status:
print('网络连接成功')
break
time.sleep_ms(20)
def on_dynreg_cb(data):
global deviceSecret,device_dyn_resigter_succed
deviceSecret = data
device_dyn_resigter_succed = True
def dyn_register_device(productKey,productSecret,deviceName):
global on_dynreg_cb,device,deviceSecret,device_dyn_resigter_succed
key = '_amp_customer_devicesecret'
deviceSecretdict = kv.get(key)
print("deviceSecretdict:",deviceSecretdict)
if isinstance(deviceSecretdict,str):
deviceSecret = deviceSecretdict
if deviceSecretdict is None or deviceSecret is None:
key_info = {
'productKey': productKey ,
'productSecret': productSecret ,
'deviceName': deviceName
}
if not device_dyn_resigter_succed:
device.register(key_info,on_dynreg_cb)
PPM_data = {}
def upload_PPM():
global PPM_data,PPM
PPM_data["hcho"]= PPM
PPM_data_str=ujson.dumps(PPM_data)
data={
'params':PPM_data_str
}
device.postProps(data)
if __name__ == '__main__':
ICCID=None
g_connect_status = False
net = None
device = None
deviceSecret = None
deviceName = None
productKey = "a1A9j0EmrQr"
productSecret = "21ATZN5PR2iuv08w"
device_dyn_resigter_succed = False
connect_network()
deviceName = modem.getDevImei()
ICCID=modem.sim.getIccid()
device = Device()
if deviceName is not None and len(deviceName) > 0 :
dyn_register_device(productKey,productSecret,deviceName)
else:
print("获取设备IMEI失败,无法进行动态注册")
while deviceSecret is None:
time.sleep(0.2)
print('动态注册成功:' + deviceSecret)
key_info = {
'region' : 'cn-shanghai' ,
'productKey': productKey ,
'deviceName': deviceName ,
'deviceSecret': deviceSecret ,
'keepaliveSec': 60,
}
print(key_info)
device.on(device.ON_CONNECT,on_connect)
device.on(device.ON_DISCONNECT,on_disconnect)
device.on(device.ON_PROPS,on_props)
device.on(device.ON_SERVICE,on_service)
device.on(device.ON_ERROR,on_error)
device.connect(key_info)
time.sleep(2)
uart1=UART()
uart1.open("serial1")
readBuf=bytearray(9)
writeBuf=bytearray(9)
writeBuf = bytearray([0xFF,0x01,0x78,0x40,0x00,0x00,0x00,0x00,0x47])
uart1.write(writeBuf)
while True:
readSize=uart1.read(readBuf)
print(readBuf)
PPM = (int(readBuf[4])*256+int(readBuf[5]))/1000
print(PPM)
upload_PPM()
time.sleep(1)
- 使用485串口读取log,配置 “replPort”: 2,串口TTL读取改为0 。
- board.json
{
"name": "haas506",
"version": "2.0.0",
"io": {
"serial1": {
"type": "UART",
"port": 0,
"dataWidth": 8,
"baudRate": 9600,
"stopBits": 1,
"flowControl": "disable",
"parity": "none"
},
"serial2": {
"type": "UART",
"port": 1,
"dataWidth": 8,
"baudRate": 9600,
"stopBits": 1,
"flowControl": "disable",
"parity": "none",
"timeout": 1000
},
"serial3": {
"type": "UART",
"port": 2,
"dataWidth": 8,
"baudRate": 115200,
"stopBits": 1,
"flowControl": "disable",
"parity": "none",
"timeout": 1000
}
},
"debugLevel": "ERROR",
"repl": "enable",
"replPort": 2
}
调试
- 调试串口使用485端口,打开设备管理器可以查看调试端口号。
- 串口调试工具使用putty
调试结果
1、串口调试工具log,网络连接成功–动态注册成功–每秒打印读取的数字及PPM数值 2、云端有数据传入,打开实时刷新,显示数据会自动更新。 点击查看数据,可以看到每次上传的具体数值。
|