画板子,有至少8个io口(分别连ds18b20、红外传感器、烟雾传感器、CO传感器,后面3个传感器都是检测到就发高电平),2个串口,1个蜂鸣器,nbiot用的YED-C724 核心板(AIR724) 后改为基于esp8266的nodemcu

1、项目简介

在这里插入图片描述

2、实现逻辑

#配置好esp8266,烧录好nodemcu的固件,编写lua脚本,识别固定协议的数据传给onenet
#通过adc检测烟雾值(mq2)
#检测CO(MQ7)
#检测火灾情况(红外传感器)
#检测ds18b20测到的的温度
#进行参数分析,判读是否符合蜂鸣器报警条件
#将参数发送给onenet(通过nodemcu),每5秒一次自动发送
#oled显示各状态参数
#如果 烟雾>=1000 ‖ co>=1000 ‖ 温度>=50 ‖ 检测到红外,就蜂鸣器提示,反之不响
#远端网页版加一个红外情况:放一个开关,检测到红外开关变on,反之off。
#火灾情况,放一个开关,烟雾>=1000 ‖ co>=1000 ‖ 温度>=50 ‖ 检测到红外,若这串结果为1开关变

3、应用场景

4、核心代码梳理

//stm32程序
void MQ2_PPM_Calibration(float RS)
{
    R0 = RS / pow(CAL_PPM / 613.9f, 1 / -2.074f);
}

float MQ2_GetPPM(void)
{

    float Vrl = 3.3f * ADC_num_smoke / 4095.f;
    float RS = (3.3f - Vrl) / Vrl * RL;
    if(HAL_GetTick() < 10000)
    {
        MQ2_PPM_Calibration(RS);
    }
    float ppm = 613.9f * pow(RS/R0, -2.074f);
    return  ppm;
}

void MQ7_PPM_Calibration(float RS)
{

    R0_CO = RS / pow(CAL_PPM_CO / 98.322, 1 / -1.458f);
}

// 获取传感器的值
float MQ7_GetPPM(void)
{
    float Vrl = 33.3f * ADC_num_co/ 4095.f;
    Vrl = ( (float)( (int)( (Vrl+0.005)*100 ) ) )/100;
    float RS_CO = (3.3f - Vrl) / Vrl * RL;
    if(HAL_GetTick() < 10000)
    {
        MQ7_PPM_Calibration(RS_CO);
    }

    float ppm = 98.322f * pow(RS_CO/R0_CO, -1.458f);

    return  ppm;
}

//复位DS18B20
void DS18B20_Rst(void)
{
    HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_RESET); //拉低DQ
    delay_us(750);    //拉低750us
    HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_SET); //DQ=1
    delay_us(15);     //15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
uint8_t DS18B20_Check(void)
{
    uint8_t retry=0;
    //SET PB1 INPUT
    while (HAL_GPIO_ReadPin(DS18B20_GPIO_Port,DS18B20_Pin) && retry<200)
    {
        retry++;
        delay_us(1);
    };
    if(retry>=200)return 1;
    else retry=0;
    while (!HAL_GPIO_ReadPin(DS18B20_GPIO_Port,DS18B20_Pin)&&retry<240)
    {
        retry++;
        delay_us(1);
    };
    if(retry>=240)return 1;
    return 0;
}
//从DS18B20读取一个位
//返回值:1/0
uint8_t DS18B20_Read_Bit(void) 			 // read one bit
{
    uint8_t data;
    HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_RESET);
    delay_us(2);
    HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_SET);
    delay_us(12);
    if(HAL_GPIO_ReadPin(DS18B20_GPIO_Port,DS18B20_Pin))data=1;
    else data=0;
    delay_us(50);
    return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
uint8_t DS18B20_Read_Byte(void)    // read one byte
{
    uint8_t i,j,dat;
    dat=0;
    for (i=1; i<=8; i++)
    {
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }
    return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(uint8_t dat)
{
    uint8_t j;
    uint8_t testb;
    for (j=1; j<=8; j++)
    {
        testb=dat&0x01;
        dat=dat>>1;
        if (testb)
        {
            HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_RESET);// Write 1
            delay_us(2);
            HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_SET);
            delay_us(60);
        }
        else
        {
            HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_RESET);// Write 0
            delay_us(60);
            HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_SET);
            delay_us(2);
        }
    }
}
//开始温度转换
void DS18B20_Start(void)// ds1820 start convert
{
    DS18B20_Rst();
    DS18B20_Check();
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0x44);// convert
}
//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在
uint8_t DS18B20_Init(void)
{
    DS18B20_Rst();
    return DS18B20_Check();
}
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250)
float DS18B20_Get_Temp(void)
{
    uint8_t temp;
    uint8_t TL,TH;
    short tem;
    float return_tem;
    DS18B20_Start();                    // ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0xbe);// convert
    TL=DS18B20_Read_Byte(); // LSB
    TH=DS18B20_Read_Byte(); // MSB

    if(TH>7)
    {
        TH=~TH;
        TL=~TL;
        temp=0;//温度为负
    } else temp=1;//温度为正
    tem=TH; //获得高八位
    tem<<=8;
    tem+=TL;//获得底八位
    return_tem = (float)tem*0.625;//转换
    if(temp)return return_tem; //返回温度值
    else return -return_tem;
}

