Autor Tema: Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC  (Leído 47547 veces)

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

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5100
    • uControl
Re: Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #15 en: 01 de Septiembre de 2007, 16:14:04 »
Diego, no sabes con que ganas he hagarrado estos "viejos" hilos tuyos, ahora que por fin me decidi por aprender CCS.

¡Gracias por escribirlos!
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 RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #16 en: 01 de Septiembre de 2007, 19:44:01 »
Asi me gusta  :mrgreen:

Para eso fueron creados, ¡que te aproveche!  ja ja ja :D  :D :D
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #17 en: 15 de Febrero de 2008, 23:16:22 »
Saludos a todos! comencé a trabajar con servos hace un tiempo, y también a programar pics con C (antes usaba ensamblador)...  y sus comentarios me han servido de mucho... en especial RedPic, eres un maestro eh!! Muchas gracias por tus aportes... aunque yo no estoy controlando los pics desde la pc, sino desde el CA/D... pero la teoría sobre el PWM es igual de aplicable...
De nuevo gracias! cuando termine algo bueno trataré de publicarlo...
Que tengan paz!! sigan divirtiéndose programando pics!!  :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 RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #18 en: 16 de Febrero de 2008, 05:59:47 »
Muchas gracias firepic. Yo también hice un experimento de CAD y generar el PMW en El Termo-Servo o un servo controlado por temperatura.:mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Ejemplito 16F876A: Controlando un SERVO con el PIC (nueva idea)
« Respuesta #19 en: 22 de Febrero de 2008, 18:22:50 »
Epale!
He estado trabajando con servos y me han ayudado mucho los trabajos de Redpic... y no tengo nada en contra de hacerlo así, pero me surgió una idea... y me gustaría que vieran qué les parece...
Con la lógica de Redpic, usamos las interrupciones de RTCC para contar los 20ms que es el período de trabajo del servo...
Y para fijar el ancho del pulso, el el valor del timer y lo compara, así:

Citar
#
        valTIMER0 = get_TIMER0();
#
        if(valTIMER0>tSERVO1){
#
           flagSERVO1=0;
#
           output_low(PIN_SERVO1);
#
        }


Me puse a hacer varios experimentos... y según lo que han comentado otros, no es a mí no mas que me pasa... resulta que a veces hay un pequeño movimiento indeseado en el servo, pequeño, pero lo hay... me puse a pensar... será que el tiempo en alto es crítico y al evaluar el valor del timer con el "if" la cosa no resulta tan exacta?
Y me vino una idea... ¿Qué tal si uso la interrupción por RTCC para contar ese tiempo?
Aquí les dejo un grafiquito como los de Redpic para mostrar lo que estoy diciendo:



De esta forma, la lógica de programación cambia un poquito:

1- Inicialmente pongo el pin que está conectado al cable "control" del servo (lo llamaré salida de ahora en adelante, por flojera) en 1, y el timer se carga con el valor correspondiente al ancho del pulso (aquí hay que tomar en cuenta el oscilador y bla, bla, bla... si... ya ustedes saben el resto del cuento)...

2- Cuando ocurre la primera interrupción, quiere decir que pasó el tiempo que yo quiero que esté el pulso en alto. Entonces pongo la salida a 0 y pongo a 1 una bandera que indica que ya terminó de contarse el "tiempo en alto".

3- Hay que hacer un cálculo sencillísimo: dividir el tiempo en ticks que el timer debería contar para hacer 20ms (con un cristal de 20M y la pre-escala de 1:64 esto es 1563) entre la precarga que le estamos colocando al timer. ¿Para qué? Pues claro, para saber la cantidad de interrupciones que deben ocurrir hasta el siguiente ciclo ¿sencillo verdad? Sí, si, ya sé... no siempre van a ser exactamente los 20ms lindos y bellos... pero ¿qué se va a hacer? Nada es perfecto jajaja... bueno esa no es la respuesta técnica... lo cierto es que según estuve investigando y por los experimentos que hice...puedo ratificar que el tiempo entre pulso y pulso no es tan crítico en los servos... entre 15ms y 30ms funciona para la mayoría... con esta lógica siempre estará entre 19ms y 21ms... ¿es un error pasable no creen?

4- Finalmente, mientras la bandera flag_pulso está en cero (la salida todavía está en 1) no hago nada... esto asegura que tenga un pulso seguro y firme siempre... cuando la bandera cambia a 1 entonces hago los cálculos por si deseo cambiar el ancho de pulso, en este ejemplo lo que tengo que hacer es usar el CAD para leer el valor de un potenciómetro y luego adecuar ese valor al que debe cargarse al timer para que cuente el ancho de pulso adecuado.

