Autor Tema: :: PWM :: CCS :: PIC18F2550 :: SERVOS::  (Leído 25747 veces)

0 Usuarios y 5 Visitantes están viendo este tema.

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #30 en: 25 de Julio de 2012, 09:56:25 »
Hola
en la actualidad ¿sobre que entorno trabajas y con que compilador?
con ese entorto ¿que clase o familias de pic puedes programar?
¿te permite otros controladores como avr, arm, ...?

Un Saludo
« Última modificación: 25 de Julio de 2012, 09:58:42 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #31 en: 25 de Julio de 2012, 10:43:33 »
  Estoy usando PikLab en linux (Kubuntu 10.04) y puede trabajar con algunos 10F, 12F, 16F, 18F, 24F, 24H, 30F y 33F.

  Uso el compilador HiTech PIC-C para las familias 10, 12 y 16 y el HiTech PIC-C18 para los 18, en ambos casos tengo la versión 9.80

  Hubo un cambio muy notorio entre la versión 9.65 y 9.80 de HiTEch para 18, y es que en los header de los pics, la forma de definir las cosas está hecha para que quede compatible con C18 de microchip.

  Como sólo lo hago por hobby, con eso me es suficiente.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #32 en: 02 de Agosto de 2012, 20:02:25 »
hola
de vuelta por este hilo,
despues de la visita por la seccion de RTOS

http://www.todopic.com.ar/foros/index.php?topic=15876.20

y hacer sondeos:

http://www.todopic.com.ar/foros/index.php?topic=38942.new#new

hemos vuelto al principio, servos e interrupciones:

http://www.todopic.com.ar/foros/index.php?topic=20918.0
http://picmania.garcia-cuervo.net/picc_servos_x_8.php

Que desastre,... una semana por la borda...!





« Última modificación: 03 de Agosto de 2012, 03:31:37 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #33 en: 03 de Agosto de 2012, 14:15:22 »
  Una forma sencilla para manejar varios servos podría ser la siguiente:

  Un timer asignado al tiempo en alto de cada señal. Un timer que genere interrupción cada 2mS (o incremente una variable y actuas cuando llegue a 2mS)

  Cuando se genera la interrupción de 2mS, activas una salida y a su vez el timer que cuenta el tiempo en alto, e incrementas una variable que indique cuantas veces se generó la interrupción de 2mS. Cuando genera la interrupción el timer de tiempo en alto apagás la salida.
  Cuando se vuelve a generar la interrupción de 2mS, activas otra salida y repetís los pasos respecto del timer que cuenta el tiempo en alto.

  Esos ciclos se repiten constantemente con lo que lograrías ir cambiando de servo. Cuando la variable que cuenta la cantidad de interrupciones de 2mS llegue a 10, ya habrán pasado los 20mS de trama por lo tanto la próxima interrupción volvería a activar al primer servo... y la historia se repite.

  Por supuesto el tiempo en alto de cada servo puede ser distinto. Para ello habría que precargar el timer de tiempo en alto con el valor adecuado. Dicho valor puede provenir de una variable para cada servo.

  Todo eso se aplicaría a el PIC esclavo de I2C.

  En el PIC maestro se podría hacer algo así:

  Conectar potenciómetros a los ADC (uno por cada servo a controlar). Se leen los ADC y se almacenan en variables. También hay que tener otra variable con el estado anterior de cada canal.
  Se evalúa cual canal cambio de valor y se envía solamente ese dato. De esa manera podrás ahorrar mucho tiempo de transmisión.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #34 en: 08 de Agosto de 2012, 14:28:07 »
Hola

gracias AngelGris, eres un buen colaborador del foro, ahora estoy probando
con la idea que me has dado, por el momento va ganando el pic, pero...

Espero terminar ganando yo

sigo con la faena..

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #35 en: 11 de Agosto de 2012, 16:28:11 »
  Te subo un programa hecho en SDCC el cual genera sobre el puerto B señales para 8 servos.
  Cada 2mS se salta la interrupción del timer0 y en base a ello cambio activo el servo correspondiente. La duración de cada servo está data por el timer1, cuyo valor se carga a partir de un array.
  En este programa el array tiene valores prefijados pero bien se puede cargar el array via I2C o cualquier otro tipo de comunicación.

Código: C
  1. unsigned int duty[8];
  2.  
  3. void timers(void) __interrupt 1                // interrupcion alta prioridad
  4. {
  5.   static unsigned int salida = 1;
  6.   static unsigned char indice = 0;
  7.  
  8.   if ((INTCONbits.T0IE) && (INTCONbits.T0IF))  //interrupcion por timer0, cada 2mS
  9.   {
  10.     LATB = salida;         // salida correspondiente en 1
  11.     T1CONbits.TMR1ON = 1;  // enciendo el timer1
  12.     TMR0L = 0x16;          
  13.     TMR0H = 0xD9;          // precargo nuevamente el timer0 (para que desborde cada 2mS)
  14.     salida = salida << 1;  
  15.     indice++;              // incremento el indice para el tiempo en alto
  16.     if (salida == 1024)
  17.     {
  18.       salida = 1;
  19.       indice = 0;
  20.     }  
  21.     TMR1L = duty[indice] & 0x0FF;
  22.     TMR1H = duty[indice] >> 8;     // precargo el timer1 con el valor correspondiente
  23.     INTCONbits.T0IF = 0;           // borro el flag interrupcion del timer0
  24.   }
  25.  
  26.   if ((PIE1bits.TMR1IE) && (PIR1bits.TMR1IF))  // interrupcion timer1, el tiempo en alto
  27.   {
  28.     LATB = 0;                     // pongo en 0 la salida actual
  29.     T1CONbits.TMR1ON = 0;         // apago el timer1
  30.     PIR1bits.TMR1IF = 0;          // borro el flag de interrupcion del timer1
  31.   }
  32.  
  33. }
  34.  
  35. void main(void)
  36. {
  37.  
  38.   TRISB = 0b00000000;    // puerto B como salida
  39.   LATB = 0;    // salida en 0
  40.  
  41. // configuro los timers y les precargo un valor
  42.  
  43.   T0CON = 0x08;
  44.   T1CON = 0x80;
  45.   TMR1L = 0x77;
  46.   TMR1H = 0xEC;
  47.   TMR0L = 0x16;
  48.   TMR0H = 0xD6;
  49.  
  50. // habilito prioridades de interrupcion
  51. // el timer0 y timer1 alta prioridad
  52.  
  53.   RCONbits.IPEN = 1;
  54.   INTCON2bits.TMR0IP = 1;
  55.   IPR1bits.TMR1IP = 1;
  56.   PIE1bits.TMR1IE = 1;
  57.   INTCONbits.T0IE = 1;
  58.   INTCONbits.GIEH = 1;
  59.  
  60.   T0CONbits.TMR0ON = 1;   // enciendo el timer0
  61.  
  62.   // valores para el tiempo en alto de los distintos servos
  63.  
  64.   duty[0] = 60535;
  65.   duty[1] = 59535;
  66.   duty[2] = 58535;
  67.   duty[3] = 57535;
  68.   duty[4] = 56535;
  69.   duty[5] = 60535;
  70.   duty[6] = 59535;
  71.   duty[7] = 58535;
  72.  
  73.   while(1)
  74.   {
  75.    
  76.   }
  77. }

  También te adjunto una captura del osciloscopio de Proteus, donde se aprecian las señales correspondientes a B0, B1, B2 y B3 que sería las cuatro primeras salidas.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #36 en: 14 de Agosto de 2012, 13:35:02 »
Hola AngelGris

Se ve muy bueno tu programa, el mio esta atascado
primero con los tick para los angulos y segundo con el dichoso i2c..
me esta dondo muchos problemas,.... y muchos no son nada logicos..

mediante la simulacion de proteus, me obliga a poner
delante y detrras de la funcion de envia desde el master al esclavo
retardos de 1s de lo contrario el debug del i2c te muestra que llega el dato
pero te muestra por el terminal virtual lo que le da la gana.

si le pones a enviar dato "1" el esclavo recibe 0 y todo se bloquea y el debug de i2c detecta Nack
si le envias dato sin esperar 1000ms, te la prepara metiendote el dato como si fuera la direcion de almacen
del dato, lo malo es que te carga ese dato a cero.
para mas descaro te sobreescribe donde no debe, descalibrando el pwm ....ufff una pesadilla

bueno casi podria escribir un libro con todos lo errores que me ha dado, uno tras otro.
no se si sera culpa del ccs o del proteus o de todo en su conjunto..



Oye AngelGris tu pwm es por harware o por software?
que cristal usas?
con el timer0 haces lo que decia redpic de la ventana? , el cambio de servo no lo veo
pero como lo haces me pierdo un poco, activas el pwm de esa salida ?



