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