Buen dia, actualmente estoy trabajando en un proyecto donde controlo un motor con un conversor Buck y quiero que por teclado pueda ingresar tres velocidades diferentes (variando su PWM) cada velocidad debe permanecer un tiempo determinado tambien por teclado por ejemplo: que la velocidad 1 permanezca un tiempo 1, luego suba a la velocidad 2 y permanezca un tiempo 2 y así para la ultima. ya puedo hacer los cambios de velocidad, pero tengo problemas con los tiempos; lo intente con un delay, pero en el montaje físico los tiempos no coinciden (demora más tiempo que el programado). estoy intentando configurar un timer, pero no funciona por eso agradeceriá cualquier ayuda que me puedan brindar adjunto el código y esquematico en proteus

:
#INCLUDE <16F887.h>
#DEVICE ADC=10
#USE DELAY(CLOCK=20000000, Crystal=20000000)
#FUSES XT,NOPROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP
#DEFINE USE_PORTB_KBD TRUE //Por defecto el teclado se conecta al puerto D
#INCLUDE <LCD.C>
#INCLUDE <KBD4x4.C>
#include <stdlib.h>
#include <string.h>
#use standard_io(b)
#define KEYHIT_DELAY 200 //Tiempo de espera del teclado en milisegundos
#byte PORTB= 6
#byte PORTC= 7
#BYTE PORTA= 5
#BYTE PORTD= 8
float R=0, R2, R3, t1=0, t2=0, t3=0;
char tecla,c;
int Timer2,Poscaler,i, seg;
int16 duty0, duty, duty1, duty2, tiempo1, tiempo2, tiempo3, cont=0;
/*===========================================================================*/
/*======================= FUNCION TECLA =======================*/
/*===========================================================================*/
//Funcion encargada de esperar a que se presione una tecla
char tecla(void)
{
char c;
do{ //espera hasta que se presione una tecla
c=kbd_getc(); //Captura valor del teclado
}
while(c=='\0');
return(c);
}
/*===========================================================================*/
/*============ FUNCION PARA DIGITAR ESCALÓN/SETPOINT =====================*/
/*===========================================================================*/
long escalon(int nd)
{
//Esta funcion captura el escalon desde el teclado, si el proceso está tomando
//datos el escalon sirve para exitar el sistema, por otro lado si el sistema
//está controlando, el escalo sirve para establecer el setpoint del sistema
long val;
int i;
char str[5]; //Variable tipo String
str[0]='0';
for(i=0;i<nd;i++)
{
c=tecla(); //Lee el valor del teclado y espera hasta que alguna tecla se pulse
delay_ms(10);
if(c=='#'){
reset_cpu();}
if(c!='*'){
lcd_gotoxy(5+i,4); //Muestra el digito presionado en el LCD
lcd_putc(c);
str[i]=c; //Almacena el dato presionado en la variable String
}
else{i=nd;} //Si se presiona * sale del For
}
val = atol(str); //Convierte el String en un valor numerico
return (val);
}
////////////////////////función_teclado_tiempo////////////////////
long escalon1(int nd)
{
//Esta funcion captura el escalon desde el teclado, si el proceso está tomando
//datos el escalon sirve para exitar el sistema, por otro lado si el sistema
//está controlando, el escalo sirve para establecer el setpoint del sistema
long val1;
int i;
char str[5]; //Variable tipo String
str[0]='0';
for(i=0;i<nd;i++)
{
c=tecla(); //Lee el valor del teclado y espera hasta que alguna tecla se pulse
delay_ms(10);
if(c=='#'){
reset_cpu();}
if(c!='*'){
lcd_gotoxy(5+i,4); //Muestra el digito presionado en el LCD
lcd_putc(c);
str[i]=c; //Almacena el dato presionado en la variable String
}
else{i=nd;} //Si se presiona * sale del For
}
val1 = atol(str); //Convierte el String en un valor numerico
return (val1);
}
#int_timer1 //TIMER1
void sampling_time(void){
cont--; //Se decrementa hasta llegar a cero
set_timer1(35536);//Carga de nuevo el timer1
if (cont<=0) // Si llega a cero, se cumplió el periodo de muestreo
{
seg++;
cont=21; // Inicializa el contador para el próximo periodo
}
}
/*===========================================================================*/
/*======================= FUNCION DEL PRINCIPAL =======================*/
/*===========================================================================*/
void main()
{
Timer2=71;
Poscaler=1;
setup_timer_2(t2_div_by_1,Timer2,Poscaler); //Configuracion de Timer 2 para establecer frec. PWM a 1kHz
setup_ccp1(ccp_pwm); //Configurar modulo CCP1 en modo PWM. Dejo en cero la salida PWM
port_b_pullups (0xFF); //Utiliza las resistencias PULL UP internas del puerto B
set_tris_c(0);
set_tris_d(0);
LCD_INIT(); //Inicializo el LCD
LCD_PUTC("\f"); //Limpio el LCD
kbd_init();
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_8 );
cont=21; //Carga Contrador para Calcular el Periodo de Muestreo
seg=0;
set_timer1(15536); // Inicializa el Timer 1 para calcular 8 Segundos de Ts
// Habilitar las interrupciones del PIC
enable_interrupts(int_timer1);
enable_interrupts(GLOBAL);
while(true)
{
lcd_gotoxy(1,1);
LCD_PUTC("velocidad 1");
lcd_gotoxy(1,4);
LCD_PUTC("V1: ");
R=escalon(4); //Llama la funcion para digitar el escalon de exitacion
//Valida si R esta entre 0 y 256 (Esto es otra forma de usar el if - else)
(R>0) ? 260:R;
duty = R;
lcd_gotoxy(1,1);
LCD_PUTC("tiempo 1");
lcd_gotoxy(1,4);
LCD_PUTC("t1: ");
t1=escalon(4); //Llama la funcion para digitar el escalon de exitacion
//Valida si R esta entre 0 y 256 (Esto es otra forma de usar el if - else)
(t1>0) ? 260:t1;
tiempo1= t1;
lcd_gotoxy(1,1);
LCD_PUTC("velocidad 2");
lcd_gotoxy(1,4);
LCD_PUTC("V2: ");
R2=escalon(4); //Llama la funcion para digitar el escalon de exitacion
//Valida si R esta entre 0 y 256 (Esto es otra forma de usar el if - else)
(R2>0) ? 260:R2;
duty1= R2;
lcd_gotoxy(1,1);
LCD_PUTC("tiempo 2");
lcd_gotoxy(1,4);
LCD_PUTC("t2: ");
t2=escalon(4); //Llama la funcion para digitar el escalon de exitacion
//Valida si R esta entre 0 y 256 (Esto es otra forma de usar el if - else)
(t2>0) ? 260:t2;
tiempo2= t2;
lcd_gotoxy(1,1);
LCD_PUTC("velocidad 3");
lcd_gotoxy(1,4);
LCD_PUTC("V3: ");
R3=escalon(4); //Llama la funcion para digitar el escalon de exitacion
//Valida si R esta entre 0 y 256 (Esto es otra forma de usar el if - else)
(R3>0) ? 260:R3;
duty2= R3;
lcd_gotoxy(1,1);
LCD_PUTC("tiempo 3");
lcd_gotoxy(1,4);
LCD_PUTC("t3: ");
t3=escalon(4); //Llama la funcion para digitar el escalon de exitacion
//Valida si R esta entre 0 y 256 (Esto es otra forma de usar el if - else)
(t3>0) ? 260:t3;
tiempo3= t3;
IF(seg==50) //Pregunta si ya se llego a 60 segundos
seg=0; //Si si, vuelva a SEG a cero
ELSE { //Si no,
for(duty=0;duty<=R;duty++){
//Muestra el SETPOINT en pantalla
lcd_gotoxy(1,4);
printf(lcd_putc,"V1: %3.1Lu",duty);
delay_ms(20);
set_pwm1_duty(duty);
}
}
//delay_ms(tiempo1);
IF(seg==60) //Pregunta si ya se llego a 60 segundos
seg=0; //Si si, vuelva a SEG a cero
ELSE //Si no,
for(duty1=duty;duty1<=R2;duty1++){
//Muestra el SETPOINT en pantalla
lcd_gotoxy(1,4);
printf(lcd_putc,"V2: %3.1Lu",duty1);
//delay_ms(20);
set_pwm1_duty(duty1);
}
IF(seg==70) //Pregunta si ya se llego a 60 segundos
seg=0; //Si si, vuelva a SEG a cero
ELSE //Si no,
for(duty2=duty1;duty2<=R3;duty2++){
//Muestra el SETPOINT en pantalla
lcd_gotoxy(1,4);
printf(lcd_putc,"V3: %3.1Lu",duty2);
//delay_ms(20);
set_pwm1_duty(duty2);
}
for(duty0=duty2;duty0>=1;duty0--){
lcd_gotoxy(1,4);
printf(lcd_putc,"apagando: %3.1Lu",duty0);
delay_ms(20);
set_pwm1_duty(duty0);
}
}
}