« Última modificación: 14 de Agosto de 2012, 13:37:28 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #37 en: 14 de Agosto de 2012, 14:09:30 »
Hola AngelGris

Se ve muy bueno tu programa, el mio esta atascado
primero con los tick para los angulos y segundo con el dichoso i2c..
me esta dondo muchos problemas,.... y muchos no son nada logicos..

mediante la simulacion de proteus, me obliga a poner
delante y detrras de la funcion de envia desde el master al esclavo
retardos de 1s de lo contrario el debug del i2c te muestra que llega el dato
pero te muestra por el terminal virtual lo que le da la gana.

si le pones a enviar dato "1" el esclavo recibe 0 y todo se bloquea y el debug de i2c detecta Nack
si le envias dato sin esperar 1000ms, te la prepara metiendote el dato como si fuera la direcion de almacen
del dato, lo malo es que te carga ese dato a cero.
para mas descaro te sobreescribe donde no debe, descalibrando el pwm ....ufff una pesadilla

bueno casi podria escribir un libro con todos lo errores que me ha dado, uno tras otro.
no se si sera culpa del ccs o del proteus o de todo en su conjunto..


  He leído el mensaje que creaste por dicha cuestión y sinceramente no respondí porque no sé que decirte al respecto. Es un problema muy muy extraño.
  Yo hice siempre pequeñas simulaciones y nunca envié un array completo, así que no sabría decirte si es problema del compilador o del simulador.


Oye AngelGris tu pwm es por harware o por software?
que cristal usas?
con el timer0 haces lo que decia redpic de la ventana? , el cambio de servo no lo veo
pero como lo haces me pierdo un poco, activas el pwm de esa salida ?


  El PWM lo controlo yo manualmente -podríamos decir que es por software- en base a los timer0 y timer1.

  Uso cristal de 20MHz.

  Con el timer0 -cada 2mS- activo una salida distinta del puerto B (sólo una está activa el resto queda con salida 0) con la instrucción "LATB = salida".
También  hago que varíe la variable salida con la instrucción "salida = salida << 1;" que rota a la izquierda el dato, por lo tanto se va activando sólo un bit a la vez; para que al entrar a la próxima interrupción por el timer0 y al hacer "LATB = salida" se produzca un nuevo cambio de servo.

  Una vez que activo la salida, activo el timer1 (eso va a establecer el tiempo en alto de la señal). Cuando se genera la interrupción por timer1 desactivo la salida. Como yo sé que sólo una salida está activa, la forma más sencilla para desactivar es poniendo todo el puerto B en 0. También apago el timer1.

  Básicamente lo que hace es ir activando sólo una salida a la vez (como si fuese un contador decimal tipo 4017), y el tiempo que permanece en alto cada salida es dado por el timer1.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #38 en: 14 de Agosto de 2012, 18:55:11 »
Hola AngelGris

como calibraste el osciloscopio para cazar las ondas,
a mi aca me da como errores de refresco?
y hay veces que hasta se cuerga el simulador.

Probaste esa implemtacion con comandos i2c?

« Última modificación: 14 de Agosto de 2012, 19:03:19 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #39 en: 14 de Agosto de 2012, 19:04:34 »
  Para que se vea así de alto los pulso ajuste el control de vertical de cada canal -los dejé en 2V/div- y también los dejé acoplados en continua.
Al cambiar eso, tuve que ajustar un poco el nivel de trigger.

  Ojo!! que también pude ser que tu señal no sea periódica y por lo tanto el osciloscopio no queda enganchado.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #40 en: 14 de Agosto de 2012, 19:53:36 »
Hola AngelGris

este es el codigo del main:

Código: C++
  1. //variables i2c
  2. int8 state, comando;
  3. //int8 iic_dato, Direc_master;
  4. int8 direc_Mas_esc, recivo=0;
  5. int8 dato[4];
  6. //int8 dato_1[4];
  7. int8 cnt=0;
  8. int8 angulo;
  9. int8 inclina;
  10. int8 motor_on;
  11.  
  12. //servos pwm soft
  13. int8 servos[]={sv_0,sv_1,sv_2,sv_3,sv_4,0,0,0,0,0};
  14.  
  15.  
  16.  
  17.  
  18.  
  19. //variables timer
  20. int8 cnt_t0=0;
  21. int8 cnt_t1=0;
  22. int1 t0=0;
  23. int1 t1=0;
  24.  
  25. #priority timer0, timer1, ssp,
  26. /*
  27. #int_RTCC
  28. void  RTCC_isr(void)
  29. {
  30.  
  31. }
  32. */
  33. #int_TIMER0
  34. void  TIMER0_isr(void)
  35. {
  36.    if(cnt_t0==20){ //cambio de ventana
  37.       cnt_t0=0;
  38.       printf("\n\r -->T0 1ms 20 ventanas  1 perido");
  39.    }
  40.    //desborda cada 1ms
  41.    set_timer0(ventana); //ventana de 1 ms cambio de svmotor
  42.    
  43.    printf("\n\r ON SERVO: %d " cnt_t0); //debug ---
  44.    switch(cnt_t0){
  45.               //sv_x seria un vector(cnt_to), y lo del timer1 otro
  46.       case 0: output_high (servos[cnt_t0]); set_timer1(g_90); break;
  47.       case 1: output_high (servos[cnt_t0]); set_timer1(g_90); break;
  48.       case 2: output_high (servos[cnt_t0]); set_timer1(g_90); break;
  49.       case 3: output_high (servos[cnt_t0]); set_timer1(g_90); break;
  50.       case 4: output_high (servos[cnt_t0]); set_timer1(g_90); break;
  51.       /*case 5: output_high (sv_0); set_timer1(g_0); break;
  52.       case 6: output_high (sv_1); set_timer1(g_0); break;
  53.       case 7: output_high (sv_2); set_timer1(g_0); break;
  54.       case 8: output_high (sv_3); set_timer1(g_0); break;
  55.       case 9: output_high (sv_4); set_timer1(g_0); break;
  56.       */
  57.    }//fin switch
  58.    printf("\n\r cnt_t0: %d "cnt_t0);
  59.    //cnt_t0=cnt_t0+1; //incremta ventana => motor
  60. }
  61.  
  62. #int_TIMER1
  63. void  TIMER1_isr(void)
  64. {
  65. output_low (servos[cnt_t0]);
  66. printf("\n\r OFF servo: %d "cnt_t0);
  67. cnt_t0=cnt_t0+1; //incremta ventana => motor
  68.  
  69.  
  70. }
  71.  
  72. /*
  73. #int_SSP
  74. void  SSP_isr(void)
  75. {
  76.  
  77. }
  78. */
  79.  
  80. #int_SSP
  81. void  SSP_isr(void){
  82. disable_interrupts(INT_SSP);
  83. //int8 comando;
  84. //master escribe de esclavo  menor de <80
  85. //master lee de esclavo      mayor de >80
  86.  
  87. state = i2c_isr_state();
  88.    if(state==0)
  89.    {
  90.       direc_Mas_esc=i2c_read();
  91.       if(direc_Mas_esc==S1){
  92.       printf("\n\r --> Direccion: %X "direc_Mas_esc);
  93.          recivo=1;
  94.       }
  95.      
  96.       //printf("\n\r Direccion : %X "direc_Mas_esc); //para solo imprime s1
  97.       //if(SSPADD==S1){
  98.       //printf("\n\r state==0 soy S1: %X "SSPADD);
  99.       //}
  100.      
  101.    }
  102.    
  103.    if(state < 0x80)
  104.    {
  105.      
  106.       //iic_dato=i2c_read();
  107.       //comando=iic_dato;
  108.       if(recivo==1){
  109.          dato[cnt]=i2c_read();
  110.          
  111.          // coreccion para lo de error en dato=1
  112.          if(dato[cnt]==10){
  113.            dato[cnt]=1;
  114.          }
  115.          
  116.          if(dato[0]==1){ // control de motor
  117.             output_high(PIN_B6);
  118.             motor_on=1;
  119.          }
  120.          
  121.          if(dato[cnt]!=0){ //control de angulo
  122.             angulo=dato[1];
  123.             inclina=dato[2];
  124.          }
  125.          ///////////////////////
  126.          
  127.          printf("\n\r dato[%u]:%u"cnt,dato[cnt]);
  128.          recivo=0;
  129.          
  130.          // para resetear almacen dato
  131.          if(dato[cnt]==99){  //cnt resetea en 3 si es 99
  132.            cnt=0;
  133.          }
  134.          else{
  135.            cnt=cnt+1;
  136.          }
  137.          
  138.       }
  139.      
  140.      
  141.      
  142.  
  143.      
  144.  
  145.      
  146.       //Aqui colocas lo que necesites hacer con el dato enviado por el maestro
  147.       //printf("\n\r comando recibo <80: %u"comando);
  148.      
  149.    }
  150.    if(state == 0x80)
  151.    {
  152.    
  153.     switch(comando)
  154.       {
  155.          Case Pide_Dato1:
  156.             i2c_write(Dato1);
  157.             output_high(PIN_B7);
  158.             delay_ms(300);
  159.             output_low(PIN_B7);
  160.            
  161.             printf("\n\r Llego dato.");
  162.             break;
  163.          Case Pide_Dato2:
  164.             i2c_write(Dato2);
  165.             output_high(PIN_B2);
  166.             break;
  167.       }
  168.    }
  169. }
  170.  
  171.  
  172. #int_BUSCOL
  173. void  BUSCOL_isr(void)
  174. {
  175.  
  176. }
  177.  
  178.  
  179.  
  180. void main()
  181. {
  182.  
  183.    setup_adc_ports(NO_ANALOGS|VSS_VDD);
  184.    setup_adc(ADC_CLOCK_DIV_2);
  185.    setup_wdt(WDT_OFF);
  186.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  187.    setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  188.    setup_timer_2(T2_DISABLED,0,1);
  189.    setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
  190.    setup_comparator(NC_NC_NC_NC);
  191.    setup_vref(FALSE);
  192.    enable_interrupts(INT_RTCC);
  193.    enable_interrupts(INT_TIMER0);
  194.    enable_interrupts(INT_TIMER1);
  195.    enable_interrupts(INT_SSP);
  196.    enable_interrupts(INT_BUSCOL);
  197.    enable_interrupts(GLOBAL);
  198. //Setup_Oscillator parameter not selected from Intr Oscillator Config tab
  199.  
  200.    // TODO: USER CODE!!
  201. set_timer0(0);
  202. set_timer1(0);
  203.  
  204. printf("\n\r Prueba de timer: ");
  205.  
  206.    while(true){
  207.       if(t0==2){
  208.          printf("\n\r -->T0 20ms");
  209.       }
  210.       if(t1==4){
  211.          printf("\n\r -->T1 40ms");
  212.       }
  213.    }
  214. }


