Autor Tema: Controlar Servo mediante pwm por software.  (Leído 4449 veces)

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

Desconectado jim_17

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 309
    • Blog personal
Controlar Servo mediante pwm por software.
« en: 18 de Junio de 2008, 17:26:00 »

Todavia soy un poco novato en esto de la programación de PIC y más aun si se trata de la programación en lenguaje C. El siguiente programa lo he realizado con el compilador PCW. El problema que se me presenta aparece en la simulacion de PROTEUS, en estos momentos no puedo realizar ningun programador y es por eso que preciso de vuestros consejos.

El programa es el que pienso utilizar en un seguidor de linea compuesto por 2 motores para el avance del seguidor y 1 servo para el giro de las curbas. Los sensores serian cny70 que estan simulados como pulsadores en PROTEUS, los sensores estan numerados de izquierda a derecha, es decir de 0º hasta 180º. 90º seria la posicion del sensor 4, el sensor 1 seria la posicion 0º y el sensor 7 seria la posicion 180º.

Para controlar el servo utilizaria pwm por software (ya que me estoy iniciando es mas comodo para mi). Ahora que tengo expuesto
el funcionamiento del seguidor de linea tengo las siguientes dudas:


1º) Querría saber si el programa que he realizado esta bien echo y los defectos que tiene o retoques que aplicariais.

2º) En la simulacion en PROTEUS el servo motor no se posiciona correctamente en los angulos predefinidos. ¿A que es debido?



Espero haber dicho claramente las dudas que tengo, espero que me podais ayudar, si no entendeis algo decidmelo.


Salu2.


Aqui el codigo

Código: C
  1. #include <16f84.h>
  2. #fuses XT,NOWDT,NOPROTECT,NOPUT,
  3. #use delay(clock = 4mhz)
  4. #use fast_io (b)
  5. #use fast_io (a)
  6.  
  7. void posicion1 (void);
  8. void posicion2 (void);
  9. void posicion3 (void);
  10. void posicion4 (void);
  11. void posicion5 (void);
  12. void posicion6 (void);
  13. void posicion7 (void);
  14.  
  15. void main (void) {
  16.    int periodo;
  17.    int bajo;
  18.    int posicion;
  19.    periodo=20000;
  20.    bajo=periodo-posicion;
  21. set_tris_a (0b00000000);
  22. set_tris_b (0b11111111);
  23.  
  24.    posicion4();
  25.    output_high (PIN_A0);
  26.    output_high (PIN_A1);
  27.  
  28.  do{
  29.    if (input (PIN_B0))
  30.       posicion1();
  31.    if (input (PIN_B1))
  32.       posicion2();
  33.    if (input (PIN_B2))
  34.       posicion3();
  35.    if (input (PIN_B3))
  36.       posicion4();
  37.    if (input (PIN_B4))
  38.       posicion5();
  39.    if (input (PIN_B5))
  40.       posicion6();
  41.    if (input (PIN_B6))
  42.       posicion7();
  43.  
  44.  }while (true);
  45. }
  46.  
  47. void posicion1 (void){
  48.    int periodo;              
  49.    int bajo;
  50.    int posicion;
  51.    posicion=300;
  52.    bajo = periodo-posicion;
  53.    output_high (PIN_A3);
  54.    delay_us(posicion);
  55.    output_low (PIN_A3);
  56.    delay_us(bajo);
  57. }
  58.  
  59.  void posicion2 (void){
  60.    int periodo;
  61.    int bajo;
  62.    int posicion;
  63.    posicion=633;
  64.    bajo = periodo-posicion;
  65.    output_high (PIN_A3);
  66.    delay_us (posicion);
  67.    output_low (PIN_A3);
  68.    delay_us (bajo);
  69. }
  70.  
  71. void posicion3 (void){
  72.    int periodo;
  73.    int bajo;
  74.    int posicion;
  75.    posicion=967;
  76.    bajo = periodo-posicion;
  77.    output_high (PIN_A3);
  78.    delay_us (posicion);
  79.    output_low (PIN_A3);
  80.    delay_us (bajo);
  81. }
  82.  
  83. void posicion4 (void){
  84.    int periodo;
  85.    int bajo;
  86.    int posicion;
  87.    posicion=1300;
  88.    bajo = periodo-posicion;
  89.    output_high (PIN_A3);
  90.    delay_us (posicion);
  91.    output_low (PIN_A3);
  92.    delay_us (bajo);
  93. }
  94.  
  95. void posicion5 (void){
  96.    int periodo;
  97.    int bajo;
  98.    int posicion;
  99.    posicion=1633;
  100.    bajo = periodo-posicion;
  101.    output_high (PIN_A3);
  102.    delay_us (posicion);
  103.    output_low (PIN_A3);
  104.    delay_us (bajo);
  105. }
  106.  
  107. void posicion6 (void){
  108.    int periodo;
  109.    int bajo;
  110.    int posicion;
  111.    posicion=1967;
  112.    bajo = periodo-posicion;
  113.    output_high (PIN_A3);
  114.    delay_us (posicion);
  115.    output_low (PIN_A3);
  116.    delay_us (bajo);
  117. }
  118.  
  119. void posicion7 (void){
  120.    int periodo;
  121.    int bajo;
  122.    int posicion;
  123.    posicion=2300;
  124.    bajo = periodo-posicion;
  125.    output_high (PIN_A3);
  126.    delay_us (posicion);
  127.    output_low (PIN_A3);
  128.    delay_us (bajo);
  129. }

