2024-06-03 16:27:41 +08:00
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* 基于 Raspberry Pico 的厨房危险(火灾)报警
|
|
|
|
|
* 使用 DS18B20温度传感器
|
|
|
|
|
* 使用 CH4 N55A甲烷气体传感器(进口)
|
|
|
|
|
* 使用 PASCO2V01 CO2二氧化碳传感器模块(进口模块暂时买不到!)
|
|
|
|
|
* 使用 MH-Z14B CO2二氧化碳传感器模块(国产)(0 - 5000ppm)
|
|
|
|
|
* 使用 ME2_CO CO一氧化碳传感器模块(国产)
|
|
|
|
|
*
|
|
|
|
|
* Date: 20240103
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "MAIN.hpp"
|
|
|
|
|
#include "DTH11.hpp"
|
|
|
|
|
#include "HC-12.hpp"
|
|
|
|
|
#include "ZC13.hpp"
|
|
|
|
|
|
|
|
|
|
#ifndef PICO_DEFAULT_LED_PIN
|
|
|
|
|
#warning pio/hello_pio example requires a board with a regular LED
|
|
|
|
|
#define PICO_DEFAULT_LED_PIN 25
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static inline bool uart_rx_program_available(PIO pio, uint sm)
|
|
|
|
|
{
|
|
|
|
|
return !pio_sm_is_rx_fifo_empty(pio, sm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 闪烁LED
|
|
|
|
|
static void light_flashing()
|
|
|
|
|
{
|
|
|
|
|
gpio_init(PICO_DEFAULT_LED_PIN);
|
|
|
|
|
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
|
|
|
|
|
gpio_put(PICO_DEFAULT_LED_PIN, 1);
|
|
|
|
|
sleep_ms(100);
|
|
|
|
|
gpio_put(PICO_DEFAULT_LED_PIN, 0);
|
|
|
|
|
sleep_ms(100);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int wifi()
|
|
|
|
|
{
|
|
|
|
|
if (cyw43_arch_init()) {
|
|
|
|
|
printf("failed to initialise\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cyw43_arch_enable_sta_mode();
|
|
|
|
|
|
|
|
|
|
printf("Connecting to Wi-Fi...\n");
|
|
|
|
|
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
|
|
|
|
|
printf("failed to connect.\n");
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
printf("Connected.\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cyw43_arch_deinit();
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取主板温度
|
|
|
|
|
float read_onboard_temperature()
|
|
|
|
|
{
|
|
|
|
|
adc_init();
|
|
|
|
|
adc_set_temp_sensor_enabled(true);
|
|
|
|
|
adc_select_input(4); // Input 4 is the onboard temperature sensor.
|
|
|
|
|
|
|
|
|
|
/* 12-bit conversion, assume max value == ADC_VREF == 3.3 V */
|
|
|
|
|
const float conversionFactor = 3.3f / (1 << 12);
|
|
|
|
|
|
|
|
|
|
float adc = (float)adc_read() * conversionFactor;
|
|
|
|
|
float tempC = 27.0f - (adc - 0.706f) / 0.001721f;
|
|
|
|
|
|
|
|
|
|
//printf("Onboard temperature %.02f°C %.02f°F\n", tempC, (tempC * 9 / 5 + 32));
|
|
|
|
|
return tempC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 温度传感器
|
|
|
|
|
float DS18B20()
|
|
|
|
|
{
|
|
|
|
|
float TEMPERATURE = -1;
|
|
|
|
|
|
|
|
|
|
One_wire one_wire(DS18B20_PIN);
|
|
|
|
|
one_wire.init();
|
|
|
|
|
rom_address_t address {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
one_wire.single_device_read_rom(address);
|
|
|
|
|
/*
|
|
|
|
|
printf("Device Address: %02x%02x%02x%02x%02x%02x%02x%02x\n",
|
|
|
|
|
address.rom[0], address.rom[1], address.rom[2], address.rom[3],
|
|
|
|
|
address.rom[4], address.rom[5], address.rom[6], address.rom[7]);
|
|
|
|
|
*/
|
|
|
|
|
one_wire.convert_temperature(address, true, false);
|
|
|
|
|
TEMPERATURE = one_wire.temperature(address);
|
|
|
|
|
//printf("Temperature: %3.1f°C\n", one_wire.temperature(address));
|
|
|
|
|
|
|
|
|
|
return TEMPERATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 甲烷气体传感器
|
|
|
|
|
int CH4()
|
|
|
|
|
{
|
|
|
|
|
int CH4_TRUE = 0;
|
|
|
|
|
|
|
|
|
|
gpio_init(PICO_DEFAULT_LED_PIN);
|
|
|
|
|
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
|
|
|
|
|
|
|
|
|
|
gpio_init(CH4_PIN); // 设置 GP14 引脚作为输入引脚
|
|
|
|
|
gpio_set_dir(CH4_PIN, GPIO_IN);
|
|
|
|
|
|
|
|
|
|
if (gpio_get(CH4_PIN) == 1) {
|
|
|
|
|
CH4_TRUE = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
sleep_ms(100);
|
|
|
|
|
return CH4_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CO2
|
|
|
|
|
static uint16_t MH_Z14B(int *MH_Z14B_DATA_IS_OK)
|
|
|
|
|
{
|
|
|
|
|
// 初始化UART
|
|
|
|
|
uart_init(UART1, BAUD_RATE);
|
|
|
|
|
gpio_set_function(UART1_TX_PIN, GPIO_FUNC_UART);
|
|
|
|
|
gpio_set_function(UART1_RX_PIN, GPIO_FUNC_UART);
|
|
|
|
|
uart_set_hw_flow(UART1, false, false);
|
|
|
|
|
uart_set_format(UART1, DATA_BITS, STOP_BITS, PARITY);
|
|
|
|
|
|
|
|
|
|
// 0x86 读气体浓度值
|
|
|
|
|
uint8_t CMD[9] = { 0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79 };
|
|
|
|
|
uart_write_blocking(UART1, CMD, 9);
|
|
|
|
|
sleep_ms(200);
|
|
|
|
|
|
|
|
|
|
// 读取
|
|
|
|
|
uint8_t CO2_DATA[9] = { 0 };
|
|
|
|
|
uart_read_blocking(UART1, CO2_DATA, 9);
|
|
|
|
|
|
|
|
|
|
// CO2 浓度
|
|
|
|
|
uint16_t CO2_CONC = (256 * CO2_DATA[2]) + CO2_DATA[3];
|
|
|
|
|
|
|
|
|
|
// 校验
|
|
|
|
|
uint8_t CHECKSUM = (0xFF - (CO2_DATA[1] + CO2_DATA[2] + CO2_DATA[3] + CO2_DATA[4] + CO2_DATA[5] + CO2_DATA[6] + CO2_DATA[7])) + 1;
|
|
|
|
|
|
|
|
|
|
if (CO2_DATA[8] == CHECKSUM && CO2_DATA[1] == 0x86) {
|
|
|
|
|
//printf("CHECKSUM: %X = %X\n", CO2_DATA[8], CHECKSUM);
|
|
|
|
|
//printf("CO2 Concentration: %d ppm\n", CO2_CONC);
|
|
|
|
|
*MH_Z14B_DATA_IS_OK = 1;
|
|
|
|
|
} else {
|
|
|
|
|
// 校准传感器 零点 (ZERO)
|
|
|
|
|
uint8_t ZERO[] = { 0XFF, 0X01, 0X87, 0X00, 0X00, 0X00, 0X00, 0X00, 0X78 };
|
|
|
|
|
uart_write_blocking(UART1, ZERO, 9);
|
|
|
|
|
sleep_ms(200);
|
|
|
|
|
|
|
|
|
|
// 校准传感器 跨度点 (SPAN)
|
|
|
|
|
uint8_t SPAN[] = { 0XFF, 0X01, 0X88, 0X07, 0XD0, 0X00, 0X00, 0X00, 0XA0 };
|
|
|
|
|
uart_write_blocking(UART1, SPAN, 9);
|
|
|
|
|
sleep_ms(200);
|
|
|
|
|
|
|
|
|
|
*MH_Z14B_DATA_IS_OK = 0;
|
|
|
|
|
printf("CO2 concentration reading failed!\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CO2_CONC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CO
|
|
|
|
|
static uint16_t ME2_CO(int IS_ANSWER, int *ME2_CO_DATA_IS_OK)
|
|
|
|
|
{
|
|
|
|
|
// 初始化UART
|
|
|
|
|
uart_init(UART0, BAUD_RATE);
|
|
|
|
|
gpio_set_function(UART0_TX_PIN, GPIO_FUNC_UART);
|
|
|
|
|
gpio_set_function(UART0_RX_PIN, GPIO_FUNC_UART);
|
|
|
|
|
uart_set_hw_flow(UART0, false, false);
|
|
|
|
|
uart_set_format(UART0, DATA_BITS, STOP_BITS, PARITY);
|
|
|
|
|
|
|
|
|
|
if (IS_ANSWER == 1) {
|
|
|
|
|
// 应答模式
|
|
|
|
|
uint8_t _ANSWER[9] = { 0xFF, 0x01, 0x78, 0x41, 0x00, 0x00, 0x00, 0x00, 0x46 };
|
|
|
|
|
uart_write_blocking(UART0, _ANSWER, 9);
|
|
|
|
|
sleep_ms(100);
|
|
|
|
|
}
|
|
|
|
|
// 读取
|
|
|
|
|
uint8_t CO_DATA[9] = { 0 };
|
|
|
|
|
uart_read_blocking(UART0, CO_DATA, 9);
|
|
|
|
|
|
|
|
|
|
// CO 浓度
|
|
|
|
|
uint16_t CO_CONC = (256 * CO_DATA[4]) + CO_DATA[5];
|
|
|
|
|
|
|
|
|
|
// 校验
|
|
|
|
|
uint8_t CHECKSUM = (0xFF - (CO_DATA[1] + CO_DATA[2] + CO_DATA[3] + CO_DATA[4] + CO_DATA[5] + CO_DATA[6] + CO_DATA[7])) + 1;
|
|
|
|
|
|
|
|
|
|
if (CO_DATA[8] == CHECKSUM && CO_DATA[1] == 0x04) {
|
|
|
|
|
//printf("CHECKSUM: %X = %X\n", CO_DATA[8], CHECKSUM);
|
|
|
|
|
//printf("CO Concentration: %d ppm\n", CO_CONC);
|
|
|
|
|
*ME2_CO_DATA_IS_OK = 1;
|
|
|
|
|
} else {
|
|
|
|
|
*ME2_CO_DATA_IS_OK = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CO_CONC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 433MHZ 无线电发送数据到服务器端(Raspberry pico W WiFi 暂时不实现)
|
|
|
|
|
int _433_MHZ(unsigned long val)
|
|
|
|
|
{
|
|
|
|
|
const uint RADIO_TRANSMIT_PIN = _433_MHZ_PIN; // 433发射模块引脚
|
|
|
|
|
const uint PULSE_LENGTH = 169; // set this to PULSELENGTH RECIEVED
|
|
|
|
|
const uint REPEAT_TRANSMIT = 4; // set this to whatever works best for you. // 重复发送
|
|
|
|
|
const uint PROTOCOL = 1; // set this to PROTOCOL RECIEVED
|
|
|
|
|
const uint BIT_LENGTH = 24; // set this to BIT LENGTH RECIEVED
|
|
|
|
|
|
|
|
|
|
gpio_init(RADIO_TRANSMIT_PIN);
|
|
|
|
|
RCSwitch mySwitch = RCSwitch();
|
|
|
|
|
mySwitch.enableTransmit(RADIO_TRANSMIT_PIN);
|
|
|
|
|
mySwitch.setProtocol(PROTOCOL);
|
|
|
|
|
mySwitch.setPulseLength(PULSE_LENGTH);
|
|
|
|
|
mySwitch.setRepeatTransmit(REPEAT_TRANSMIT);
|
|
|
|
|
|
|
|
|
|
mySwitch.send(val, BIT_LENGTH);
|
|
|
|
|
sleep_ms(10);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 简单编码通过433MHZ发送
|
|
|
|
|
int addDigit(int number, int digit)
|
|
|
|
|
{
|
|
|
|
|
char TEMP[BUFER] = { 0 };
|
|
|
|
|
|
|
|
|
|
snprintf(TEMP, sizeof(TEMP), "%d%d%d", digit, number, digit);
|
|
|
|
|
|
|
|
|
|
return atoi(TEMP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 核心0发送数据到核心1, 核心1判断是否有数据到来.
|
|
|
|
|
static void core1_main()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
multicore_fifo_push_blocking(CH4());
|
|
|
|
|
watchdog_update();
|
|
|
|
|
|
|
|
|
|
sleep_ms(1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main()
|
|
|
|
|
{
|
|
|
|
|
stdio_init_all();
|
|
|
|
|
sleep_ms(1000);
|
|
|
|
|
|
|
|
|
|
set_sys_clock_khz(250000, true);
|
|
|
|
|
|
|
|
|
|
int FIFO_ = -1;
|
|
|
|
|
float TEMPERATURE = -1;
|
|
|
|
|
float ONBOARD_TEMPERATURE = -1;
|
|
|
|
|
uint16_t CO2_DATA = -1;
|
|
|
|
|
uint16_t CO_DATA = -1;
|
|
|
|
|
int MH_Z14B_DATA_IS_OK = 0;
|
|
|
|
|
int ME2_CO_DATA_IS_OK = 0;
|
|
|
|
|
|
|
|
|
|
// core1
|
|
|
|
|
multicore_reset_core1();
|
|
|
|
|
multicore_launch_core1(core1_main);
|
|
|
|
|
|
|
|
|
|
if (watchdog_caused_reboot()) { // 判断是否从看门狗启动或者正常启动
|
|
|
|
|
printf("Rebooted by Watchdog!\n");
|
|
|
|
|
} else {
|
|
|
|
|
printf("Clean boot\n");
|
|
|
|
|
}
|
|
|
|
|
watchdog_enable(8300, 1); // 8秒检测是否重新加载看门狗计数器. (不更新计数器则重启硬件, 最高8秒)
|
|
|
|
|
watchdog_start_tick(12);
|
|
|
|
|
|
|
|
|
|
_HC_12_INIT();
|
|
|
|
|
ZC13_INIT();
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
|
|
|
|
|
watchdog_update(); // 喂狗
|
|
|
|
|
|
|
|
|
|
// RP2040温度
|
|
|
|
|
ONBOARD_TEMPERATURE = read_onboard_temperature();
|
|
|
|
|
if (ONBOARD_TEMPERATURE != -1) {
|
|
|
|
|
printf("Onboard temperature %.02f°C %.02f°F\n", ONBOARD_TEMPERATURE, (ONBOARD_TEMPERATURE * 9 / 5 + 32));
|
|
|
|
|
//_433_MHZ(addDigit(ONBOARD_TEMPERATURE, SIGN_RP2040));
|
|
|
|
|
|
|
|
|
|
char ONBOARD_TEMPERATURE_TEMP[BUFER] = { 0 };
|
|
|
|
|
sprintf(ONBOARD_TEMPERATURE_TEMP, "Onboard temperature %.02f°C %.02f°F\n", ONBOARD_TEMPERATURE, (ONBOARD_TEMPERATURE * 9 / 5 + 32));
|
|
|
|
|
_HC_12(ONBOARD_TEMPERATURE_TEMP);
|
|
|
|
|
}
|
|
|
|
|
watchdog_update(); // 喂狗
|
|
|
|
|
|
|
|
|
|
// CH4
|
|
|
|
|
FIFO_ = multicore_fifo_pop_blocking();
|
|
|
|
|
if (FIFO_ == 1) {
|
|
|
|
|
printf("Kitchen danger (fire) alarm detects CH4!!!\n");
|
|
|
|
|
light_flashing();
|
|
|
|
|
FIFO_ = -1;
|
|
|
|
|
//_433_MHZ(addDigit(4, SIGN_CH4));
|
|
|
|
|
}
|
|
|
|
|
watchdog_update(); // 喂狗
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
if (1 == CH4()) {
|
|
|
|
|
printf("Kitchen danger (fire) alarm detects CH4!!!\n");
|
|
|
|
|
light_flashing();
|
|
|
|
|
_HC_12("Kitchen danger (fire) alarm detects CH4!!!\n");
|
|
|
|
|
}
|
|
|
|
|
watchdog_update(); // 喂狗
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// DS18B20
|
|
|
|
|
TEMPERATURE = DS18B20();
|
|
|
|
|
if (TEMPERATURE != -1) {
|
|
|
|
|
if (TEMPERATURE >= 10) {
|
|
|
|
|
printf("Temperature: %.3f°C\n", TEMPERATURE);
|
|
|
|
|
}
|
|
|
|
|
//_433_MHZ(addDigit(TEMPERATURE, SIGN_DS18B20));
|
|
|
|
|
|
2024-06-04 09:54:09 +08:00
|
|
|
|
if (TEMPERATURE != 85) {
|
|
|
|
|
char TEMPERATURE_TEMP[BUFER] = { 0 };
|
|
|
|
|
sprintf(TEMPERATURE_TEMP, "Temperature: %.3f°C\n", TEMPERATURE);
|
|
|
|
|
_HC_12(TEMPERATURE_TEMP);
|
|
|
|
|
|
|
|
|
|
TEMPERATURE = -1;
|
|
|
|
|
}
|
2024-06-03 16:27:41 +08:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
watchdog_update(); // 喂狗
|
2024-06-04 09:54:09 +08:00
|
|
|
|
|
|
|
|
|
// ZC13 CH4 传感器
|
|
|
|
|
char CH4_DATA[BUFER] = { 0 };
|
|
|
|
|
sprintf(CH4_DATA, "CH4 Concentration: %d\n", ZC13("ZC05"));
|
|
|
|
|
_HC_12(CH4_DATA);
|
2024-06-03 16:27:41 +08:00
|
|
|
|
watchdog_update(); // 喂狗
|
|
|
|
|
|
|
|
|
|
// ME2_CO CO
|
|
|
|
|
// 50 ppm(百万分之一):长时间暴露可能会导致头痛、恶心、疲劳等不适症状。
|
|
|
|
|
// 200 ppm:短时间暴露可能会导致轻微的头痛、疲劳和呼吸困难。
|
|
|
|
|
// 800 ppm:短时间暴露可能会导致头晕、恶心和死亡。
|
|
|
|
|
// 1600 ppm:短时间暴露可能会导致昏迷、危及生命。
|
|
|
|
|
CO_DATA = ME2_CO(0, &ME2_CO_DATA_IS_OK);
|
|
|
|
|
if (CO_DATA != -1 && ME2_CO_DATA_IS_OK == 1) {
|
|
|
|
|
printf("CO Concentration: %d ppm\n", CO_DATA);
|
|
|
|
|
//_433_MHZ(addDigit(CO_DATA, SIGN_CO));
|
|
|
|
|
|
|
|
|
|
char CO_DATA_TEMP[BUFER] = { 0 };
|
|
|
|
|
sprintf(CO_DATA_TEMP, "CO Concentration: %d ppm\n", CO_DATA);
|
|
|
|
|
_HC_12(CO_DATA_TEMP);
|
|
|
|
|
}
|
|
|
|
|
watchdog_update(); // 喂狗
|
|
|
|
|
|
|
|
|
|
// MH_Z14B CO2
|
|
|
|
|
CO2_DATA = MH_Z14B(&MH_Z14B_DATA_IS_OK);
|
|
|
|
|
if (CO2_DATA != -1 && MH_Z14B_DATA_IS_OK == 1) {
|
|
|
|
|
printf("CO2 Concentration: %d ppm\n", CO2_DATA);
|
|
|
|
|
//_433_MHZ(addDigit(CO2_DATA, SIGN_CO2));
|
|
|
|
|
|
|
|
|
|
char CO2_DATA_TEMP[BUFER] = { 0 };
|
|
|
|
|
sprintf(CO2_DATA_TEMP, "CO2 Concentration: %d ppm\n", CO2_DATA);
|
|
|
|
|
_HC_12(CO2_DATA_TEMP);
|
|
|
|
|
}
|
|
|
|
|
printf("\r\n");
|
|
|
|
|
|
|
|
|
|
watchdog_update(); // 喂狗
|
|
|
|
|
sleep_ms(3000);
|
|
|
|
|
watchdog_update(); // 喂狗
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|