en el fichreo de cabecera:

Código: C++
  1. #include <18F2550.h>
  2. #device adc=8
  3.  
  4. #FUSES NOWDT                    //No Watch Dog Timer
  5. #FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
  6. #FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
  7. #FUSES NOPROTECT                //Code not protected from reading
  8. #FUSES NOBROWNOUT               //No brownout reset
  9. #FUSES BORV20                   //Brownout reset at 2.0V
  10. #FUSES NOPUT                    //No Power Up Timer
  11. #FUSES NOCPD                    //No EE protection
  12. #FUSES STVREN                   //Stack full/underflow will cause reset
  13. #FUSES NODEBUG                  //No Debug mode for ICD
  14. #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
  15. #FUSES NOWRT                    //Program memory not write protected
  16. #FUSES NOWRTD                   //Data EEPROM not write protected
  17. #FUSES IESO                     //Internal External Switch Over mode enabled
  18. #FUSES FCMEN                    //Fail-safe clock monitor enabled
  19. #FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
  20. #FUSES NOWRTC                   //configuration not registers write protected
  21. #FUSES NOWRTB                   //Boot block not write protected
  22. #FUSES NOEBTR                   //Memory not protected from table reads
  23. #FUSES NOEBTRB                  //Boot block not protected from table reads
  24. #FUSES NOCPB                    //No Boot Block code protection
  25. #FUSES MCLR                     //Master Clear pin enabled
  26. #FUSES LPT1OSC                  //Timer1 configured for low-power operation
  27. #FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
  28. #FUSES PLL12                    //Divide By 12(48MHz oscillator input)
  29. #FUSES CPUDIV4                  //System Clock by 4
  30. #FUSES USBDIV                   //USB clock source comes from PLL divide by 2
  31. #FUSES VREGEN                   //USB voltage regulator enabled
  32.  
  33.  
  34. //esclavos
  35. #define S1 0xB0
  36. #define S2 0xB2
  37. #define S4 0xB4
  38. #define S6 0xB6
  39. #define S8 0xB8
  40.  
  41. // define los servos
  42. #define sv_0 PIN_B7
  43. #define sv_1 PIN_B6
  44. #define sv_2 PIN_B5
  45. #define sv_3 PIN_B4
  46. #define sv_4 PIN_B3
  47. /*
  48. #define sv_5 PIN_B7
  49. #define sv_6 PIN_B6
  50. #define sv_7 PIN_B5
  51. #define sv_8 PIN_B4
  52. #define sv_9 PIN_B3
  53.  
  54. */
  55. // tick para grados 16 bit : 65536 tick 0.2us -->13107.2us
  56.  
  57. //tiempo entre servomotor
  58. const int16 ventana = 60536;  // 65536 - 5000 = n tick para INT 1000us :1ms
  59.  
  60. const int16 g_0   = 64936;    //65536 -  600  120us
  61. const int16 g_90  = 63661;    //65536 - 1875  375us
  62. const int16 g_180 = 62386;    //65536 - 3150  630us
  63.  
  64. //const int16 g_45  = 63661;    //65536 - 1875  375us
  65. //const int16 g_135 = 63661;    //65536 - 1875  375us
  66.  
  67. static int16 valor_PWM[8]={g_90, g_0,g_180,0,0,0,0,0};
  68. static int16 ini_PWM[8]={g_90, g_90, g_90, g_90,0,0,0,0};
  69.  
  70. #define Pide_Dato1 2
  71. #define Pide_Dato2 3
  72. #define dato1 4
  73. #define dato2 5
  74.  
  75. #use delay(clock=20000000)
  76. #define I2C_SCL   PIN_B7
  77. #define I2C_SDA   PIN_C4
  78. #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
  79. #use i2c(Master,Slow,sda=PIN_C4,scl=PIN_B7)

