0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

CPK-RA2L1评估板(5)室内空气质量监测系统设计

冬至子 来源:快乐小鸟 作者:快乐小鸟 2023-10-11 14:30 次阅读

一、背景
有幸参加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,具体信息如下图

1.jpg

2.jpg

在 RA Smart Configurator 种添加UART0,配置好引脚和波特率

1.jpg

在 RA Smart Configurator 种添加I2C1

1.jpg

四、编写代码

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("begin
    n");
    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实现数据的可视化,随时随地查看室内空气质量。

1.jpg

2.jpg

3.jpg

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 质量监测系统

    关注

    0

    文章

    5

    浏览量

    5545
  • DHT11
    +关注

    关注

    19

    文章

    264

    浏览量

    57175
  • I2C通信
    +关注

    关注

    0

    文章

    22

    浏览量

    8756
  • RT-Thread
    +关注

    关注

    31

    文章

    1148

    浏览量

    38869
  • oled模块
    +关注

    关注

    0

    文章

    4

    浏览量

    2784
收藏 人收藏

    评论

    相关推荐

    【绝对领域】 室内空气监测净化系统

    (IEQ)的重要性不言而喻。一个人每天需要1公斤食品2公斤饮水,但所需空气则为10公斤,室内空气质量(IAQ)对人的健康保障、舒适感受和工作学习效率尤为重要。在经历了18世纪工业革命带
    发表于 12-31 11:42

    【Tisan物联网申请】室内空气质量监测系统

    申请理由:监控室内空气质量, 将传感器信息经由ESP8266处理后实时发送到服务器,手机可以实时查看室内空气质量,并且可以给室内的设备节
    发表于 10-15 10:09

    【NanoPi2申请】室内空气质量监测系统

    申请理由:一直从事嵌入式开发 主要方向为基于OPENWRT的智能路由器研发,之前也给bananapi编译过安卓 没有深入玩过 这次希望能有机会能试用nanopi2项目描述:通过激光颗粒传出感器 +18B20+湿度传感器 实时监控室内空气质量 然后控制家里
    发表于 11-11 11:00

    【OneNET麒麟座试用申请】空气质量数据监测

    项目名称:空气质量数据监测站试用计划:空气质量数据监测站用于测试空气质量监测及数据采集,实现野外
    发表于 04-05 15:03

    【NXP LPC54110试用申请】室内空气质量调节系统

    项目名称:室内空气质量调节系统试用计划:1.计划通过二氧化碳,甲醛,可燃气体,pm2.5,温度,湿度等传感器对室内进行检测,并根据数据控制空调,pm2.5过滤机,门窗开关,换气扇等
    发表于 08-02 17:53

    室内空气净化监测系统(硬件原理图+PCB+源码+手机APP等)

    为解决室内污染,室内空气监测净化系统孕育而生,它基于物联网技术,除了空气检测、净化的同时也可作为室内智能家居的总控制端。而且其体积小巧,结构
    发表于 09-29 09:38

    室内空气净化监测系统设计

    为解决室内污染,室内空气监测净化系统孕育而生,它基于物联网技术,除了空气检测、净化的同时也可作为室内智能家居的总控制端。而且其体积小巧,结构
    发表于 10-09 17:01

    空气质量传感器在室内空气清新机中的应用是什么?

    TGS2600空气质量传感器有什么特点?空气质量传感器在室内空气清新机中的应用是什么?
    发表于 06-16 08:35

    一种智能化室内空气质量监测与控制方案

    提出了一种智能化室内空气质量监测与控制方案。该设计利用温湿度传感器对人们能够直观感受到的室内舒适度体验进行监控,利用甲醛传感器模组对室内主要危害气体甲醛进行检测。此外,该
    发表于 11-19 06:55

    关于基于单片机的室内空气质量检测系统的设计

    前一段时间,做了一个关于基于单片机的室内空气质量检测系统的设计
    发表于 11-19 06:18

    GSM网络的室内空气质量监测系统设计_魏庆丽

    GSM网络的室内空气质量监测系统设计_魏庆丽
    发表于 03-19 18:58 2次下载

    室内空气质量检测系统设计

    室内空气质量检测
    发表于 06-19 16:20 35次下载

    室内空气质量监测仪7575型的特点优势及应用范围

    Q-Trak®室内空气质量监测仪7575型可提供快速,准确的信息,以评估关键的室内空气质量(IAQ)参数。
    的头像 发表于 10-25 15:46 1870次阅读

    室内空气质量监测系统

    电子发烧友网站提供《室内空气质量监测系统.zip》资料免费下载
    发表于 10-19 10:24 3次下载
    <b class='flag-5'>室内空气质量</b><b class='flag-5'>监测</b><b class='flag-5'>系统</b>

    室内空气质量监测器开源分享

    电子发烧友网站提供《室内空气质量监测器开源分享.zip》资料免费下载
    发表于 02-06 14:24 2次下载
    <b class='flag-5'>室内空气质量</b><b class='flag-5'>监测</b>器开源分享