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;
- 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--;
- }
- #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);
- }
- }
- }
Nenhum comentário:
Postar um comentário