como mis servos van de 0 grados en 120us y el 180 es 630us
la ventana o cambio de servo la puse en 1ms ya que el periodo es de 20ms
podia haber apurado mas o puesto mas pequeña
pero queria cifras redondas.

como el periodo es de 20 ms puedo ponerle 20 ventanas de 1 ms, 20 cambio de servo,
para probar le enviaba 10 servos pero al final le deje solo 5 servos, los simulo con led
pero no se ven nada , se ven encendidos todo el rato y pense yo,.. no deberian de verse apagados
el pulso de mi 90 grados es de 375 us y el resto del tiempo estan en off.

con el timer0 cuento las ventanas(los cambio de servo), y enciendo el servo correspondiente iniciando el timer0
con el timer 0 cuando entra en INT incremento ventana, y apago servo

lo del osciloscopio no hay manera se ha colgado al meno una docena de veces el proteus.
ademas me da uno mesajes un poco raros,

PIC18 MEMORY PC=0x022E write 0x00 (0) to unimplemented memory address 0x0f95 does nothing
PIC18 MEMORY PC=0x0226 Read of unimplemented memory address 0x0f8D returns zero
..
.
.
..

esto se repite pero cambiando las direcciones.
cada pocos us


ya lo he corregido lo de los errores de color rojo
en el timer1 copiar-pegar me jugo un mala pasada
en vez de ponerla en bajo la ponia en alto.

este codigo ya funciona.

bueno ahora si que se ve..
es tal como yo pensaba se aprecia un leve parpadeo y el mayor
tiempo estan apagados..

pero me quedan muy separadas las señales

ahora solo queda pegarme con el i2c..

miedo me da..ufff.





« Última modificación: 14 de Agosto de 2012, 20:39:44 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #41 en: 14 de Agosto de 2012, 20:41:30 »

..................

bueno ahora si que se ve..
es tal como yo pensaba se aprecia un leve parpadeo y el mayor
tiempo estan apagados..

pero me quedan muy separadas las señales

ahora solo queda pegarme con el i2c..

miedo me da..ufff.


  ¿A qué te refieres con "me quedan muy separadas las señales"?  Si el tiempo de "ventana" es de 1 mS, cada canal de servo tendría que ir a 1 justamente cada 1 mS. Mide ese tiempo con el osciloscopio de Proteus a ver cuanto te da.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #42 en: 14 de Agosto de 2012, 21:18:52 »
Hola

configure el timer en cada canal le puse 2 (2-2)
y en la debebajo del timer 20m, 50m o 100m
con 10 empieza la serie

pero he descubierto que el cursor vertical no me empieza en el blanco
de subida de la primera señal pudiera deberse a que el timer al principio lo arranco en 0.

midiendo con 20ms
con los cursores me mide, el flanco de subina del primero me parece desfasado -16ms
y aparece a la derecha del cursor vertical
en los otros:


2º: 32ms
3º: 77ms
4º: 123ms


 voy a cambiar la resolucion para medir el periodo entero
en cada señal de motor.
Cambio la resolucion a 100ms en el de debajo del triger:
y mido de flanco positivo a flanco positivo en la primera señal.


