Autor Tema: Servo controlado mediante pwm por hardware  (Leído 5627 veces)

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

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Servo controlado mediante pwm por hardware
« en: 20 de Marzo de 2008, 03:49:10 »
Para poder usar los módulos hardware CCP con el Servo no se puede usar con fosc=4MHz,
ya que así el Tmáx=(255+1)·4·1/4MHz·16=4096us  [ T=(PR2+1)·4·Tosc·TMR2preesc ], con
lo que la fmín=1/Tmáx=1/4096us=244,14Hz y esta frecuencia no nos sirve ya que los
servos funcionan entre 50Hz y 100Hz. La solución es modificar la fosc.

1er PROGRAMA:

Usaremos una fosc=200KHz, con ella y cargando el PR2 con 249 y con TMR2preesc=4
conseguimos: T=(249+1)·4·1/200KHz·4=20ms con lo que la F=1/T=1/20ms=50Hz

Código: [Seleccionar]
#include <16F877.h>
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, WRT
#use delay(Clock=200000) //fosc=200KHz (para que no salgan decimales en CCPR1L)
#include <lcd.c>

#use fast_io(A)
#use fast_io(B)

#byte port_a = 5
#byte port_b = 6

void main(void)
{
int8 w;
long CCPR1L_DER,CCPR1L_CEN,CCPR1L_IZQ; //Usaremos los 2 bits de CCPCON1<5:4>
//Si usaramos int en la fórmula de CCPR1L
//aparecería un 4, que no nos sirve, ya que
//dá lugar a decimales

set_tris_a(0b11111111);
set_tris_b(0b00000000);

setup_ccp1(CCP_PWM);
setup_ccp2(CCP_PWM);
setup_timer_2(T2_DIV_BY_4,249,1); //T=(PR2+1)·4·Tosc·TMR2preesc
//PR2=(T/(4·Tosc·TMR2preesc))-1=
//=(20ms/(4·(1/200KHz)·4))-1=249
lcd_init();

lcd_gotoxy(1,1);
printf(lcd_putc,"S1c");
lcd_gotoxy(5,1);
printf(lcd_putc,"S2c");

CCPR1L_DER=100;
CCPR1L_CEN=75;
CCPR1L_IZQ=50;

set_pwm1_duty(CCPR1L_CEN); // Inicialmente Servos al centro
set_pwm2_duty(CCPR1L_CEN);

while (1)
{

if (w!=port_a)
{
w=port_a;
switch(port_a)
{

//------------------------------------- SERVO 1 ------------------------------------

case 1:
lcd_gotoxy(1,1);
printf(lcd_putc,"S1d");
set_pwm1_duty(CCPR1L_DER); // Derecha (2ms)
break;
case 2:
lcd_gotoxy(1,1);
printf(lcd_putc,"S1c"); // Centro (1,5ms)
set_pwm1_duty(CCPR1L_CEN);
break;
case 4:
lcd_gotoxy(1,1);
printf(lcd_putc,"S1i"); // Izquierda (1ms)
set_pwm1_duty(CCPR1L_IZQ);
break;

//------------------------------------- SERVO 2 ------------------------------------

case 9:
lcd_gotoxy(5,1);
printf(lcd_putc,"S2d"); // Derecha (2ms)
set_pwm2_duty(CCPR1L_DER);
break;
case 10:
lcd_gotoxy(5,1);
printf(lcd_putc,"S2c"); // Centro (1,5ms)
set_pwm2_duty(CCPR1L_CEN);
break;
case 12:
lcd_gotoxy(5,1);
printf(lcd_putc,"S2i"); // Izquierda (1ms)
set_pwm2_duty(CCPR1L_IZQ);
break;
}
}
}
}

//Calculos:

// T=(PR2+1)·4·Tosc·TMR2preesc ---> PR2=
// Duty=(CCPR1L:CCPCON1<5:4>)·Tosc·TMR2preesc --> CCPR1L:CCPCON1<5:4>=Duty/(Tosc·TRM2preesc)

// T=(249+1)·4·1/200KHz·4=20ms con lo que la F=1/T=1/20ms=50Hz
// CCPR1L:CCPCON1<5:4>=1,5ms/(1/200KHz)·4=75 Servos al centro
// CCPR1L:CCPCON1<5:4>=1ms/(1/200KHz)·4=50 Izquierda
// CCPR1L:CCPCON1<5:4>=2ms/(1/200KHz)·4=100 Derecha


2º PROGRAMA:

Usaremos una fosc=1MHz a partir del oscilador interno de un PIC16F88, con ella y
cargando el PR2 con 255 y con TMR2preesc=16 conseguimos: T=(255+1)·4·1/1MHz·16=16,38ms
con lo que la F=1/T=1/16,38ms=61,05Hz

Código: [Seleccionar]
#include <16F88.h>
#fuses NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, WRT, INTRC_IO, NOMCLR
//NOMCLR para que lea un 0 en el pin RA5 y no tenga que cambiar el valor de los case
//Si se quisiera enviar el pwm por RB3 añadiriamos el fuse ccpb3, por omisión, pwm por RB0

