#define __ATmega2560__
#define __AVR_ATmega2560__
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <stdint.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdbool.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <math.h> // Inclua math.h para usar a função pow
#include "usart.h"
#include "lcd.h"
#define PI 3.14159
#define BETA 3950 // do sensor de temperatura
#define GAMMA 0.7 // do photoresistor
#define RL10 50 // photoresistor
#define THRESHOLD 853 // crepúsculo
#define FAROL PD7 // faróis
#define R 16 // Diâmetro do pneu em polegadas
#define MAX_VELOCIDADE 200.0 // Velocidade máxima permitida em km/h
#define SENSOR_RODA PINJ
#define MASCARA_SENSOR (1 << PINJ1)
#define recirculacao_sinal PD3
#define recirculacao_led PC1
volatile uint32_t tick;
volatile uint16_t timer, espera;
volatile float velocidade, speed;
volatile float distancia = 0;
volatile float comprimento = 2 * PI / 8 * (0.0254 * R / 2);
uint8_t recirculando = 0;
const int ac_max = 30;
const int ac_min = 17;
int ar_condicionado = 23;
// ISR para interrupção de mudança de pino
ISR(PCINT1_vect) {
if (!(SENSOR_RODA & MASCARA_SENSOR)) {
velocidade = comprimento * 1000000 / (tick * 512 + OCR1A * 0.5); // divide a distância pelo tempo (tick = 4096us e OCR1A = 4us)
velocidade = velocidade * 3.6; // transforma m/s para km/h
if (velocidade > MAX_VELOCIDADE) { // Limita a velocidade ao valor máximo permitido
velocidade = MAX_VELOCIDADE;
}
tick = 0; // zera a variável que mede o tempo
TCNT1 = 0x00; // zera o contador que mede o tempo
distancia += comprimento;
}
}
// Função para configurar o Timer1
void timer1_config(void) {
TCCR1A = 0; // Timer mode with no output
TCCR1B = (1 << CS11) | (1 << CS10); // Prescaler 64
TCNT1 = 0; // Initialize counter
TIMSK1 = (1 << TOIE1); // Enable overflow interrupt
}
// Função para configurar a interrupção externa
void external_interrupt_config(void) {
DDRD &= ~(1 << recirculacao_sinal); // Configura PD3 como entrada
PORTD |= (1 << recirculacao_sinal); // Habilita pull-up em PD3
EICRA |= (1 << ISC11); // Configura interrupção para borda de descida no INT1
EIMSK |= (1 << INT1); // Habilita interrupção externa INT1
EICRA |= (1 << ISC31); // Configura interrupção para borda de descida no INT3
EIMSK |= (1 << INT3); // Habilita interrupção externa INT3
}
// ISR para o Timer1 overflow
ISR(TIMER1_OVF_vect) {
tick++;
}
// ISR para o botão de recirculação
ISR(INT3_vect) {
recirculando = !recirculando;
if (recirculando) {
PORTC ^= (1 << recirculacao_led); // Comuta
}
}
// Função para transmitir uma string pela USART
void transmiteString(const char *str) {
while (*str) {
USART0_transmite(*str); // Transmite um caractere
str++;
}
}
// Função para transmitir um número pela USART
void transmiteNum(int num) {
char buffer[16]; // Buffer para converter o número para string
sprintf(buffer, "%d", num); // Converte o número para string
transmiteString(buffer); // Usa transmiteString para enviar
}
// Função para inicializar o ADC
void adc_config(void) {
// Selecionar a referência de tensão(5V) para AVCC com um capacitor em AREF
ADMUX = (1 << REFS0);
// Configurar a prescaler para 128 para uma taxa de amostragem de 125 kHz com um clock de 16 MHz
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
}
// Função para ler o canal ADC especificado
uint16_t ler_adc(uint8_t canal) {
// Certifique-se de que o canal está entre 0 e 7
if (canal > 7) {
return 0;
}
// Configurar o canal (limpando bits de canal, então definindo o canal desejado)
ADMUX = (ADMUX & 0xF0) | (canal & 0x07);
// Iniciar a conversão
ADCSRA |= (1 << ADSC);
// Esperar a conversão terminar (ADSC será limpo após a conclusão)
while (ADCSRA & (1 << ADSC));
// Retornar o valor convertido
return ADCW; // ADCW é o valor de 16 bits da conversão
}
void setup(void) {
adc_config(); // Configura o ADC para leitura do valor analógico
USART0_configura(); // Configura a USART para comunicação serial
DDRD |= (1 << FAROL); // Configura o pino do LED/luz como saída
LCD_Init(); // Inicializa o LCD
timer1_config(); // Configura o Timer1
external_interrupt_config(); // Configura a interrupção externa
sei(); // Habilita interrupções globais
// Configurações para a recirculação
DDRC |= (1 << recirculacao_led); // Configura o pino do LED de recirculação como saída
}
int main(void) {
setup();
char buffer[16];
while (1) {
sei(); // Certifique-se de que as interrupções estão habilitadas
// Lendo o sensor de temperatura externa
uint16_t valor_temperatura_externa = ler_adc(1);
float temperatura_ex = 1 / (log(1 / (1023.0 / valor_temperatura_externa - 1)) / BETA + 1.0 / 298.15) - 273.15;
transmiteString("A temperatura externa é: ");
transmiteNum((int)temperatura_ex);
transmiteString("°C\n");
LCD_gotoxy(0, 0);
LCD_string("T. Ext: ");
dtostrf(temperatura_ex, 4, 1, buffer);
LCD_string(buffer);
LCD_string(" C");
// Lendo o sensor de temperatura interna
uint16_t valor_temperatura_interna = ler_adc(5);
float temperatura_in = 1 / (log(1 / (1023.0 / valor_temperatura_interna - 1)) / BETA + 1.0 / 298.15) - 273.15;
transmiteString("A temperatura interna é: ");
transmiteNum((int)temperatura_in);
transmiteString("°C\n");
LCD_gotoxy(1, 0);
LCD_string("T. Int: ");
dtostrf(temperatura_in, 4, 1, buffer);
LCD_string(buffer);
LCD_string(" C");
// Lendo a temperatura na saída do ar condicionado
uint16_t valor_temperatura_arcond = ler_adc(7);
float temperatura_arcond = 1 / (log(1 / (1023.0 / valor_temperatura_arcond - 1)) / BETA + 1.0 / 298.15) - 273.15;
transmiteString("A temperatura na saída do ar condicionado é: ");
transmiteNum((int)temperatura_arcond);
transmiteString("°C\n");
_delay_ms(2000); // Delay para exibir os valores no LCD
LCD_Clear();
LCD_gotoxy(0, 0);
LCD_string("AC Temp: ");
dtostrf(temperatura_arcond, 4, 1, buffer);
LCD_string(buffer);
LCD_string(" C");
// Lendo o fotoresistor
uint16_t valor_luminosidade = ler_adc(3); // Leitura do pino A2
float v_luz = (float)valor_luminosidade / 1023;
float luminosidade = 500 * pow(v_luz, GAMMA) * RL10;
transmiteString("Luminosidade: ");
transmiteNum((int)luminosidade);
transmiteString(" Lux\n");
LCD_gotoxy(1, 0);
LCD_string("Lum: ");
dtostrf(luminosidade, 4, 1, buffer);
LCD_string(buffer);
LCD_string(" Lux");
if (luminosidade < THRESHOLD) {
PORTD |= (1 << FAROL); // Liga o farol
} else {
PORTD &= ~(1 << FAROL); // Desliga o farol
}
_delay_ms(2000); // Delay para exibir os valores no LCD
LCD_Clear();
LCD_gotoxy(0, 0);
LCD_string("AC Set: ");
itoa(ar_condicionado, buffer, 10);
LCD_string(buffer);
LCD_string(" C");
// Exibir a velocidade no LCD
LCD_Clear();
LCD_gotoxy(0, 0);
LCD_string("Velocidade: ");
dtostrf(velocidade, 4, 1, buffer);
LCD_string(buffer);
LCD_string(" km/h");
// Exibir a distância percorrida no LCD
LCD_gotoxy(1, 0);
LCD_string("Distancia: ");
dtostrf(distancia, 4, 2, buffer);
LCD_string(buffer);
LCD_string(" km");
_delay_ms(1000); // Atualiza a cada segundo
}
return 0;
}