Siento que el codigo no este comentado, en cuanto pueda lo edito.

Tambien os dejo los archivos de proteus
Share the world !

Blog's

http://www.area0x33.com

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5100
    • uControl
Re: Controlar Servo mediante pwm por software.
« Respuesta #1 en: 18 de Junio de 2008, 17:29:51 »
Hola Jim!
¿Estás seguro de que puedes controlar un servo con PWM?

Es decir....la electronica del servo de encarga de todo, a partir de la duracion de la parte "alta" del pulso que recibe cada 20ms, asi que un PWM no.....aaah, te refieres a la generacion de esa señal cuando pones  "Controlar Servo mediante pwm"?

Saludos  :mrgreen:
Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert

Desconectado jim_17

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 309
    • Blog personal
Re: Controlar Servo
« Respuesta #2 en: 18 de Junio de 2008, 18:02:44 »
Weno y eso no se llama pwm ¿?, :( tengo un mal concepto de pwm entonces :D, lo que quiero es controlar un servo mediante una señal de 20ms en la cual el servo se posiciona en el centro con una señal de 1.3 y a los extremos con una señal de 2.3 y 0.3 respectivamente.
Share the world !

Blog's

http://www.area0x33.com

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5100
    • uControl
Re: Controlar Servo mediante pwm por software.
« Respuesta #3 en: 18 de Junio de 2008, 18:06:51 »
Si, se llama PWM :)

Yo me di cuenta a mitad de escribirte la respuesta. Es que nunca me puse a pensar en los servos de esa manera.

Deberia ser una frecuencia de 50 HZ, y un duty cycle variable entre el porcentaje que surja de convertir los 2.3 y 0.3 ms....CREO que serian 11.5% y 1.5%, no?
Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert

Desconectado Slalen

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1079
    • Página web personal de Guillermo Herrero González
Re: Controlar Servo mediante pwm por software.
« Respuesta #4 en: 18 de Junio de 2008, 18:24:02 »
Buenas!!!

A ver, he leído el código y yo creo que el PWM está bien hecho. Pero mira a ver si puedes simularlo con proteus para ver el tiempo real que tardan los retardos.

seguramente los tengas que hacer algo menores y después poner alguna instrucción para compensar el error.

Cuando tengo que controlar servos siempre uso ensamblador por ese motivo.

Un apunte a tu código, en esta parte:
Código: [Seleccionar]
if (input (PIN_B0))
     posicion1();
  if (input (PIN_B1))
     posicion2();
  if (input (PIN_B2))
     posicion3();
  if (input (PIN_B3))
     posicion4();
  if (input (PIN_B4))
     posicion5();
  if (input (PIN_B5))
     posicion6();
  if (input (PIN_B6))
     posicion7();

El problema de este código es que si se activan varias entradas a la vez el programa tendría que activar todas las subrutinas y el servo no se posicionaría.

Si lo quieres hacer con if, yo pondría algo así:
Código: [Seleccionar]
  if (input (PIN_B0))
     posicion1();
  else
    if (input (PIN_B1))
       posicion2();
    else
      if (input (PIN_B2))
        posicion3();
      else
         if (input (PIN_B3))
            posicion4();
         else
            if (input (PIN_B4))
             posicion5();
           else
              if (input (PIN_B5))
                 posicion6();
              else
                 if (input (PIN_B6))
                    posicion7();

Así si se hay activa una entrada no mira el estado del resto y se olvida.

Lo malo que así tendría más peso el PB0 que el reto.

Lo que te recomiendo es que hagas algo con "case"


Desconectado jim_17

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 309
    • Blog personal
Re: Controlar Servo mediante pwm por software.
« Respuesta #5 en: 18 de Junio de 2008, 20:51:46 »
Aaaahhh Okey! es que de momento no tengo el prototipo para hacer pruebas (NO hay money) por que tengo que ahorrar para la universidad. Como todavia no se usar las interrupciones ni los timer hago el pwm mediante software, poco a poco lo iré mejorando pero querría saber si en la vida real esos retardos estarian bien para controlar el servo.