#use fast_io(A)

#byte port_a = 5

void main(void)
{
int8 w;
long CCPR1L_DER,CCPR1L_CEN,CCPR1L_IZQ; //Usaremos los 2 bits de CCPCON1<5:4>
//Si usaramos int en lugar de long,
//en la fórmula de CCPR1L aparecería un 4
set_tris_a(0b11111111);
set_tris_b(0x00);

setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_16,255,1); //T=(PR2+1)·4·Tosc·TMR2preesc
//PR2=(T/(4·Tosc·TMR2preesc))-1=
//=(16,384ms/(4·(1/1MHz)·16))-1=255

setup_oscillator(OSC_1MHZ);

// Duty=(CCPR1L:CCPCON1<5:4>)·Tosc·TMR2preesc
// CCPR1L:CCPCON1<5:4>=Duty/(Tosc·TRM2preesc)
CCPR1L_DER=125; //CCPR1L:CCPCON1<5:4>=2ms/(1/1MHz)·16=125   Derecha
CCPR1L_CEN=94; //CCPR1L:CCPCON1<5:4>=1,5ms/(1/1MHz)·16=93,75=94  Servo al centro
CCPR1L_IZQ=62; //CCPR1L:CCPCON1<5:4>=1ms/(1/1MHz)·16=62,5=62   Izquierda



set_pwm1_duty(CCPR1L_CEN); // Inicialmente Servo al centro

while (1)
{
if (w!=port_a)
{
w=port_a;
switch(port_a)
{
case 1:
set_pwm1_duty(CCPR1L_DER); // Derecha (2ms)
break;
case 2:
set_pwm1_duty(CCPR1L_CEN); // Centro (1,5ms)
break;
case 4:
set_pwm1_duty(CCPR1L_IZQ); // Izquierda (1ms)
break;
}
}
}
}

Estos programas no han sido provados físicamente, tan solo por PROTEUS.

Os adjunto más abajo los ficheros .c, .hex y .dsn para que los podais simular.

Un saludo

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Servo controlado mediante pwm por hardware
« Respuesta #1 en: 20 de Marzo de 2008, 08:54:33 »
Siempre me ha llamado la atención que Microchip no tenga resuelto este tema para la frecuencia de oscilación más alta, siendo los servos una aplicación tan común.
Gracias Pocher.

Desconectado gu1llermo

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 217
Re: Servo controlado mediante pwm por hardware
« Respuesta #2 en: 20 de Marzo de 2008, 09:43:24 »
Esta era la solución:

Código: [Seleccionar]
#use delay(Clock=200000)//fosc=200KHz (para que no salgan decimales en CCPR1L)
 :shock:  :D que bueno, en verdad no lo sabía, gracias por la inf y el post completo, ahora los que tinen servos podrán jugar un ratico. :mrgreen:

Está muy buena la información, pero tengo una duda: ¿para el caso del 1er programa: tengo que usar un oscilador externo de 200Khz?

Saludos.
« Última modificación: 20 de Marzo de 2008, 09:59:54 por gu1llermo »

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Servo controlado mediante pwm por hardware
« Respuesta #3 en: 20 de Marzo de 2008, 13:53:35 »
Sí debes construirte un OSC de esa frecuencia. Internos no recuerdo si había algún PIC que trabajase a esa frecuencia.

El oscilador se puede configurar de 4 maneras distintas, dependiendo de la velocidad y del tipo de circuito oscilador empleado.

-  XT: Es un acrónimo que viene de XTAL (o cristal en castellano). Este modo de funcionamiento implica varias cosas. La primera es que tendremos que disponer de un cristal de cuarzo externo al PIC. Este cristal entregará los pulsos necesarios al microcontrolador con una frecuencia determinada. La exactitud de este dispositivo es muy alta, por lo que lo hace muy recomendable para casi todas las aplicaciones. De esto podemos entender que habrá que algún elemento externo al PIC, que son, el cristal y dos condensadores. El valor del cristal generalmente será de 4Mhz (como mucho), y los condensadores serán cerámicos de entre 15 y 33 nF.

-   RC: Este es el sistema más sencillo y económico. Se basa en un montaje con una resistencia y un condensador (acrónimo proveniente de la combinación de palabras inglesas: Resistor - Capacitor). La velocidad a la que oscile el PIC dependerá de los valores del condensador y de la resistencia. Estos valores los podemos encontrar en la sección dedicada al oscilado o en el dataste del PIC. La máxima frecuencia que podremos emplear con este sistema será de 1.5MHz.

-    HS: Para cuando necesitemos aplicaciones de alta velocidad, entre 4 y 10Mhz. Este montaje se basa también en un cristal de cuarzo, como el XT

-    LP: (Low Power) Este descenso del consumo en el PIC que anuncia esta modalidad de funcionamiento significa que la frecuencia de oscilación será menor que en la configuración XT. La velocidad máxima a la que podemos poner el PIC con este oscilador es de 200Khz. Al igual que el XT y el HS, necesitaremos de un cristal de cuarzo y unos condensadores.

