Lo prometido es deuda, asi que aqui tenemos la segunda parte de este proyecto.
En este vídeo podeis ver cómo es el control de la aceleración del coche, que antes era encendido/apagado y ahora acelera más cuanto más movemos la palanca:
El programa está hecho en CCS y es muy simple. Se divide en dos partes: 1) la lectura del pulso del servo a través del puerto B y 2) la generación de PWM proporcinal a la velocidad, a través del puerto A y B. 1) Lectura del pulso del servo. Esta parte es la más crítica ya que hemos de leer con precisión los pulsos que irían a un servo y convertirlo en una numeración. Para eso usaremos el timer0 del pic. Préviamente hemos calculado los "ticks" que contará este timer y cómo ajustamos el preescaler. Por ejemplo, para el cristal de 4Mhz, sabiendo que un servo en reposo o 50% da un pulso de 1,5ms. xtal=4 incremento:Xtal/4=1us x 8(preescaler) =8us Entonces el contador contará para: 1ms: 1,5ms/8us = 125 1,5ms: 1,5ms/8us = 187 2ms: 1,5ms/8us = 250 Hemos escogido el preescaler de 8 para abarcar esta horquilla entre 0 y 255.
- #include <16F84.H>
- #FUSES NOWDT //No Watch Dog Timer
- #FUSES HS //para cristal de 6MHz
- #FUSES PUT //power up timer habilitado
- #FUSES NOPROTECT//lectura habilitada del codigo del pic
- //#use delay(clock=4000000) // 4 MHz OSC
- //#use delay(clock=3579000) // 4 MHz OSC
- #use delay(clock=6000000) // 6 MHz OSC
- #USE FAST_IO (A)
- #USE FAST_IO (B)
- #define PIN_SERVOi1 PIN_B4
- #define PIN_SERVOi2 PIN_B5
- #define PIN_SERVOi3 PIN_B6
- #define PIN_SERVOi4 PIN_B7
- #define PIN_MOTOR1R PIN_A0
- #define PIN_MOTOR1L PIN_A1
- #define PIN_MOTOR2R PIN_A2
- #define PIN_MOTOR2L PIN_A3
- #define PIN_MOTOR3R PIN_B0
- #define PIN_MOTOR3L PIN_B1
- #define PIN_MOTOR4R PIN_B2
- #define PIN_MOTOR4L PIN_B3
- #define PIN_LED PIN_A4
- /*
- xtal=3,57 incremento= 1.117 x 8 = 8,94 us
- 1.5ms= 167
- ULIMIT= 167 +10
- LLIMIT= 167 -10
- xtal=558k inc= 7.168 x 1
- =195
- xtal=6 inc= 0,666 x 16 =10.66666
- =140
- */
- #define ULLIMIT 140
- #define ULIMIT 150
- #define LLIMIT 130
- int8 tempo,ledco;
- int8 timerco1,motor1L,motor1R;
- int8 timerco2,motor2L,motor2R;
- int8 timerco3,motor3L,motor3R;
- int8 timerco4,motor4L,motor4R;
- int8 scounter;
- int8 semaforo;
- boolean ledb;
- //**********************************************************************************
- //**********************************************************************************
- #INT_RB
- void interrupcionRB() {
- SWITCH(input_b()&0xF0){
- case 0b00010000:set_timer0(0); semaforo=1;break;
- case 0b00100000:set_timer0(0); semaforo=2;break;
- case 0b01000000:set_timer0(0); semaforo=3;break;
- case 0b10000000:set_timer0(0); semaforo=4;break;
- case 0:
- switch (semaforo){
- case 1:timerco1=get_timer0();semaforo=0;ledco++;break;
- case 2:timerco2=get_timer0();semaforo=0;ledco++;break;
- case 3:timerco3=get_timer0();semaforo=0;ledco++;break;
- case 4:timerco4=get_timer0();semaforo=0;ledco++;break;
- }
- default:
- semaforo=0;
- }
- //**********************************************************************************
- //****************************** M A I N *****************************************
- //**********************************************************************************
- void main(){
- set_tris_a(0); // todo salida
- set_tris_b(0b11110000); // todo salida rb4,6,7 entrada
- output_a(0);
- output_b(0);
- output_high(PIN_LED);
- setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16); //activamos timer0 como interno
- set_timer0(0);
- motor1L,motor1R=0;
- motor2L,motor2R=0;
- motor3L,motor3R=0;
- motor4L,motor4R=0;
- timerco1,timerco2,timerco3,timerco4=ULLIMIT;
- enable_interrupts(INT_RB);
- enable_interrupts(GLOBAL);
- for(ledco=0;ledco<5;ledco++) {output_bit(PIN_LED,ledb);
- ledb=!ledb;
- delay_ms(500);
- }
- while(1){ //bucle infinito
- for(tempo=0;tempo<=100;tempo++){
- // PWM DEL MOTOR
- //evaluamos aqui para no perder tiempo
- if(tempo==95 ){
- if(ledco++ >254){
- output_bit(PIN_LED,ledb);
- ledb=!ledb;
- ledco=0;
- }
- }else if(tempo==96 ){
- if(timerco1 > ULIMIT ){ motor1R=(--timerco1-ULIMIT)*3;motor1L=0;}
- else if(timerco1 < LLIMIT) {motor1L=(LLIMIT-timerco1++)*3;motor1R=0;}
- else{motor1R=0;motor1L=0;}
- }else if(tempo==97 ){
- if(timerco2 > ULIMIT ){ motor2R=(--timerco2-ULIMIT)*3;motor2L=0;}
- else if(timerco2 < LLIMIT) {motor2L=(LLIMIT-timerco2++)*3;motor2R=0;}
- else{motor2R=0;motor2L=0;}
- }else if(tempo==98 ){
- if(timerco3 > ULIMIT ){ motor3R=(--timerco3-ULIMIT)*3;motor3L=0;}
- else if(timerco3 < LLIMIT) {motor3L=(LLIMIT-timerco3++)*3;motor3R=0;}
- else{motor3R=0;motor3L=0;}
- }else if(tempo==99 ){
- if(timerco4 > ULIMIT ){ motor4R=(--timerco4-ULIMIT)*3;motor4L=0;}
- else if(timerco4 < LLIMIT) {motor4L=(LLIMIT-timerco4++)*3;motor4R=0;}
- else{motor4R=0;motor4L=0;}
- }
- output_bit(PIN_MOTOR1R,(motor1R >tempo));
- output_bit(PIN_MOTOR1L,(motor1L >tempo));
- output_bit(PIN_MOTOR2R,(motor2R >tempo));
- output_bit(PIN_MOTOR2L,(motor2L >tempo));
- output_bit(PIN_MOTOR3R,(motor3R >tempo));
- output_bit(PIN_MOTOR3L,(motor3L >tempo));
- output_bit(PIN_MOTOR4R,(motor4R >tempo));
- output_bit(PIN_MOTOR4L,(motor4L >tempo));
- delay_us(100);
- } //bucle tempo
- } //end while
- }