5- No hay más que decir... como dice el conejo Box: esto es todo amigos!!

Bien aquí les dejo el código... a mí me funciona perfectamente... pero POR FAVOR, todos, y especialmente ustedes, amigos sabios del ccs en este foro, me dicen sus opiniones!!  :)
La configuración del circuito, como se darán cuenta en el código es:
PIC16F876 (barato y fácil de conseguir jejeje)
Cristal 20MHz
Potenciómetro conectado a Canal 0 (RA0) [puede ser otro dispositivo apropiado, como algún sensor; yo lo hice inicialmente con un potenciómetro sólo de prueba]
Control del Servo conectado a RC4
Servo HS-300.

Paz y bien para todos!
Nos leemos en el foro!  :mrgreen:

Código: [Seleccionar]
//////////////////////////////////////////////////
// Lee el canal 0 del pic y modifica      //
//       PWM para control de servo            //
//////////////////////////////////////////////////

//Definiciones generales previas:
//PIC16F876
//Cristal de 20MHz
//Pin donde está conectado la línea de control del servo
//El programa está hecho para un servo, pero esta lógica
//puede ampliarse de forma sencilla para abarcar más servos.

#include <16f876.h>
#device PIC16F876 ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay(CLOCK=20000000)
#define servo_1 PIN_C4

int canal_adc=0; //para elegir qué servo mover (elige el potenciómetro a leer)
int ancho_pulso=0;     //el valor que se va a cargar en el timer0 y que representa el ancho del pulso
int n=0;      //la cantidad de veces que se
int flags=0;
int i=0;
int16 j=0;
int16 valor=0;

#bit flag_pulso = flags.0


const int tmr_pulso_minimo = 39;
const int tmr_pulso_medio  = 117;
const int tmr_pulso_maximo = 195;
const int16 periodo = 1563;

void conf_conversion (int canal) //Función que configura el CAD del pic y fija canal a leer.
{
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(RA0_RA1_RA3_ANALOG);
set_adc_channel(canal);
delay_us(20);
}

int16 conversion()          //Esta función es la conversión en sí misma, devuelve
{ //el valor de 10 bits correspondiente a la lectura del canal analógico.
int16 value=0;
value=read_adc();
return(value);
}

void ajusta_pwm () //Esta función fija los parámetros para el siguiente pulso de la PWM.
{
float escala=0;
valor=conversion(); //Lee el valor analógico del dispositivo conectado al pic (ej: potenciómetro).
escala=1024/(tmr_pulso_maximo-tmr_pulso_minimo);//Escala para convertir a un valor que se cargará a timer0
ancho_pulso=(int)(valor/escala);        //y es proporcional al ancho de pulso deseado.
ancho_pulso=256-tmr_pulso_minimo-ancho_pulso;     //El valor se carga en el timer.
n=(int)(periodo/ancho_pulso); //Calcula la cantidad de interrupciones necesarias
      //para completar un período de PWM (aprox. 20ms)
}

#INT_RTCC //Función de interrupción por sobreflujo en timer0.
RTCC_isr ()
{
if(i==1)         //La ocurrencia de la primera interrupción indica al pic
{   //que ha transcurrido el tiempo del ancho de pulso deseado,
output_low(servo_1); //de manera que la señal debe fijarse a cero (fin del pulso).
flag_pulso=1;     //y fijo a 1 una bandera que indica que el pulso ya terminó (flag_pulso).
}
if(i==n)         //Si ha interrumpido la cantidad de veces necesarias
{    //para completar un período:
i=0;   // -Aclaro el contador.
output_high(SERVO_1);  // -La señal a 1 (comienza próxima ciclo, comienza nuevo pulso).
flag_pulso=0;      // -Aclaro bandera (flag_pulso) que indica que el pulso no ha terminado.
}
i++; //Cuenta cada vez que ocurre interrupción por sobreflujo en timer 0.
set_rtcc(ancho_pulso); //Y vuelvo a cargar el valor deseado al timer, que es proporcional al ancho de pulso.
}

