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