Hardware
O hardware continua sendo composto por um sensor de Efeito Hall, LEDs e um microcontrolador. A grande alteração no circuito é a troca do MSP430 por um ATtiny44. O principal motivo é ter as ferramentas (compilador e gravador) mais disponíveis.
O modelo do sensor é o A1120 (que vimos aqui). Além de permitir trabalhar com 3V (no caso com uma bateria do tipo "moeda" CR2032), este sensor tem uma saída digital (o que permitiria usar o ATtiny2313, ligeiramente mais barato e capaz de acionar mais LEDs, mas sem ADC). A saída do sensor é do tipo "open drain", o que requer um resistor de pullup; usei o pullup interno do ATtiny.
O circuito (incluindo um conector para programação) fica assim:
A montagem foi feita em uma placa padrão, infelizmente o pouco espaçamento entre os LEDs impediu alinhá-los bem (o que não é problema quando a roda está girando).
Software
Para este projeto eu decidi fazer um software bem simples. A lógica toda é feita no loop principal, as interrupções não são nem habilitadas. Toda vez que o sensor é detectado é lido o valor do Timer1, que em seguida é zerado. Desta forma temos uma medição do tempo para a roda dar uma volta. Este tempo é dividido por 16, criando assim 16 setores. O início de cada setor é determinado olhando o valor do Timer1; para cada setor é programado um padrão nos LEDs conforme uma tabela. Se o tempo de uma volta ultrapassa o que pode ser medido pelo Timer1 os LEDs ficam apagados.
O software fica assim:
#include <stdio.h> #include <stdlib.h> #include <inttypes.h> #include <avr/io.h> #include <avr/interrupt.h> // Conexões do hardware #define SENSOR _BV(PB0) #define LED_VD _BV(PB1) // Variaveis static const uint8_t imagem[16] = { 0x80, 0xC1, 0x82, 0xC3, 0x84, 0xC5, 0x86, 0xC7, 0x88, 0xC9, 0x8A, 0xCB, 0x8C, 0xFD, 0x8E, 0x00 }; // Rotinas static void initHw (void); // Programa principal int main(void) { uint8_t fOvf = 1; uint8_t fSensor = 0; uint16_t tempo = 0; uint16_t prox = 0; uint16_t passo = 0; uint8_t setor = 0; // Inicia o hardware initHw (); // Eterno enquanto dure for (;;) { // Trata o sensor if (fSensor) { // já detectou o sensor, aguardando desligar fSensor = (PINB & SENSOR) == 0; if (!fSensor) PORTB &= ~LED_VD; // apaga LED verde } else if ((PINB & SENSOR) == 0) { // Detectou sensor if (fOvf == 0) { // funcionamento normal tempo = TCNT1; // registra o tempo da volta PORTA = imagem [0]; // LEDs para o primeiro setor passo = tempo >> 4; // divide a volta em 16 setores prox = passo; setor = 1; } else { // ultrapassou o tempo máximo fOvf = 0; // limpa o flag, vamos tentar de novo } TCNT1 = 0; // reinicia a contagem de tempo fSensor = 1; // lembra que detectou o sensor PORTB |= LED_VD; // indica detecção } // Testa overflow do timer if (TIFR1 & _BV(TOV1)) { fOvf = 1; // ultrapassou o tempo máximo PORTA = 0; // apaga os LEDs tempo = 0; // não atualizar os LEDs TIFR1 |= _BV(TOV1); // limpa o aviso do timer } // Atualiza os LEDs if (tempo != 0) { if (TCNT1 >= prox) { PORTA = imagem [setor++]; // passa para o setor seguinte prox += passo; if (setor == 16) tempo = 0; // acabaram os setores } } } } // Inicia o hardware static void initHw (void) { // Port A são os LEDs DDRA = 0xFF; // tudo saida PORTA = 0; // LEDs apagados // PORT B tem o sensor e o LED verde DDRB &= ~SENSOR; // sensor é entrada DDRB |= LED_VD; // LED é saida PORTB = SENSOR; // com pullup // Timer 1 // Modo normal, clock/1024 TCCR1A = 0; TCCR1B = _BV(CS12) | _BV(CS10); TCCR1C = 0; }O vídeo abaixo é um pequeno teste.
Nenhum comentário:
Postar um comentário