quinta-feira, outubro 30, 2014

Disquetes Musicais: Teste da Placa de Controle

Vejamos aqui alguns primeiros testes da Placa de Controle, que usa um ATtiny2313 para controlar as unidades de disquete e um relê.


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.
  1. #include <inttypes.h>  
  2. #include <avr/io.h>  
  3. #include <avr/interrupt.h>  
  4. #include <avr/sleep.h>  
  5.   
  6. // Bits correspondentes aos pinos de E/S  
  7. #define DDR_RELE    DDRD  
  8. #define PORT_RELE   PORTD  
  9. #define BIT_RELE   _BV(PD5)  
  10.   
  11. // Programa Principal  
  12. int main (void)  
  13. {  
  14.     // Configura os pinos do rele  
  15.     DDR_RELE |= BIT_RELE;  
  16.     PORT_RELE &= ~BIT_RELE;  
  17.       
  18.     // Configura o timer 0  
  19.     TCCR0A = 0;                    // Modo normal: overflow a cada 256 contagens  
  20.     TCCR0B = _BV(CS01) | _BV(CS00);// Usar clkIO/64: int a cada 64*256/16000 ms  
  21.                                    //   = 1,024 ms  
  22.     TIMSK = _BV(TOIE0);            // Interromper no overflow  
  23.   
  24.     // Permite interrupções  
  25.     sei ();  
  26.       
  27.     // Loop infinito  
  28.     for (;;)  
  29.     {  
  30.         set_sleep_mode(SLEEP_MODE_IDLE);  
  31.         sleep_mode();  
  32.     }  
  33. }  
  34.   
  35. // Tratamento da interrupção do timer 0  
  36. ISR (TIMER0_OVF_vect)  
  37. {  
  38.     static uint16_t cntRele = 976;  
  39.   
  40.     if (--cntRele != 0)  
  41.         return;  
  42.     cntRele = 976;  
  43.     PORT_RELE ^= BIT_RELE;  
  44. }  
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:
  1. #include <inttypes.h>  
  2. #include <avr/io.h>  
  3. #include <avr/interrupt.h>  
  4. #include <avr/sleep.h>  
  5.   
  6. // Bits correspondentes aos pinos de E/S  
  7. #define DDR_RELE    DDRD  
  8. #define PORT_RELE   PORTD  
  9. #define BIT_RELE   _BV(PD5)  
  10.   
  11. #define DDR_DISQ    DDRB  
  12. #define PORT_DISQ   PORTB  
  13. #define PIN_DISQ    PINB  
  14.   
  15. #define DIR_A  _BV(PB7)  
  16. #define STEP_A _BV(PB4)  
  17. #define TRK0_A _BV(PB1)  
  18.   
  19. static uint8_t dirA = 1;  
  20. static uint8_t stepA = 1;  
  21. static uint8_t trkA = 79;  
  22.   
  23. // Programa Principal  
  24. int main (void)  
  25. {  
  26.     // Configura os pinos do rele  
  27.     DDR_RELE |= BIT_RELE;  
  28.     PORT_RELE &= ~BIT_RELE;  
  29.       
  30.     // Configura os pinos de controle da unidade de disquete  
  31.     DDR_DISQ |= DIR_A | STEP_A;     // DIR e STEP são saídas  
  32.     DDR_DISQ &= ~TRK0_A;            // TRK0 é entrada  
  33.     PORT_DISQ |= DIR_A | STEP_A;    // DIR e STEP em repouso no nível alto  
  34.     PORT_DISQ &= ~TRK0_A;           // Sem pullup em TRK0  
  35.       
  36.     // Configura o timer 0  
  37.     TCCR0A = 0;                    // Modo normal: overflow a cada 256 contagens  
  38.     TCCR0B = _BV(CS01) | _BV(CS00);// Usar clkIO/64: int a cada 64*256/16000 ms  
  39.                                    //   = 1,024 ms  
  40.     TIMSK = _BV(TOIE0);            // Interromper no overflow  
  41.   
  42.     // Permite interrupções  
  43.     sei ();  
  44.       
  45.     // Loop infinito  
  46.     for (;;)  
  47.     {  
  48.         set_sleep_mode(SLEEP_MODE_IDLE);  
  49.         sleep_mode();  
  50.     }  
  51. }  
  52.   
  53. // Tratamento da interrupção do timer 0  
  54. ISR (TIMER0_OVF_vect)  
  55. {  
  56.     static uint8_t cntDisq = 100;  
  57.   
  58.     if (--cntDisq == 0)     // hora de mover  
  59.     {  
  60.         cntDisq = 100;  
  61.         PORT_DISQ ^= STEP_A;    // pulsa STEP  
  62.         stepA ^= 1;  
  63.         if (stepA == 1)     // andou um passo  
  64.         {  
  65.             if (dirA == 0)  // avançando  
  66.             {  
  67.                 if (++trkA == 79)   // chegou ao fim  
  68.                 {  
  69.                     dirA = 1;  
  70.                     PORT_DISQ |= DIR_A;  
  71.                     PORT_RELE ^= BIT_RELE;  
  72.                 }  
  73.             }  
  74.             else            // recuando  
  75.             {  
  76.                 if ((--trkA == 0) || ((PIN_DISQ & TRK0_A) == 0))  
  77.                 {                   // chegou ao começo  
  78.                     trkA = 0;  
  79.                     dirA = 0;  
  80.                     PORT_DISQ &= ~DIR_A;  
  81.                     PORT_RELE ^= BIT_RELE;  
  82.                 }  
  83.             }  
  84.         }  
  85.     }  
  86. }  
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: