Danger-alarm/SOFTWARE/Source/MAIN.cpp

381 lines
11 KiB
C++
Raw Normal View History

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));
if (TEMPERATURE != 85) {
char TEMPERATURE_TEMP[BUFER] = { 0 };
sprintf(TEMPERATURE_TEMP, "Temperature: %.3f°C\n", TEMPERATURE);
_HC_12(TEMPERATURE_TEMP);
TEMPERATURE = -1;
}
}
watchdog_update(); // 喂狗
// ZC13 CH4 传感器
char CH4_DATA[BUFER] = { 0 };
sprintf(CH4_DATA, "CH4 Concentration: %d\n", ZC13("ZC05"));
_HC_12(CH4_DATA);
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;
}