/* 向onenet平台发数据函数
 * return 1 ok; 0 fail
 */
uint8_t send_onenet(void)
{
    char text[200];
    uint8_t len;

    memset(text, 0, sizeof(text));

    //组包
    memset(text, 0, sizeof(text));

    sprintf(text, "{\"id\": 123,\"dp\": {\"SMOKE\": [{\"v\": %.2f}],\"FIRE\": [{\"v\": %d}],\"RED\": [{\"v\": %d}],\"TEMP\": [{\"v\": %.2f}],\"CO\": [{\"v\": %.2f}]}}",check_smoke, fire_sta, red_sta, check_temp, check_co);

    //封包
    len = strlen(text);

    HAL_UART_Transmit(&huart1, (uint8_t *)text, len, 0xFFFF); //发送

    return 1;
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
    /* USER CODE BEGIN 1 */
    uint16_t clk, adcBuf[3];
    tx_nbiot[0] = 0xff;
    tx_nbiot[1] = 0x74;
    tx_nbiot[13] = 0xff;
    /* USER CODE END 1 */

    /* MCU Configuration--------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_ADC1_Init();
    MX_USART1_UART_Init();
    MX_USART3_UART_Init();
    /* USER CODE BEGIN 2 */
    OLED_Init();
    OLED_ColorTurn(0);//
    OLED_DisplayTurn(0);//
    OLED_Refresh();
    OLED_Clear();
    OLED_ShowString(0,0,"TEMP:    .      C",12);
    OLED_ShowString(0,10,"CO:        .    PPM",12);
    OLED_ShowString(0,20,"SMO:       .    PPM",12);
    OLED_ShowString(0,30,"RED:      ",12);
		OLED_ShowString(0,40,"FIRE:      ",12);


    OLED_Refresh();

    //__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);//open uart1 RXNE
    HAL_Delay(100);
    HAL_GPIO_WritePin(GPIOA, BEEP_Pin, GPIO_PIN_SET);

    DS18B20_Init();
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
        //OLED_Clear();
        clk++;


//////////////nbiot receive
        if(rx_ok)
        {
            //rx_order++;
            rx_ok = 0;
        }
//////////////send nbiot/display
        if(clk % 20 == 0) //1s -- 10
        {
            //check smoke
            //HAL_ADC_Start_IT(&hadc1);
            for(uint8_t i=0; i<3; i++)
            {
                HAL_ADC_Start(&hadc1);
                HAL_ADC_PollForConversion(&hadc1,0xffff);
                adcBuf[i]=HAL_ADC_GetValue(&hadc1);
            }

            ADC_num_smoke = adcBuf[0];
            ADC_num_co = adcBuf[1];
            ADC_num_fire = adcBuf[2];

            check_smoke = MQ2_GetPPM();

            intS = (int)check_smoke;
            float tmp = check_smoke-intS;
            decS = tmp * 100;
            OLED_ShowNum(25,20,intS,6,12);
            OLED_ShowNum(72,20,decS,2,12);

            //check  CO  //10ppm - 10000ppm
            check_co = MQ7_GetPPM();

            intCO = (int)check_co;
            float tmpC0 = check_co-intCO;
            decCO = tmpC0 * 100;
            OLED_ShowNum(25,10,intCO,6,12);
            OLED_ShowNum(72,10,decCO,2,12);

//            OLED_ShowNum(39,2,CO>>8,4,12);
//            OLED_ShowNum(80,2,CO&0xff,2,12);

            //check  fire

            if(HAL_GPIO_ReadPin(GPIOA,FIRE_DO_Pin))
            {
                red_sta = 0;
                OLED_ShowString(55,30,"NO  ",12);
            }
            else
            {
                red_sta = 1;
                OLED_ShowString(55,30,"YES",12);
            }

            //check  DS18B20
            check_temp = DS18B20_Get_Temp()/10;
            intT = (int)check_temp;          /*合成实际温度整数部分****精度相对上面的更高*/
            float tem_tmp = check_temp-intT;         /*合成实际温度小数部分*/
            decT = tem_tmp*100;

            OLED_ShowNum(40,0,intT,2,12);
            OLED_ShowNum(60,0,decT,2,12);

            tx_nbiot[2] = decT;
            tx_nbiot[3] = tem_tmp;
            tx_nbiot[4] = CO>>8;
            tx_nbiot[5] = CO&0xff;
            tx_nbiot[6] = intS / 256;
            tx_nbiot[7] = intS % 256;
            tx_nbiot[8] = decS;
            tx_nbiot[9] = fire_sta;
//            tx_nbiot[10] = motor_sta;
//            tx_nbiot[11] = alarm_sta;
//            tx_nbiot[12] = beep_sta + 5;

            //alarm
            temp = tx_nbiot[2];
            hump = tx_nbiot[4];
            smoke = check_smoke;
            if((temp > 40) || (CO > 50))
            {


            }
            else
            {

            }

            if(smoke > 300)
            {
                alarm_smoke = 1;
            }
            else if(smoke < 100)
            {
                alarm_smoke = 0;
            }
            else //30-300 fan
            {
                alarm_smoke = 0;
            }

            if(alarm_smoke || fire_sta)
                alarm_sta = 1;
            else alarm_sta = 0;

            if(alarm_sta)//beep
            {
//                HAL_GPIO_WritePin(GPIOA, BEEP_Pin, GPIO_PIN_RESET); //active
            }
            else
            {
//                  HAL_GPIO_WritePin(GPIOA, BEEP_Pin, GPIO_PIN_SET);
            }
						
						if(check_smoke>=1000 || check_co>=1000 || check_temp>=50 || red_sta)//check_smoke, fire_sta, red_sta, check_temp, check_co
							fire_sta = 1;
						else fire_sta = 0;
						if(!fire_sta)
            {
                OLED_ShowString(55,40,"NO  ",12);
						  	HAL_GPIO_WritePin(GPIOA, BEEP_Pin, GPIO_PIN_SET);
							  
            }
            else
            {
                OLED_ShowString(55,40,"YES",12);
							  HAL_GPIO_WritePin(GPIOA, BEEP_Pin, GPIO_PIN_RESET); //active
            }
						
        }
        if(clk % 50 == 0) //1s -- 10
        {
            send_onenet();//tx onenet data
        }
				
        HAL_Delay(100);
        OLED_Refresh();
    }

    /* USER CODE END 3 */
}


