#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <U8g2lib.h>
#define NUM_FIRE_SENSE 2
#define GPIO_LED_Operation 25 // 运行指示灯
#define GPIO_LED_Fire 18 // 火焰指示灯
#define GPIO_LED_Smoke 19 // 烟雾浓度超标指示灯
#define GPIO_BUZZ 33 // 蜂鸣器
#define GPIO_INPUT_VAL_SMOKE_SENSE 32 // 烟雾浓度灵敏度调节
#define GPIO_INPUT_VAL_SMOKE 4 // 烟雾传感器
#define GPIO_INPUT_VAL_BUTTON_FIRE_AWARE 7 // 知晓火情按钮
#define GPIO_INPUT_VAL_BUTTON_SMOKE_AWARE 8 // 知晓烟雾超标按钮
#define GPIO_INPUT_VAL_SMOKE_TRIGGER 5 // 烟雾超标
#define GPIO_INPUT_VAL_FIRE_1 26 // 火焰检测1
#define GPIO_INPUT_VAL_FIRE_2 27 // 火焰检测2
typedef struct
{
uint32_t val_smoke;
uint8_t val_smoke_out_of_range;
uint8_t val_on_fire[NUM_FIRE_SENSE];
} STATUS_VAL;
typedef struct
{
uint32_t val_smoke_val;
uint8_t val_smoke;
uint8_t val_fire;
} OUTPUT_STATE;
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 22, /* data=*/ 21);
STATUS_VAL status_val;
OUTPUT_STATE op_state;
uint32_t out_of_range_value = 0;
uint8_t aware_smoke = 0;
uint8_t aware_fire = 0;
const uint8_t fast_pinmode_output[] = {GPIO_LED_Operation, GPIO_LED_Fire, GPIO_LED_Smoke, GPIO_BUZZ};
const uint8_t fast_pinmode_input_analog[] = {GPIO_INPUT_VAL_SMOKE_SENSE, GPIO_INPUT_VAL_SMOKE};
const uint8_t fast_pinmode_input_digital[] = {GPIO_INPUT_VAL_BUTTON_FIRE_AWARE, GPIO_INPUT_VAL_BUTTON_SMOKE_AWARE, GPIO_INPUT_VAL_SMOKE_TRIGGER};
const uint8_t fast_fire_sense[NUM_FIRE_SENSE] = {GPIO_INPUT_VAL_FIRE_1, GPIO_INPUT_VAL_FIRE_2};
void setup()
{
gpio_init();
u8g2_init();
param_init();
digitalWrite(GPIO_LED_Operation, LOW);
digitalWrite(GPIO_LED_Fire, HIGH);
digitalWrite(GPIO_LED_Smoke, HIGH);
digitalWrite(GPIO_BUZZ, HIGH);
for(uint8_t i = 0; i < 10; i++)
{
uint32_t temp_val = analogRead(GPIO_INPUT_VAL_SMOKE_SENSE);
out_of_range_value += temp_val;
}
out_of_range_value /= 10;
xTaskCreate(display_task, "display_task", 4096, (void *) &op_state, 5, NULL);
xTaskCreate(led_task, "led_task", 4096, (void *) &op_state, 4, NULL);
xTaskCreate(buzz_task, "buzz_task", 4096, (void *) &op_state, 6, NULL);
xTaskCreate(aware_timeout_smoke, "aware_smoke", 4096, (void *) &op_state, 3, NULL);
xTaskCreate(aware_timeout_fire, "aware_fire", 4096, (void *) &op_state, 3, NULL);
Serial.begin(115200);
}
void loop()
{
get_status(&status_val);
confirm_alarm(&status_val, &op_state);
delay(100);
}
void u8g2_init(void)
{
u8g2.begin();
u8g2.enableUTF8Print();
u8g2.setFont(u8g2_font_wqy13_t_gb2312);
u8g2.setDrawColor(1);
u8g2.setFontPosTop();
u8g2.setFontDirection(0);
}
void gpio_init(void)
{
for(uint8_t i = 0; i < 4; i++)
{
pinMode(fast_pinmode_output[i], OUTPUT);
digitalWrite(fast_pinmode_output[i], HIGH);
}
for(uint8_t i = 0; i < 2; i++)
pinMode(fast_pinmode_input_analog[i], INPUT);
for(uint8_t i = 0; i < 3; i++)
pinMode(fast_pinmode_input_digital[i], INPUT_PULLUP);
for(uint8_t i = 0; i < NUM_FIRE_SENSE; i++)
pinMode(fast_fire_sense[i], INPUT_PULLUP);
}
void param_init(void)
{
uint8_t c[NUM_FIRE_SENSE];
for(uint8_t i = 0; i < NUM_FIRE_SENSE; i++)
c[i] = 0;
set_struct_status_val(&status_val, 0, 0, c);
}
void set_struct_status_val(STATUS_VAL *val, uint32_t a, uint8_t b, uint8_t *c)
{
val->val_smoke = a;
val->val_smoke_out_of_range = b;
for(uint8_t i = 0; i < NUM_FIRE_SENSE; i++)
val->val_on_fire[i] = c[i];
}
void get_status(STATUS_VAL *val)
{
uint32_t a = analogRead(GPIO_INPUT_VAL_SMOKE); // 读烟雾数值
uint8_t b = digitalRead(GPIO_INPUT_VAL_SMOKE_TRIGGER); // 读烟雾阈值
uint8_t c[NUM_FIRE_SENSE];
for(uint8_t i = 0; i < NUM_FIRE_SENSE; i++)
c[i] = digitalRead(fast_fire_sense[i]);
set_struct_status_val(val, a, b, c);
}
void confirm_alarm(STATUS_VAL *val, OUTPUT_STATE *tmp_state)
{
float fire_status = 0.0f;
for(uint8_t i = 0; i < NUM_FIRE_SENSE; i++)
{
if(val->val_on_fire[i] == 1)
fire_status = fire_status + 1.0f;
}
float threshold_val = NUM_FIRE_SENSE * 0.5f; //超过一半的火焰检测器检测到火焰
if(fire_status >= threshold_val)
tmp_state->val_fire = 1;
else
tmp_state->val_fire = 0;
tmp_state->val_smoke_val = val->val_smoke;
if(tmp_state->val_smoke_val >= out_of_range_value || val->val_smoke_out_of_range == 1)
tmp_state->val_smoke = 1;
else
tmp_state->val_smoke = 0;
}
void display_task(void *param)
{
OUTPUT_STATE *output_state;
output_state = (OUTPUT_STATE *)param;
while(1)
{
uint32_t val_smoke = output_state->val_smoke_val;
uint8_t led_smoke = output_state->val_smoke;
uint8_t led_fire = output_state->val_fire;
/** state 1 **/
u8g2.clearBuffer();
u8g2.setCursor(0, 8);
u8g2.print("烟雾浓度:");
u8g2.drawStr(65, 8, String(val_smoke).c_str());
if(led_fire)
{
u8g2.setCursor(0, 40);
u8g2.print("有明火! 请注意!");
}
else
{
u8g2.setCursor(0, 40);
u8g2.print("无火源");
}
u8g2.sendBuffer();
delay(300);
/** state 2 **/
u8g2.clearBuffer();
u8g2.setCursor(0, 8);
u8g2.print("烟雾浓度:");
if(!led_smoke)
u8g2.drawStr(65, 8, String(val_smoke).c_str());
if(!led_fire)
{
u8g2.setCursor(0, 40);
u8g2.print("无火源");
}
u8g2.sendBuffer();
delay(300);
/** state 3**/
u8g2.clearBuffer();
u8g2.setCursor(0, 8);
u8g2.print("烟雾浓度:");
u8g2.drawStr(65, 8, String(val_smoke).c_str());
if(!led_fire)
{
u8g2.setCursor(0, 40);
u8g2.print("无火源");
}
else
{
u8g2.setCursor(0, 40);
u8g2.print("有明火! 请注意!");
}
u8g2.sendBuffer();
delay(300);
/** state 4**/
u8g2.clearBuffer();
u8g2.setCursor(0, 8);
u8g2.print("烟雾浓度:");
if(!led_smoke)
u8g2.drawStr(65, 8, String(val_smoke).c_str());
if(!led_fire)
{
u8g2.setCursor(0, 40);
u8g2.print("无火源");
}
u8g2.sendBuffer();
delay(300);
}
}
void led_task(void *param)
{
OUTPUT_STATE *output_state;
output_state = (OUTPUT_STATE *)param;
while(1)
{
uint8_t led_smoke = output_state->val_smoke;
uint8_t led_fire = output_state->val_fire;
if(led_smoke)
{
digitalWrite(GPIO_LED_Smoke, LOW);
vTaskDelay(500);
digitalWrite(GPIO_LED_Smoke, HIGH);
vTaskDelay(500);
}
else digitalWrite(GPIO_LED_Smoke, HIGH);
if(led_fire)
{
digitalWrite(GPIO_LED_Fire, LOW);
vTaskDelay(500);
digitalWrite(GPIO_LED_Fire, HIGH);
vTaskDelay(500);
}
else digitalWrite(GPIO_LED_Fire, HIGH);
vTaskDelay(500);
}
}
void buzz_task(void *param)
{
OUTPUT_STATE *output_state;
output_state = (OUTPUT_STATE *)param;
while(1)
{
uint8_t led_smoke = output_state->val_smoke;
uint8_t led_fire = output_state->val_fire;
if(!aware_smoke)
{
if(led_smoke)
{
digitalWrite(GPIO_BUZZ, LOW);
vTaskDelay(100);
digitalWrite(GPIO_BUZZ, HIGH);
vTaskDelay(100);
}
else digitalWrite(GPIO_BUZZ, HIGH);
}
else digitalWrite(GPIO_BUZZ, HIGH);
vTaskDelay(200);
if(!aware_fire)
{
if(led_fire)
{
digitalWrite(GPIO_BUZZ, LOW);
vTaskDelay(300);
digitalWrite(GPIO_BUZZ, HIGH);
vTaskDelay(300);
}
else digitalWrite(GPIO_BUZZ, HIGH);
}
else digitalWrite(GPIO_BUZZ, HIGH);
vTaskDelay(200);
}
}
void aware_timeout_smoke(void *param)
{
OUTPUT_STATE *output_state;
output_state = (OUTPUT_STATE *)param;
uint8_t tmp_smoke = 0;
while(1)
{
if(digitalRead(GPIO_INPUT_VAL_BUTTON_SMOKE_AWARE) == 0)
{
vTaskDelay(30);
if(digitalRead(GPIO_INPUT_VAL_BUTTON_SMOKE_AWARE) == 0)
tmp_smoke = 1;
}
if(tmp_smoke == 1 && (output_state->val_smoke == 1 || output_state->val_smoke_val >= out_of_range_value))
{
tmp_smoke = 0;
aware_smoke = 1;
uint32_t i = 3000;
while(i > 0)
{
i--;
vTaskDelay(100);
if(analogRead(GPIO_INPUT_VAL_SMOKE) < out_of_range_value)
{
aware_smoke = 0;
tmp_smoke = 0;
break;
}
}
}
vTaskDelay(300);
}
}
void aware_timeout_fire(void *param)
{
OUTPUT_STATE *output_state;
output_state = (OUTPUT_STATE *)param;
uint8_t tmp_fire = 0;
while(1)
{
if(digitalRead(GPIO_INPUT_VAL_BUTTON_FIRE_AWARE) == 0)
{
vTaskDelay(30);
if(digitalRead(GPIO_INPUT_VAL_BUTTON_FIRE_AWARE) == 0)
tmp_fire = 1;
}
if(tmp_fire == 1 && output_state->val_fire == 1)
{
tmp_fire = 0;
aware_fire = 1;
uint32_t i = 3000;
while(i > 0)
{
i--;
vTaskDelay(100);
if(output_state->val_fire == 0)
break;
}
aware_fire = 0;
}
vTaskDelay(300);
}
}