基于小凌派开发板的烟雾检测传感器设计

描述

烟雾检测传感器使用的是MQ-2烟雾传感器。MQ-2型烟雾传感器属于二氧化锡半导体气敏材料,属于表面离子式N型半导体。处于200~300摄氏度时,二氧化锡吸附空气中的氧,形成氧的负离子吸附,使半导体中的电子密度减少,从而使其电阻值增加。当与烟雾接触时,如果晶粒间界处的势垒收到烟雾的调至而变化,就会引起表面导电率的变化。利用这一点就可以获得这种烟雾存在的信息,烟雾的浓度越大,导电率越大,输出电阻越低,则输出的模拟信号就越大。


使用MQ-2烟雾传感器来检测周围环境烟雾浓度,再通过小凌派开发板采集信号。因为采集的信号是电压值所以通过adc转换成数字信号。这里有个需要注意的地方RK2206的ADC默认参考电压是内部2.4v所以初始化ADC时通过配置soc_con29 寄存器改成外部3.3v参考电压。

 

参考代码:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
typedef union{    uint32_t value;    struct    {        uint16_t gRF_saradc_ana_reg_low: 4;        uint16_t grf_saradc_vol_sel: 1;        uint16_t grf_saradc_ana_reg_high: 11;        struct        {            uint16_t grf_saradc_ana_reg_low: 4;            uint16_t grf_saradc_vol_sel: 1;            uint16_t grf_saradc_ana_reg_high: 11;        } rw;    };} GRF_SOC_CON29;static uint32_t iss_adc_dev_init(iss_mq2_dev_s *adc){    if (PinctrlInit(adc->adc) != 0)    {        printf("adc pin %d init faiLED
", adc->adc.gpio);    }    if (LzSaradcInit() != 0)    {        printf("saradc  %d init failed
", adc->port);    }    volatile GRF_SOC_CON29 *soc = (GRF_SOC_CON29*)&GRF->SOC_CON29;    soc->rw.grf_saradc_vol_sel = 1;    soc->grf_saradc_vol_sel    = 0;    soc->rw.grf_saradc_vol_sel = 0;       adc->init = 1;    return 0;}

(左右移动查看全部内容)

 

读取ADC电压:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
static float iss_get_voltage(void){    unsigned int ret;    unsigned int data;
    ret = LzSaradcReadValue(m_iss_mq2, &data);    if (ret != 0)    {        printf("ADC Read Fail
");    }    return (float)data * 3.3  / 1024;}

(左右移动查看全部内容)

 

计算ppm值:
阻值R与空气中被测气体的浓度C的计算关系式
log R = mlog C + n (m,n均为常数)

 

传感器的电阻计算:
Rs = (Vc/VRL-1) X RL
Vc为回路电压,VRL是传感器4脚6脚输出电压,RL是负载

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
#define  CAL_PPM            20             //校准环境中PPM值#define  RL                  1              //RL阻值float e53_iss_get_mq2_ppm(void){    float voltage, rs, ppm;
    voltage = iss_get_voltage();    rs = (5 - voltage) / voltage * RL; //计算rs    ppm = 613.9f * pow(rs / m_r0, -2.074f); //计算ppm    return ppm;}

(左右移动查看全部内容)

 

ppm值校准:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
void e53_iss_mq2_ppm_calibration(void){    float voltage = iss_get_voltage();    float rs = (5 - voltage) / voltage * RL;       m_r0 = rs / pow(CAL_PPM / 613.9f, 1 / -2.074f);    printf("R0 =%f
", m_r0);}

(左右移动查看全部内容)

 

因为使用的是无源蜂鸣器,所以通过pwm驱动蜂鸣器报警。

 

pwm初始化:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
static uint32_t iss_pwm_dev_init(iss_pwm_dev_s *p){    if (PwmIoInit(p->pwmio) != 0)    {        printf("Pwm pin  %d init failed
", p->pwmio.pwm.gpio);    }    if (LzPwmInit(p->port) != 0)    {        printf("Pwm  %d init failed
", p->port);    }       p->init = 1;    return 0;}

(左右移动查看全部内容)

 

pwm 启动:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
static uint32_t iss_pwm_start(iss_pwm_dev_s *pwm){    if (pwm->init == 0)    {        printf("PWM not init
");        return 1;    }    else if (LzPwmstart(pwm->port, pwm->duty * pwm->cycle / 100, pwm->cycle) != 0)    {        printf("PWM Start Fail
");        return 1;    }    pwm->onoff = 1;    return 0;}

(左右移动查看全部内容)

 

pwm停止:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
static uint32_t iss_pwm_stop(iss_pwm_dev_s *pwm){    if (pwm->init == 0)    {        printf("PWM not init
");        return 1;    }    else if (pwm->onoff == 0)    {        return 0;    }    else if (LzPwmStop(pwm->port) != 0)    {        printf("PWM Stop Fail
");        return 1;    }    pwm->onoff = 0;    return 0;}

(左右移动查看全部内容)

 

蜂鸣器报警控制,需要报警时启动pwm,不需要报警时停止pwm:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
void e53_iss_beep_status_set(e53_iss_status_e status){    if (status == ON)    {        iss_pwm_start(&m_iss_beep);    }    if (status == OFF)    {        iss_pwm_stop(&m_iss_beep);    }}

(左右移动查看全部内容)

 

整个模块初始化:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
uint32_t e53_iss_init(){uint32_t ret = 1;
    ret = iss_led_dev_init(&m_iss_led);    if (ret != 0)    {        printf(“led init err
”);    }    ret = iss_pwm_dev_init(&m_iss_beep);    if (ret != 0)    {         printf(“pwm init err
”);    }    ret = iss_adc_dev_init(&m_iss_mq2);    if (ret != 0)    {         printf(“adc init err
”);    }    return ret;}

(左右移动查看全部内容)

 

创建一个任务处理函数
这里需要注意的是ppm校准需要提前测试,再把值写死到代码里。

 

还有需要注意的是mq2传感器需要预热,即提前通电大约半分钟到一分钟左右。用手放在传感器外壳感觉微微发热即可。如果不预热就开始测量其测量值会偏差很大,而且会随着加热而变化。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
void e53_iss_thread(void *args){    float ppm = 0;    uint32_t id    = 0;    uint8_t  index = 0;
    e53_iss_init();    printf("%s
", __FUNCTION__);    /*传感器校准*/    LOS_Msleep(2000); // 开机2s后进行校准    // e53_iss_mq2_ppm_calibration(); // 校准传感器校准后不需要重复调用    while (1)    {        ppm = e53_iss_get_mq2_ppm();        printf("ppm:%.1f 
", ppm);        /*判断是否达到报警阈值*/        if (ppm > e53_iss_get_mq2_alarm_value())        {            e53_iss_beep_status_set(ON);            printf("over %u ppm alarm
", e53_iss_get_mq2_alarm_value());        }        else        {            e53_iss_led_status_set(OFF);            e53_iss_beep_status_set(OFF);        }LOS_Msleep(1000);    }}

(左右移动查看全部内容)

 

最后创建一个任务调用上面处理函数即可。

 

烧写程序后通过串口打印结果

  •  
  •  
ppm:55.6ppm:60.9

(左右移动查看全部内容)

 

当检测到烟雾超过设定值时蜂鸣器报警响起。低于设置值时蜂鸣器停止报警。这样基于小凌派的烟雾报警功能就实现了。

 

原文标题:基于小凌派 RK2206 鸿蒙开发板实现烟雾报警功能

文章出处:【微信公众号:HarmonyOS官方合作社区】欢迎添加关注!文章转载请注明出处。

 
审核编辑:汤梓红
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分