jueves, 3 de marzo de 2011

Servomotor y Pic

Controlando un Servomotor con un pic16f877, por medio de la interrupción del timer0.
Código que realice para entender el funcionamiento del servomotor, aclaro que no es la única forma de realizarlo, y no conozco cual sea la mejor, esta es la primera aplicación que realizo para controlar uno.Si crees que un poco de teoría no te vendrá mal te recomiendo este link: [Servomotor]Bueno si ya conoces la teoría, o eres de los que creen que aquí ay que arriesgar, manos a la obra. 


Estoy usando el pic16f877a, 3 botones, 1 lcd, y por su puesto un Servo.

Como ya sabemos la forma de controlar el servo es por medio de PWM, osea un tiempo en alto y otro en bajo, a una frecuencia de 50hz -Osea todo el ciclo completo cada 20mS-, mi servo es el de la imagen, usado en aeromodelismo, no cuenta con datasheet, -no tiene marca- y no hace un giro exacto de 180º, Su tiempo de operación ronda de los 0.7mS para 0º y 2.7mS para hacer un giro de -casi- 180º.



[Código]
#include <16f877a.h>
#use delay(clock=20000000)
#fuses HS, NOWDT, NOLVP, NOPROTECT
#define LCD_E     PIN_d0
#define LCD_CK    PIN_d1
#define LCD_DAT   PIN_d2
#define LCD_LED   PIN_d3
#include <3pins.c>
#use fast_io(B)

int cont=0;
int pos=16;

#int_timer0                 
 void Pwm()
  {
   set_timer0(150);
   cont++;

   if(cont>=200)
      {
       cont=0;
      }
   if(cont<pos)
    {
      output_high(PIN_B0);
    }
   if(cont=pos)
    {
      output_low(PIN_B0);
    }
  }
void main()
 {
  lcd_init();
  set_tris_b(0b11111110);                   // Pin B0 como salida,
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4); // Preescaler de 4
  EXT_INT_EDGE(l_TO_H);                   // se desborda de Alto a bajo
  enable_interrupts(INT_timer0);         // Activar timer0
  enable_interrupts(global);            // Activar Interrupciones Globales
  set_timer0(150);

   while(1)
    {
    lcd_gotoxy(1,1);
    printf(lcd_putc,"Posicion: ");

    if(Input(Pin_b4))
      delay_ms(100);
    if(Input(Pin_b4))
     {
      pos=7;
      lcd_gotoxy(1,2);
      printf(lcd_putc,"     0 Grados  ");
     }

    if(Input(Pin_b5))
      delay_ms(100);
    if(Input(Pin_b5))
     {
      pos=15;
      lcd_gotoxy(1,2);
      printf(lcd_putc,"     90 Grados  ");
     }

    if(input(pin_b6))
      delay_ms(100);
    if(Input(Pin_b6))
     {
      pos=27;
      lcd_gotoxy(1,2);
      printf(lcd_putc,"     180 Grados  ");
     }
    }
}

[Descripción del código]

El objetivo del código es que al presionar un botón conectado al pin_B4 ponga en alto por 0.7mS el pin_B0 del pic y transcurrido ese tiempo mantenga ese pulso en bajo por 17.3mS, y repetir este proceso indefinidamente, asegurando el ciclo de trabajo por 20mS. -De similar forma para 90º y 180º con sus respectivos tiempos-.
La forma en la que logro esto es usando el timer0, el cual usando el oscilador de 20Mhz, iniciando el timer0 con un valor de 150 y con un preescaler de 4 obtengo que cada 100uS  -0.1 mS- el timer0 desvordara y atenderá la interrupción llamada #int_timer0, dentro de esta interrupción ay una variable llamada cont, la cual contara las veces que desborda el timer0, dentro de esta misma función ay 3 condiciones, la primera reviza si el contador no a sobrepasado los 200 desvordamientos para no superar los 20mS (200 * 0.1mS = 20mS), una ves que sobrepase el contador se reinicia a 0, la otra condición es para poner el servo en la posición indicada por los botones, (B4, B5, B6). Por ejemplo si queremos ponerlo en 90º presionamos el boton B5, el cual tiene un valor de 15 en la variable pos la cual es checada en la segunda condición, la cual compara el valor cont con el valor pos y si cont es menor a pos pone en alto el pin_B0, y la tercera es cuando los dos valores son idénticos apaga esta señal por los 18.5mS restantes (185 desbordamientos).

[Vídeo]




Aquí la representación visual de todo lo dicho.

