Detectando o Imã
Relembrando, o sensor usado fornece uma tensão proporcional ao campo magnético a que é submetido. Longe do imã, temos uma tensão de 4.5/2 V. À medida que o sensor se aproximar de um imã esta tensão irá baixar ou subir, dependendo do polo. Pelo teste anterior, a leitura do SD16 com o sensor longe do imã é de 88 (considerando somente o byte mais significativo do resultado).
Uma primeira ideia seria usar um limite único para detectar o imã. Por exemplo, considerar que quando o valor passar de 110 estamos próximos do imã. Entretanto, é provável que as leituras oscilem o que poderia causar uma sequência de detecções em uma única passagem pelo imã.
O mais seguro é colocar uma histerese no teste. Por exemplo, considerar que estamos próximos do imã quando o valor passar de 120 e só voltar a considerar que estamos longe quando o valor cair abaixo de 100. Desta forma, mesmo que o valor passe de 120, baixe para 110 e depois volte para 120 consideramos uma única detecção.
Para ficarmos independentes da polaridade do imã, usamos também dois valores abaixo do de repouso (neste teste, vamos detectar o imã quando o valor ficar abaixo de 56 e considerar que nos afastamos dele quando o valor ficar acima de 76).
Fixando o Circuito e o Imã
O circuito é fixado na válvula do pneu. A posição do imã é relativamente crítica, neste teste ele ficou preso ao freio.

O Software de Teste
O software de teste implementa a histerese mencionada acima. A cada detecção é incrementado um contador, que é apresentado nos LEDs.
- /*
- Spoke-o-dometer
- Teste3 - Teste do sensor em movimento
- Daniel Quadros - abril, 2009
- */
- #include <msp430.h>
- // Valor para contar 1ms c/ clock de 12KHz
- #define TEMPO_1MS 12 // 1ms * 12KHz
- // Limites para detectar passagem pelo imã
- #define VREPOUSO 88 // 01011000
- #define VPOS_1 120 // 01111000
- #define VPOS_2 100 // 01111000
- #define VNEG_1 56 // 00111000
- #define VNEG_2 76 // 00111000
- #define FALSE 0
- #define TRUE 1
- typedef unsigned char byte;
- static byte bDetectou = FALSE; // TRUE qdo detecta o imã
- static unsigned int cont = 0;
- // Rotinas Locais
- static void Led (unsigned int valor);
- // Programa Principal
- void main (void)
- {
- // Desliga Watchdog
- WDTCTL = WDTPW + WDTSSEL + WDTHOLD;
- // Altera a configuração de clock para ativar o VLOCLK
- BCSCTL3 |= LFXT1S1;
- // Programa entradas e saídas
- P1SEL = 0xC0; // P1.0 a P1.5 -> LEDs
- // P1.6 e P1.7 são A3+ e A3-
- P1DIR = 0x3F;
- P1OUT = 0; // Todos as saídas em zero
- P2SEL = 0; // Todos os pinos como I/O
- P2DIR = 0xFF; // Todos os pinos como saída
- P2OUT = 0; // Todos as saídas em zero
- // Programa o ADC
- // MSP430F2013 -> SD16
- SD16CTL = SD16VMIDON + SD16REFON + SD16SSEL_1; // 1.2V ref, SMCLK
- SD16INCTL0 = SD16INCH_3; // PGA = 1x, Diff inputs A3- & A3+
- SD16CCTL0 = SD16SNGL + SD16UNI + SD16IE; // Single conversion, Unipolar, 256 SR, Int enable
- SD16CTL &= ~SD16VMIDON; // VMID off: used to settle ref cap
- SD16AE = SD16AE6 + SD16AE7; // P1.6 & P1.7: A3+/- SD16_A inputs
- // Dá um tempinho para estabilizar a alimentação
- while (cont < 0xFF)
- cont++;
- cont = 0;
- // Alimentação já deve estar estável, vamos ligar o DCO
- BCSCTL1 = CALBC1_1MHZ;
- DCOCTL = CALDCO_1MHZ;
- // Programar a interrupção de tempo real p/ cada 10ms
- TACCR0 = TEMPO_1MS;
- TACTL = TASSEL_1 + MC_1 + TAIE; // ACLK, up mode, interrupt
- // O nosso programa principal vai ficar dormindo,
- // todo o tratamento será feito na interrupção
- _BIS_SR(LPM3_bits + GIE); // Dorme tratando interrupção
- // Nuca vai chegar aqui
- while (1)
- ;
- }
- // Tratamento da interrupção do Timer A
- #pragma vector=TIMERA1_VECTOR
- __interrupt void Timer_A_TO(void)
- {
- switch (TAIV)
- {
- case 10: // overflow
- SD16CTL |= SD16REFON; // Liga a referência do SD16
- SD16CCTL0 |= SD16SC; // Inicia uma conversão
- _BIC_SR_IRQ (SCG1+SCG0); // Manter osciladores ligados
- break;
- case 2: // CCR1, não utilizado
- break;
- }
- }
- // Tratamento da interrupção do SD16
- #pragma vector = SD16_VECTOR
- __interrupt void SD16ISR(void)
- {
- unsigned int result;
- SD16CTL &= ~SD16REFON; // Desliga referência do SD16_A
- result = SD16MEM0 >> 8; // Pega resultado (limpa IFG)
- if (!bDetectou && ((result > VPOS_1) || (result < VNEG_1)))
- {
- bDetectou = TRUE;
- Led (++cont);
- }
- else if (bDetectou && (result < VPOS_2) && (result > VNEG_2))
- bDetectou = FALSE;
- _BIS_SR_IRQ (SCG1+SCG0); // voltar para LPM3
- }
- // Mostra resultado nos LEDs
- static void Led (unsigned int valor)
- {
- // vamos mostrar somente os 7 bits menos significativos
- valor &= 0x7F;
- valor <<= 1;
- P1OUT = (P1OUT & 0xC0) | (valor & 0x3E);
- P2OUT = (P2OUT & 0x3F) | (valor & 0xC0);
- }
Na próxima parte (se tudo correr bem) vamos começar a mostrar mensagens.
Nenhum comentário:
Postar um comentário