1º  -70ms a 915ms
2º  -25ms a 960ms
2º   20ms a 1.01s
3º   70ms a 1.05s


estado mirando con esta misma resolucion
y en alto esta 0.01s en algunos en otros varia de una señal a otra y ademas tambien varia
entre pulsos del mismo motor..

que cosa mas rara.


« Última modificación: 14 de Agosto de 2012, 21:22:50 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #43 en: 14 de Agosto de 2012, 22:12:18 »
  Como primer medida te recomiendo "comentar" los "printf" que tengas en las interrupciones. Para evitar ese tiempo de mas.

  Como segunda medida, eliminar el "switch" ya que no tiene sentido hacer un switch de la variable cnt_t0 y en cada caso hacer "output_high (servos[cnt_t0])". Siempre realizas la misma instrucción sea cual fuere el valor de cnt_t0, por lo tanto pierdes tiempo en las evaluaciones del "switch" innecesariamente.

  Tercer, es conveniente primero activar la salida y el timer1, y luego hacer las evaluaciones necesarias.

  Cuarto, en la interrupción del timer1 también debes apagar el mismo, para que no siga contando y pueda saltar nuevamente la interrupción.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #44 en: 15 de Agosto de 2012, 08:59:56 »
Hola AngelGris

Lo del printf ya lo habia hecho, me di cuanta despues,
ya le estoy aciendo las modificaciones sucesivas.

cuando entra en el timer 0  que haces primero:
 activar el timer1 y  empezar a contar tiempo en alto
o activar de nuevo el timer 0

¿es posible saber cuanto timepo dura cada intrucción?
y en base a eso recarcular los timer para corregir ese error?

el perido entre flancos de subida de cada señal me sale 20.60ms
des el cursor vertical al primer pulso de la señal le cuesta 6.70ms.
entre pulso y pulso es decir la ventana me va 1.10ms

y me da un error creo que tiene que ver con el encendido y apagado del timer..
no se es asi..

error: OSCTUNE register not fully modelled - the TUNx bits are not modelled

este es un bucle..de este error.

el code modificaco quedo asi..solo en main lo demas todo igual

