O comportamento gerado pelo firmware é o seguinte:
- Durante um período "longo" (2 minutos no código abaixo) a abóbora está "dormindo" (LEDs apagados e servomotor na posição de boca fechada).
- Ao "acordar" os LEDs dos olhos são acesos e o servomotor muda de posição para "abrir a boca da abóbora".
- Completada a abertura, é aceso o LED dentro da boca. A boca permanece aberta por alguns segundos.
- O servo motor retorna rapidamente para a posição de boca fechada, ao final do fechamento os LEDs são apagados.
enum { DORMINDO, ABRINDO, ABERTA, FECHANDO } estAbobora;A interrupção de timer do PIC, que é programada para ocorrer a cada 64 microsegundos, é utilizada para gerar o sinal PWM de controle do servomotor e para decrementar um contador que indica a passagem de um décimo de segundo.
unsigned int16 cntDSeg; unsigned int16 cnt_periodo; unsigned int8 cnt_duty, duty; ////////////////////////////////////////////// // Interrupcao de tempo real // Ocorre a cada 64 uSeg ////////////////////////////////////////////// #int_RTCC void RTCC_isr() { SET_TIMER0 (192); // conta de 192 a 255 // Trata Servo if ((estAbobora != DORMINDO) && (estAbobora != ABERTA) { if (--cnt_periodo == 0) { // fim de um ciclo cnt_periodo = TMPUS_PERIODO/TMPUS_OVF; cnt_duty = duty; output_high (MOTOR); } else if (cnt_duty != 0) { cnt_duty--; if (cnt_duty == 0) output_low (MOTOR); } } if (cntDSeg != 0) cntDSeg--; }O programa principal contém a iniciação do hardware e a lógica de mudança de estado a cada décimo de segundo:
#define MOTOR PIN_A2 #define LED_OLHO PIN_A4 #define LED_BOCA PIN_A5 #define TMPUS_OVF 64l // tempo uSeg entre interrupções do timer #define TMPUS_PERIODO 20000l // periodo do PWM em uSeg #define TMPUS_DSEG 100000l #define TMPDSEG_DORME 1000 #define TMPDSEG_ABRINDO 3 #define TMPDSEG_FECHANDO 1 #define TMPDSEG_ABERTA 30 #define DUTY_0 400 // tempo para 0 graus #define DUTY_90 1000 // tempo para 90 graus #define DUTY_180 1600 // tempo para 180 graus #define DUTY_ABERTA 768 #define DUTY_FECHADA 576 unsigned int16 cntEstado; void main() { // configura os periféricos #use fast_io(A) set_tris_A(0xCB); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); SET_TIMER0 (192); // conta de 192 a 255 setup_timer_1(T1_DISABLED); setup_comparator(NC_NC); setup_vref(FALSE); output_high (LED_BOCA); output_high (LED_OLHO); output_low (MOTOR); // inicia as variaveis estAbobora = FECHANDO; cntDSeg = TMPUS_DSEG/TMPUS_OVF; cnt_periodo = TMPUS_PERIODO/TMPUS_OVF; cnt_duty = duty = DUTY_FECHADA / TMPUS_OVF; cntEstado = 3; enable_interrupts(INT_RTCC); enable_interrupts(GLOBAL); for (;;) { // Trata atualização do estado a cada décimo de segundo if (cntDSeg == 0) { disable_interrupts(GLOBAL); cntDSeg = TMPUS_DSEG/TMPUS_OVF; if (--cntEstado == 0) { switch (estAbobora) { case DORMINDO: estAbobora = ABRINDO; duty = DUTY_FECHADA / TMPUS_OVF; output_high (LED_OLHO); cntEstado = TMPDSEG_ABRINDO; break; case ABRINDO: if (duty == (DUTY_ABERTA / TMPUS_OVF)) { estAbobora = ABERTA; output_high (LED_BOCA); cntEstado = TMPDSEG_ABERTA; } else { duty++; cntEstado = TMPDSEG_ABRINDO; } break; case ABERTA: estAbobora = FECHANDO; cntEstado = TMPDSEG_FECHANDO; break; case FECHANDO: if (duty == (DUTY_FECHADA / TMPUS_OVF)) { estAbobora = DORMINDO; output_low (LED_BOCA); output_low (LED_OLHO); output_low (MOTOR); cntEstado = TMPDSEG_DORME; } else { duty--; cntEstado = TMPDSEG_FECHANDO; } break; } } enable_interrupts(GLOBAL); } } }No próximo post da série vamos ver a montagem da minha "abóbora" (que acabou sendo uma esfera de isopor).
Nenhum comentário:
Postar um comentário