/**
Igor Klaus Reichert
*/
#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
// =========================================================================================
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;
}
// =========================================================================================
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;
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?"
botao_fan = 1;
}
}
// =========================================================================================
// CONFIGURAÇÃO MEDIÇÃO DISTANCIA E VELOCIDADE
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
float roda = 2 * 3.1415 * 0.3;
float distancia_total = 0;
int16_t pulsos_no_segundo;
float velocidade_atual = 0;
float distancia = 0;
uint8_t tick = 0;
void medicao_dist_pulse(void) {
_delay_ms(10);
dist_segunda_leitura = 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
}
// Agora, o botão foi liberado
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
}
}
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
sei(); // habilita as interrupções globalmente
// 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
}
// =========================================================================================
int main()
{
configura_sistema();
char buffer[8];
LCD_Init(); /* Inicialização do LCD */
ADC_configura(); // Configuramos o conversor AD
sei(); // habilita as interrupções globalmente
// TEMPERATURA
const float BETA = 3950; // Deve corresponder ao coeficiente beta do termistor
int tempanalogico;
float tempcelsius = 24;
// ILUMINAÇÃO
const float GAMMA = 0.7;
const float RL10 = 50;
int luxanalogico;
float luxtensao;
float luxresistencia;
float lux;
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
float temp_ar = 20;
uint8_t ar_ligado = 0;
// VELOCIDADE
DDRD = DDRD & (~(1 << DDD3)); // Seta PC0 como entrada - Botão
PORTD = PORTD | (1 << PORTD3); // Configura um resistor de pull-UP em PC0
int pulsos = 10;
while (1)
{
// SENSOR DE TEMPERATURA
tempanalogico = ADC_medida(0);
tempcelsius = 1 / (log(1 / (1023. / tempanalogico - 1)) / BETA + 1.0 / 298.15) - 273.15;
LCD_gotoxy(0, 0);
LCD_string("Ti:");
dtostrf(tempcelsius, 0, 1, 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 < 100) {
LCD_gotoxy(1, 0);
LCD_string("ON ");
PORTC |= (1 << PORTC4);
}
else {
LCD_gotoxy(1, 0);
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, 8);
LCD_string("Ta:");
dtostrf(temp_ar, 0, 1, buffer);
LCD_string(buffer);
LCD_string("C ");
if (botao_up) {
temp_ar += 0.5;
botao_up = 0;
}
else if (botao_down) {
temp_ar -= 0.5;
botao_down = 0;
}
} else if (ar_ligado == 0) {
LCD_gotoxy(0, 8);
LCD_string(" ");
}
// VELOCIDADE E DISTANCIA
medicao_dist_pulse();
distancia = (roda * pulsos_no_segundo / 1000.0);
distancia_total += distancia;
LCD_gotoxy(1, 4);
dtostrf(distancia_total, 1, 1, buffer);
LCD_string(buffer);
LCD_string("km");
dtostrf(contador_pulsos, 1, 1, buffer);
LCD_string(buffer);
}
}