// Define a frequência do clock para 16MHz
#define F_CPU 16000000UL
// Inclui as bibliotecas necessárias
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "lib_serial.h"
#include "lib_lcd.h"
#include <stdio.h>
#include "lib_dht22.h"
// Variável para controlar o estado do buzzer
char buzzerAtivo = 0; // 0 = desativado, 1 = ativado
// Frequência do som em Hz
#define SOUND_FREQUENCY 4500
// Pino do buzzer
#define BUZZER_PIN PORTB5
// Função para atualizar o estado dos LEDs de acordo com as zonas ativas
void atualizarLEDs() {
if (PINB & ((1 << PINB0) | (1 << PINB1))) {
PORTC |= (1 << PORTC4); // Ligar o LED A
LCD_PrintXY(0, 0, "Z:A ON ");
}
if (PINB & ((1 << PINB2) | (1 << PINB3))) {
PORTB |= (1 << PORTB4); // Ligar o LED B
LCD_PrintXY(0, 1, "Z:B ON ");
}
}
// controle do buzzer para o sensor de temperatura
void controlarTemperatura(int16_t temp) {
if (temp > 300) { // 300 representa 30 graus em décimos de grau Celsius
// Calcula o número de ciclos para a frequência desejada
unsigned int cycles = F_CPU / (SOUND_FREQUENCY * 4);
// Mantém o som ativado enquanto a temperatura for maior que 30 graus
while (temp >= 300) {
// Ciclo para criar um som de "alarme" com frequência
for (int i = 0; i < 5; i++) {
// Liga o pino do buzzer para metade do ciclo
PORTB |= (1 << BUZZER_PIN);
_delay_us(cycles);
// Desliga o pino do buzzer para a outra metade do ciclo
PORTB &= ~(1 << BUZZER_PIN);
_delay_us(cycles);
}
// Aguarde um curto período entre os ciclos
_delay_ms(1);
// Releia a temperatura para verificar se ela ainda está acima de 30 graus
if (DHT_Ler(&temp, NULL) == -1) {
break;
}
}
} else {
// Desliga o som do buzzer se a temperatura estiver abaixo de 30 graus
PORTB &= ~(1 << BUZZER_PIN);
}
}
// funçao para controle do buzzer
void controlebuzzer(){
// Configura o pino do buzzer como saída
DDRB |= (1 << BUZZER_PIN);
// Calcula o número de ciclos para a frequência desejada
unsigned int cycles = F_CPU / (SOUND_FREQUENCY * 2);
// Mantém o som ativado indefinidamente
if (buzzerAtivo) {
// Ciclo para criar um som de "alarme" com frequência
for (int i = 0; i < 5; i++) {
// Liga o pino do buzzer para metade do ciclo
PORTB |= (1 << BUZZER_PIN);
_delay_us(cycles );
// Desliga o pino do buzzer para a outra metade do ciclo
PORTB &= ~(1 << BUZZER_PIN);
_delay_us(cycles );
}
}
}
int main(void) {
int16_t temp = 0;
int16_t umid = 0;
// inicia as comunicaçoes serial, e do lcd
LCD_Init();
USART_Init();
// Configura o pino PB5 como saída para controlar o buzzer
DDRB |= (1 << DDB5);
// Configura os pinos do botões
DDRC &= ~(1 << DDC5);
DDRC &= ~(1 << DDC3);
DDRC &= ~(1 << DDC2);
// Configura os pinos PB4 e PC4 como saídas para controlar os LEDs
DDRB |= (1 << DDB4);
DDRC |= (1 << DDC4);
// Configura os pinos dos sensores no PortB (PB0, PB1, PB2, PB3) como entradas
DDRB &= ~((1 << DDB0) | (1 << DDB1) | (1 << DDB2) | (1 << DDB3));
// Habilita interrupções de mudança de nível no PortB
PCICR |= (1 << PCIE0);
// Configura quais pinos específicos (PB0, PB1, PB2, PB3) vão gerar interrupções de mudança
PCMSK0 |= ((1 << PCINT0) | (1 << PCINT1) | (1 << PCINT2) | (1 << PCINT3));
// Habilita interrupções globais
SREG |= (1 << SREG_I);
// variavel do estado anterior do botão
char estado_anterior_alarme = 0;
char estado_anterior_zona_a = 0;
char estado_anterior_zona_b = 0;
while(1) {
char botao_alarme = PINC & (1 << PINC5);
char botao_zona_a = PINC & (1 << PINC3);
char botao_zona_b = PINC & (1 << PINC2);
{
// controle para ativação e dasativação da zona.
if(botao_zona_a && !estado_anterior_zona_a){
PORTC &= ~(1 << PORTC4);
LCD_PrintXY(0, 0, "Z:A OFF ");
}
//atualiza o estado anterior
estado_anterior_zona_a = botao_zona_a;
if(botao_zona_b && !estado_anterior_zona_b){
PORTB &= ~(1 << PORTB4);
LCD_PrintXY(0, 1, "Z:B OFF ");
}
//atualiza o estado anterior
estado_anterior_zona_b = botao_zona_b;
}
{
// controle para desativaçao do alarme
if (botao_alarme && !estado_anterior_alarme ) {
// Desliga o buzzer quando o botão é pressionado
buzzerAtivo = 0;
LCD_PrintXY(8, 0, "A: OFF ");
}
//atualiza o estado anterior
estado_anterior_alarme = botao_alarme;
}
// controle do buzzer
controlebuzzer();
// Verifica a temperatura
controlarTemperatura(temp);
if (DHT_Ler(&temp, &umid) != -1) {
LCD_PrintXY(9, 1, "T:");
char str_valor[10];
if (temp & 0x8000) { // Verifica se o bit de sinal está definido
temp = temp & 0x7FFF; // Limpa o bit de sinal
sprintf(str_valor, "-%d.%d", temp / 10, temp % 10); // Para DHT22, a temperatura é de 16 bits com uma casa decimal
} else {
sprintf(str_valor, "%d.%d", temp / 10, temp % 10); // Para DHT22, a temperatura é de 16 bits com uma casa decimal
}
LCD_Print(str_valor);
sprintf(str_valor, "%c", 0b11011111);
LCD_Print(str_valor);
LCD_Print("C");
}
else {
LCD_Clear();
LCD_PrintXY(0, 1, "DHT22: Erro!");
}
}
}
// Implementação da ISR (Rotina de Interrupção)
ISR(PCINT0_vect) {
atualizarLEDs();
// Verifica se pelo menos um dos sensores está ativo
if (PINB & (1 << PINB0) || PINB & (1 << PINB1) || PINB & (1 << PINB2) || PINB & (1 << PINB3)) {
buzzerAtivo = 1; // Ativa o buzzer
}
if (PINB & (1 << PINB0)) {
LCD_PrintXY(8, 0, "A: 1 ON ");
USART_Tx_String("alame 1 disparado\r\n");
}
if (PINB & (1 << PINB1)) {
LCD_PrintXY(8, 0, "A: 2 ON ");
USART_Tx_String("alame 2 disparado\r\n");
}
if (PINB & (1 << PINB2)) {
LCD_PrintXY(8, 0, "A: 3 ON ");
USART_Tx_String("alame 3 disparado\r\n");
}
if (PINB & (1 << PINB3)) {
LCD_PrintXY(8, 0, "A: 4 ON ");
USART_Tx_String("alame 4 disparado\r\n");
}
}