31 comentarios:

  1. saludos oyes en donde conseguiste esa libreria para el servo se ve muy atractivo je je je je por cierto buen tutorial....

    ResponderEliminar
  2. No recuerdo de donde la baje, pero si gustas la busco y pego el enlace de la librería.

    Saludos!!

    ResponderEliminar
  3. hola podrias compartir la libreriadel servo?

    ResponderEliminar
  4. Hola me puedes pacompartir el archibo que creaste o .hex

    ResponderEliminar
  5. No te sirve el código? Esta para compilarse tal cual.

    Saludos!!

    ResponderEliminar
  6. no por que en la libreria #include <3pins.c> me marca error y tambien en la salidas para el lcd

    ResponderEliminar
  7. soy yo de nuevo espero que me puedas ayudar por favor

    ResponderEliminar
  8. No encontré el Hex, y por ahora no tengo el compilador instalado, La librería la puedes descargar de aquí:

    http://byborre.blogspot.mx/2011/01/lcd-con-3-pines.html

    ResponderEliminar
  9. Pero no afecta nada si borro #include<3pins.c> y los comandos de lcd
    por que lo que mas me interesa es el control del servo con los tres botones como lo tienes.
    Gracias.

    ResponderEliminar
  10. No, no afecta, únicamente tendrías que quitar como bien dices la linea de: #include<3pins.c>,

    las definiciones de la lcd:
    #define LCD_E PIN_d0
    #define LCD_CK PIN_d1
    #define LCD_DAT PIN_d2
    #define LCD_LED PIN_d3

    La inicialización del lcd:

    lcd_init()

    Y las lineas que están en los if

    lcd_gotoxy(1,2);
    printf(lcd_putc," 0 Grados ");

    Saludos!!

    ResponderEliminar
  11. como seria exactamente el codigo para no utilizar la lcd soy nuevo en esto

    ResponderEliminar
  12. Tal cual como esta escrito el código en el post, quitando las lineas que dice un mensaje arriba del tuyo.

    Saludos!!

    ResponderEliminar
  13. corri el programa sin el lcd, al arrancar el programa el angulo de mi servo va a -90° y no me responden los pulsadores, me parece que es la configuracion del servo en el proteus, o pueda que alguna otra cosa este fallando? las especificaciones del modelo del proteus mande de un angulo de -90° a 90° con tiempo de 1 - 2 ms ...

    ResponderEliminar
  14. DONDE PUEDO ENCONTRAR ESE SERVOMOTOR O DESCARGARLO XFA??

    ResponderEliminar
  15. para los q no les funciona la libreia de la lcd la solucion es la siguiente si se fijan bien cuando descargaron la libreria de la LCD ella no se llama 3pins.c como dice en el codigo sino lcd3pines.c las librerias hasy q llamarlas desde el compilador con el nombre correcto por q o sino el compilador no la va a encontrar ya le cambie el nombre y la encontro 0 errores espero les sirva y nuevamnete alguno de uds tienen ese servomotor q aparece en la imagen

    ResponderEliminar
  16. HOLA AMIGO TENGO UNA DUDA, TENGO UN PIC 18F4550 Y NECESITO GENERAR MAS SALIDAS PWM PUESTO QU ESTE PIC SOLO TIENE 2, TIENES IDEA DE COMO HACERLO? MUCHAS GRACIAS

    ResponderEliminar
  17. Hola! Si te fijas en mi programación yo no utilizo el PWM por Hardware sino por Software, para que tu programación quede mejor en cuanto a tiempos, puedes utilizar un Timer, y vas contando los desbordes.

    supongamos un TMR que desborda a 1mS (Una idea vaga) quieres 4 PWM. con perdiodo de 10mS
    1) 10% en alto
    2) 30% en alto
    3) 50% en alto
    4) 90% en alto

    Inicias los 4 pines en alto, al primer desborde pones en bajo el 1) esperas 3 desbordes bajas el 2) esperas 5 desbordes bajas el 3) esperas 9 desbordes bajas el 4) al 10° desborde pones todos los pines en alto y reinicias el ciclo.

    (Obviamente los tiempos son teóricos, con ellos no te funciona un servo, adecua tus tiempos únicamente)

    Saludos!

    P.D: Para mayor resolución que tus desbordes sean en el menor tiempo posible.

    ResponderEliminar
  18. Amigo gracias por responder, no se si conozcas pinguino, es un lenguaje muy similar al arduino, quisiera saber si me podrías colaborar para realizar la programación alli e intentado muchas formas y no e podido..

    ResponderEliminar
  19. Hola!! Ni de Pingüino ni de Arduino.

    Soy mas de C, te puedo ayudar con CCS, C18 o C30.

    Disculpa, pero puedes tratar pidiendo ayuda en el foro de uControl, o TodoPic.

    Saludos! ;)

    ResponderEliminar
  20. jejeje bueno muchas gracias :), pero de todos modos me sirve C, entonces si tienes alguito para el pic 18f4550 te agradecería, al menos la configuración de los puertos tengo que controlar 6 servos.

    ResponderEliminar
  21. :/ No tengo a la mano nada, Te recomiendo C18, inicia con el codigo, y vamos resolviendo dudas puntuales, si quieres inicia configurando el timer 0, poniendo un toggle en la interrupción que atiende dicho timer, así observas como trabaja el timer. Después vamos tirando código parte por parte.

    O bien, para que no te la compliques configura un timer (El que gustes ) pero en Pingüino, con un poco de suerte y le entiendo algo.

    Configura tu timer a X tiempo, y en cada desborde toggleamos un pin, y observamos que pasa.

    Saludos!

    ResponderEliminar
  22. ok muchas gracias entonces iniciare y estaremos en contacto (Y).

    ResponderEliminar
  23. hola oye ya hice la simulacion en proteus y pase el codigo en pic C y no me funciona me puedes explicar como funciona lo de pwm en tu codigo?
    te lo agradeceria

    ResponderEliminar
  24. viejo buen tuto le agradeceria si me facilitara la libreria de ese SERVO para PROTEUS mi correo giogan177@gmail.com agradesco su pronta RTA

    ResponderEliminar
  25. Respuestas
    1. ¿Que no funciona? en el vídeo se muestra funcionando, y el código es el mismo?

      Eliminar
  26. Borre: Me podras orientar con alguna idea o consejo para controlar el servo sin utilizar Botones

    osea posicionarlo en algun punto o llevarlo de un extremo al otro, ¿debo de utilizar otra variable?

    o ¿manejarlo con ciclos for?,¿tendras un ejemplo?,cualquier aportacion...Gracias.

    ResponderEliminar
  27. hola puedes pasarme la libreria del servomotor para proteus

    ResponderEliminar
  28. Hola donde consigo la librería #include <3pins.c>

    ResponderEliminar
    Respuestas
    1. http://byborre.blogspot.mx/2011/01/lcd-con-3-pines.html

      Saludos

      Eliminar