Carregando Firmware na Placa
Um dos meus cuidados no projeto da placa foi garantir que todos os sinais necessários para a carga de firmware estivessem acessíveis no conector. O primeiro passo, portanto, foi fazer um cabo para ligação do meu ISBtinyISP (na verdade, qualquer carregador que tenha o conector padrão de 6 pinos):
Com o cabo feito, podemos fazer um teste rápido com o avrdude, confirmando que o ATtiny é reconhecido.
Felicidade é um Relé Pulsando
Para alimentar a placa e conectar as unidades é preciso um outro cabo:
O meu primeiro firmware é o equivalente a um LED piscando: um relé pulsando.
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
// Bits correspondentes aos pinos de E/S
#define DDR_RELE DDRD
#define PORT_RELE PORTD
#define BIT_RELE _BV(PD5)
// Programa Principal
int main (void)
{
// Configura os pinos do rele
DDR_RELE |= BIT_RELE;
PORT_RELE &= ~BIT_RELE;
// Configura o timer 0
TCCR0A = 0; // Modo normal: overflow a cada 256 contagens
TCCR0B = _BV(CS01) | _BV(CS00);// Usar clkIO/64: int a cada 64*256/16000 ms
// = 1,024 ms
TIMSK = _BV(TOIE0); // Interromper no overflow
// Permite interrupções
sei ();
// Loop infinito
for (;;)
{
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_mode();
}
}
// Tratamento da interrupção do timer 0
ISR (TIMER0_OVF_vect)
{
static uint16_t cntRele = 976;
if (--cntRele != 0)
return;
cntRele = 976;
PORT_RELE ^= BIT_RELE;
}
O vídeo abaixo mostra o resultado:Movendo a Cabeça
O segundo firmware testa os sinais de controle da unidade de disquete. O relê é usado para indicar quando ocorre a mudança de posição:
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
// Bits correspondentes aos pinos de E/S
#define DDR_RELE DDRD
#define PORT_RELE PORTD
#define BIT_RELE _BV(PD5)
#define DDR_DISQ DDRB
#define PORT_DISQ PORTB
#define PIN_DISQ PINB
#define DIR_A _BV(PB7)
#define STEP_A _BV(PB4)
#define TRK0_A _BV(PB1)
static uint8_t dirA = 1;
static uint8_t stepA = 1;
static uint8_t trkA = 79;
// Programa Principal
int main (void)
{
// Configura os pinos do rele
DDR_RELE |= BIT_RELE;
PORT_RELE &= ~BIT_RELE;
// Configura os pinos de controle da unidade de disquete
DDR_DISQ |= DIR_A | STEP_A; // DIR e STEP são saídas
DDR_DISQ &= ~TRK0_A; // TRK0 é entrada
PORT_DISQ |= DIR_A | STEP_A; // DIR e STEP em repouso no nível alto
PORT_DISQ &= ~TRK0_A; // Sem pullup em TRK0
// Configura o timer 0
TCCR0A = 0; // Modo normal: overflow a cada 256 contagens
TCCR0B = _BV(CS01) | _BV(CS00);// Usar clkIO/64: int a cada 64*256/16000 ms
// = 1,024 ms
TIMSK = _BV(TOIE0); // Interromper no overflow
// Permite interrupções
sei ();
// Loop infinito
for (;;)
{
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_mode();
}
}
// Tratamento da interrupção do timer 0
ISR (TIMER0_OVF_vect)
{
static uint8_t cntDisq = 100;
if (--cntDisq == 0) // hora de mover
{
cntDisq = 100;
PORT_DISQ ^= STEP_A; // pulsa STEP
stepA ^= 1;
if (stepA == 1) // andou um passo
{
if (dirA == 0) // avançando
{
if (++trkA == 79) // chegou ao fim
{
dirA = 1;
PORT_DISQ |= DIR_A;
PORT_RELE ^= BIT_RELE;
}
}
else // recuando
{
if ((--trkA == 0) || ((PIN_DISQ & TRK0_A) == 0))
{ // chegou ao começo
trkA = 0;
dirA = 0;
PORT_DISQ &= ~DIR_A;
PORT_RELE ^= BIT_RELE;
}
}
}
}
}
O vídeo abaixo mostra o resultado:Ok, temos uma placa de controle funcionando! Agora é preciso fazer o firmware de controle e fazer o software que envia os comandos a partir do arquivo MIDI.




Nenhum comentário:
Postar um comentário