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.
#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: