/**
* Sistema de Monitoramento Ambiental para Raspberry Pi Pico
* * --- DESCRIÇÃO DO PROJETO ---
* Este código implementa um sistema de monitoramento completo que lê sensores
* de temperatura (DHT22), luz (LDR) e gás (MQ-2), e aciona
* atuadores específicos e distintos para cada condição de alerta.
* O projeto inclui um alerta mecânico/visual para temperatura (Servo + LED),
* um alerta sonoro para gás (Buzzer) e um alarme externo visual (Relé + LED).
* * --- NOTA IMPORTANTE PARA TESTES NO WOKWI ---
* O componente simulado do sensor de gás (MQ-2) no Wokwi possui uma
* característica específica: na inicialização, ele reporta um valor ADC alto
* por padrão, ignorando a posição do seu slider de PPM.
* O código abaixo possui um "loop de estabilização inteligente" para lidar com isso.
*
* * (ATENÇÃO) (LEIA) COMO PROCEDER NO TESTE:
* 1. Inicie a simulação (clique no botão 'Play').
* 2. Você verá no monitor serial mensagens de "Estabilizando sensor de gas...".
* 3. Para que o programa continue, você precisa "acordar" o sensor. Simplesmente
* mova seu slider de PPM PARA A ESQUERDA.
* 4. Ao fazer isso, o sensor atualizará seu valor para o correto (baixo), o loop de
* estabilização será concluído, e o sistema iniciará a operação normal.
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/adc.h"
#include "hardware/pwm.h"
#include "dht.h"
// =================================================================================
// --- MAPEAMENTO DE PINOS E CONSTANTES ---
// =================================================================================
// --- Pinos dos Sensores ---
const uint DHT_PIN = 15;
const uint LDR_PIN_ADC = 0; // Canal ADC 0 (GP26)
const uint MQ2_PIN_ADC = 1; // Canal ADC 1 (GP27)
// --- Pinos dos Atuadores ---
// REQUISITO TÉCNICO: Uso de pinos GPIO para controle de relé, motor vibracall e LED IR;
const uint SERVO_PIN = 16; // Alerta Mecânico de Temperatura (Servo Motor)
const uint LED_TEMP_PIN = 21; // Alerta Visual de Temperatura (LED Laranja/Amarelo)
const uint BUZZER_GAS_PIN = 19; // Alerta Sonoro de Gás (Buzzer)
const uint IR_LED_PIN = 3; // LED de Baixa Luminosidade (simulador de IR)
const uint RELAY_PIN = 18; // Relé para Alarme Externo de Gás
// --- Limiares de Ativação (Thresholds) ---
const float TEMP_THRESHOLD = 30.0f;
const uint16_t LDR_THRESHOLD = 1000;
const uint16_t GAS_THRESHOLD = 2500;
// Variáveis globais para os "slices" de PWM
uint slice_servo_num;
uint slice_gas_num;
// =================================================================================
// --- INICIALIZAÇÃO DOS COMPONENTES ---
// =================================================================================
/**
* Configura todos os pinos dos atuadores como saídas
* e define seus estados iniciais como "desligado".
*/
void init_actuators() {
// REQUISITO TÉCNICO: Uso adequado de resistores de pull-up/pull-down, se necessário;
// (O principal foi o uso de resistores de limitação de corrente de 220Ω para os LEDs)
// Configuração do Servo Motor para operar em 50Hz
gpio_set_function(SERVO_PIN, GPIO_FUNC_PWM);
slice_servo_num = pwm_gpio_to_slice_num(SERVO_PIN);
pwm_config config = pwm_get_default_config();
pwm_config_set_clkdiv(&config, 100);
pwm_config_set_wrap(&config, 25000); // 125MHz / (100 * 25000) = 50Hz (período de 20ms)
pwm_init(slice_servo_num, &config, true);
pwm_set_gpio_level(SERVO_PIN, 625); // Posição inicial: 0 graus (~0.5ms de pulso)
// Configuração do LED de Alerta de Temperatura
gpio_init(LED_TEMP_PIN);
gpio_set_dir(LED_TEMP_PIN, GPIO_OUT);
gpio_put(LED_TEMP_PIN, 0);
// Configuração do Buzzer de Alerta de Gás para um tom agudo (~2kHz)
gpio_set_function(BUZZER_GAS_PIN, GPIO_FUNC_PWM);
slice_gas_num = pwm_gpio_to_slice_num(BUZZER_GAS_PIN);
pwm_set_wrap(slice_gas_num, 6250);
pwm_set_clkdiv(slice_gas_num, 10);
pwm_set_chan_level(slice_gas_num, PWM_CHAN_B, 3125); // 50% duty cycle
pwm_set_enabled(slice_gas_num, false);
// Configuração do LED de Baixa Luminosidade
gpio_init(IR_LED_PIN);
gpio_set_dir(IR_LED_PIN, GPIO_OUT);
gpio_put(IR_LED_PIN, 0);
// Configuração do Relé (Alarme Externo de Gás)
gpio_init(RELAY_PIN);
gpio_set_dir(RELAY_PIN, GPIO_OUT);
gpio_put(RELAY_PIN, 0);
}
// =================================================================================
// --- FUNÇÃO PRINCIPAL ---
// =================================================================================
int main() {
// Inicializações padrão
stdio_init_all();
sleep_ms(2000);
init_actuators();
adc_init();
adc_gpio_init(26 + LDR_PIN_ADC);
adc_gpio_init(26 + MQ2_PIN_ADC);
printf("Sistema de Monitoramento\n");
printf("===================================================\n");
printf("Estabilizando sensor de gas... (Aguardando interacao manual no Wokwi)\n");
// Loop de estabilização inteligente para lidar com a peculiaridade do Wokwi
uint16_t initial_gas_value;
do {
adc_select_input(MQ2_PIN_ADC);
initial_gas_value = adc_read();
printf("... Leitura de estabilizacao do gas: %d (aguardando cair abaixo de %d)\n", initial_gas_value, GAS_THRESHOLD);
sleep_ms(1000);
} while (initial_gas_value > GAS_THRESHOLD);
printf(">>> Sensor de gas estabilizado! Sistema Ativo. <<<\n");
printf("==================================================\n");
// Loop principal de operação do sistema
while (1) {
// --- 1. LEITURA DOS SENSORES ---
// REQUISITO: Detectar aumento de temperatura ambiente com o sensor DHT 22;
// REQUISITO TÉCNICO: Leitura do DHT-22
dht_reading dht_result;
read_from_dht(DHT_PIN, &dht_result);
// REQUISITO: Verificar queda de luminosidade com o sensor LDR;
// REQUISITO TÉCNICO: Leitura do LDR em divisor de tensão com ADC;
adc_select_input(LDR_PIN_ADC);
uint16_t ldr_value = adc_read();
// REQUISITO: Identificar presença de gás/fumaça com sensor MQ-2;
// REQUISITO TÉCNICO: Leitura do sensor de gás MQ-2 em sinal analógico;
adc_select_input(MQ2_PIN_ADC);
uint16_t gas_value = adc_read();
// Exibição do status no monitor serial para depuração
if(dht_result.temp_c > -999.0f) {
printf("Temperatura: %.1f C | Luminosidade (ADC): %d | Gas (ADC): %d\n",
dht_result.temp_c, ldr_value, gas_value);
} else {
printf("Falha na leitura do DHT | Luminosidade (ADC): %d | Gas (ADC): %d\n",
ldr_value, gas_value);
}
// --- 2. LÓGICA DE CONTROLE E RESPOSTA DOS ATUADORES ---
// REQUISITO: Responder com atuadores específicos a cada evento monitorado, de forma individual ou combinada.
// REQUISITO: Quando a temperatura ultrapassar 30°C, um alerta físico deve ser ativado.
// (Adaptação: Servo Motor para um alerta mecânico e um LED para um alerta visual)
if (dht_result.temp_c > TEMP_THRESHOLD) {
pwm_set_gpio_level(SERVO_PIN, 1875); // Move servo para 90 graus (~1.5ms de pulso)
gpio_put(LED_TEMP_PIN, 1); // Acende o LED de alerta de temperatura
printf(">>> ALERTA DE TEMPERATURA: Servo e LED ativados.\n");
} else {
pwm_set_gpio_level(SERVO_PIN, 625); // Retorna servo para 0 graus
gpio_put(LED_TEMP_PIN, 0); // Apaga o LED
}
// REQUISITO: Quando a luz ambiente for baixa, um LED infravermelho deve acender.
// (Adaptação: LED comum para simular o alerta visual de baixa luz)
if (ldr_value > LDR_THRESHOLD) {
gpio_put(IR_LED_PIN, 1);
printf(">>> ALERTA DE LUMINOSIDADE: LED ativado.\n");
} else {
gpio_put(IR_LED_PIN, 0);
}
// REQUISITO: Ao detectar gás, um relé deve acionar um dispositivo externo para um alarme.
// (Aprimoramento: O sistema também ativa um buzzer dedicado com tom agudo)
if (gas_value > GAS_THRESHOLD) {
pwm_set_enabled(slice_gas_num, true); // Ativa o alarme sonoro de gás
gpio_put(RELAY_PIN, 1); // Ativa o relé para o alarme visual externo
printf(">>> ALERTA DE GAS: Alarme sonoro e externo ativados.\n");
} else {
pwm_set_enabled(slice_gas_num, false);
gpio_put(RELAY_PIN, 0);
}
printf("----------------------------------------------------\n");
sleep_ms(2000); // Pausa de 2 segundos entre os ciclos
}
return 0;
}