一、背景
有幸參加RT-Thread的活動,體驗RT-Thread Studio 和瑞薩 CPK-RA2L1評估板。本篇結合前面的文章,暫時制作一個空氣質量監測系統,主要使用:DHT11、PMS1003, OLED模塊, 后續繼續擴展甲醛,CO2, IAQ模塊
二、模塊信息
三、新建工程
這里使用的模塊,我們需要提前分配好引腳:UART0 采集PMS1003, DHT11 使用P0208 引腳, OLED I2C1通信 使用P0205 P0206,
配置RT-Thread Settings ,添加u8g2 庫,配置i2c,具體信息如下圖
在 RA Smart Configurator 種添加UART0,配置好引腳和波特率
在 RA Smart Configurator 種添加I2C1
四、編寫代碼
hal_entery.c
/*
- Copyright (c) 2006-2021, RT-Thread Development Team
- SPDX-License-Identifier: Apache-2.0
- Change Logs:
- Date Author Notes
- 2021-10-10 Sherman first version
/
#include
#include "hal_data.h"
#include
#include "dht11.h"
#include
#include "pms1003.h"
#include
#include
#include
//#define DBG_ENABLE
//#define DBG_SECTION_NAME "pms_series"
//#define DBG_LEVEL DBG_LOG
//#define DBG_COLOR
//#define DBG_ENABLE
#define LED1_PIN "P502" / Onboard LED pins /
#define USER_INPUT "P004"
/ ******* DHT11 /
#define DATA_PIN 0x0208 //P208 dht11
#define THREAD_PRIORITY 5
#define THREAD_STACK_SIZE 1024
#define THREAD_TIMESLICE 10
static rt_thread_t tid_dht11 = RT_NULL;
/ PMS1003 /
//tx P101 rx P100
#define PMS_SERIES_UART "uart0"
#ifdef PMS_SERIES_SAMPLE_USING_DMA
struct rt_messagequeue pms_mq;
#else
struct rt_semaphore pms_sem;
#endif
pms_device_t PMS1003;
struct rx_msg
{
rt_device_t dev;
rt_size_t size;
};
/ OLED /
static rt_thread_t tid_oled = RT_NULL;
int temp = 0;
int humi = 0;
int PM2_5 = 0;
int PM10 = 0;
static void Dht11ThreadEntry(void *parameter)
{
dht_device_t sensor = dht_create(DATA_PIN);
rt_int32_t temp_;
rt_int32_t humi_;
while (1)
{
if(dht_read(sensor))
{
temp_ = dht_get_temperature(sensor) / 10;
humi_ = dht_get_humidity(sensor) / 10;
temp = temp_;
humi = humi_;
// rt_kprintf("Temp: %d, Humi: %dn", temp, humi);
}
else
{
// rt_kprintf("Read dht sensor failed.n");
}
rt_thread_mdelay(500);
}
dht_delete(sensor);
}
int dht11_init()
{
rt_err_t ret = RT_EOK;
tid_dht11 = rt_thread_create("dht11",
Dht11ThreadEntry,
RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY,
THREAD_TIMESLICE);
if (tid_dht11 != RT_NULL)
{
rt_thread_startup(tid_dht11);
}
else
{
ret = RT_ERROR;
}
return ret;
}
//INIT_APP_EXPORT(dht11_init);
void pms_series_debug(pms_device_t dev)
{
rt_kprintf("beginn");
rt_kprintf("PM1_0_CF1 = %5dtPM2_5_CF1 = %5dtPM10_0_CF1 = %5dn",dev->PM1_0_CF1,dev->PM2_5_CF1,dev->PM10_0_CF1);
rt_kprintf("PM1_0_amb = %5dtPM2_5_amb = %5dtPM10_0_amb = %5dn",dev->PM1_0_amb,dev->PM2_5_amb,dev->PM10_0_amb);
rt_kprintf("air_0_3um = %5dtair_0_5um = %5dtair_1_0um = %5dn",dev->air_0_3um,dev->air_0_5um,dev->air_1_0um);
rt_kprintf("air_2_5um = %5dt",dev->air_2_5um);
rt_kprintf("version = %5d errorCode = %5dn",dev->version,dev->errorCode);
rt_kprintf("********************************over****************************n");
}
static void serial_thread_entry(void *parameter)
{
#ifndef PMS_SERIES_SAMPLE_USING_DMA
rt_err_t result;
char ch;
pms_device_t dev = parameter;
while (1)
{
while (rt_device_read(dev->serial, 0, &ch, 1) == 0)
{
rt_sem_control(&pms_sem, RT_IPC_CMD_RESET, RT_NULL);
rt_sem_take(&pms_sem, RT_WAITING_FOREVER);
}
result = pms_get_byte(dev,ch);
if (result == RT_EOK)
{
// pms_series_debug(dev); // for debug
PM2_5 = dev->PM2_5_CF1;
PM10 = dev->PM10_0_CF1;
// rt_kprintf("air_2_5um = %dn",PM2_5);
}
}
#endif
#ifdef PMS_SERIES_SAMPLE_USING_DMA
struct rx_msg msg;
rt_err_t result;
rt_uint32_t rx_length;
static rt_uint8_t rx_buffer[RT_SERIAL_RB_BUFSZ + 1];
pms_device_t dev = parameter;
while (1)
{
rt_memset(&msg, 0, sizeof(msg));
result = rt_mq_recv(&pms_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
if (result == RT_EOK)
{
rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
rx_buffer[rx_length] = '?';
result = frame_check(dev,rx_buffer,rx_length);
if (result == RT_EOK)
{
pms_series_debug(dev);
rt_kprintf("rx buff success");
}
else
{
rt_kprintf("rx buff error");
}
}
}
#endif
}
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
RT_ASSERT(dev);
#ifndef PMS_SERIES_SAMPLE_USING_DMA
if (size > 0)
{
rt_sem_release(&pms_sem);
}
return RT_EOK;
#endif
#ifdef PMS_SERIES_SAMPLE_USING_DMA
rt_err_t result;
struct rx_msg msg;
msg.dev = dev;
msg.size = size;
result = rt_mq_send(&pms_mq, &msg, sizeof(msg));
if ( result == -RT_EFULL)
{
rt_kprintf("message queue full!n");
}
return result;
#endif
}
int PMS1003Init()
{
static pms_device_t dev = NULL;
rt_err_t ret = RT_EOK;
dev = pms_init(PMS_SERIES_UART);
#ifndef PMS_SERIES_SAMPLE_USING_DMA
rt_sem_init(&pms_sem, "pms_sem", 0, RT_IPC_FLAG_FIFO);
rt_device_open(dev->serial, RT_DEVICE_FLAG_INT_RX);
rt_device_set_rx_indicate(dev->serial, uart_input);
#endif
#ifdef PMS_SERIES_SAMPLE_USING_DMA
static char msg_pool[256];
rt_err_t result;
result = rt_mq_init(&pms_mq, "pms_mq",
msg_pool,
sizeof(struct rx_msg),
sizeof(msg_pool),
RT_IPC_FLAG_FIFO);
if (result != RT_EOK)
{
rt_kprintf("init message queue failed.n");
}
result = rt_device_open(dev->serial, RT_DEVICE_FLAG_DMA_RX);
if (result != RT_EOK)
{
rt_kprintf("open device failed.n");
}
result = rt_device_set_rx_indicate(dev->serial, uart_input);
if (result != RT_EOK)
{
rt_kprintf("set rx indicate failed.n");
}
#endif
rt_thread_t thread = rt_thread_create("pms1003", serial_thread_entry, dev, 1024, 3, 10);
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
ret = RT_ERROR;
}
return ret;
}
//INIT_APP_EXPORT(PMS1003Init);
char tmp_buff[18]={'?'};
char pm_buff[16]={'?'};
char pm10_buff[16]={'?'};
static int F_clean = 0;
static void OledThreadEntry(void *parameter)
{
u8g2_t u8g2;
u8g2_Setup_ssd1306_i2c_128x64_noname_f( &u8g2, U8G2_R0, u8x8_byte_rtthread_hw_i2c, u8x8_gpio_and_delay_rtthread);
u8g2_InitDisplay(&u8g2);
u8g2_SetPowerSave(&u8g2, 0);//是否開啟省電模式 , 1 表示啟用顯示器的省電模式,屏幕上看不到任何東西, 0 表示禁用省電模式
u8g2_ClearBuffer(&u8g2);
u8g2_SetFont(&u8g2, u8g2_font_unifont_t_arabic); //u8g2_font_ncenB08_tr u8g2_font_unifont_t_symbols
while (1)
{
sprintf(tmp_buff, "Temp:%dt Humi:%dt", temp, humi);
sprintf(pm_buff, "PM2.5:%d", PM2_5);
sprintf(pm10_buff, "PM10:%d", PM10);
rt_thread_mdelay(300);
if (1 == F_clean)
{
u8g2_ClearBuffer(&u8g2);
}
else if (50 == F_clean)
{
u8g2_ClearBuffer(&u8g2);
F_clean = 0;
}
u8g2_DrawStr(&u8g2, 1, 10, &tmp_buff);
u8g2_SendBuffer(&u8g2);
u8g2_DrawStr(&u8g2, 1, 30, &pm_buff);
u8g2_SendBuffer(&u8g2);
u8g2_DrawStr(&u8g2, 1, 50, &pm10_buff);
u8g2_SendBuffer(&u8g2);
rt_kprintf("F_clean:%d n",F_clean++);
}
}
int OLED_Init()
{
rt_err_t ret = RT_EOK;
tid_oled = rt_thread_create("oled",
OledThreadEntry,
RT_NULL,
1024,
2,
THREAD_TIMESLICE);
if (tid_oled != RT_NULL)
{
rt_thread_startup(tid_oled);
}
else
{
ret = RT_ERROR;
}
return ret;
}
//INIT_APP_EXPORT(OLED_Init);
void hal_entry(void)
{
rt_kprintf("nHello RT-Thread!n");
rt_uint32_t led1_pin = rt_pin_get(LED1_PIN);
dht11_init();
PMS1003Init();
OLED_Init();
while (1)
{
rt_pin_write(led1_pin, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(led1_pin, PIN_LOW);
rt_thread_mdelay(500);
}
}
void irq_callback_test(void *args)
{
rt_kprintf("n IRQ03 triggered n");
}
void icu_sample(void)
{
/* init */
rt_uint32_t pin = rt_pin_get(USER_INPUT);
rt_kprintf("n pin number : 0x%04X n", pin);
rt_err_t err = rt_pin_attach_irq(pin, PIN_IRQ_MODE_RISING, irq_callback_test, RT_NULL);
if (RT_EOK != err)
{
rt_kprintf("n attach irq failed. n");
}
err = rt_pin_irq_enable(pin, PIN_IRQ_ENABLE);
if (RT_EOK != err)
{
rt_kprintf("n enable irq failed. n");
}
}
MSH_CMD_EXPORT(icu_sample, icu sample);
dht11.c
/*
- Copyright (c) 2006-2021, RT-Thread Development Team
- SPDX-License-Identifier: Apache-2.0
- Change Logs:
- Date Author Notes
- 2023-03-08 DYC the first version
/
#include "dht11.h"
#include
#include "hal_data.h"
#include
#define DBG_TAG "sensor.asair.dhtxx"
#ifdef PKG_USING_DHTXX_DEBUG
#define DBG_LVL DBG_LOG
#else
#define DBG_LVL DBG_ERROR
#endif
#include
/ timing /
#define DHT1x_BEGIN_TIME 20 / ms /
#define DHT2x_BEGIN_TIME 1 / ms /
#define DHTxx_PULL_TIME 30 / us /
#define DHTxx_REPLY_TIME 100 / us /
#define MEASURE_TIME 40 / us /
RT_WEAK void rt_hw_us_delay(rt_uint32_t us)
{
rt_uint32_t delta;
us = us * (SysTick->LOAD / (1000000 / RT_TICK_PER_SECOND));
delta = SysTick->VAL;
while (delta - SysTick->VAL < us) continue;
}
/ * - This function will split a number into two part according to times.
- @param num the number will be split
- @param integer the integer part
- @param decimal the decimal part
- @param times how many times of the real number (you should use 10 in this case)
- @return 0 if num is positive, 1 if num is negative
*/
int split_int(const int num, int *integer, int *decimal, const rt_uint32_t times)
{
int flag = 0;
if (num < 0) flag = 1;
int anum = num<0 ? -num : num;
integer = anum / times;
decimal = anum % times;
return flag;
}
/ - This function will convert temperature in degree Celsius to Kelvin.
- @param c the temperature indicated by degree Celsius
- @return the result
/
float convert_c2k(float c)
{
return c + 273.15;
}
/ * - This function will convert temperature in degree Celsius to Fahrenheit.
- @param c the temperature indicated by degree Celsius
- @return the result
/
float convert_c2f(float c)
{
return c * 1.8 + 32;
}
/ * - This function will convert temperature in degree Fahrenheit to Celsius.
- @param f the temperature indicated by degree Fahrenheit
- @return the result
/
float convert_f2c(float f)
{
return (f - 32) * 0.55555;
}
/ * - This function will read a bit from sensor.
- @param pin the pin of Dout
- @return the bit value
/
static uint8_t dht_read_bit(const rt_base_t pin)
{
uint8_t retry = 0;
while(rt_pin_read(pin) && retry < DHTxx_REPLY_TIME)
{
retry++;
rt_hw_us_delay(1);
}
retry = 0;
while(!rt_pin_read(pin) && retry < DHTxx_REPLY_TIME)
{
retry++;
rt_hw_us_delay(1);
}
rt_hw_us_delay(MEASURE_TIME);
return rt_pin_read(pin);
}
/ * - This function will read a byte from sensor.
- @param pin the pin of Dout
- @return the byte
*/
static uint8_t dht_read_byte(const rt_base_t pin)
{
uint8_t i, byte = 0;
for(i=0; i<8; i++)
{
byte <<= 1;
byte |= dht_read_bit(pin);
}
return byte;
}
/** - This function will read and update data array.
- @param dev the device to be operated
- @return RT_TRUE if read successfully, otherwise return RT_FALSE.
/
rt_bool_t dht_read(dht_device_t dev)
{
RT_ASSERT(dev);
uint8_t i, retry = 0, sum = 0;
#ifdef PKG_USING_DHTXX_INTERRUPT_DISABLE
rt_base_t level;
#endif
/ Reset data buffer /
rt_memset(dev->data, 0, DHT_DATA_SIZE);
/ MCU request sampling /
rt_pin_mode(dev->pin, PIN_MODE_OUTPUT);
rt_pin_write(dev->pin, PIN_LOW);
if (dev->type == DHT11) {
rt_thread_mdelay(DHT1x_BEGIN_TIME); / Tbe /
} else {
rt_thread_mdelay(DHT2x_BEGIN_TIME);
}
#ifdef PKG_USING_DHTXX_INTERRUPT_DISABLE
level = rt_hw_interrupt_disable();
#endif
rt_pin_mode(dev->pin, PIN_MODE_INPUT_PULLUP);
rt_hw_us_delay(DHTxx_PULL_TIME); / Tgo /
/ Waiting for sensor reply /
while (rt_pin_read(dev->pin) && retry < DHTxx_REPLY_TIME)
{
retry++;
rt_hw_us_delay(1); / Trel /
}
if(retry >= DHTxx_REPLY_TIME) return RT_FALSE;
retry = 0;
while (!rt_pin_read(dev->pin) && retry < DHTxx_REPLY_TIME)
{
retry++;
rt_hw_us_delay(1); / Treh /
};
if(retry >= DHTxx_REPLY_TIME) return RT_FALSE;
/ Read data /
for(i=0; i {
dev->data[i] = dht_read_byte(dev->pin);
}
#ifdef PKG_USING_DHTXX_INTERRUPT_DISABLE
rt_hw_interrupt_enable(level);
#endif
/ Checksum */
for(i=0; i {
sum += dev->data[i];
}
if(sum != dev->data[4]) return RT_FALSE;
return RT_TRUE;
}
/** - This function will get the humidity from dhtxx sensor.
- @param dev the device to be operated
- @return the humidity value
/
rt_int32_t dht_get_humidity(dht_device_t const dev)
{
RT_ASSERT(dev);
rt_int32_t humi = 0;
switch(dev->type)
{
case DHT11:
humi = dev->data[0] * 10 + dev->data[1];
break;
default:
break;
}
return humi;
}
/ * - This function will get the temperature from dhtxx sensor.
- @param dev the device to be operated
- @return the temperature value
/
rt_int32_t dht_get_temperature(dht_device_t const dev)
{
RT_ASSERT(dev);
rt_int32_t temp = 0;
switch(dev->type)
{
case DHT11:
temp = dev->data[2] * 10 + (dev->data[3] & 0x7f);
if(dev->data[3] & 0x80) {
temp = -temp;
}
break;
default:
break;
}
return temp;
}
/ * - This function will init dhtxx sensor device.
- @param dev the device to init
- @param pin the pin of Dout
- @return the device handler
*/
rt_err_t dht_init(struct dht_device *dev, const rt_base_t pin)
{
if(dev == NULL)
return -RT_ERROR;
dev->type = DHT_TYPE;
dev->pin = pin;
rt_memset(dev->data, 0, DHT_DATA_SIZE);
rt_pin_mode(dev->pin, PIN_MODE_INPUT_PULLUP);
return RT_EOK;
}
// 1、初始化類型
dht_device_t dht_create(const rt_base_t pin)
{
dht_device_t dev;
dev = rt_calloc(1, sizeof(struct dht_device));
if (dev == RT_NULL)
{
LOG_E("Can't allocate memory for dhtxx device");
return RT_NULL;
}
dev->type = DHT_TYPE;
dev->pin = pin;
rt_memset(dev->data, 0, DHT_DATA_SIZE);
rt_pin_mode(dev->pin, PIN_MODE_INPUT_PULLUP);
return dev;
}
void dht_delete(dht_device_t dev)
{
if (dev)
rt_free(dev);
}
dht11.h
/*
- Copyright (c) 2006-2021, RT-Thread Development Team
- SPDX-License-Identifier: Apache-2.0
- Change Logs:
- Date Author Notes
- 2023-03-08 DYC the first version
/
#ifndef SRC_DHT11_H_
#define SRC_DHT11_H_
#include
#include
#include
#include
#include
#define DHTLIB_VERSION "0.9.0"
#define DHT_DATA_SIZE 5
/ sensor model type */
#define DHT11 0
#define DHT_TYPE DHT11
struct dht_device
{
rt_base_t pin;
rt_uint8_t type;
rt_uint8_t data[DHT_DATA_SIZE];
rt_mutex_t lock;
};
typedef struct dht_device *dht_device_t;
dht_device_t dht_create(const rt_base_t pin);
void dht_delete(dht_device_t dev);
rt_err_t dht_init(struct dht_device *dev, const rt_base_t pin);
rt_bool_t dht_read(dht_device_t dev);
rt_int32_t dht_get_humidity(dht_device_t dev);
rt_int32_t dht_get_temperature(dht_device_t dev);
float convert_c2k(float c);//將攝氏溫度轉為開氏溫度
float convert_c2f(float c);//將攝氏溫度轉為華氏溫度
float convert_f2c(float f);//將華氏溫度轉為攝氏溫度
rt_int32_t split_int(const rt_int32_t num, rt_int32_t *integer,
rt_int32_t *decimal, const rt_uint32_t times);
rt_err_t rt_hw_dht_init(const char *name, struct rt_sensor_config cfg);
#endif / SRC_DHT11_H_ */
pms1003.c
/*
Copyright (c) 2006-2021, RT-Thread Development Team
SPDX-License-Identifier: Apache-2.0
Change Logs:
Date Author Notes
2023-03-08 DYC the first version
*/
//#define DBG_SECTION_NAME "pms_series"
//#define DBG_LEVEL DBG_LOG
//#define DBG_COLOR
#include
#include
#include "pms1003.h"
#define RT_SERIAL_RB_BUFSZ 64
#define COMM_START1 0x42
#define COMM_START2 0x4D
#define FRAME_HEAD1 0x00
#define FRAME_HEAD2 0x01
#define FRAME_LENH 0x02
#define FRAME_LENL 0x03
#define FRAME_RECEIVE 0x04
#define FRAME_CHECK 0x05
rt_err_t frame_check(pms_device_t dev,rt_uint8_t *buf,rt_uint16_t len)
{
rt_uint16_t sum=0;
RT_ASSERT(dev);
for(uint8_t i=0;i<(len-2);i++)
{
sum += buf[i];
}
if((buf[len-1] == (sum&0xFF)) && (buf[len-2] == (sum >> 8)))
{
dev->PM1_0_CF1 = ((rt_uint16_t)(buf[4])<<8) | buf[5];
dev->PM2_5_CF1 = ((rt_uint16_t)(buf[6])<<8) | buf[7];
dev->PM10_0_CF1 = ((rt_uint16_t)(buf[8])<<8) | buf[9];
dev->PM1_0_amb = ((rt_uint16_t)(buf[10])<<8) | buf[11];
dev->PM2_5_amb = ((rt_uint16_t)(buf[12])<<8) | buf[13];
dev->PM10_0_amb = ((rt_uint16_t)(buf[14])<<8) | buf[15];
dev->air_0_3um = ((rt_uint16_t)(buf[16])<<8) | buf[17];
dev->air_0_5um = ((rt_uint16_t)(buf[18])<<8) | buf[19];
dev->air_1_0um = ((rt_uint16_t)(buf[20])<<8) | buf[21];
dev->air_2_5um = ((rt_uint16_t)(buf[22])<<8) | buf[23];
dev->version = buf[len - 4];
dev->errorCode = buf[len - 3];
return RT_EOK;
}
return RT_ERROR;
}
rt_err_t pms_get_byte(pms_device_t dev, char data)
{
rt_err_t result;
static uint8_t state = FRAME_HEAD1;
static uint8_t cnt = 0;
static rt_uint8_t buf[40] = {0};
RT_ASSERT(dev);
if(state == FRAME_HEAD1 && data == COMM_START1)
{
buf[cnt++] = data;
state = FRAME_HEAD2;
}
else if (state == FRAME_HEAD2 && data == COMM_START2)
{
buf[cnt++] = data;
state = FRAME_LENH;
}
else if (state == FRAME_LENH)
{
buf[cnt++] = data;
state = FRAME_LENL;
}
else if (state == FRAME_LENL)
{
buf[cnt++] = data;
state = FRAME_RECEIVE;
}
else if (state == FRAME_RECEIVE)
{
buf[cnt++] = data;
if(cnt >= COMM_LEN - 1)
state = FRAME_CHECK;
}
else if (state == FRAME_CHECK)
{
buf[cnt++] = data;
state = FRAME_HEAD1;
cnt = 0;
result = frame_check(dev, buf, COMM_LEN);
if (result == RT_EOK)
{
LOG_D("check success");
return result;
}
else
{
LOG_E("check error");
}
}
else {}
return result;
}
pms_device_t pms_init(const char *uart_name)
{
pms_device_t dev;
RT_ASSERT(uart_name);
dev = rt_calloc(1, sizeof(struct pms_device));
if (dev == RT_NULL)
{
LOG_E("Can't allocate memory for pms device %s",uart_name);
return RT_NULL;
}
dev->serial = rt_device_find(uart_name);
if (!dev->serial)
{
rt_free(dev);
rt_kprintf("find %s failed!n", uart_name);
}
else
{
dev->config.baud_rate = BAUD_RATE_9600;
dev->config.data_bits = DATA_BITS_8;
dev->config.stop_bits = STOP_BITS_1;
dev->config.parity = PARITY_NONE;
dev->config.bit_order = BIT_ORDER_LSB;
dev->config.invert = NRZ_NORMAL;
dev->config.rx_bufsz = RT_SERIAL_RB_BUFSZ;
dev->config.reserved = 0;
rt_device_control(dev->serial, RT_DEVICE_CTRL_CONFIG, &dev->config);
}
return dev;
}
void pms_deinit(pms_device_t dev)
{
RT_ASSERT(dev);
rt_free(dev);
}
pms1003.h
/*
Copyright (c) 2006-2021, RT-Thread Development Team
SPDX-License-Identifier: Apache-2.0
Change Logs:
Date Author Notes
2023-03-08 DYC the first version
*/
#ifndef SRC_PMS1003_H_
#define SRC_PMS1003_H_
#define DBG_TAG "pms_series"
#define DBG_LVL DBG_INFO
#include
#include
#include
#define COMM_LEN 32
struct pms_device
{
rt_device_t serial;
struct serial_configure config;
rt_uint16_t len;
rt_uint16_t PM1_0_CF1;
rt_uint16_t PM2_5_CF1;
rt_uint16_t PM10_0_CF1;
rt_uint16_t PM1_0_amb;
rt_uint16_t PM2_5_amb;
rt_uint16_t PM10_0_amb;
rt_uint16_t air_0_3um;
rt_uint16_t air_0_5um;
rt_uint16_t air_1_0um;
rt_uint16_t air_2_5um;
rt_uint16_t air_5_0um;
rt_uint16_t air_10_0um;
rt_uint8_t version;
rt_uint8_t errorCode;
rt_uint16_t checksum;
};
typedef struct pms_device *pms_device_t;
pms_device_t pms_init(const char *uart_name);
rt_err_t frame_check(pms_device_t dev,rt_uint8_t buf,rt_uint16_t len);
rt_err_t pms_get_byte(pms_device_t dev, char data);
void pms_deinit(pms_device_t dev);
#endif / SRC_PMS1003_H_ */
五、燒錄驗證與擴展
基本功能做完了,由于后續買的co2, 甲醛, IAQ模塊還在路上,后續到了會繼續往該系統中添加,還要與ESP8266 模塊通信,完成本地系統數據遠程訪問,通過blinker實現數據的可視化,隨時隨地查看室內空氣質量。
-
質量監測系統
+關注
關注
0文章
5瀏覽量
5557 -
DHT11
+關注
關注
19文章
277瀏覽量
57580 -
I2C通信
+關注
關注
0文章
22瀏覽量
8824 -
RT-Thread
+關注
關注
31文章
1285瀏覽量
40085 -
oled模塊
+關注
關注
0文章
4瀏覽量
2819
發布評論請先 登錄
相關推薦
評論