//lua脚本
cfg = {}
cfg.ssid = "esp8266"
cfg.pwd = "esp8266test"
 
wifi.setmode(wifi.STATIONAP)
wifi.sta.config(cfg)
wifi.sta.connect()
 
 
DeviceId = "704xxx0230"
ProductId ="41xxx85"
AuthoTnfo = "96jNf6YzxxxxxSznrgULsQ="
KeepAlive = 200 
host = "183.230.40.39"
port = 6002 
 
 
myClient = mqtt.Client(DeviceId, KeepAlive, ProductId, AuthoTnfo)
--print("115200 8-n-1")
uart.setup(0, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1, 0)

        
timer1 = tmr.create()

timer2 = tmr.create()
 
function ReConnect()
    if wifi.sta.getip() == nil then
        print("Connect AP,waitting...")
    else
        print("Connected AP,Success!")
        --print("IP is:"..wifi.sta.getip())
        --print("MAC address:"..wifi.sta.getmac())
        timer1:stop()
 
        myClient:connect(host, port, function(client)
           -- print("Connected OneNET success!")
            gpio.write(pin,gpio.LOW) 
        end)
        
       
        uart.on("data", function(data) 
            cnt = string.len(data)
            timer1.stop(1)
            timer1.interval(1, 1)
            timer1.start(1)
            --uart.write(0, data)
            --print("len:",string.len(data))
            ---print(type(data))
            if(cnt == 13) then
                cnt = 0
                if(string.find(data,"t") == 1) then
                    --print("t!") 
                    --print(string.byte(data,2))
                    --print(string.byte(data,3)/100)
                    TEM = string.byte(data,2) + string.byte(data,3)/100
                    HUM = string.byte(data,4) + string.byte(data,5)/100
                    SMOKE = string.byte(data,6)*256 + string.byte(data,7)+ string.byte(data,8)/100
                    LED = string.byte(data,9)
                    MOTOR = string.byte(data,10)
					ALARM_STA = string.byte(data,11)
					BEEP_STA = string.byte(data,12)
                end
            end
            Update_Message()
        end, 0)
        
        myClient:on("message", function(client , topic , message)
            --print("get a message.\n")
            --print(topic..":"..message)
        print("order:"..message)
        end)
 
        --timer2:alarm(3000, tmr.ALARM_AUTO, Update_Message)
    end
end
 
timer1:alarm(1000,tmr.ALARM_AUTO,ReConnect)


     
function Update_Message()
    info = {}
    info.tem = TEM
    info.hum = HUM
    info.smoke = SMOKE
    info.led = LED
    info.motor = MOTOR
	info.alarm = ALARM_STA
    info.beep = BEEP_STA 
 
    --TEM = TEM + 1
    --HUM = HUM - 1
    --SMOKE = SMOKE + 0.1
    ok,message = pcall(cjson.encode, info)
    --print("message:"..message)
 
    header = string.char(3, 0 ,string.len(message))..message
    myClient:publish("$dp", header, 0, 0, function(client)
        --print("Publish info success!")
    end)
end

5、部分参考资料

http://www.openedv.com/
https://wiki.openluat.com/
http://wiki.yinerda.com/index.php/YED-C724
在这里插入图片描述

6、注意事项

#YED-C724好像不需要物联网卡
#用打火机的气体可以模拟co、烟雾及火灾情况
#烟雾检测的时候前几分钟一般是校准时间
#ESP8266脚本的信息要和远端的onenet上的信息一致

完整可运行项目地址

或 点击下方”大饼匠人“卡片,关注并回复"14"免费下载开发资料

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