Código: C++
  1. //variables i2c
  2. int8 state, comando;
  3. //int8 iic_dato, Direc_master;
  4. int8 direc_Mas_esc, recivo=0;
  5. int8 dato[4];
  6. //int8 dato_1[4];
  7. int8 cnt=0;
  8. int8 angulo;
  9. int8 inclina;
  10. int8 motor_on;
  11.  
  12. //servos pwm soft
  13. int8 servos[]={sv_0,sv_1,sv_2,sv_3,sv_4,0,0,0,0,0};
  14.  
  15.  
  16.  
  17.  
  18.  
  19. //variables timer
  20. int8 cnt_t0=0;
  21. int8 cnt_t1=0;
  22. int1 t0=0;
  23. int1 t1=0;
  24.  
  25. #priority timer0, timer1, ssp,
  26. /*
  27. #int_RTCC
  28. void  RTCC_isr(void)
  29. {
  30.  
  31. }
  32. */
  33. #int_TIMER0
  34. void  TIMER0_isr(void)
  35. {  
  36.    
  37.    output_high (servos[cnt_t0]);             //activo servo
  38.    //ventana de 1 ms cambio de svmotor
  39.    set_timer0(ventana);                      //desborda cada 1ms
  40.    setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);   //activo timer1
  41.    set_timer1(g_90);                         //tiempo en alto
  42.  
  43.    if(cnt_t0==20){ //cambio de ventana
  44.       cnt_t0=0;
  45.       //printf("\n\r -->T0 1ms 20 ventanas  1 perido");
  46.    }
  47.  
  48.    //printf("\n\r cnt_t0: %d "cnt_t0);
  49.    //cnt_t0=cnt_t0+1; //incremta ventana => motor
  50. }
  51.  
  52. #int_TIMER1
  53. void  TIMER1_isr(void)
  54. {
  55. output_low (servos[cnt_t0]);     //apago motor
  56. //printf("\n\r OFF servo: %d "cnt_t0-1);
  57. cnt_t0=cnt_t0+1;                 // incremta ventana => motor
  58. setup_timer_1(0);                // desactivo timer 1
  59.  
  60. }
  61.  
  62. /*
  63. #int_SSP
  64. void  SSP_isr(void)
  65. {
  66.  
  67. }
  68. */
  69.  
  70. #int_SSP
  71. void  SSP_isr(void){
  72. disable_interrupts(INT_SSP);
  73. //int8 comando;
  74. //master escribe de esclavo  menor de <80
  75. //master lee de esclavo      mayor de >80
  76.  
  77. state = i2c_isr_state();
  78.    if(state==0)
  79.    {
  80.       direc_Mas_esc=i2c_read();
  81.       if(direc_Mas_esc==S1){
  82.       printf("\n\r --> Direccion: %X "direc_Mas_esc);
  83.          recivo=1;
  84.       }
  85.      
  86.       //printf("\n\r Direccion : %X "direc_Mas_esc); //para solo imprime s1
  87.       //if(SSPADD==S1){
  88.       //printf("\n\r state==0 soy S1: %X "SSPADD);
  89.       //}
  90.      
  91.    }
  92.    
  93.    if(state < 0x80)
  94.    {
  95.      
  96.       //iic_dato=i2c_read();
  97.       //comando=iic_dato;
  98.       if(recivo==1){
  99.          dato[cnt]=i2c_read();
  100.          
  101.          // coreccion para lo de error en dato=1
  102.          if(dato[cnt]==10){
  103.            dato[cnt]=1;
  104.          }
  105.          
  106.          if(dato[0]==1){ // control de motor
  107.             output_high(PIN_B6);
  108.             motor_on=1;
  109.          }
  110.          
  111.          if(dato[cnt]!=0){ //control de angulo
  112.             angulo=dato[1];
  113.             inclina=dato[2];
  114.          }
  115.          ///////////////////////
  116.          
  117.          printf("\n\r dato[%u]:%u"cnt,dato[cnt]);
  118.          recivo=0;
  119.          
  120.          // para resetear almacen dato
  121.          if(dato[cnt]==99){  //cnt resetea en 3 si es 99
  122.            cnt=0;
  123.          }
  124.          else{
  125.            cnt=cnt+1;
  126.          }
  127.          
  128.       }
  129.      
  130.      
  131.      
  132.  
  133.      
  134.  
  135.      
  136.       //Aqui colocas lo que necesites hacer con el dato enviado por el maestro
  137.       //printf("\n\r comando recibo <80: %u"comando);
  138.      
  139.    }
  140.    if(state == 0x80)
  141.    {
  142.    
  143.     switch(comando)
  144.       {
  145.          Case Pide_Dato1:
  146.             i2c_write(Dato1);
  147.             output_high(PIN_B7);
  148.             delay_ms(300);
  149.             output_low(PIN_B7);
  150.            
  151.             printf("\n\r Llego dato.");
  152.             break;
  153.          Case Pide_Dato2:
  154.             i2c_write(Dato2);
  155.             output_high(PIN_B2);
  156.             break;
  157.       }
  158.    }
  159. }
  160.  
  161.  
  162. #int_BUSCOL
  163. void  BUSCOL_isr(void)
  164. {
  165.  
  166. }
  167.  
  168.  
  169.  
  170. void main()
  171. {
  172.  
  173.    setup_adc_ports(NO_ANALOGS|VSS_VDD);
  174.    setup_adc(ADC_CLOCK_DIV_2);
  175.    setup_wdt(WDT_OFF);
  176.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  177.    setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  178.    setup_timer_2(T2_DISABLED,0,1);
  179.    setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
  180.    setup_comparator(NC_NC_NC_NC);
  181.    setup_vref(FALSE);
  182.    enable_interrupts(INT_RTCC);
  183.    enable_interrupts(INT_TIMER0);
  184.    enable_interrupts(INT_TIMER1);
  185.    enable_interrupts(INT_SSP);
  186.    enable_interrupts(INT_BUSCOL);
  187.    enable_interrupts(GLOBAL);
  188. //Setup_Oscillator parameter not selected from Intr Oscillator Config tab
  189.  
  190.    // TODO: USER CODE!!
  191. set_timer0(ventana);
  192. setup_timer_1(0);  // timer 1 no activo T1_DISABLED = 0
  193. //set_timer1(0);
  194.  
  195. printf("\n\r Prueba de timer: ");
  196.  
  197.    while(true){
  198.       if(t0==2){
  199.          printf("\n\r -->T0 20ms");
  200.       }
  201.       if(t1==4){
  202.          printf("\n\r -->T1 40ms");
  203.       }
  204.    }
  205. }

solo modifique el timer0 y el timer1
y dentro del main donde se inicia el timer delante del while.

sigo investigando.


« Última modificación: 15 de Agosto de 2012, 09:46:18 por pajaro »


 

anything