Como visto na parte 1, optei pelo microcontrolador MSP430G2231. O desenvolvimento foi feito com o IAR Kickstart. Para gravar o software na Flash do MSP430 usei a Launchpad.
O programa principal consiste em parar o watchdog (que é ativado automaticamente após um reset), programar as entradas e saídas digitais (pinos não usados são programados como saída para reduzir o consumo), ativar o clock auxiliar (ACLK) de 32KHz dividido por 8 (o que inclui selecionar os capacitores apropriados), programar o Timer A (mais sobre isto adiante) e colocar o microcontrolador no modo LPM3
- #define POT BIT0
- #define LED BIT2
- #define DISPARO BIT3
- #define NAO_USADO (BIT4 | BIT5 | BIT6 | BIT7)
- #define POT_ADC INCH_1;
- int main( void )
- {
- // Stop watchdog timer to prevent time out reset
- WDTCTL = WDTPW + WDTHOLD;
- // inicia led
- P1DIR = LED | POT | DISPARO | NAO_USADO;
- P1OUT = 0;
- // Ativa o clock de 32KHz
- BCSCTL1 |= DIVA_3; // ACLK /8
- BCSCTL3 |= XCAP_3; // 12.5pF
- // init timer A
- CCTL0 = CCIE; // CCR0 interrupt enabled
- CCR0 = 512;
- TACTL = TASSEL_1 + MC_1; // ACLK upmode
- _BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interrupt
- }
O timer A tem por entrada um clock de 32768/8 Hz. Programado para o upmode com uma contagem máxima de 512, ele gera uma interrupção a cada 1/8 de segundo. A rotina de interrupção é uma máquina de estados:
- #define T_LED 2 // tempo de LED aceso em 1/8 seg
- #define T_PAUSA 8 // tempo entre apagar o LED e disparar a foto em 1/8 seg
- #define T_DISPARO 2 // tempo que mantem ativo o disparo em 1/8 seg
- static volatile unsigned int pot;
- // Timer A interrupt service routine
- // Ocorre a cada 32768/8/512 = 1/8 segundo
- #pragma vector=TIMERA0_VECTOR
- __interrupt void Timer( void )
- {
- static byte estado = 0;
- static unsigned int cnt = 1;
- static unsigned int tempo = 10;
- static unsigned int pot_ant = 0;
- if (estado == 0)
- {
- if (--cnt == 0)
- {
- // Inicio de um novo ciclo
- // solta o disparo
- P1OUT &= ~DISPARO;
- // ler o potenciômetro
- P1OUT |= POT; // alimenta o potenciômetro
- ADC10CTL0 &= ~ENC;
- ADC10CTL0 = ADC10SHT_3 + ADC10ON + ADC10IE;
- ADC10CTL1 = ADC10SSEL_3 + POT_ADC;
- ADC10CTL0 |= ENC + ADC10SC;
- estado = 1;
- }
- }
- else if (estado == 1)
- {
- // Leu o potenciômetro, determina o novo tempo
- int dif = (pot > pot_ant) ? (pot - pot_ant) : (pot_ant - pot);
- if (dif > 16)
- {
- // mudou significativamente a posição
- unsigned int aux = pot >> 4;
- if (aux < 10)
- tempo = 10 + 2*aux; // 10 a 28seg, passo = 2 seg
- else if (aux < 20)
- tempo = 30 + 10*(aux-10); // 30 a 120 seg, passo = 10 seg
- else if (aux < 35)
- tempo = 150 + 30*(aux-20); // 150 a 570 seg, passo = 30 seg
- else if (aux < 55)
- tempo = 600 + 60*(aux-35); // 10 a 29 min, passo = 1 min
- else
- tempo = 1800 + 10*(aux-55); // 30 a 75 min, passo = 5 min
- pot_ant = pot;
- }
- cnt = tempo << 3; // converte p/ oitavos de segundo
- cnt -= T_LED + T_PAUSA + T_DISPARO;
- estado = 2;
- }
- else if (estado == 2)
- {
- // Aguardando tempo para acender o LED
- if (--cnt == 0)
- {
- // acende o led
- P1OUT |= LED;
- cnt = T_LED;
- estado = 3;
- }
- }
- else if (estado == 3)
- {
- // Aguardando tempo para apagar o LED
- if (--cnt == 0)
- {
- // apaga o LED
- P1OUT &= ~LED;
- cnt = T_PAUSA;
- estado = 4;
- }
- }
- else if (estado == 4)
- {
- // Aguardando tempo para disparar foto
- if (--cnt == 0)
- {
- // dispara a foto
- P1OUT |= DISPARO;
- cnt = T_DISPARO;
- estado = 0;
- }
- }
- }
- 0: aguardando o inicio de um novo ciclo
- 1: aguardando a leitura da posição do potenciômetro
- 2: aguardando para acender o LED
- 3: aguardando para apagar o LED
- 4: aguardando para disparar a foto
Após alguns testes, decidi que o LED ficaria aceso por 2/8 de segundo, o disparo seria comandado 1 segundo após apagar o LED e que o sinal de disparo ficaria ativo por 2/8 de segundo. Este último parâmetro é importante, já que o acoplador ótico é quem mais consome energia. O valor adotado pressupõe que não será usado o foco automático.
O aguardo da leitura do potenciômetro é feito com o microcontrolador dormindo. A interrupção do ADC (conversor analógico digital) salva o valor lido e retira a alimentação do potenciômetro.
- // Interrupção de fim da conversão
- #pragma vector=ADC10_VECTOR
- __interrupt void Adc_isr( void )
- {
- pot = ADC10MEM;
- P1OUT &= ~POT;
- }
- 10 a 28 segundos, passo de 2 segundos
- 30 a 120 segundos, passo de 10 segundos
- 150 a 570 segundos, passo de 30 segundos
- 10 a 29 minutos, passo de 1 minuto
- 30 a 75 minutos, passo de 5 minutos
Nenhum comentário:
Postar um comentário