Autor Tema: Lectura adc y servo  (Leído 4193 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Skualo

  • PIC10
  • *
  • Mensajes: 42
Lectura adc y servo
« en: 11 de Julio de 2008, 07:29:51 »
Tengo sensores de distancia por infrarojo y necesito medir valores analogicos pero al hacerlo los servos me van mal van a golpecitos porque supongo que le retrasa la frecuencia sabeis si puedo acer algo para solucionarlo? El programa es el de redpic para controlar servos desde el pc editado.

Código: CSS
  1. // servo_pwm_232
  2. // Ejemplo con un servo FUTABA S3003
  3. // Alimentación y pulsos a 5V
  4. // Cuadro de Tiempos :
  5. //    Periodo 20 ms (Frecuencia 50 Hz)
  6. //    Ancho Pulso minimo 0.5 ms
  7. //    Ancho pulso medio  1.5 ms
  8. //    Ancho pulso maximo 2.5 ms
  9. //    TMR0 a 1:16 -> 1 RTCC cada 4.096 ms
  10. //                -> 1 Tick cada 0.096 / 256 = 0.016 ms
  11. //                -> 20 ms = (4 x RTCC completas) + (1 * RTCC - 30 ticks
  12. //    Ancho Pulso minimo 0.5 ms ->  31 ticks de TMR0
  13. //    Ancho pulso medio  1.5 ms ->  93 ticks de TMR0
  14. //    Ancho pulso maximo 2.5 ms -> 155 ticks de TMR0
  15. #include <16f877a.h>
  16. #fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
  17. #use delay(clock=4000000)
  18. #use standard_io(b)
  19. #define PIN_SERVO1 PIN_d5
  20. #define PIN_SERVO2 PIN_d6
  21. int sensor1b=0;
  22. int sensor2b=0;
  23. const int AJUSTE_FINO_DE_RTCC =  30;
  24. const int ticks_PULSO_MINIMO  =  31;
  25. const int ticks_PULSO_MEDIO   =  93;
  26. const int ticks_PULSO_MAXIMO  = 155;
  27. int i,h=0,a=0,b=5000;
  28. int1 flagRTCC     = 0;
  29. int   contRTCC    = 0;
  30. int1 flagSERVO1 = 0;
  31. int   tSERVO1     = ticks_PULSO_MEDIO;
  32. int1 flagSERVO2 = 0;
  33. int   tSERVO2     = ticks_PULSO_MEDIO;
  34.  #int_RTCC
  35.  RTCC_isr(){
  36.  ++contRTCC;  
  37.  if(contRTCC==4){  
  38.  set_TIMER0(AJUSTE_FINO_DE_RTCC);  
  39.  }
  40.  if(contRTCC==5){  
  41.  flagRTCC=1;  
  42.  contRTCC=0x00;  
  43.  }}
  44.  void main() {
  45.  int ValTIMER0;
  46.  setup_counters(RTCC_INTERNAL,RTCC_DIV_16);
  47.  enable_interrupts(int_rda);
  48.  enable_interrupts(global);
  49.   setup_adc(ADC_CLOCK_INTERNAL );
  50. setup_adc_ports( ALL_ANALOG );
  51.  set_TIMER0(0);
  52.  enable_interrupts(INT_RTCC);
  53.  
  54.  do {
  55. tservo1=85;
  56. tservo2=85;
  57. set_adc_channel( 0 );
  58. sensor1b=read_adc();
  59. set_adc_channel( 1 );
  60. sensor2b=read_adc();
  61.  
  62.  // DISPARO DEL PULSO PWM    
  63.  if(flagRTCC==1){      
  64.  flagRTCC=0;    
  65.  output_high(PIN_SERVO1);    
  66.  flagSERVO1=1;    
  67.  output_high(PIN_SERVO2);    
  68.  flagSERVO2=1;
  69.  }    
  70.  // CONTROL DE ANCHO DEL PULSO PWM  
  71.  if(flagSERVO1==1){    
  72.  valTIMER0 = get_TIMER0();
  73.  if(valTIMER0>tSERVO1){  
  74.  flagSERVO1=0;        
  75.  output_low(PIN_SERVO1);
  76.  }      
  77.  }  
  78.   if(flagSERVO2==1){
  79.   valTIMER0 = get_TIMER0();
  80.   if(valTIMER0>tSERVO2){
  81.   flagSERVO2=0;
  82.   output_low(PIN_SERVO2);
  83.   }
  84.  
  85.  }
  86.  
  87.  }while (true);
  88.  }

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Lectura adc y servo
« Respuesta #1 en: 11 de Julio de 2008, 10:16:21 »
Si el servo te va "a golpecitos" es porque el pic no está generando correctamente la PWM.
Si tienes un osciloscopio ve qué hay en la salida que está conectada al servo.
Analiza si las "ediciones" que le hiciste al programa original del maestro RedPic no te están causando problemas.
Por otro lado, lee la datasheet del micro sobre el módulo del convertidor A/D, generalmente se requiere una espera entre la elección del canal a convertir y la conversión en sí. Tú no la estás haciendo.
Y tampoco veo la relación entre lo que estás leyendo del canal analógico y la PWM del servo.
Yo diría que quitaras momentáneamente la parte de la conversión y le des al servo valores fijos para moverlo usando el código adaptado que tienes. Luego que puedas manejar el servo perfectamente, pasas a la parte de manejar los servos a partir de los sensores.
Bueno sólo son sugerencias.
Te deseo éxito.
Saludos, nos leemos!  :mrgreen:

"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado Skualo

  • PIC10
  • *
  • Mensajes: 42
Re: Lectura adc y servo
« Respuesta #2 en: 11 de Julio de 2008, 11:39:20 »
Se que ese es el problema porque si quito esta parte del codigo
Código: CSS
  1. set_adc_channel( 0 );sensor1b=read_adc();set_adc_channel( 1 );sensor2b=read_adc();
el servo va perfecto pero si lo pongo m va a tironcitos e probado lo de poner la espera y mejora un pokito y tambien creando una funcion con la lectura mejora mas pero aun no va perfecto.

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Lectura adc y servo
« Respuesta #3 en: 11 de Julio de 2008, 12:21:17 »
Ahora no consigo el enlace en todopic, pero en este link verás un código bien completo para manejar un servo; este código es una versión mejorada que hizo el maestro RedPic del que tú tienes.
Está fácil de entender y puedes adaptarlo a tus necesidades.
Espero te sea útil.
Saludos, nos leemos!  :mrgreen:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: Lectura adc y servo
« Respuesta #4 en: 11 de Julio de 2008, 12:43:47 »
Y por que no usar un PWM hardware?

Es evidente que este software no hace un PWM, porque dudo mucho que alguna vez el ancho del pulso sea constante con este código, si no utilizas una base de tiempo estable y configurable (temporizadores) y algún método que haga uso eficiente de ello, para controlar el ciclo útil de una señal de período constante, dudo mucho que los servos vayan como debe ser y no a saltitos, porque los primeros que te fastidian el período constante son las lecturas de los ADC que nunca terminarán en los mismos tiempos porque los conversores AD de los PICs son de aproximaciones sucesivas.

Saludos
Reinier

Desconectado Skualo

  • PIC10
  • *
  • Mensajes: 42
Re: Lectura adc y servo
« Respuesta #5 en: 11 de Julio de 2008, 13:11:02 »
Tienes algun circuito para crear por hardware el pwm, porque parece una wena idea almenos una preocupacion menos, lo unico que se me ocurre es hacerlo con el 555.

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Lectura adc y servo
« Respuesta #6 en: 11 de Julio de 2008, 13:31:45 »
Maestro Reiniertl, estoy de acuerdo con vos en que por hardware es mucho mejor, pero el detalle es que el micro que está usando skualo no permite generar una PWM de 50Hz con el módulo PWM que trae. Por eso la solución es implementarlo por software.
Se podría generar con un hard externo al micro, pero me parece que es desperdiciar recursos, pues el micro lo puede hacer.
Yo estoy haciendo actualmente un proyecto que incluye manejo de servos, y también hago la generación de 4 PWM distintas por soft, usando interrupción por timer, en mi caso timer0, aunque puede usarse otro. Yo lo hago de otra forma, pero también usando interrupciones. Y el movimiento es bastante preciso. El link que dí a la página del maestro Redpic también tiene un software que funciona fenomenalmente.
Y yo también estoy usando conversión A/D, además de operaciones matemáticas y otras operaciones. Pero el movimiento de los servos se mantiene preciso. Debe haber algún error en su código que le ocasiona ese problema.
Yo sugeriría a Skualo tratar de ordenar mejor el código, y seguro que se soluciona la cosa.
Ok un cordial saludo a ambos, nos leemos!  :mrgreen:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado Skualo

  • PIC10
  • *
  • Mensajes: 42
Re: Lectura adc y servo
« Respuesta #7 en: 11 de Julio de 2008, 13:42:44 »
Lo malo del link que me diste que todos los servos van por igual tendre que averiguar si se puede controlar por separado aver si llego a entender el codigo jejeje

Saludos

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: Lectura adc y servo
« Respuesta #8 en: 11 de Julio de 2008, 14:25:06 »
Entonces se puede hacer un PWM de este tipo, que lógicamente no requerirá mucha resolución utilizando cualquier temporizador, de modo que se tenga una interrupción cada cierto tiempo, tomemos como ejemplo este PWM que tiene frecuencia de 50Hz, o mejor un período de 20ms y dividamos este en 100 partes, para tener una "resolución porcentual" que vaya de 1-100%, obtenemos que 20/100=200us, ahora cogemos un timer cualquiera, yo utilizaría el Timer1 y el CCP, para fijar una frecuencia exacta de 200us. y en la interrupción del timer o del CCP programo la subida o bajada del pin del PWM.

Unas banderas y unos contadores me permitirían hacer la lógica de cuando subir y bajar el pin, una variable global puede servir para establecer de cuanto debe ser el ciclo útil 0-100% y con estas cosillas podemos hacer  un PWM de 50Hz, pero donde el elemento que lleva la cuenta del tiempo es un dispositivo HW (temporizador o temporizador+otro periférico) no debemos dejar en poder del uC esto de andar llevando el tiempo para este tipo de procesos, porque pueden verse cosas raritas.

Saludos
Reinier

PD: firepic, gracias por la categoría de maestro, pero me faltan un par de meses para comenzar mi carrera de profesor. De momento me conformo con ser un colaborador más del foro. Además tu te diste cuenta que el PWM del PIC no se puede utilizar en este caso porque sus posibilidades de configuración no nos permiten períodos tan bajos.

Skualo, el PIC que utilizas tiene dos PWM integrados, lástima que no puedas utilizarlo, o tendrías que bajar mucho la frecuencia de trabajo del PIC, pero eso no creo que te convenga, de todos modos con las señas que te doy y un poco de esfuerzo de tu parte podrás hacer lo que quieres sin grandes problemas, cuando te trabes llégate por acá.

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Lectura adc y servo
« Respuesta #9 en: 11 de Julio de 2008, 15:06:15 »
Lo malo del link que me diste que todos los servos van por igual tendre que averiguar si se puede controlar por separado aver si llego a entender el codigo jejeje
La idea no es que te copies todo el código, porque tus necesidades son diferentes. Lo que quiero que veas es la lógica del programa. O como te ha explicado muy bien el gran reiniertl, el cómo de generar la PWM con la interrupción del temporizador.
La forma como yo lo hago no es tan elegante como la que usa el maestro RedPic, pero funciona.
Lo que sí me copié de su programa es la lógica que usa para el manejo de varios servos con una sóla interrupción, gracias a la magistral explicación que añade.
Es algo así:

Código: C
  1. ////////////////////////////////////////////////////////////////////// Interrupción que genera PWM para control de servos
  2. #INT_TIMER0                                              
  3. void pwm_servos (void)
  4. {
  5.    switch (i)                                              
  6.    {                                                        
  7.       case 0:                                              
  8.          output_high (servo_1);                            
  9.          tiempo = tiempo_s1;                                
  10.          break;                                            
  11.       case 1:                                                  
  12.          output_low (servo_1);                                
  13.          tiempo = tmr_pulso_maximo - tiempo_s1;                      
  14.          break;                                            
  15.       case 2:                                                  
  16.          output_high (servo_2);                            
  17.          tiempo = tiempo_s2;
  18.          break;
  19.       case 3:
  20.          output_low (servo_2);
  21.          tiempo = tmr_pulso_maximo - tiempo_s2;
  22.          break;        
  23.       default:
  24.          tiempo = tmr_pulso_maximo;                        
  25.          break;                                            
  26.    }                                                          
  27.    i++;                                                    
  28.    if (i==10) i=0;
  29.         set_rtcc(256-tiempo);                                    
  30. }

Espero que con esto puedas guiarte.
Con esta función en la interrupción, puedes mover dos servos, pero se puede ampliar para manejar hasta 8.
Lo que sí debes hacer es llamar a la función al inicio del programa, antes de la interrupción, para que comience la PWM del primer servo. Y claro que deberás configurar el timer (en mi caso lo hago con timer0) con la preescala adecuada a tu frecuencia de oscilación.
Como te dije, es mi forma de hacerlo. Reiniertl me ha dado algunas ideas para mejorar esa rutina con lo del CCP y demás. Trataré de tomar en cuenta sus recomendaciones para proyectos futuros.

PD: firepic, gracias por la categoría de maestro, pero me faltan un par de meses para comenzar mi carrera de profesor. De momento me conformo con ser un colaborador más del foro.
Bueno lo de maestro lo digo porque así te considero. Tu participación en ucontrol me parece sencillamente excelente. Y no hay duda de que tienes bastante experiencia con los micros. Por otro lado, genial que comiences carrera como profesor! Yo lo viví y de verdad que es muy satisfactorio. Me alegro por tí y espero que te vaya muy bien! No quiero desviar el tema del hilo, pero tampoco quería dejar de felicitarte.  :lol:

Saludos, nos leemos!  :mrgreen:
« Última modificación: 12 de Julio de 2008, 23:30:09 por firepic »
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado Skualo

  • PIC10
  • *
  • Mensajes: 42
Re: Lectura adc y servo
« Respuesta #10 en: 12 de Julio de 2008, 14:01:42 »
estoy intentandome hacer un programa propio para poderlo entender, el problema que tengo es que por ejemplo con un divisor 1:16 a 4mhz el timer0 cuenta 4,096ms y si son 20mhz 20,48ms.
Mi primera pregunta seria si cambio el divisor en que me afecta el tiempo como lo calculo? y tambien queria saber que el timer0 por ejemplo si no quiero que cuente desde cero puedo poner set_timer0(x) x que seria un numero de 0 a 255?

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Lectura adc y servo
« Respuesta #11 en: 12 de Julio de 2008, 23:38:13 »
estoy intentandome hacer un programa propio para poderlo entender, el problema que tengo es que por ejemplo con un divisor 1:16 a 4mhz el timer0 cuenta 4,096ms y si son 20mhz 20,48ms.
Creo que has hecho mal el cálculo. Si tienes un cristal más rápido, a 20MHz, pues cuenta menos tiempo, con esa pre-escala serían 819.2us
El cálculo es así:
Tiempo=Fosc^-1*4*Pre-escala*(256-cantidad cargada en timer).
Para los casos que tú mencionas:
T1=(4e6)^-1*4*16*256=4.096ms.
T2=(20e6)^-1*14*6*256=819.2us.

Sobre la segunda pregunta, es correcto. Puedes cargar un valor previo al timer, así es como lo hago yo, con la instrucción set_rtcc que es equivalente a set_timer0.

Ok saludos, nos leemos!  :mrgreen:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado Skualo

  • PIC10
  • *
  • Mensajes: 42
Re: Lectura adc y servo
« Respuesta #12 en: 13 de Julio de 2008, 11:21:47 »
Es verdad jejeje muchas gracias lo e solucionado ya y e ordenado un poco las cosas y e conseguido poder leer adc y acer señales estables pero aora tengo un nuevo problema y es que cuando conecto el gpt todo funciona bien servos y lectura pero cuando conecto 5v del ordenador los servos van lentos y la lectura va bien, ademas me e fijado que si toco los pines de la señal de los servos estos empiezan a funcionar correctamente.
Podria ser ruido o algo asi? lo que no entiendo es que el icsp tiene 5 pines y no creo que le quite ruido con los otros 3 no? porque los 5 voltios los estoy cogiendo del gtp para acer pruevas y no va pero es conectarle el icsp y todo funciona genial.

Alguna idea¿?

Saludos !