『瀚思彼岸』» 智能家居技术论坛

 找回密码
 立即注册
查看: 17906|回复: 14

攀藤G5+WidoraAIR(ESP32) 空气质量检测 接入HomeAssistant

[复制链接]

1

主题

11

帖子

104

积分

论坛分享达人

积分
104
金钱
93
HASS币
0
发表于 2017-11-17 22:42:25 | 显示全部楼层 |阅读模式
    接触HomeAssistant大概一周了,在论坛找到了很多教程学习。现在特发一个使用攀藤G5通过WidoraAIR(EPS32)接入HomeAssistant教程以回报论坛。
    一、硬件介绍:
           1.攀藤G5是一款可以同时监测空气中颗粒物浓度和甲醛浓度的二合一传感器。其中颗粒物浓度的监测基于激光散射原理,可连续采集并计算单位体积内空气中不同粒径的悬浮颗粒物个数,即颗粒物浓度分布,进而换算成为质量浓度。甲醛浓度的监测基于电化学原理,具有高精度、高稳定性的特点。颗粒物浓度数值和甲醛浓度数值合并以通用数字接口形式输出。
              检测出来的数据通过串口发出来,波特率:9600kbps 校验位:无 停止位:1位

攀藤数据输出格式1

攀藤数据输出格式1

攀藤数据输出格式2

攀藤数据输出格式2

        2.WidoraAIR是一款ESP32板子。把攀藤G5接到WidoraAIR第2号串口上,也就是16、17号IO口上。(16:RX,17:TX)。注意攀藤的RX接WidoraAIR的TX,攀藤的TX接WidoraAIR的RX。其实我们只要接收攀藤发送的数据,所以只接攀藤的TX到WidoraAIR的RX也是可以的。攀藤需要5V供电,这个直接接到WidoraAIR的Vin,当然别忘了共地(GND接GND)
  二、软件部分:
      1.HomeAssistant的配置:
#####################################
sensor:

  - platform: mqtt
    state_topic: 'stat/kqzl'
    name: 'Jia Quan'
    unit_of_measurement: 'mg/m3'
    value_template: '{{ value_json.jiaquan }}'
  - platform: mqtt
    state_topic: 'stat/kqzl'
    name: 'PM2.5'
    unit_of_measurement: 'μg/m3'
    value_template: '{{ value_json.pm2p5 }}'
  - platform: mqtt
    state_topic: 'stat/kqzl'
    name: 'PM1.0'
    unit_of_measurement: 'μg/m3'
    value_template: '{{ value_json.pm1p0 }}'
  - platform: mqtt
    state_topic: 'stat/kqzl'
    name: 'PM10'
    unit_of_measurement: 'μg/m3'
    value_template: '{{ value_json.pm10 }}'

########################################
新手可能面对这一堆配置不能理解,下面我截取一段讲解一下:
sensor:
  - platform: mqtt
    state_topic: 'stat/kqzl'
    name: 'Jia Quan'
    unit_of_measurement: 'mg/m3'
    value_template: '{{ value_json.jiaquan }}'


