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;
- }
Nenhum comentário:
Postar um comentário