/**
Igor Klaus Reichert
202020897
**/
#define __AVR_ATmega2560__
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <util/delay.h>
#include "usart.h"
#include "lcd.h"
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
//Buffers
char load[16];
char buffer[8];
// TEMPERATURA
const float BETA = 3950; // Deve corresponder ao coeficiente beta do termistor
int tempanalogico;
float tempcelsius = 24;
float temp_ar = 20;
uint8_t ar_ligado = 0;
// ILUMINAÇÃO
const float GAMMA = 0.7;
const float RL10 = 50;
int luxanalogico;
float luxtensao;
float luxresistencia;
float lux;
// LEITURA BOTAO
uint8_t primeira_leitura = 0; // Variável para verificação de mudança de estado
uint8_t segunda_leitura = 0; // Variável para verificação de mudança de estado
uint8_t botao_up = 0;
uint8_t botao_down = 0;
uint8_t botao_fan = 0;
// VELOCIDADE E DISTANCIA
uint8_t dist_primeira_leitura = 0; // Variável para verificação de mudança de estado
uint8_t dist_segunda_leitura = 0; // Variável para verificação de mudança de estado
volatile uint16_t contador_pulsos = 0; // Variável para contar pulsos
double roda = 2 * 3.1415 * 0.3;
double distancia_total = 0;
int16_t pulsos_no_segundo;
float velocidade_atual = 0;
double distancia = 0;
volatile uint16_t tick = 0;
long kmh;
// =========================================================================================
void ADC_configura(void)
{
ADCSRA = 0x87; // ADEN=1 ADSC=0 ADATE=0 ADIE=0 ADIF=0 ADPS[2:0]=111
ADCSRB = 0x00; // bit[7]=reservado=0 ACME=0 bits[5:4]=reservado=0 MUX[5]=0 ADTS[2:0]=000
ADMUX = 0x45; // REFS[1:0]=01 ADLAR=0 MUX[4:0]=00101
}
uint16_t ADC_medida(uint8_t entrada) {
ADMUX = (ADMUX & 0xF0) | (entrada & 0x0F); // Configura a entrada
ADCSRA |= (1 << ADSC); // Faz a conversão
while (ADCSRA & (1 << ADSC)); // Aguarda a conversão ser concluída
return ADC;
}
// =========================================================================================
void leitura_botao_up(void) {
_delay_ms(15);
segunda_leitura = primeira_leitura; // Atualiza a segunda leitura com o valor da primeira
primeira_leitura = (PINC & (1 << PINC6)); // Atualizada a leitura do botão
if (!primeira_leitura && segunda_leitura) { //verifica se a chave foi pressionada "houve transição de nível?"
botao_up = 1;
}
}
void leitura_botao_down(void) {
_delay_ms(15);
segunda_leitura = primeira_leitura; // Atualiza a segunda leitura com o valor da primeira
primeira_leitura = (PINC & (1 << PINC2)); // Atualizada a leitura do botão
if (!primeira_leitura && segunda_leitura) { //verifica se a chave foi pressionada "houve transição de nível?"
botao_down = 1;
}
}
void leitura_botao_fan(void) {
_delay_ms(15);
segunda_leitura = primeira_leitura; // Atualiza a segunda leitura com o valor da primeira
primeira_leitura = (PINC & (1 << PINC0)); // Atualizada a leitura do botão
if (!primeira_leitura && segunda_leitura) { //verifica se a chave foi pressionada "houve transição de nível?"
while (!primeira_leitura) {
primeira_leitura = (PINC & (1 << PINC0)); // Atualizada a leitura do botão
}
botao_fan = 1;
}
}
// =========================================================================================
// CONFIGURAÇÃO MEDIÇÃO DISTANCIA E VELOCIDADE
void medicao_dist_pulse(void) {
_delay_ms(10);
dist_segunda_leitura = dist_primeira_leitura; // Atualiza a segunda leitura com o valor da primeira
dist_primeira_leitura = (PIND & (1 << PIND3)); // Atualizada a leitura do botão
if (dist_primeira_leitura && !dist_segunda_leitura) {
// Detectou o pressionamento do botão
// Aguarde até que o botão seja liberado
while (dist_primeira_leitura) {
dist_primeira_leitura = (PIND & (1 << PIND3)); // Atualizada a leitura do botão
}
contador_pulsos++;
}
}
ISR(TIMER0_COMPA_vect)
{
tick++; // variável tick é incrementada a cada 1 ms
if (tick == 1000) // se transcorreu 1000 ms = 1 s
{
PORTB = PORTB ^ (1 << PORTB7);
pulsos_no_segundo = contador_pulsos;
contador_pulsos = 0;
tick = 0; // começamos um novo intervalo de 1 s
transmissao_usart(); // transmite os dados na usart
}
}
void configura_sistema(void)
{
/* configura o timer0 para gerar interrupções a cada 1 ms e executar a rotina
de interrupção TIMER0_COMPA_vect */
TCCR0A = 0x02; // saídas OC0A e OC0B como portas normais. COM0A[1:0]=00 COM0B[1:0]=00 WGM0[2:0]=010
TCCR0B = 0x03; // dividimos a frequência de relógio por 64. FOC0A = 0 FOC0B = 0 WGM0[2:0]=010 CS0[2:0] = 011
TIMSK0 = 0x02; // interrupções ocorrem no overflow do contador. OCIE0B = 0 OCIE0A = 1 TOIE0 = 0
OCR0A = 0xF9; // valor de TOP = 249 = 0xF9
TCNT0 = 0x00; // zeramos o contador
// Configura PB7 como um terminal de saída. Este terminal é ligado a um LED
DDRB = DDRB | (1 << DDB7); // faz o terminal TERMINAL_LED uma saída
PORTB = PORTB & (~(1 << PORTB7)); // envia o valor 0 para o terminal TERMINAL_LED
// LED pisca a fins de teste
}
// =========================================================================================
// CONFIGURAÇÃO TRANSMISSAO USART
void transmissao_usart(void) {
dtostrf(lux, 6, 0, load);
USART0_transmite_string_FLASH(PSTR("Luminosidade: "));
USART0_transmite_string_RAM(load);
USART0_transmite_string_FLASH(PSTR(" lux. \n"));
if (lux < 400) {
USART0_transmite_string_FLASH(PSTR("FAROL LIGADO!!"));
} else {
USART0_transmite_string_FLASH(PSTR("FAROL DESLIGADO!!"));
}
USART0_transmite_string_FLASH(PSTR("\nDistância percorrida: "));
dtostrf(distancia_total, 3, 3, load);
USART0_transmite_string_RAM(load);
USART0_transmite_string_FLASH(PSTR(" km \nVelocidade atual:"));
dtostrf(kmh, 3, 2, load);
USART0_transmite_string_RAM(load);
USART0_transmite_string_FLASH(PSTR(" km/h \nAr condicionado: "));
if (ar_ligado) {
USART0_transmite_string_FLASH(PSTR("LIGADO"));
USART0_transmite_string_FLASH(PSTR("\nTemperatura do ar condicionado: "));
dtostrf(temp_ar, 3, 1, load);
USART0_transmite_string_RAM(load);
USART0_transmite_string_FLASH(PSTR(" celsius"));
} else {
USART0_transmite_string_FLASH(PSTR("DESLIGADO"));
}
USART0_transmite_string_FLASH(PSTR("\nTemperatura interna: "));
dtostrf(tempcelsius, 3, 1, load);
USART0_transmite_string_RAM(load);
USART0_transmite_string_FLASH(PSTR(" celsius\n\n"));
}
void config_registradores(void) {
// ILUMINAÇÃO
DDRC = DDRC | (1 << DDC4); // Seta PL6 como saída - farol
// AR CONDICIONADO
DDRC = DDRC & (~(1 << DDC6)); // Seta PC6 como entrada - Botão
PORTC = PORTC | (1 << PORTC6); // Seta Pull-up em PC6
DDRC = DDRC & (~(1 << DDC2)); // Seta PC2 como entrada - Botão
PORTC = PORTC | (1 << PORTC2); // Seta Pull-up em PC2
DDRC = DDRC & (~(1 << DDC0)); // Seta PC0 como entrada - Botão
PORTC = PORTC | (1 << PORTC0); // Seta Pull-up em PC0
// VELOCIDADE
DDRD = DDRD & ~(1 << DDD3); // Configura PD3 como entrada (0)
PORTD = PORTD & ~(1 << PORTD3); // Configura um resistor pull-down (0)
}
// =========================================================================================
int main()
{
configura_sistema(); //configuramos as interrupções
LCD_Init(); // incia o LCD
ADC_configura(); // Configuramos o conversor AD
sei(); // habilita as interrupções globalmente
USART0_configura(); // configuramos a USART0
config_registradores(); //configuramos os registradores
while (1)
{
// SENSOR DE TEMPERATURA
tempanalogico = ADC_medida(0);
//tempcelsius = 1 / (log(1 / (1023. / tempanalogico - 1)) / BETA + 1.0 / 298.15) - 273.15;
tempcelsius = tempanalogico;
LCD_gotoxy(1, 10);
LCD_string("Ti:");
dtostrf(tempcelsius, 0, 0, buffer);
LCD_string(buffer);
LCD_string("C");
// SENSOR DE ILUMINAÇÃO
luxanalogico = ADC_medida(1);
luxtensao = luxanalogico / 1024. * 5;
luxresistencia = 2000 * luxtensao / (1 - luxtensao / 5);
lux = pow(RL10 * 1e3 * pow(10, GAMMA) / luxresistencia, (1 / GAMMA));
if (lux < 400) {
LCD_gotoxy(0, 6);
LCD_string("ON ");
PORTC |= (1 << PORTC4);
}
else {
LCD_gotoxy(0, 6);
LCD_string("OFF");
PORTC &= ~(1 << PORTC4);
}
//CONTROLE DO AR CONDICIONADO
leitura_botao_up();
leitura_botao_down();
leitura_botao_fan();
if (botao_fan & !ar_ligado) {
ar_ligado = 1;
botao_fan = 0;
} else if (botao_fan && ar_ligado) {
ar_ligado = 0;
botao_fan = 0;
}
if (ar_ligado) {
LCD_gotoxy(0, 10);
LCD_string("AC:");
dtostrf(temp_ar, 0, 0, buffer);
LCD_string(buffer);
LCD_string("C ");
if (botao_up) {
temp_ar += 1;
botao_up = 0;
} else if (botao_down) {
temp_ar -= 1;
botao_down = 0;
}
} else if (!ar_ligado) {
LCD_gotoxy(0, 10);
LCD_string(" ");
}
// VELOCIDADE E DISTANCIA
medicao_dist_pulse();
distancia = (roda * pulsos_no_segundo / 1000.0);
distancia_total += distancia;
LCD_gotoxy(0, 0);
dtostrf(distancia_total, 1, 1, buffer);
LCD_string(buffer);
LCD_gotoxy(0, 3);
LCD_string("km");
kmh = roda * pulsos_no_segundo * 3.6;
LCD_gotoxy(1, 0);
dtostrf(kmh, 3, 1, buffer);
LCD_string(buffer);
LCD_gotoxy(1, 5);
LCD_string("km/h");
}
}