main()
{
int canal_an=0; //Indica qué canal del CAD voy a leer.
setup_counters(RTCC_INTERNAL,RTCC_DIV_64);//Configura el timer0 (RTCC), aquí uso pre-escala de 1:64
enable_interrupts(INT_RTCC); //Habilita interrupción por sobreflujo en timer0
enable_interrupts(GLOBAL);   //Habilita interrupciones globales
conf_conversion(canal_an);   //Llama a la función para configurar el CAD
ajusta_pwm(); //Llama a función para preparar primer ciclo de PWM
i=n;       //inicializa i en n, de manera que
RTCC_isr(); //cuando entre en esta función coloque la señal a 1 (inicia pulso).
while(TRUE) //Un ciclo infinito.
{
if(flag_pulso==1)ajusta_pwm(); //Si ya pasó el pulso, ajusta PWM (de este modo el pic no hará nada
} //durante el tiempo que dure el pulso, el cual es crítico
} //en lo que respecta a controlar el servo.
« Última modificación: 22 de Febrero de 2008, 18:32:16 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 RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #20 en: 22 de Febrero de 2008, 18:32:52 »
Pues si señor Firepic, tiene usted toda la razón. Y tiene tanta razón que exactamente eso es lo que he hecho en este Algoritmo para controlar hasta 8 servos con una sola interrupción (en C) (La diferencia de casi dos años entre estos dos hilos míos debe notarse en algo)  :mrgreen: :mrgreen: :mrgreen: :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #21 en: 22 de Febrero de 2008, 20:35:54 »
Excelente trabajo Don RedPic!! Gracias por la respuesta... no sé si es casualidad, pero parece que después de llevar tiempo programando uno empieza a programar igual que muchos otros programadores verdad?  :D  y como siempre buenísimas explicaciones! Nuevamente gracias!  :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 RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #22 en: 22 de Febrero de 2008, 21:14:21 »
Si, tienes mucha razón en eso. Al cabo de un tiempo las mismas cosas terminan haciéndose de la misma forma. Vamos aprendiendo y comprendiendo tanto los problemas que nos planteamos como las soluciones que les damos.

En otro hilo por ahí comentábamos cómo nos ocurría muy a menudo que descubríamos solos cosas que hacía años que eran cosa común entre los programadores experimentados, y cómo sentíamos en esos momentos una extraña mezcla de orgullo por haber sido capaces de desarrollar estos conceptos sin ayuda externa y desilusión al descubrir que no éramos, ni mucho menos, los primeros en hacerlo.

Y estos casos son doblemente gratificantes en personas que ya tenemos una edad abundante, ya que nos igualaba en una característica muy de la juventud: la de creer siempre que lo que descubrimos es la primera vez que se descubre.

Vana ilusión que cura la edad pero que hace calentar el estómago cuando se siente de nuevo mientras se peinan canas desde hace años.  :mrgreen: :mrgreen: :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #23 en: 26 de Febrero de 2008, 00:24:39 »
Mis saludos don RedPic! gracias por tus respuestas, ahora veo que no sólo eres un maestro con los pic, sino que también le metes un poco a la poesía :D Bueno excelente! mis felicitaciones!
Ok, nos leemos en el foro!  :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 Deirdre

  • PIC10
  • *
  • Mensajes: 10
Re: Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #24 en: 22 de Abril de 2008, 05:45:03 »
Bueno, decir que yo he estado haciendo prubas conel "ejemplito" del PRicnpio y que me ha ido de maravilla. No me acoradba nada de lo de PWM y las explicaciones son maravillosas.  :-/GRACIAS!!!!!!!!!!!!!!!!!!

Desconectado pirate_x

  • PIC10
  • *
  • Mensajes: 24
    • Pirata, Inc Electronics
Re: Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #25 en: 05 de Septiembre de 2008, 08:53:57 »
Muy buen ejemplo, tenia una idea sobre hacerlo de esta forma y aqui me ha quedado super claro.
tengo una pregunta..

al momento de setear el timer:
"
set_TIMER0(AJUSTE_FINO_DE_RTCC);
                                                                               "

no es necesario volverlo a set_TIMER0(0); nuevamente??????, se resetea automaticamente para los demas flagRTCC ???

Saludos.

Desconectado CSIC

  • PIC10
  • *
  • Mensajes: 1
Re:Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #26 en: 15 de Marzo de 2017, 22:39:09 »
y como seria el diagrama de conexion?

Desconectado stretchmame32

  • PIC10
  • *
  • Mensajes: 6
Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #27 en: 04 de Junio de 2017, 23:28:25 »
concuerdo con redpic, en realidad es muy sencillo controlar este tipo de servomotores usando pwm aqui el ejemplo de la aplicacion

Desconectado josecuello

  • PIC10
  • *
  • Mensajes: 2
Re:Ejemplito 16F876A: Controlando un SERVO con el PIC desde nuestro PC
« Respuesta #28 en: 10 de Junio de 2019, 16:46:57 »
y para pasar el código a XC8 como hago?


 

anything