Bueno recien veo que mi explicacion esta un poco mal en la matematica, la voy a corregir, se me escapo una suma por ahi.
****************
EDIT: Recien veo que modificaste toper y topbr, yo lo hice como estaba antes. asi que el codigo estan cambiados, pero es basicamente los nombres.
Si queres simularlo comenza primero con la simulacion cuando esta funcionando (RB4=1), y asignale los valores manualmente a topbr/toper/cero.
Esto implica que tengas que cambiar la parte del codigo al comienzo, en vez de leerlo de la EEPROM que directamente le cargues el numero. Una ves funcionando eso, avanzas a el tema de la EEPROM
**************************
En fin aca esta el codigo:
#include <16f876a.h>
#device adc =10
#use delay (clock=8M)
#fuses XT,NOWDT,NOPROTECT,NOLVP
#include <internal_eeprom.c>
#use fast_io(B)
#use fast_io(c)
#use fast_io(a)
//******declaracion de variables******************************
unsigned int16 cursor=0,toper,topbr,cero,ciclo_util=0;
float Ai,Ad,Bi,Bd;
//***********************************************************
void main()
{
int i;
set_tris_c(0b00000000);
output_c(0b00000000);
set_tris_b(0b11111111);
output_b(0b00000000);
//****************ADC**************************
setup_adc_ports(AN0);//* entrada analogica*//
setup_adc (ADC_CLOCK_INTERNAL);
setup_COUNTERS(RTCC_internal.rtcc_div_8);
// *************PWM**************************************
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_16,255, 1);
set_pwm1_duty(ciclo_util);
//**************Recupero Valores************************
//Aqui sis se reinicio tomo los valores , los calculo para lo que esta guardado en el EEPROM
toper=read_int16_eeprom(0x120);
delay_ms(15);
topbr=read_int16_eeprom(0x122);
delay_ms(15);
cero=read_int16_eeprom(0x124);
Ai = (float)511 / (cero-toper); // Valores recta izquierda y derecha:
Bi = ((float)-511*toper)/(cero-toper); // Yi = Ai*X +Bi
Ad = (float)512 / (topbr-cero); // Yd = Ad*x +Bd
Bd = 511 - (((float)512*cero)/(topbr-cero));
WHILE (1)
{
set_adc_channel (0);
delay_us (20);
for(i=0;i<8;i++) //Promediado del ADC
{
cursor = read_adc ();
}
cursor /= 8;
//*********************************************
// Programacion
//*********************************************
if (input(pin_b4)==0) // switch que habilita la configuracion de parametros
{
if (input(pin_b1)==1) // switch que habilita para establecer
{ // el limite izquierdo ( toper)
delay_ms(20); // Antirebote
while(input(pin_b1)); // Espero hasta que suelte
if(cursor!=toper && cero>toper)
{
// Introducir comprobacion de rangos
write_int16_eeprom(0x120, cursor); // escribe en la memoria
Ai = (float)511 / (cero-toper); // Calcula los nuevos coeficientes de la izquierda
Bi = ((float)-511*toper)/(cero-toper);
}
}
if (input(pin_b2)==1) //switch que habilita para establecer
{ // el limite derecho ( topbr)
delay_ms(20); // Antirebote
while(input(pin_b2)); // Espero hasta que suelte
if(cursor!=topbr && cero<topbr)
{
// Introducir comprobacion de rangos
write_int16_eeprom(0x122, cursor); // escribe en la memoria
Ad = (float)512 / (topbr-cero); // Calcula los coeficientes de la derecha
Bd = 511 - (((float)512*cero)/(topbr-cero));
}
if (input(pin_b3)==1) // switch que habilita para establecer
{ // el centro (cero)
delay_ms(20); // Antirebote
while(input(pin_b3)); // Espero hasta que suelte
if(cursor!=cero)
{
// Introducir comprobacion de rangos
write_int16_eeprom(0x124, cursor); // escribe en la memoria
Ai = (float)511 / (cero-toper); // Calcula ambos coeficientes ya que
Bi = ((float)-511*toper)/(cero-toper); // cambia el centro y cambian ambas rectas
Ad = (float)512 / (topbr-cero);
Bd = 511 - (((float)512*cero)/(topbr-cero));
}
}
}
//********************************************
// Funcionamiento normal
//********************************************
if (input(pin_b4)==1)//switch que habilita el funcionamiemto
{
if(cursor<topbr){cursor=topbr;} // Fijo los limites de la entrada
if(cursor>toper){cursor=toper;}
if(cursor>cero) // Caso que Cursor sea mayor a cero
{ // Es decir lado derecho
a = (Ad*cursor) + Bd;
}
else if (cursor<cero) // Caso Cursor sea menor a 0
{ // Es decir lado izquierdo
a = (Ai*cursor) + Bi;
}
else // Caso que cursor este al medio
{
a=511;
}
if(a!=ciclo_util) // Luego de los calculos
{ // Si cambia lo actualizo al duty
set_pwm1_duty(a);
ciclo_util=a;
}
}
}
}
Funcionamiento?
RB4 tiene una llave.
RB1,RB2,RB3 son botones.
Para el lado que pone a 0 el pin RB4 activa el modo de configuracion, este modo te permite girar tu "cursor" y al presionar RB1 se fija el izquierdo, al presionar RB2 el derecho y RB3 el centro. Una ves posicionado "cursor" se presiona el boton y cuando se suelta comienza a grabarlo en la EEPROM.
No le puse el codigo que limita estas funciones para posibles errores. Eso ya lo comente antes. Igual estan los comments donde se deberian colocar.
Al comienzo del programa se toma los datos de la EEPROM y se calculan los 2 coeficientes de la recta A y B de cada una => Y = Ax + B, siendo el siguiente caracter el lado que corresponden Ai,Bi izquierda y el otro derecha.
Cuando calculo esto ? lo calculo al comienzo del programa y queda guardado en 4 float, el otro caso que tenga que calcularlo es cuando se cambie algun limite, si se cambia el izquierdo entonces debo modificar unicamente la recta izquierda, si es el derecho solo la recta de la derecha, ahora si es el centro, afecta a ambos, por lo tanto calculo las 2.
Finalmente cuando el programa esta marchando se cumple:
Limite izquierda = 0% duty PWM (0)
Centro = 50% duty PWM (511)
Limite derecha = 100% duty PWM ( 1023 )
Sea cual sea el limite de la izquierda, el centro y el limite de la derecha. Siempre y cuando se cumpla que toper < cero < topbr
Visto de otra forma
Lim Izq -------- Centro --------- Lim Der
0% 50% 100%
Los calculos del los factores Ai,Bi,Ad,Bd los hice con C en XC8 por que no poseo CCS pero imagino que seran correctos tambien en el otro compilador, los simule y verifique y me dan valores correctos con los que deben ser.
Espero que funcione ya que no posee nada raro el programa, y perdon por haber metido bastante teoria sobre rectas, es que si queres generarlas dinamicamente como vos queres y no con unos valores fijos entonces no le veo otra escapatoria.
Siguiendo un poco mas el tema, esto es para algo que no posea creo que demasiado movimiento.
El principal problema por ahi es el desgaste del potenciometro si es que vas a usar eso.
Si queres eliminar el problema de contacto y desgaste aun mas, ya vas a tener que pensar en un sensor optico.