]<span class="texto_mini">Codigo:</span>[hr /
Codigo:
...
#define PIN_SERVO1 PIN_B0
#define PIN_SERVO2 PIN_B1
...
int1 flagSERVO1 = 0;
int tSERVO1 = ticks_PULSO_MEDIO;
int1 flagSERVO2 = 0;
int tSERVO2 = ticks_PULSO_MEDIO;
...
// DISPARO DEL PULSO PWM
if(flagRTCC==1){
flagRTCC=0;
output_high(PIN_SERVO1);
flagSERVO1=1;
output_high(PIN_SERVO2);
flagSERVO2=1;
}
// CONTROL DE ANCHO DEL PULSO PWM
if(flagSERVO1==1){
valTIMER0 = get_TIMER0();
if(valTIMER0>tSERVO1){
flagSERVO1=0;
output_low(PIN_SERVO1);
}
if(flagSERVO2==1){
valTIMER0 = get_TIMER0();
if(valTIMER0>tSERVO2){
flagSERVO2=0;
output_low(PIN_SERVO2);
}
}
...
// Periodos Prefijados
case "1": tSERVO1=ticks_PULSO_MINIMO;
break;
case "2": tSERVO1=ticks_PULSO_MEDIO;
break;
case "3": tSERVO1=ticks_PULSO_MAXIMO;
break;
// Inc Dec Periodo
case "+": if(++tSERVO1>ticks_PULSO_MAXIMO){
tSERVO1=ticks_PULSO_MAXIMO;
}
break;
case "-": if(--tSERVO1<ticks_PULSO_MINIMO){
tSERVO1=ticks_PULSO_MINIMO;
}
break;
case "a": tSERVO2=ticks_PULSO_MINIMO;
break;
case "b": tSERVO2=ticks_PULSO_MEDIO;
break;
case "c": tSERVO2=ticks_PULSO_MAXIMO;
break;
// Inc Dec Periodo
case "m": if(++tSERVO2>ticks_PULSO_MAXIMO){
tSERVO2=ticks_PULSO_MAXIMO;
}
break;
case "n": if(--tSERVO2<ticks_PULSO_MINIMO){
tSERVO2=ticks_PULSO_MINIMO;
}
break;
...
void eco_servos(void){
printf("S1=%u S2=%u
",tSERVO1,tSERVO2);
}



de poque no utilizar un PWM como el TL494 para controlar el ciclo de trabajo a una frecuencia dada por : 
Código: [Seleccionar]do {
// DISPARO DEL PULSO PWM
if(flagRTCC==1){
flagRTCC=0;
output_high(PIN_SERVO1);
flagSERVO1=1;
}
// CONTROL DE ANCHO DEL PULSO PWM
if(flagSERVO1==1){
valTIMER0 = get_TIMER0();
if(valTIMER0>tSERVO1){
flagSERVO1=0;
output_low(PIN_SERVO1);
}
}
}
} while (TRUE);
int1 flagRTCC = 1asi el servo comenzara a moverse desde el primer ms, no? :-)#int_RTCC
void RTCC_isr(void){
contRTCC = contRTCC + 1;
set_TIMER0(6); //en vez de 6 podemos poner "ajuste_fino_RTCC" y declararlo como constante arriba... No te lo tomes a mal RedPic, es broma :-)
if(contRTCC==5){
flag5RTCC=1;
contRTCC=0;
}
}valTIMER0 = get_TIMER0() - 6;#
valTIMER0 = get_TIMER0();
#
if(valTIMER0>tSERVO1){
#
flagSERVO1=0;
#
output_low(PIN_SERVO1);
#
}
//////////////////////////////////////////////////
// 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.