首先yaml格式的配置文件是严格缩进的,所以各位一定要注意各行的缩进。
  sensor:
    表示你配置的是传感器。不同的设备,HomeAssistant在表现它们的数据的形式上有所不同。比如说sensor,HomeAssistant显示的数值和数据曲线图;而Light则显示一个开关按钮。
  - platform: mqtt 表示数据来源平台。这是说明数据是从mqtt协议的消息中来。我们是通过WidoraAIR将数据通过Mqtt发送出去。
    state_topic: 'stat/kqzl'  表示这个数据状态订阅的主题(Topic),就是哪个主题的mqtt消息是这个传感器关心的。这个跟后面我们的WidoraAIR的代码是对应的。
    name: 'Jia Quan' 表示传感器的名字,如果要显示汉字,请参考论坛的汉化相关帖子。
    unit_of_measurement: 'mg/m3'  表示传感器数据的单位。注意相同单位的数据会在“历史”页面显示在同一个曲线表格中,用颜色区分。
    value_template: '{{ value_json.jiaquan }}'  表示HomeAssistant怎么从mqtt消息中获取数据。我们发送给HomeAssistant的消息看起来像这样子的:{"jiaquan": 22.30,"pm2p5" : 43.70,"pm1p0" : 43.70,"pm10" : 43.70},这里表示获取消息里面的jiaquan这项数据。
    2.WidoraAIR的代码。
        开发平台:Arduino core for ESP32 WiFi chip (https://github.com/espressif/arduino-esp32
        使用到的库:pubsubclient(https://github.com/knolleary/pubsubclient
                            下载地址:https://github.com/knolleary/pubsubclient/archive/v2.6.zip
        下面贴出代码:

/*ESP32做了两件事:
1/ 从攀藤G5读取数据
2/ 通过Mqtt传出数据
*/

#include <WiFi.h>
#include <PubSubClient.h>

/* 改成你自己的wifi信息 */
const char* ssid = "muhome2g";
const char* password = "KuangShan3";
/* 你的MQTT Server地址*/
const char* mqtt_server = "192.168.1.151";

WiFiClient espClient;
PubSubClient client(espClient);

/*LED GPIO pin*/
const char led = 25;

/* topics */
#define TOPICMD  "cmnd/light/l1/power"
#define TOPICST  "stat/light/l1/power"
#define TOPICKQ  "stat/kqzl"//这就是刚刚给大家说的HomeAssistant订阅的Topic

long lastMsg = 0;
char msg[80];
u8_t timecount = 0;;

HardwareSerial Serial1(2);

int dataSum = 0;

//攀藤G5的数据格式
struct _panteng {
        unsigned char len[2];
        unsigned char pm1_cf1[2];
        unsigned char pm2_5_cf1[2];
        unsigned char pm10_0_cf1[2];
        unsigned char pm1_0[2];
        unsigned char pm2_5[2];
        unsigned char pm10_0[2];
        unsigned char pml0_3[2];
        unsigned char pml0_5[2];
        unsigned char pml1_0[2];
        unsigned char pml2_5[2];
        unsigned char pml5[2];
        unsigned char pml10[2];
        unsigned char jq[2];
        unsigned char check[2];
} panteng;
int pm1_0, pm2_5, pm10_0, jq;        //PM1.0、PM2.5、PM10

//#define DEBUG

void receivedCallback(char* topic, byte* payload, unsigned int length) {
        Serial.print("Message received: ");
        Serial.println(topic);

        Serial.print("payload: ");
        for (int i = 0; i < length; i++) {
                Serial.print((char)payload);
        }
        Serial.println();
        if (length > 1)
  {
    if ((char)payload[1] == 'N') {
      Serial.println("Light ON");
      digitalWrite(led, HIGH);
      client.publish(TOPICST, "ON");
    }
    else {
      digitalWrite(led, LOW);
      Serial.println("Light OFF");
      client.publish(TOPICST, "OFF");
    }
  }

}

void mqttconnect() {
        /* Loop until reconnected */
        while (!client.connected()) {
                Serial.print("MQTT connecting ...");
                /* client ID */
                String clientId = "ESP32Client";
                /* connect now */
                if (client.connect(clientId.c_str())) {
                        Serial.println("connected");
                        /* subscribe topic with default QoS 0*/
                        client.subscribe(TOPICMD);
                }
                else {
                        Serial.print("failed, status code =");
                        Serial.print(client.state());
                        Serial.println("try again in 5 seconds");
                        /* Wait 5 seconds before retrying */
                        delay(5000);
                }
        }
}

void setup() {
        Serial1.begin(9600);
        Serial.begin(115200);
        // We start by connecting to a WiFi network
        Serial.println();
        Serial.print("Connecting to ");
        Serial.println(ssid);

        WiFi.begin(ssid, password);

        while (WiFi.status() != WL_CONNECTED) {
                delay(500);
                Serial.print(".");
        }
        /* set led as output to control led on-off */
        pinMode(led, OUTPUT);

        Serial.println("");
        Serial.println("WiFi connected");
        Serial.println("IP address: ");
        Serial.println(WiFi.localIP());

        /* configure the MQTT server with IPaddress and port */
        client.setServer(mqtt_server, 1883);
        /* this receivedCallback function will be invoked
        when client received subscribed topic */
        client.setCallback(receivedCallback);
}
void loop() {
        /* if client was disconnected then try to reconnect again */
        if (!client.connected()) {
                mqttconnect();
        }
        /* this function will listen for incomming
        subscribed topic-process-invoke receivedCallback */
        client.loop();
        //读取攀藤G5 数据
        byte c;
        char str[100];
        static int state = 0;
        static int count = 0;
        if (Serial1.available()) {
                c = Serial1.read();
                dataSum += c;
                switch (state) {
                case 0:
                        if (0x42 == c)
                        {
                                state = 1;
                                dataSum = 0;
                        }
                        break;
                case 1:
                        if (0x4d == c) {
                                state = 2;
                                count = 0;
                        }
                        break;
                case 2:
                        ((unsigned char *)&panteng)[count++] = c;

                        if (count > 30) {
#ifdef DEBUG
                                Serial.println(dataSum - panteng.check[0] - panteng.check[1], HEX);
                                Serial.println(panteng.check[0] * 256 + panteng.check[1], HEX);

#endif

                                state = 0;
                                if ((dataSum - panteng.check[0] - panteng.check[1]) == (panteng.check[0] * 256 + panteng.check[1]))
                                {
#ifdef DEBUG
                                        Serial.println("Data check ok");
                                        //计数 采集5次穿一次 也就是5s                       
#endif
                                        timecount++;
                                        pm1_0 = panteng.pm1_0[0] * 256 + panteng.pm1_0[1];
                                        pm2_5 = panteng.pm2_5[0] * 256 + panteng.pm2_5[1];
                                        pm10_0 = panteng.pm10_0[0] * 256 + panteng.pm10_0[1];
                                        jq = panteng.jq[0] * 256 + panteng.jq[1];

                                        if (timecount > 60)
                                        {
                                                timecount = 0;
                                                //发送空气信息mqtt
                                                //{
                                                //        "jiaquan": 22.30,
                                                //                "pm2p5" : 43.70,
                                                //                "pm1p0" : 43.70,
                                                //                "pm10" : 43.70
                                                //}
                                                //{"jiaquan": 22.30,"pm2p5" : 43.70,"pm1p0" : 43.70,"pm10" : 43.70}
                                                sprintf(msg, "{\"jiaquan\":%d,\"pm2p5\":%d,\"pm1p0\":%d,\"pm10\":%d}",jq,pm2_5,pm1_0,pm10_0);
                                                Serial.println(msg);
                                                client.publish(TOPICKQ, msg);
                                        }
#ifdef DEBUG
                                        Serial.print("jq:");
                                        Serial.println(jq);
                                        Serial.print("pm2.5:");
                                        Serial.println(pm2_5);
#endif
                                }
                        }
                        break;
                default:
                        break;
                }
        }
}

为了方便大家使用 把代码传附件 esp32MqttTest.zip (2.1 KB, 下载次数: 63)

最后放出效果图:

效果1

效果1

效果2

效果2

效果3

效果3

评分

参与人数 3金钱 +27 收起 理由
xwesley + 5
windgo + 10 大神666!
+ 12 谢谢分享!

查看全部评分

回复

使用道具 举报

66

主题

778

帖子

4401

积分

论坛元老

Rank: 8Rank: 8

积分
4401
金钱
3618
HASS币
20
发表于 2017-11-17 23:41:29 | 显示全部楼层
顶大神!!!!
回复

使用道具 举报

4

主题

313

帖子

1965

积分

金牌会员

Rank: 6Rank: 6

积分
1965
金钱
1652
HASS币
0
发表于 2017-11-18 13:34:40 | 显示全部楼层
这个是甲醛二合一的,我看其他论坛有人说甲醛检测就是出厂日期算两年就不行了,pm2.5可以多用所以他们建议买分开的。这个也不是听懂就是听说。
回复

使用道具 举报

24

主题

608

帖子

3476

积分

元老级技术达人

积分
3476
金钱
2863
HASS币
0

卓越贡献

发表于 2017-11-19 17:48:48 来自手机 | 显示全部楼层
666了。谢谢分享
回复

使用道具 举报

1

主题

4

帖子

29

积分

新手上路

Rank: 1

积分
29
金钱
25
HASS币
0
发表于 2017-12-15 12:27:01 | 显示全部楼层
大神好,请教两个问题:
1、可以用ESP8266吗,和ESP32有什么区别?
2、WidoraAIR的供电是怎么解决的。
谢谢!
回复

使用道具 举报

0

主题

32

帖子

231

积分

中级会员

Rank: 3Rank: 3

积分
231
金钱
199
HASS币
0
发表于 2018-1-15 15:35:00 | 显示全部楼层
ESP8266 是单核 Tensilica L106 (32位MCU)的Wi-Fi芯片,主频最高可达160MHz。

ESP32 是双核Tensilica L108 (32 位MCU)的Wi-Fi芯片,主频更高可达250MHz,性能更强,内存更大有400KB SRAM。另外还集成了蓝牙BLE。

由于ESP32的MCU性能更强,内存更大,可以处理包括音频、视频在内的更复杂Wi-Fi应用。还可以应用在需要蓝牙和Wi-Fi共存的IOT场景中。

参考 https://esp32.com/viewtopic.php?t=86

WidoraAIR 可以5v锂电,参考官网说明
回复

使用道具 举报

1

主题

96

帖子

499

积分

中级会员

Rank: 3Rank: 3

积分
499
金钱
402
HASS币
0
发表于 2018-2-6 12:49:12 | 显示全部楼层
感谢大神分享
回复

使用道具 举报

0

主题

11

帖子

67

积分

注册会员

Rank: 2

积分
67
金钱
56
HASS币
0
发表于 2018-2-13 23:30:19 | 显示全部楼层
请问大神,我想用python写一个上传到MQTT的程序,是否有mqtt client基于python的库?
回复

使用道具 举报

0

主题

44

帖子

290

积分

中级会员

Rank: 3Rank: 3

积分
290
金钱
246
HASS币
0
发表于 2018-12-9 13:53:20 | 显示全部楼层
大神,用你的代码,编译有错误咋回事?

arduino.ar(HardwareSerial.cpp.o).bss.Serial1+0x0): multiple definition of `Serial1'
sketch/esp32MqttTest.ino.cpp.o.bss.Serial1+0x0): first defined here
collect2: error: ld returned 1 exit status
回复

使用道具 举报

0

主题

44

帖子

290

积分

中级会员

Rank: 3Rank: 3

积分
290
金钱
246
HASS币
0
发表于 2018-12-9 22:19:48 | 显示全部楼层
大神,代码编译出错,麻烦给看一下,不知如何修改
arduino.ar(HardwareSerial.cpp.o).bss.Serial1+0x0): multiple definition of `Serial1'
sketch/esp32MqttTest.ino.cpp.o.bss.Serial1+0x0): first defined here
collect2: error: ld returned 1 exit status
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-11-15 02:39 , Processed in 0.164611 second(s), 42 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表