Gracias por las respuestas.
Share the world !

Blog's

http://www.area0x33.com

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Controlar Servo mediante pwm por software.
« Respuesta #6 en: 18 de Junio de 2008, 21:21:24 »
Saludos!
Así con retardos debe funcionar, pero lo veo poco óptimo, pues no te permite hacer nada más mientras le estás enviando la señal al servo....
Si usas el buscador del foro posiblemente consigas el hilo "Controlando hasta 8 servos con una sola interrupción" del maestro redpic, me parece una forma mucho mejor de controlar los servos y procesar otras tareas a la vez...
Bueno no más es una observación...
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 pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Controlar Servo mediante pwm por software.
« Respuesta #7 en: 19 de Junio de 2008, 04:47:52 »
Varios fallos:

- En el PIC de PROTEUS tienes 1Mhz y deben ser 4Mhz

- Las variables las tienes como int, así no te funcionará ya que 20000 no le entra. Declaralas cono globales y tipo long

- Para que funcione un servo debes de estar contínuamente enviando el pwm. Tú no lo haces en el primer posicion4(); En el while(1) debes de estar contínuamente apretando los pulsadores, tenlo en cuenta.

- Debes de poner resistencias a tierra con todos los pulsadores, para que en el estado de reposo tome un cero en las entradas.

- Como ya te han indicado con delays no es la mejor solución para controlar un Servo ya que el micro no puede hacer otras cosas.

- Como ya te han indicado con delays deberás corregir la posición de los Servos ya que no va a salir exacto.

Un saludo

Desconectado jim_17

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 309
    • Blog personal
Re: Controlar Servo mediante pwm por software.
« Respuesta #8 en: 19 de Junio de 2008, 08:53:14 »
Varios fallos:

- En el PIC de PROTEUS tienes 1Mhz y deben ser 4Mhz

- Las variables las tienes como int, así no te funcionará ya que 20000 no le entra. Declaralas cono globales y tipo long

- Para que funcione un servo debes de estar contínuamente enviando el pwm. Tú no lo haces en el primer posicion4(); En el while(1) debes de estar contínuamente apretando los pulsadores, tenlo en cuenta.

- Debes de poner resistencias a tierra con todos los pulsadores, para que en el estado de reposo tome un cero en las entradas.

- Como ya te han indicado con delays no es la mejor solución para controlar un Servo ya que el micro no puede hacer otras cosas.

- Como ya te han indicado con delays deberás corregir la posición de los Servos ya que no va a salir exacto.

Un saludo


Gracias por los aportes, intentaré en estos dias estudiarme un poco el tema de interrupcines y timer para poder hacer otras cosas con el PIC.

Lo de los pulsadores que tienen que estar continuamente pulsados, eso ya lo habia pensado pero al ser cny70 los sensores que utilizaré pues pensé que cuando detectasen linea, estarian a 1 lógico hasta que dejasen de detectar entonces generarian la señal de posicionamiento del servo continuamente.

Tambien me falta definir una condicion que es cuando el robot seguidor pierde la linea y ningun sensor detecta.

Las variables para hacerlas globales se hace con la funcion #define variable = X  ?


Salu2.

Share the world !

Blog's

http://www.area0x33.com

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Controlar Servo mediante pwm por software.
« Respuesta #9 en: 19 de Junio de 2008, 09:16:21 »
No, simplemente defínelas (cortar y pegar) encima del main y ya seran globales. Acuérdate, tipo long (ó bien int16)

PD. Con delay_us() te funcionará, puedes comprobarlo en el simulador. Cuando lo hayas hecho mejóralo haciéndolo por interrupción que es lo suyo.
« Última modificación: 19 de Junio de 2008, 09:19:37 por pocher »

Desconectado jim_17

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 309
    • Blog personal
Re: Controlar Servo mediante pwm por software.
« Respuesta #10 en: 19 de Junio de 2008, 13:25:44 »
Jueeeee chicos !!! muchas gracias, ahora me va medianamente bien, solo falta cuadrar un poco la posicion retocando los delay, intentaré estudiarme lo de las interrupciones, el asm no lo domino nada ni la arquitectura del pic, de momento el aprendizaje que estoy haciendo es a traves de esta web y diferentes manuales, pero el curso que viene ya empiezo 1º Curso de electronica industrial en la UNI !!!


Salu2 espero poder tener este miniproyecto junto con el luchador de sumo para octubre o asi que será mas o menos cuando tenga un poco de dinero para comprar todo lo necesario.
Share the world !

Blog's

http://www.area0x33.com


 

anything