Un saludo


Desconectado gu1llermo

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 217
Re: Servo controlado mediante pwm por hardware
« Respuesta #4 en: 20 de Marzo de 2008, 15:10:56 »
Ah! oka, yo siempre e usado los cristales de 20Mhz, no sabía que existían cristales de 200KHz.

Entonces según lo que explicas también pudimos haber colocado LP en vez de XT, cierto? pero no RC porque no es una red RC, valga la redundancia, y mucho menos HS porque no está entre 4Mhz y 20MHz.

Solo son unas pequeñas dudillas técnicas que me gustaría aclarar  :mrgreen:

Gracias de antemano y saludos.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Servo controlado mediante pwm por hardware
« Respuesta #5 en: 20 de Marzo de 2008, 17:02:32 »
En efecto el fuse para 200khz debiera haber sido LP en lugar de XT. Eso un montaje real lo hubiese delatado, sin embargo PROTEUS lo deja pasar (por desgracia).

Una pregunta Guillermo para mandar números binarios desde el VTERM de PROTEUS uso el Ctrl+a para enviar un 1, ..., Ctrl+z para enviar un 26 pero como se hace para enviar un 0 (Con Ctrl+@ no se activa el Servo0)

Un saludo

Desconectado gu1llermo

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 217
Re: Servo controlado mediante pwm por hardware
« Respuesta #6 en: 20 de Marzo de 2008, 18:34:43 »
No sabía que podíamos enviar datos de esa forma con el virtual terminal, de dónde sacastes esa información porqué busqué en internet y en éste foro y no conseguí nada, por otro lado conecté mi hp48gx al puerto COM1 y en el proteus conecté el virtual terminal con el COMPIM, de tal forma que cualquier dato que envíe el virtual terminal lo recibe mi hp y probé todas las combinaciones posibles del teclado, ctrl+tecla, ctrl+shift+tecla, ctrl+alt+tecla, ctrl+shift+alt+tecla, y nada que dí con ese número, en mi hp no puedo editar el carácter 0, me dice que es un carácter nulo (Error: Can´t edit null char) pero si lo puedo enviar, lo que te podría recomendar es que edites el programa para que el valor recibido le restes 1, es decir cuando le envíes el índice del servo a controlar nada más  :wink: y así si puedes controlar todos, desde el 1 al 16.

Es decir, ésta parte:

Código: [Seleccionar]
i=getc();
quedaría así:

Código: [Seleccionar]
i=getc()-1;
Saludos.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Servo controlado mediante pwm por hardware
« Respuesta #7 en: 21 de Marzo de 2008, 03:39:24 »
Por si alguién no sabe de qué estamos hablando, todo esto se refiere a la recepción RS232 empleada en estos programas:  http://www.todopic.com.ar/foros/index.php?topic=20918.0

Guillermo esas combinaciones de teclas son caracteres de control no imprimibles y pensaba que era la forma en que enviabas la información a los Servos. Por eso te pregunté como se enviaba el 0, porque con Ctrl+@ no me va y no sé como hacerlo.

De todas formas yo modificaría el programa para enviar caracteres "normales" y no caracteres de control. Es decir si quiero enviar por ejemplo un 26 primero envio el 2, luego el 6 y luego un Return que detectaría el PIC para saber que se ha terminado. ¡Ah! y la recepción de caracteres la haría por interrupción RDA, es más segura.

Un saludo

Desconectado gu1llermo

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 217
Re: Servo controlado mediante pwm por hardware
« Respuesta #8 en: 21 de Marzo de 2008, 15:19:09 »
Hola pocher, te respondía aquí

Saludos.

Desconectado sokoloko

  • PIC12
  • **
  • Mensajes: 77
Re: Servo controlado mediante pwm por hardware
« Respuesta #9 en: 01 de Octubre de 2010, 10:06:26 »
Hola,

Es solo para confirmar que el segundo programa de Pocher con el 16F88, lo he montado en una plaquita y funciona perfectamente.

He hecho algun cambio para que admitiera una entrada analogica y es divertido ver como "copia" los movimientos del potenciometro.

Saludos!!!!

Desconectado panxoo_15

  • PIC10
  • *
  • Mensajes: 1
Re: Servo controlado mediante pwm por hardware
« Respuesta #10 en: 20 de Diciembre de 2010, 18:34:49 »
HOLA CHICOS !
NEcesito de su ayuda !!
me parecio interesante lo que hicieron !!
lo que pasa que es el dia de mñn tengo que
presentar mi proyecto y no lo he podido terminar
estoy haciendo un robot con servos !
y mi profesor mñn si o si
quiere casi el 80 % de todo !!
y queria saber si uds me podian mandar lo que tienen
de este proyecto se los agradeceria mucho !!
pliss
espero sus respuestas !!
les dejo mi msn !
panchoo_15@hotmail.com

Gracias Chicos !!!