# Mostrar voltaje sin usar ADC



## callecuatro1976 (Ago 29, 2018)

hola  necesito ayuda con un problema que no se como resolver , tengo un programa que muestra la tensión , un voltámetro la muestra es por el adc pero cuando pongo una carga se mueve mucho la muestra , como puedo hacer para mostrarla en el lcd que quede fija , por mas que haya pequeñas oscilaciones .


```
#include <16f886.h>
#device ADC=10
#use     delay(internal = 8MHz)                           
#define  LCD_DATA_PORT getenv("SFR:PORTC")
#include <flex_lcd.c>

#define LCD_RW_PIN    PIN_C3
//#include <internal_eeprom.c>


int1 flagHayDatos=0;
float const ticks_us = 4.0;          // microsegundos por Tick del Timer 1 @ 8 MHz. (Osc. Interno)
//float const ticks_us = 8.0;          // microsegundos por Tick del Timer 1 @ 8 MHz. (Osc. Cristal)
long int  var2=0;
int8 flancos;
int8 flag_flanco;
int16 periodo1,periodo2,periodo3;
int16 tiempo_alto,tiempo_bajo,tiempo_total;
float us_alto,us_bajo,us_total,valor2,amper, duty;
   int porcentaje, porcentaje2;
   int frecuencia;
  
int16 valor_adc;
   float voltaje;
int8   ciclo_activo=1;
void voltaje(void);
  int16 cont3;   
  
  
#INT_EXT
void sdi_externa_RB0 (void)
{
   flancos++;                          // Incrementar la variable "flancos"
  
   if(!flag_flanco)                    // Si el flanco del pulso es bajo...
   {
      if(flancos == 1)                 // Si el conteo de flancos es 1...
      {
         set_timer1(0);                // Limpiar el Timer 1
         periodo1 = get_timer1();      // "periodo1" tendrá el tiempo del pulso en alto.
      }
      if(flancos == 3)                 // Si el conteo de flancos es 3...
         periodo3 = get_timer1();      // "periodo3" tendrá el tiempo del pulso en alto.
        
         EXT_INT_EDGE(H_TO_L);         // Establecer la interrupción por flanco de bajada.
         flag_flanco = 1;              // Indicar que el próximo flanco será de bajada.
   }
   else                                // Caso contrario. (Pulso en estado alto)...
   {
      periodo2 = get_timer1();         // "periodo2" tendrá el valor del pulso en bajo.
      EXT_INT_EDGE(L_TO_H);            // Establecer la interrupción por flanco de subida.
      flag_flanco = 0;                 // Indicar que el próximo flanco será de subida.
       if(flagHayDatos==0){       // Si los datos anteriores han sido procesados ...
      flagHayDatos=1;          // Indico que ya hay nuevos datos de flancos para calcular
    }
   }

   if(flancos > 2)flancos = 0;         // Si la variable "flancos" llega a 3, ponerla a 0.
}



void establecer_ciclo (int8 ciclo)
{
  
   set_pwm1_duty(ciclo);   // Establecer el ciclo activo
   lcd_gotoxy(10,3);
   // Obtener el porcentaje del ciclo activo.
   porcentaje2 = (ciclo / 24.5) *10;
   // Mostrar el porcentaje del ciclo activo para la carga.            
   printf(lcd_putc,"PWM:%02u%%",porcentaje2,);
        voltaje();
 
    
}
void voltaje (void)
{
int16 valor_adc;
float voltaje;
 set_adc_channel(0); // Establecer la lectura del canal ADC 10
   delay_us(62);
   valor_adc = read_adc(); // Tomar la lectura del voltaje.
   voltaje = ((valor_adc * 18.0) / 1023);
 
  lcd_gotoxy(11,1);
  printf(lcd_putc,"V=%4.1fV ",voltaje);
    
delay_ms(30);
} 

void pulsadores()
{   
   if (input(PIN_A4)==0)
   {
    while(!input(pin_a4)){
      ciclo_activo ++;  // Incrementar el ciclo activo.
      if (ciclo_activo > 249) ciclo_activo = 249;   // No permitir que el ciclo activo suba de 249
      delay_ms(10);
      establecer_ciclo(ciclo_activo);
      
   }
   }
   if (input(PIN_A5)==0)
   {
    while(!input(pin_a5)){
      ciclo_activo --;  // Disminuir el ciclo activo.
      delay_ms(10);
       if (ciclo_activo <= 1) ciclo_activo = 2;  // No permitir que el ciclo activo baje de 1
      establecer_ciclo(ciclo_activo);
      
   }
  
}
}
void energia()   
{
// set_adc_channel(11);
 //  delay_us(50);
 //  ene = read_adc();
 // if(ene<200)
if(input(pin_B4)==0){
cont3++;
delay_ms(1);
if (cont3 >10) {
write_eeprom(03,ciclo_activo );
delay_ms(50);
cont3 = 0;             
               }
                  }
}

void main()
{
  
 ciclo_activo =read_eeprom(03);                   
    establecer_ciclo(ciclo_activo);   
    
 setup_ccp1(CCP_PWM);
   setup_timer_2(T2_DIV_BY_4,249,1);   // 1000 Hz. @ 4 MHz.
   set_pwm1_duty(1);                   // Ciclo activo al mínimo
  
   setup_adc_ports(sAN1|san3|san11);
   setup_adc(ADC_CLOCK_INTERNAL);
  
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
   enable_interrupts(int_ext);
   ext_int_edge(0,L_TO_H);
   enable_interrupts(global);
 
   #ZERO_RAM   // Limpiar RAM. (Variables en 0)
   lcd_init();
    establecer_ciclo(ciclo_activo);
    
   while (true)
   {
 
    if(flagHayDatos==1){
  
      if((periodo3 > periodo2) && (periodo2 > periodo1))
      {
         tiempo_alto = periodo2 - periodo1;                 // Obtener el periodo del pulso en estado alto.
         tiempo_bajo = periodo3 - periodo2;                 // Obtener el periodo del pulso en estado bajo.
         tiempo_total = tiempo_alto + tiempo_bajo;          // Obtener el periodo de la frecuencia.
         us_alto = ticks_us * tiempo_alto;                  // Obtener el periodo en microsegundos del pulso en alto.
         us_bajo = ticks_us * tiempo_bajo;                  // Obtener el periodo en microsegundos del pulso en bajo.
         us_total = ticks_us * tiempo_total;                // Obtener los microsegundos en total de la frecuencia.
         frecuencia = 1 / (us_total / 1000000);             // Obtener la frecuencia.
         duty = ((float) tiempo_bajo / (float)(tiempo_bajo + tiempo_alto));
          porcentaje = (duty * 100) + 10; // Físicamente el + 0.5 puede no ser necesario. (Ajusta desviación pero consume ROM)       
      }
       flagHayDatos=0;
    }
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Hz:%03u ",frecuencia);
       if(porcentaje < 3)porcentaje = 0;
      if(porcentaje > 95)porcentaje = 99;
    
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Duty:%02u%% ",porcentaje );
    
      
       flagHayDatos=0;
      
      delay_ms(100); // Retardo para disminuir parpadeos en la pantalla. (No afecta interrupción externa.)
      if(flagHayDatos==0){
      frecuencia = 0;
      porcentaje=0;
  
    
      }
      
    pulsadores();
 
   voltaje();
energia();
 
 
  set_adc_channel(1);
    delay_us(30);
   amper=0;
  for(var2=0;var2<50;var2++)
  {
    amper=amper+ read_adc();
    delay_us(62); 
  }

  valor2 = amper / 50;
  valor2 = valor2 * 20 / 1023;

  lcd_gotoxy(11,2);
  printf(lcd_putc,"A=%4.2f",valor2);
  delay_ms(60);
 
   }
 
   }
```


----------



## martin00624 (Ago 29, 2018)

Hola buen dia, el problema es que la fuente tiene poco filtro a la salida, o el capacitor esta en mal estado, podes agregar en la entrada del adc una red r c como 10.000 ohm en serie, y un capacitor de .33 micrifaradios en paralelo a la entrada del adc


----------



## callecuatro1976 (Ago 29, 2018)

Si cambio la función de voltaje,  la saco y en la función de ciclo activo donde muestro un porcentaje de la carga,  saco ese porcentaje y muestro el voltaje de 1 a 18 volt sería mejor,  no importaría ahi las oscilaciones porque no se verían en pantalla,  ahora como calculo eso ahi estoy trabado!


----------



## chclau (Ago 29, 2018)

Realiza un refresco de la lectura que se envia al LCD solo si la diferencia con la lectura anterior es mayor a un umbral determinado, o cada tantos segundos.


----------



## martin00624 (Ago 29, 2018)

Consulta, el problema es un planteo para solucionar con programación, o queres un indicador estable?
(de que fuente se trata y que tipo de adc usas)? manda foto


----------



## Gudino Roberto duberlin (Ago 29, 2018)

Hola, sube un esquema completo de cómo realizas la conexión al ADC.


----------



## callecuatro1976 (Ago 29, 2018)

La fuente funciona muy bien solo oscila la muestra del voltaje en el lcd! Yo quería hacerla fija que con programación se muestre sin oscilaciones,  con retardos no funciona te pone lento todo el programa


----------



## Gudino Roberto duberlin (Ago 29, 2018)

De cuánto hablamos en porcentaje la oscilación que mencionas?
Puede haber un problema de ruido eléctrico en la entrada al ADC. Pero cómo no hay circuito, difícil opinar.
Quizás añadiendo un condensador en la entrada se soluciona el problema.


----------



## chclau (Ago 29, 2018)

callecuatro1976 dijo:


> La fuente funciona muy bien solo oscila la muestra del voltaje en el lcd! Yo quería hacerla fija que con programación se muestre sin oscilaciones,  con retardos no funciona te pone lento todo el programa


El problema es que usas retardos, que es una cosa que debes dejar de usar a los pocos dias que comenzaste a aprender programacion. Aprende a realizar temporizadores por interrupciones. Los retardos son como usar muletas para aprender a caminar. Si tienes bien las piernas debes arrojar las muletas lo antes posible.


----------



## callecuatro1976 (Ago 29, 2018)

La oscilación real de la fuente medida con tester es nada 0.100 pero en la muestra del pic en de 0.500 y se mueve constantemente,  ya se puso capacitores se probó de todo,  por eso hay que hacerlo por software, voy a sacar el porcentaje y ver si puedo hacer una muestra ahi promediando el ciclo activo y mostrando como si fuera voltaje
set_pwm1_duty(ciclo);   // Establecer el ciclo activo
   lcd_gotoxy(10,3);

   porcentaje2 = (ciclo / 24.5) *10;
El cambio lo haría acá porcentaje 2=(ciclo *24) / 1023;  
Esto creo que mostraría algo y sacaría el porcentaje de la muestra lcd 

   printf(lcd_putc,"PWM:%02u%%",porcentaje2,);
        voltaje();


----------



## Gudino Roberto duberlin (Ago 29, 2018)

La tensión que magnitud tiene? Además es AC o DC?


----------



## callecuatro1976 (Ago 29, 2018)

La tension es de 0 a 18 volt dc


----------



## Gudino Roberto duberlin (Ago 29, 2018)

callecuatro1976 dijo:


> La tension es de 0 a 18 volt dc


Costará mucho subir un esquema sobre cómo sondeas la tensión?
Pues se puede saber si los GNDs están unidos, distancia de la muestra de tensión hasta el ADC.
El cable es mallado? etc.


----------



## yorsk2004 (Ago 29, 2018)

Algunas veces se hace lo que dice chclau:


chclau dijo:


> Realiza un refresco de la lectura que se envía al LCD solo si la diferencia con la lectura anterior es mayor a un umbral determinado, o cada tantos segundos.



Se hace así:
1. Se declara una variable auxiliar del mismo tipo de la variable principal en la que guardara la lectura del ADC.
2. Se comprueba que la diferencia absoluta entre la variable principal y la variable auxiliar sea mayor o igual a la máxima tolerancia permitida.
3. Solo si se cumple lo anterior, se muestra el dato de la variable principal en la LCD. Ademas se guarda el dato de la variable principal en la la variable auxiliar, esto se hace antes de salir de la comprobación.

Ejemplo con relación a la función voltaje () de su código:

```
void voltaje (void)
{
   int16 valor_adc, valor_adc_auxiliar;
   float voltaje;
   set_adc_channel(0);
   valor_adc = read_adc();
   if ((valor_adc - valor_adc_auxiliar) >= 10 || (valor_adc_auxiliar  - valor_adc) >= 10)) //Tolerancia de 10 unidades digitales
   {
      voltaje = ((valor_adc * 18.0) / 1023);
      lcd_gotoxy(11,1);
      printf(lcd_putc,"V=%2.2f V",voltaje);
      valor_adc_auxiliar = valor_adc;
   }
}
```


----------



## callecuatro1976 (Ago 29, 2018)

lo probe y me funciona peor!
 esto es lo que decía pero estoy errado lo estoy calculando mal ya que el pwm va hasta 5 volt 

void establecer_ciclo (int8 ciclo)
{
    float voltaje;
    set_pwm1_duty(ciclo);   // Establecer el ciclo activo

   voltaje = (ciclo * 24.5) /1023;
  lcd_gotoxy(11,1);
  printf(lcd_putc,"V=%4.1fV ",voltaje);
  }

porque va de la mano con esto
void pulsadores() 
{   
   if (input(PIN_A4)==0)
   {
    while(!input(pin_a4)){
      ciclo_activo ++;  // Incrementar el ciclo activo.
      if (ciclo_activo > 249) ciclo_activo = 249;   // No permitir que el ciclo activo suba de 249
      delay_ms(10);
      establecer_ciclo(ciclo_activo);

   }
   }
   if (input(PIN_A5)==0)
   {
    while(!input(pin_a5)){
      ciclo_activo --;  // Disminuir el ciclo activo.
      delay_ms(10);
       if (ciclo_activo <= 1) ciclo_activo = 2;  // No permitir que el ciclo activo baje de 1
      establecer_ciclo(ciclo_activo);

   }

}
}


----------



## yorsk2004 (Ago 29, 2018)

callecuatro1976 dijo:


> Lo voy a probar! Como me dicen pero no afecta cuando con los pulsadores cambio el valor del pwm?


No, no afecta cuando se cambia el valor del ciclo útil desde los pulsadores.



callecuatro1976 dijo:


> Y tardaría en mostrar el dígito que con el pulsador va cambiando de 0,1 a 0,1


No, no tardaría con el código que se propuso. Recordar que la tolerancia máxima propuesta es de 10 unidades digitales entonces según su código será: 18V*10/1023 = 0.18 V pero esa tolerancia la define usted como diseñador. Podría ser tan solo 1 unidad digital lo que equivale a: 18V*1/1023 = 0.02 V.

El código propuesto podría llegar afectar si se utiliza la variable voltaje en otras funciones pero revisando su código original esta variable solo tiene importancia en la visualización por medio de la LCD. El código prepuesto es solo un "truco" para evitar el parpadeo y/u oscilaciones en la presentación en la LCD.


callecuatro1976 dijo:


> lo probe y me funciona peor!


Entonces intenta con este código:

```
void voltaje (void)
{
   int16 valor_adc, valor_adc_auxiliar;
   float voltaje;
   set_adc_channel(0);
   valor_adc = read_adc();
   voltaje = ((valor_adc * 18.0) / 1023); //Se sacó esta línea de las sentencias del IF
   if ( ( (valor_adc - valor_adc_auxiliar) >= 10) || ( (valor_adc_auxiliar  - valor_adc) >= 10) ) //Tolerancia de 10 unidades digitales
   {
      lcd_gotoxy(11,1);
      printf(lcd_putc,"V=%2.2f V",voltaje);
      valor_adc_auxiliar = valor_adc;
   }
}
```
Esta linea no la tiene el primer código que usted compartió. 


callecuatro1976 dijo:


> voltaje = (ciclo * 24.5) /1023;


----------



## callecuatro1976 (Ago 29, 2018)

La línea voltaje = (ciclo * 24.5) /1023; son las pruebas que empecé hacer para ver si puedo mostrar el voltaje por software sin usar el acd,  el voltaje que tengo que mostrar es de 1 a 18,  por medio del ciclo activo, quiero ver si funciona,  sabiendo que se mueve de 0 a 5 volt el pwm lo multiplicó y divido como el adc,  pero no creo que sea así!


----------



## pandacba (Ago 29, 2018)

Podes subir tu esquema para ver que esta mal en el hardware


----------



## callecuatro1976 (Ago 29, 2018)

El hardware esta bien todo esta bien!  Yo quería mostrarlo de otra manera,  yo poner la tensión fija con los pulsadores y adaptar el pwm a ese valor!


----------



## pandacba (Ago 29, 2018)

Si todo esta bien, entonces no hay ningún problema, que es lo que haces preguntando en este foro?


----------



## callecuatro1976 (Ago 29, 2018)

Pido ayuda porque no se como hacerlo,  lo que quiero hacer es: cuando aprieto el pulsador que muestre el " voltaje " subir de 0.1 a 0.2,  0.3 así subiendo un truco de muestra no una medición por adc,  y así hasta llegar a 18.0 volt

Si uso un contador de 0 a 18 y lo uso en la función de ciclo de pwm?

void voltaje()
{
float voltaje;
voltaje= ciclo_activo;
voltaje=voltaje /14;
 lcd_gotoxy(11,1);
  printf(lcd_putc,"V=%4.1fV ",voltaje);

}

asi me funciona pero me lo muestra al revés cunado subo desciende e viceversa .


----------



## Gudino Roberto duberlin (Ago 30, 2018)

Yo pienso que habría que juntar firmas para que el compañero suba un esquema del proyecto.


----------



## callecuatro1976 (Ago 30, 2018)

Gudino Roberto duberlin dijo:


> Yo pienso que habría que juntar firmas para que el compañero suba un esquema del proyecto.


Tengo que armarlo todo,  o buscarlo mejor dicho


----------



## yorsk2004 (Ago 30, 2018)

Ahora no entiendo que es lo que quiere realmente hacer porque usted ha planteado al menos dos objetivos:



callecuatro1976 dijo:


> hola  necesito ayuda con un problema que no se como resolver , tengo un programa que muestra la tensión , un voltámetro la muestra es por el adc pero cuando pongo una carga se mueve mucho la muestra , como puedo hacer para mostrarla en el lcd que quede fija , por mas que haya pequeñas oscilaciones





callecuatro1976 dijo:


> Pido ayuda porque no se como hacerlo,  lo que quiero hacer es: cuando aprieto el pulsador que muestre el " voltaje " subir de 0.1 a 0.2,  0.3 así subiendo un truco de muestra no una medición por adc,  y así hasta llegar a 18.0 volt



Lo que usted quiere es ¿variar el ancho de pulso de la señal PWM por medio de dos pulsadores, uno para aumentar y el otro para disminuir? y también ¿mostrar en una LCD el valor del voltaje promedio de la señal PWM y el porcentaje del ancho de pulso?


callecuatro1976 dijo:


> Tengo que armarlo todo,  o buscarlo mejor dicho



Al menos captura del trabajo en el simulador.


----------



## callecuatro1976 (Ago 30, 2018)

Así es eso mismo!!


----------



## yorsk2004 (Ago 30, 2018)

Utiliza el modo PWM del modulo CCP del PIC es mas sencillo que hacerlo por software.
Idealmente el PIC solo puede sacar hasta 5V cuando el ciclo de trabajo es 100%, entonces si necesita sacar un voltaje de hasta 18V debe colocar un circuito externo que amplifique el voltaje.


----------



## callecuatro1976 (Ago 30, 2018)

yorsk2004 dijo:


> Utiliza el modo PWM del modulo CCP del PIC es mas sencillo que hacerlo por software.
> Idealmente el PIC solo puede sacar hasta 5V cuando el ciclo de trabajo es 100%, entonces si necesita sacar un voltaje de hasta 18V debe colocar un circuito externo que amplifique el voltaje.


Si lo amplifico con lm338 para tener los 18 volt pasando por un filtro pasa bajo,  ahora estoy trabajando en el esquema así lo subo,  y viendo como hacer el promedio para mostrar la tensión


----------



## yorsk2004 (Ago 30, 2018)

El LM338 es un regulador de tensión por lo tanto idealmente nunca podrá sacar mas voltaje que el de su entrada.

Si el voltaje de salida es tan solo una señal de información o la carga es de muy baja potencia entonces puede usar un OP-AMP con configuración amplificador no inversor y le ajustas la ganancia.

Pero si en cambio tienes un motor o una carga que demande mas de algunos cientos de miliamperios entonces se complica la cosa, pienso que en este caso hay que recurrir a un convertidor DC-DC.


----------



## callecuatro1976 (Ago 30, 2018)

Perdón lm358 uso para amplificar la señal de la salida del pic!


----------



## pandacba (Ago 30, 2018)

No hace falta hacer eso si tienes en algunas de las fuente de alimentación esa tensión disponible o partiendo de un duplicador o triplicador o aún mejor utilizar un regulador ajustable para que entregue entre 1.2V y 18V


----------



## miglo (Ago 31, 2018)

No es por ser molesto, ojo la de veces que se le ha pedido al compañero que suba el esquema, al final estoy de acuerdo con gudino, juntemos firmas jeje, o no quiere compartir con el foro y solo quiere recibir, o no sabe subir el esquema.


----------



## Scooter (Ago 31, 2018)

Todo esto son temas ya tratados, los retardos y las oscilaciones en la lectura de un ADC.
Eso de que la fuente no oscila... Si el ADC lo mide será que sí que oscila. Un polímero lleva un conversor de doble rampa que es muy sencillo, muy preciso y muy lento. Por eso no oscila la lectura del polímero y sí que oscila la lectura del ADC.

Lo más sencillo es promediar lecturas consecutivas.
Lo más lógico es nunca usar retardos salvo que se haga un programa de un proceso ultrahipersimple.


----------



## callecuatro1976 (Sep 4, 2018)

```
void tension()
{

long voltaje;

  if (input(PIN_A4)==0)
   {
    while(!input(pin_a4)){
      voltaje++;  // Incrementar
      if (voltaje > 18) voltaje = 18;  
      delay_ms(10);

    }
   }
  if (input(PIN_A5)==0)
   {
    while(!input(pin_a5)){
      voltaje --;
       if (voltaje <= 1) voltaje = 0;
         delay_ms(10);
 
    }
   }
 
        lcd_gotoxy(11,1);
  printf(lcd_putc,"V=%0.2lu",voltaje);

}
```


Hola miembros del foro opté por hacerlo así , ahora , ¿Porque no me corre el contador ?

Como sería un contador de 0 a 18 ascendente y descendente con pulsador y la cuenta que muestre sea con coma,  ejemplo 1,2
1,3
1,4
Así sube y baja!
No me doy idea del código si uso if o un for


----------



## Fogonazo (Sep 4, 2018)

callecuatro1976 dijo:


> Como seria un contador de 0 a 18 ascendente y descendente con pulsador y la cuenta que muestre sea con coma,  ejemplo 1,2
> 1,3
> 1,4
> Así suba y baje!
> No me doy idea del código si uso if o un for



¿ Como sería la presentación de los números *< 10* ?, ¿ *0,9* por ejemplo ?

Si ese es el caso, solo dejas la coma fija en el display, en lo demás es un contador común y corriente.


----------



## callecuatro1976 (Sep 5, 2018)

```
#include <16f886.h>
#device ADC=10
#use     delay(internal = 8MHz)                           
#define  LCD_DATA_PORT getenv("SFR:PORTC")
#include <flex_lcd.c>

#define LCD_RW_PIN    PIN_C3




int voltaje=0;


void tension()
{

 
  if (input(PIN_A4)==0)
   {
    while(!input(pin_a4)){
      voltaje++;  // Incrementar
        delay_ms(10);
 if (voltaje > 18) {
 voltaje=18;
 
 }

    

    }
   }
  if (input(PIN_A5)==0)
   {
    while(!input(pin_a5)){
            delay_ms(10);
      voltaje --; 
  if (voltaje <= 1) {
  voltaje = 0;
  }
  
    }
   }
  
           lcd_gotoxy(11,1);
  printf(lcd_putc,"V=%0.3u",voltaje);
}
 void main ()
 {
 

  
  
  lcd_init(); 
  
  
   while (true)
   {
  
  
  
   tension();
  
   }
 }
```

hola estoy trabajando en este codigo y no me cuanta 1 en 1 y seria un contador decimal tendia que contar 0.1 0.2 0.3 asi hasta 18.0 pero todavia no lo puedo hacer andar gracias por responder


----------



## Gudino Roberto duberlin (Sep 5, 2018)

Hola, habría que ver el esquema eléctrico o imagen de simulación para saber cómo conectas las entradas.
Pero viendo rápidamente tu código, en el bucle del decremento está mal condicionado.
Pues tú le dices que si voltaje es menor o igual a 1 entonces será 0. Y ahí generas un underflow. Pues voltaje valiendo ahora 0 cuando se ejecute voltaje-- lo decrementa aún más y ahora será 255.
Deberías hacer lo sig.

if(voltaje>0) voltaje--;

Y para el tope superior puedes hacer:

if(voltaje<18) voltaje++;


----------



## callecuatro1976 (Sep 5, 2018)

si no se porque no me suma 1 en 1 ahí esta la simulacion
lo que no quiero que se de vuelta , cuando pulso que llego a cero y si sigo pulsando que quede en cero y asi cuando llego a 18 si sigo pulsando que quede en 18.0


----------



## Gudino Roberto duberlin (Sep 5, 2018)

No tengo Proteus para simular, mejor sube una imagen.


----------



## roberttorres (Sep 5, 2018)

Lo que estoy viendo con tu código, es que el anti rebote que estas implementado esta mal, por eso no esta sumando de a uno, la forma correcta seria así:

```
void tension(){
 
  if (input(PIN_A4)==0){
    while(!input(pin_a4)){}
      voltaje++;  // Incrementar
         if (voltaje > 18){ voltaje=18;}
   }
 
  if (input(PIN_A5)==0){
    while(!input(pin_a5)){}
     voltaje --; 
       if (voltaje > 18) {voltaje = 0;}
   }
  
  lcd_gotoxy(11,1);
  printf(lcd_putc,"V=%2.1u",voltaje);
}
```


----------



## callecuatro1976 (Sep 5, 2018)

```
#include <16f886.h>
#device ADC=10
#use     delay(internal = 8MHz)                           
#define  LCD_DATA_PORT getenv("SFR:PORTC")
#include <flex_lcd.c>

#define LCD_RW_PIN    PIN_C3



 int  voltaje=0;


void tension()
{


 
  if (input(PIN_A4)==0)
   {
    while(!input(pin_a4)){
      delay_ms(10);
for(voltaje=0;voltaje <18;voltaje++)
{
delay_ms(60);
           lcd_gotoxy(11,1);
  printf(lcd_putc,"V=%3u",voltaje);
}

    }
   }
  if (input(PIN_A5)==0)
   {
    while(!input(pin_a5)){
            delay_ms(10);
    for(voltaje=18;voltaje >0;voltaje--){
    
    delay_ms(60);
             lcd_gotoxy(11,1);
  printf(lcd_putc,"V=%3u",voltaje);
    }

  
    
   }
  
   }
}
 void main ()
 {
 

  
  
  lcd_init(); 
  
  
   while (true)
   {
  
  
  
   tension();
  
   }
 }
 
 lo hice asi y me cuenta y baja pero estoy mas cerca , como puedo ponerle coma ala muetra no se me ocurre
```



roberttorres dijo:


> Lo que estoy viendo con tu código, es que el anti rebote que estas implementado esta mal, por eso no esta sumando de a uno, la forma correcta seria así:
> 
> ```
> void tension(){
> ...


asi funciona pero cuando mantengo apretado el pulsador tendría que subir rápido y se queda , es difícil hacerlo pero con paciencia saldrá y su aya , gracias


----------



## Gudino Roberto duberlin (Sep 5, 2018)

A ver veamos. Algo así que uso desde tiempo.

if(!input(PIN_A4))                                               // Comprueba Botón pulsado
  {
    if(rebote<200)rebote++;
    if(rebote==150&&voltaje<18) voltaje++;
}
else rebote=0;

Los valores de rebote, depende de la velocidad del micro, lo que hace ésta variable auxiliar es incrementar el valor de voltaje sólo una vez cuándo es pulsado el botón.
Con un arreglo adicional puede hacerse que incremente uno a uno si se mantiene presionado el botón.
Fíjate que no uso ningún delay, y si el tiempo de incremento es muy rápido, sólo hay que aumentar el o los valores de "rebote" hasta dónde sea necesario.


----------



## callecuatro1976 (Sep 5, 2018)

Si me esta volviendo loco,  todavía me falta mostrarlo con coma,  pensé en ver de mostrar 18, mostrar 180 pero no se bien como meter el punto


----------



## Gudino Roberto duberlin (Sep 5, 2018)

callecuatro1976 dijo:


> Si me esta volviendo loco,  todavía me falta mostrarlo con coma,  pensé en ver de mostrar 18, mostrar 180 pero no se bien como meter el punto



Fíjate si el compilador admite ésto, sino deberás declarar a la variable voltaje cómo float:

printf(lcd_putc,"V=%3.1f",voltaje);


----------



## D@rkbytes (Sep 5, 2018)

callecuatro1976 dijo:


> todavía me falta mostrarlo con coma. Pensé en vez de mostrar 18, mostrar 180 pero no sé bien cómo meter el punto.


De esta forma es sencillo pero se consume algo de ROM:


```
#include <16f887.h>
#use delay(INTERNAL = 4 MHz)

#include <lcd.c>

#define    pin_decr    PIN_E0
#define    pin_incr    PIN_E1

void mostrar_conteo (float conteo)
{
    if(conteo < 10)
    {    
        lcd_gotoxy(1,1);
        printf(lcd_putc,"Conteo: 0%0.1f ", conteo);    // Si conteo es menor a 10, se muestra un 0 a la izquierda.
    }
    else
    {
        lcd_gotoxy(1,1);
        printf(lcd_putc,"Conteo: %0.1f ", conteo);
    }
}

void main (void)
{
    float conteo = 9.0;
     
    lcd_init();
     
    mostrar_conteo(conteo);
     
    while (TRUE)
    {
        if(!input_state(pin_decr))
        {
            conteo -= 0.1;
            if(conteo <= 0) conteo = 0;
             
            mostrar_conteo(conteo);
             
            while(!input_state(pin_decr));
        }
         
        if(!input_state(pin_incr))
        {
            conteo += 0.1;
            if(conteo > 18) conteo = 18;
             
            mostrar_conteo(conteo);
             
            while(!input_state(pin_incr));
        }
    }
}
```


----------



## callecuatro1976 (Sep 5, 2018)

Una pregunta se puede usar los pulsadores para dos funciones distintas?  Con un pulso mover el contador y el mismo pulso incremente otra variable de una función distinta! No se si me explico bien
funciona perfecto muchas gracias , como puedo hacer para que tenga el pulsador apretado suba rápido?


----------



## D@rkbytes (Sep 5, 2018)

Sí se puede, incluso ejecutar otras tareas.
Para que la cuenta se realice más rápido se debe usar un contador que cuando alcance cierto número, disminuya un retardo.
Todo esto mientras se mantenga pulsado por cierto tiempo determinado por la cuenta, si no se cumple la cuenta, entonces hará lento el conteo.
Al salir de la rutina se debe limpiar el contador.

En algún ejemplo de PICBasic hice algo así, pero no recuerdo en qué post lo subí.


----------



## callecuatro1976 (Sep 5, 2018)

Ok un contador con un ciclo for se podría hacer?  Lo voy a intentar!  Gracias


----------



## D@rkbytes (Sep 5, 2018)

Con un bucle for no, simplemente empiezas a incrementar un contador mientras se mantenga presionado el pulsador.
Si el contador llega a X número, entonces reduces una variable int16 que establezca el retardo.


----------



## DJ T3 (Sep 5, 2018)

Si quieres con coma, debes poner "float" en vez de "int", y en vez de "voltaje=0", tienes que poner "voltaje=0.0".
Asi mismo la suma;
voltaje = voltaje + 0.1;
La resta;
voltaje = voltaje - 0.1;
Y los limites;
if(voltaje != 18.0){}
Y
if(voltaje != 0.0){}

Quizas en vez de "!=" Puedas usar ">" y "<".


----------



## callecuatro1976 (Sep 5, 2018)

el contador para incremente rápido tendría que ser asi

```
#include <16f886.h>
#device ADC=10
#use     delay(internal = 8MHz)                           
#define  LCD_DATA_PORT getenv("SFR:PORTC")
#include <flex_lcd.c>

#define LCD_RW_PIN    PIN_C3


 


void mostrar_conteo (float conteo)
{
    if(conteo < 10)
    {   
        lcd_gotoxy(1,1);
        printf(lcd_putc,"v: %0.1f ", conteo);    // Si conteo es menor a 10, se muestra un 0 a la izquierda.
    }
    else
    {
        lcd_gotoxy(1,1);
        printf(lcd_putc,"v: %0.1f ", conteo);
    }
}

void main (void)
{
    float conteo = 1.0;
    
    lcd_init();
    
    mostrar_conteo(conteo);
    
    while (TRUE)
    {
        if(!input_state(pin_a4))
        {
        
            conteo -= 0.1;
            if(conteo <= 0) conteo = 0;
            
            mostrar_conteo(conteo);
              while(!input_state(pin_a4) );
              
              
                 if(input(pin_a4)==0){
          while(!input(pin_a4)){
          conteo--;}
      
        
        
        if(!input_state(pin_a5))
        {
            conteo += 0.1;
            if(conteo > 18) conteo = 18;
            
            mostrar_conteo(conteo);
           while(!input_state(pin_a5));
          
        }
    }
    }
}
```


```
#include <16f886.h>
#device ADC=10
#use     delay(internal = 8MHz)                           
#define  LCD_DATA_PORT getenv("SFR:PORTC")
#include <flex_lcd.c>

#define LCD_RW_PIN    PIN_C3


 



#define    pin_decr    PIN_a4
#define    pin_incr    PIN_a5

void mostrar_conteo (float conteo)
{
    if(conteo < 10)
    {   
        lcd_gotoxy(1,1);
        printf(lcd_putc,"Conteo: %0.1f ", conteo);   
    }
    else
    {
        lcd_gotoxy(1,1);
        printf(lcd_putc,"Conteo: %0.1f ", conteo);
    }
}

void main (void)
{
    float conteo = 0.0;
     int16 cont;
    
    lcd_init();
    
    mostrar_conteo(conteo);
    
    while (TRUE)
    {
        if(!input_state(pin_decr))
        {
    
            conteo -= 0.1;
            if(conteo <= 0) conteo = 0;
            
            mostrar_conteo(conteo);
         }
          
        
        
        if(!input_state(pin_incr))
        {
    

             if(cont<200)cont++;

    
            conteo += 0.1;
            if(conteo > 18) conteo = 18;
            
            mostrar_conteo(conteo);
             while(!input_state(pin_incr));
              
        
            
          
        
        }
    }
}
```

no pudo hacer que cuente rápido o cuanta rápido o de uno en uno no entendí del tiempo del rebote


----------



## D@rkbytes (Sep 5, 2018)

Esa función la he implementado de otras maneras, (más optimizada) pero esta es una forma de hacerlo:

```
#include <16f887.h>
#use delay(INTERNAL = 4 MHz)

#include <lcd.c>

#define    pin_decr    PIN_E0
#define    pin_incr    PIN_E1

void mostrar_conteo (float conteo)
{
    if(conteo < 10)
    {   
        lcd_gotoxy(1,1);
        printf(lcd_putc,"Conteo: 0%0.1f ", conteo);
    }
    else
    {
        lcd_gotoxy(1,1);
        printf(lcd_putc,"Conteo: %0.1f ", conteo);
    }
}

void main (void)
{
    float conteo = 9.0;
    int16 cont_r = 0, retardo;
    
    lcd_init();
    
    mostrar_conteo(conteo);
    
    while (TRUE)
    {
        retardo = 200;
        
        if(!input_state(pin_decr))
        {
            while(!input_state(pin_decr))
            {
                cont_r ++;
                
                if(cont_r > 9)        // Si "cont_r" llega a 10, se reduce el retardo.
                    retardo = 50;
                else
                    retardo = 250;
                    
                conteo -= 0.1;
            
                if(conteo <= 0)
                {
                    conteo = 0;
                    cont_r = 0;        // Para evitar el desborde por mantener el pulsador presionado.
                }
            
                mostrar_conteo(conteo);
                
                delay_ms(retardo);
            }
            cont_r = 0;                // Limpiar "cont_r" si no se entra al bucle.
        }
        
        if(!input_state(pin_incr))
        {
            while(!input_state(pin_incr))
            {
                cont_r ++;
                
                if(cont_r > 9)        // Si "cont_r" llega a 10, se reduce el retardo.
                    retardo = 50;
                else
                    retardo = 250;
                    
                conteo += 0.1;
            
                if(conteo > 18)
                {
                    conteo = 18;
                    cont_r = 0;        // Para evitar el desborde por mantener el pulsador presionado.
                }
            
                mostrar_conteo(conteo);
                
                delay_ms(retardo);
            }
            cont_r = 0;                // Limpiar "cont_r" si no se entra al bucle.
        }
    }
}
```


----------



## callecuatro1976 (Sep 5, 2018)

Necesito si tenes tiempo que me expliques las líneas del temporizado, quiero lograr en algún momento poder hacer aunque sea algo más sencillo,  gracias por el tiempo invertido
Otra consulta todo ese programa se podía hacer en una función así la agrego en un programa?  El While true puede estar dentro de una función?


----------



## D@rkbytes (Sep 5, 2018)

Con lo que comenté se me hizo más que suficiente para comprender lo que se está haciendo.
Son instrucciones muy básicas que se comprenden al ir leyendo.
Y si comprendes el uso específico que se le está dando al código, verás que no se puede implementar como función.


----------



## callecuatro1976 (Sep 5, 2018)

Si veo que no se puede hacer una función voy a probar de adaptarlo y subo lo que hice,  gracias


```
#include <16f886.h>
#device ADC=10
#use     delay(internal = 8MHz)                          
#define  LCD_DATA_PORT getenv("SFR:PORTC")
#include <flex_lcd.c>

#define LCD_RW_PIN    PIN_C3
//#include <internal_eeprom.c>


int1 flagHayDatos=0;
float const ticks_us = 4.0;          // microsegundos por Tick del Timer 1 @ 8 MHz. (Osc. Interno)
//float const ticks_us = 8.0;          // microsegundos por Tick del Timer 1 @ 8 MHz. (Osc. Cristal)
long int  var2=0;
int8 flancos;
int8 flag_flanco;
int16 periodo1,periodo2,periodo3;
int16 tiempo_alto,tiempo_bajo,tiempo_total;
float us_alto,us_bajo,us_total,valor2,amper, duty;
   int porcentaje;
   int frecuencia;
 

int8   ciclo_activo=1;

  int16 cont3;  
 



  #define    pin_decr    PIN_a5
#define    pin_incr   PIN_a4
  int16 cont4;
   float conteo = 0;



void energia2()  
{
// set_adc_channel(11);
//  delay_us(50);
//  ene = read_adc();
// if(ene<200)
if(input(pin_B4)==0){
cont4++;
delay_ms(1);
if (cont4 >10) {
write_eeprom(04,conteo);
delay_ms(50);
cont4 = 0;            
               }
                  }
}


#INT_EXT
void sdi_externa_RB0 (void)
{
   flancos++;                          // Incrementar la variable "flancos"
 
   if(!flag_flanco)                    // Si el flanco del pulso es bajo...
   {
      if(flancos == 1)                 // Si el conteo de flancos es 1...
      {
         set_timer1(0);                // Limpiar el Timer 1
         periodo1 = get_timer1();      // "periodo1" tendrá el tiempo del pulso en alto.
      }
      if(flancos == 3)                 // Si el conteo de flancos es 3...
         periodo3 = get_timer1();      // "periodo3" tendrá el tiempo del pulso en alto.
       
         EXT_INT_EDGE(H_TO_L);         // Establecer la interrupción por flanco de bajada.
         flag_flanco = 1;              // Indicar que el próximo flanco será de bajada.
   }
   else                                // Caso contrario. (Pulso en estado alto)...
   {
      periodo2 = get_timer1();         // "periodo2" tendrá el valor del pulso en bajo.
      EXT_INT_EDGE(L_TO_H);            // Establecer la interrupción por flanco de subida.
      flag_flanco = 0;                 // Indicar que el próximo flanco será de subida.
       if(flagHayDatos==0){       // Si los datos anteriores han sido procesados ...
      flagHayDatos=1;          // Indico que ya hay nuevos datos de flancos para calcular
    }
   }

   if(flancos > 2)flancos = 0;         // Si la variable "flancos" llega a 3, ponerla a 0.
}



void establecer_ciclo (int8 ciclo)
{
   
    set_pwm1_duty(ciclo);   // Establecer el ciclo activo




 

   
}



 
void pulsadores()
{  
   if (input(PIN_A4)==0)
   {
    while(!input(pin_a4)){
      ciclo_activo ++;  // Incrementar el ciclo activo.
      if (ciclo_activo > 249) ciclo_activo = 249;   // No permitir que el ciclo activo suba de 249
      delay_ms(10);
      establecer_ciclo(ciclo_activo);
     
   }
   }
   if (input(PIN_A5)==0)
   {
    while(!input(pin_a5)){
      ciclo_activo --;  // Disminuir el ciclo activo.
       if (ciclo_activo <= 1) ciclo_activo = 2;  // No permitir que el ciclo activo baje de 1
          delay_ms(10);
      establecer_ciclo(ciclo_activo);
     
   }
 
}
}



void energia()  
{
// set_adc_channel(11);
//  delay_us(50);
//  ene = read_adc();
// if(ene<200)
if(input(pin_B4)==0){
cont3++;
delay_ms(1);
if (cont3 >10) {
write_eeprom(03,ciclo_activo );
delay_ms(50);
cont3 = 0;            
               }
                  }
}
void mostrar_conteo (float conteo)
{
    if(conteo < 10)
    {  
        lcd_gotoxy(11,1);
        printf(lcd_putc,"V: %0.1f ", conteo);
    }
    else
    {
        lcd_gotoxy(11,1);
        printf(lcd_putc,"V: %0.1f ", conteo);
    }
}
void main()
{
 
ciclo_activo =read_eeprom(03);                  
    establecer_ciclo(ciclo_activo);  
   
setup_ccp1(CCP_PWM);
   setup_timer_2(T2_DIV_BY_4,249,1);   // 1000 Hz. @ 4 MHz.
   set_pwm1_duty(1);                   // Ciclo activo al mínimo
 
   setup_adc_ports(sAN1|san3|san11);
   setup_adc(ADC_CLOCK_INTERNAL);
 
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
   enable_interrupts(int_ext);
   ext_int_edge(0,L_TO_H);
   enable_interrupts(global);

   #ZERO_RAM   // Limpiar RAM. (Variables en 0)
   lcd_init();
    establecer_ciclo(ciclo_activo);
        float conteo = 0;
    int16 cont_r = 0, retardo;
   
   while (true)
   {

    if(flagHayDatos==1){
 
      if((periodo3 > periodo2) && (periodo2 > periodo1))
      {
         tiempo_alto = periodo2 - periodo1;                 // Obtener el periodo del pulso en estado alto.
         tiempo_bajo = periodo3 - periodo2;                 // Obtener el periodo del pulso en estado bajo.
         tiempo_total = tiempo_alto + tiempo_bajo;          // Obtener el periodo de la frecuencia.
         us_alto = ticks_us * tiempo_alto;                  // Obtener el periodo en microsegundos del pulso en alto.
         us_bajo = ticks_us * tiempo_bajo;                  // Obtener el periodo en microsegundos del pulso en bajo.
         us_total = ticks_us * tiempo_total;                // Obtener los microsegundos en total de la frecuencia.
         frecuencia = 1 / (us_total / 1000000);             // Obtener la frecuencia.
         duty = ((float) tiempo_bajo / (float)(tiempo_bajo + tiempo_alto));
          porcentaje = (duty * 100) + 10; // Físicamente el + 0.5 puede no ser necesario. (Ajusta desviación pero consume ROM)      
      }
       flagHayDatos=0;
    }
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Hz:%03u ",frecuencia);
       if(porcentaje < 3)porcentaje = 0;
      if(porcentaje > 95)porcentaje = 99;
   
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Duty:%02u%% ",porcentaje );
   
     
       flagHayDatos=0;
     
      delay_ms(100); // Retardo para disminuir parpadeos en la pantalla. (No afecta interrupción externa.)
      if(flagHayDatos==0){
      frecuencia = 0;
      porcentaje=0;
 
   
      }
 
    pulsadores();


energia();
energia2();

  set_adc_channel(1);
    delay_us(30);
   amper=0;
  for(var2=0;var2<50;var2++)
  {
    amper=amper+ read_adc();
    delay_us(62);
  }

  valor2 = amper / 50;
  valor2 = valor2 * 20 / 1023;

  lcd_gotoxy(11,2);
  printf(lcd_putc,"A=%4.2f",valor2);
  delay_ms(60);




   
   
        retardo = 200;
       
        if(!input_state(pin_decr))
        {
            while(!input_state(pin_decr))
            {
                cont_r ++;
               
                if(cont_r > 9)        // Si "cont_r" llega a 10, se reduce el retardo.
                    retardo = 50;
                else
                    retardo = 250;
                   
                conteo -= 0.1;
           
                if(conteo <= 0)
                {
                    conteo = 0;
                    cont_r = 0;        // Para evitar el desborde por mantener el pulsador presionado.
                }
           
                mostrar_conteo(conteo);
               
                delay_ms(retardo);
            }
            cont_r = 0;                // Limpiar "cont_r" si no se entra al bucle.
        }
       
        if(!input_state(pin_incr))
        {
            while(!input_state(pin_incr))
            {
                cont_r ++;
               
                if(cont_r > 9)        // Si "cont_r" llega a 10, se reduce el retardo.
                    retardo = 50;
                else
                    retardo = 250;
                   
                conteo += 0.1;
           
                if(conteo > 18)
                {
                    conteo = 18;
                    cont_r = 0;        // Para evitar el desborde por mantener el pulsador presionado.
                }
           
                mostrar_conteo(conteo);
               
                delay_ms(retardo);
            }
            cont_r = 0;                // Limpiar "cont_r" si no se entra al bucle.
        }
       
       
       
       
    }

}
```



Acá está todo el trabajo pero cómo me imaginaba no funciona bien , no van de la mano el voltaje que es el contador y el ciclo activo , hay que seguir trabajando.


----------



## D@rkbytes (Sep 6, 2018)

Si tienes ADC, lo mejor sería leer el voltaje y mostrarlo, no hacerlo por partes separadas.
Y si lo que te preocupa es que el voltaje no se muestre estable en la pantalla, hay varias formas de solucionarlo.


----------



## callecuatro1976 (Sep 6, 2018)

Si no logro que quede estable probé de todo,  promedios, capacitores,que limpie pantalla cada segundo y no me queda bien, las bobinas que conecto tienen mucho ruido eléctrica!


----------



## D@rkbytes (Sep 6, 2018)

Usa un timer para mostrar la lectura cada X milisegundos, por ejemplo, cada 500 o 1000 milisegundos.
También es conveniente usar una tensión de referencia para el conversor AD.

Algo así como en el siguiente ejemplo:
Voltímetro con el ADC del PIC


----------



## callecuatro1976 (Sep 7, 2018)

hola estuve haciendo pruebas y con la ayuda de ustedes pude avanzar en la idea , tengo algunos problemas como de costumbre subo el archivo y la simulación , consulta porque se me da vuelta la variable y como calculo para que cuando el pwm este en 5 volt la muestra este en 18.0 , graciaS


----------



## callecuatro1976 (Sep 8, 2018)

Ya resolví lo que se me daba vuelta la variable,  ahora estoy trabajando en que sea igual la muestra de la pantalla y el pwm!

No puedo guardar el dato de la muestra del lcd del voltaje en la memoria eeprom , subo el programa para que puedan ver , gracias


----------



## D@rkbytes (Sep 17, 2018)

Sí se guardan, pero únicamente cuando RB4 se encuentra en estado bajo como lo declaraste en el programa.
Sin embargo, en el esquema el pin RB4 siempre está en estado alto por R3.


----------



## callecuatro1976 (Sep 17, 2018)

Si no me esta funcionando, si me guarda el ciclo activo,  pero la muestra del contador no y se me defaza la tensión con respecto a la muestra del lcd,  porque cuando corta la energía siempre me inicia 0,  tenias razón es bastante difícil hacerlo así!


----------



## D@rkbytes (Sep 17, 2018)

En la simulación a mi sí me guardó las dos variables, pero colocando un pulsador hacia tierra en RB4.
Y es lógico que obtengas una cosa por un lado y otra por otro lado, porque digamos que no hay una sincronía.
Hacerlo de esa forma es un engaño sin sentido, teniendo los recursos del microcontrolador para hacerlo de forma correcta. (ADC)


----------



## callecuatro1976 (Sep 18, 2018)

La fuente la tengo con el adc, quería lograr hacerlo de esa manera para que quede mas estable solo cuando apretar los pulsadores,  colocando un capacitor de 10 uf lo más cerca de la pata del pic queda estable y no se mueva nada, solo te muestra una caída de 0.100 de la fuente


----------



## D@rkbytes (Sep 18, 2018)

No sé qué estés tratando de hacer, pero de cualquier forma, no es correcto así.
La lectura del ADC siempre va a variar si se tiene como referencia el mismo VDD del microcontrolador.
Por eso te mencioné lo de usar otra referencia y un Timer para tomar la lectura cada x tiempo.
Promediar también funciona pero si lo haces correctamente, pero tienes el siguiente error.
Estás realizando 49 lecturas y luego divides la suma por 50.

Ten en cuenta que var2<50 nada más llegará hasta 49.


----------



## callecuatro1976 (Sep 24, 2018)

Hola nuevamente , vengo un problema que no se como resolver , estoy tratando de medir con un voltímetro directamente la salida , hice la etapa de amplificación con el lm358 , me mide de 1 volt en 1 volt , como hago hago para que muestre 0.1 en el voltímetro?

```
nclude <16f886.h>
#device ADC=10
#use     delay(internal = 8MHz)                          
#include <flex_lcd416.c>
#define led PIN_B5

//#include <internal_eeprom.c>



int8   ciclo_activo=1;
  int16 cont3;    

void establecer_ciclo (int8 ciclo)
{
 

   set_pwm1_duty(ciclo);   // Establecer el ciclo activo

}


void pulsadores()
{  
   if (input(PIN_A4)==0)
   {
    while(!input(pin_a4)){
      ciclo_activo ++;  // Incrementar el ciclo activo.
      if (ciclo_activo > 249) ciclo_activo = 249;   // No permitir que el ciclo activo suba de 249
      delay_ms(15);
      establecer_ciclo(ciclo_activo);
     
   }
   }
   if (input(PIN_A5)==0)
   {
    while(!input(pin_a5)){
      ciclo_activo --;  // Disminuir el ciclo activo.
      delay_ms(15);
       if (ciclo_activo <= 1) ciclo_activo = 2;  // No permitir que el ciclo activo baje de 1
      establecer_ciclo(ciclo_activo);
       
   }
 
}
}

 
void memoria()
{
int16 cont;    
   if(input(pin_a2)==0){
          while(!input(pin_a2)){
          cont++;
          delay_ms(5);
          if (cont >500){
         
          write_eeprom(00,ciclo_activo ); // guardo el dato ciclo activo
         delay_ms(50);
   
         cont = 0;
          }
          }
       
           ciclo_activo =read_eeprom(00); // paso el dato a la variable ciclo_activo
         
     
         
           cont=0;
            delay_ms(50);
             establecer_ciclo(ciclo_activo);
           
            }

}

void memoria1()
{
int16 cont1;    
   if(input(pin_a3)==0){
          while(!input(pin_a3)){
          cont1++;
          delay_ms(5);
          if (cont1 >500){
         
          write_eeprom(01,ciclo_activo ); // guardo el dato ciclo activo
         delay_ms(50);
   
         cont1 = 0;
          }
          }
       
           ciclo_activo =read_eeprom(01); // paso el dato a la variable ciclo_activo
       
       
         
           cont1=0;
            delay_ms(50);
             establecer_ciclo(ciclo_activo);
             
            }
}  


void energia()  
{
// set_adc_channel(11);
//  delay_us(50);
//  ene = read_adc();
// if(ene<200)
if(input(pin_B4)==0){
cont3++;
delay_ms(1);
if (cont3 >10) {
write_eeprom(03,ciclo_activo );
delay_ms(50);
cont3 = 0;            
               }
                  }
}

void main()
{
 
ciclo_activo =read_eeprom(03);                  
    establecer_ciclo(ciclo_activo);  
   
setup_ccp1(CCP_PWM);
   setup_timer_2(T2_DIV_BY_4,249,1);   // 1000 Hz. @ 4 MHz.
   set_pwm1_duty(1);                   // Ciclo activo al mínimo



   #ZERO_RAM   // Limpiar RAM. (Variables en 0)

    establecer_ciclo(ciclo_activo);
 
   
   while (true)
   {
  pulsadores();
   memoria();
memoria1();

energia();



       
       
       
       
    }



   }
```

Lo que necesito que el ciclo activo se muestre más dividido ! Estuve tomando mediciones en la salida del pwm después del filtro pasa bajo y cada vez que pulso sube 200 milivolt el pwm, cómo puedo hacer para que suba de 50 milivolt?


----------



## Dr. Zoidberg (Sep 25, 2018)

callecuatro1976 dijo:


> estuve tomando medicaciones


Bue....


----------



## callecuatro1976 (Sep 26, 2018)

Dr. Zoidberg dijo:


> Bue....


es necesario a veces!


----------



## Gudino Roberto duberlin (Sep 26, 2018)

callecuatro1976 dijo:


> Hola,  estuve tomando medicaciones en la salida del pwm después del filtro pasa bajo y cada vez que pulso sube 200 milivolt el pwm, como puedo hacer para que suba de 50 milivolt?


Hola, bueno el PWM debería tener un incremento/decremento de duty de un 1/4 de lo que actualmente tiene. Así en lugar de escalonar de a 200mV lo haría de a 50mV.


----------



## callecuatro1976 (Sep 26, 2018)

Como lo cambio?  En la configuración del time?

¿ Sirve si pongo set_pwm1_duty(1%2); ésta línea así funciona?


----------



## D@rkbytes (Sep 26, 2018)

Eso no tiene sentido y no se puede establecer cualquier valor para el ciclo activo.
Todo tiene un motivo y un por qué, y para eso están las fórmulas en la hoja de datos.

Suponiendo que eso fuera válido, al compilador le daría lo mismo 1/2 que 0.5
Y establecer ese valor quedará totalmente fuera del rango para el registro CCPR(X)L

Por ejemplo, si quiero generar PWM a 1 KHz con un ciclo activo del 50 % con FOsc = 4 MHz:
Tomando como referencia la fórmula de la hoja de datos, tendríamos qué...
PR2 = 249 y CCPR1L = 124
Así que en PICC quedaría como:
setup_timer_2(T2_DIV_BY_4, 249, 1);
set_pwm1_duty(124);    // Ciclo activo al 50 %

Entonces, si el valor máximo para un ciclo activo del 100 % es 249, CCPR1L no puede ser superior a 249
Lo que se establecería de esta forma: set_pwm1_duty(249); // Ciclo activo al 100 %
Y obviamente los registros no trabajan con decimales o variables del tipo float.
Por lo tanto, lo que propones no funciona ni tiene sentido.

Te recomiendo que leas muy bien la hoja de datos para que comprendas mejor cómo funcionan los módulos de los PIC.


----------



## callecuatro1976 (Sep 26, 2018)

Si tenes razón,  estoy sin poder hacerlo andar, no se porque en cada vez que pulso me sube de 1 volt y vaya de 1 volt a la vez,  no puedo lograr que suba de 50 milivolt por cada vez que se pulsa el botón!


----------



## D@rkbytes (Sep 26, 2018)

No creo que eso sea posible ni usando el módulo CCP a su máxima resolución. (10 bits) O sea, 1023 pasos, sin contar el 0
De hecho, el ciclo activo se puede mantener sin cambios pasando de 800 a 820 en CCPR(XH/L) si se usara a 10 bits.
O en 8 bits puede no haber cambios del ciclo activo si se pasa de 80 a 85 en CCPR1L


----------



## callecuatro1976 (Oct 16, 2018)

Hola consulta para no habrír otro post,  puedo usar dos pulsadores apretados al mismo tiempo para guardar el dato en la memoria,  yo uso para variar el ciclo activo los pin a4 y a5 se puede declarar en el if a4 y a5 para guardar el dato?


----------



## D@rkbytes (Oct 16, 2018)

No veo el motivo del por qué no, pero... ¿Por qué no haces la prueba?


----------



## callecuatro1976 (Oct 16, 2018)

Duda lo declaró así if(input (Pin_a4&pin_a5)) así está bien?
Tengo una duda lo declaró if(input (pin_a4&pin_a5)) esta decisión es correcta?


----------



## D@rkbytes (Oct 16, 2018)

callecuatro1976 dijo:


> Tengo una duda, lo declaro: if(input (pin_a4&pin_a5))
> ¿Esta decisión es correcta?


No. Deben ser dos lecturas completas con una comparación AND
O sea: if (input_state(PIN_A4) && input_state(PIN_A5))


----------



## callecuatro1976 (Oct 17, 2018)

No me funciono! Cuando apretó los dos botones juntos siempre se dispara para arriba o abajo y no puedo guardar el dato que quiero!


----------



## D@rkbytes (Oct 17, 2018)

Suena lógico que pase eso si existen sentencias anteriores.
Tal vez funcione usar una selección con switch () o enmascarar los bits.


----------



## callecuatro1976 (Dic 15, 2018)

hola miembros del foro , estoy haciendo mejoras en mi fuente y quiero sacar la lectura del adc , pero seguir mostrando los datos de voltaje en pantalla y no se como hacer los cambien en la función del ciclo activo para que muestre un valor aproximado de 0 volt a 18 

```
void establecer_ciclo (int8 ciclo)
{
  
     set_pwm1_duty(ciclo);   // Establecer el ciclo activo
    lcd_gotoxy(1,3);
   // Obtener el porcentaje del ciclo activo.
   porcentaje2 = (ciclo / 24.5) *10;
   // Mostrar el porcentaje del ciclo activo para la carga.
   printf(lcd_putc," Rf:%02u%%",porcentaje2,);
  
        
}
```
en el código muestra porcentaje , en ves de porcentaje quiero mostrar voltaje , necesito una idea de como cambiarlo , gracias


----------



## pandacba (Dic 15, 2018)

Es simple, matemática pura, sin usar tus variables
Valor_max
X%
x%=ciclo expresado en porcentaje

(X5 * Valor_max)/100= valor_dc

Es mucho más práctico utilizar el ADC del micro, uno esterno, o un CI dedicado y no perder tanto tiempo y seguir sin tener nada, hay cosas en las  que hay que ser prácticos sobre todo si no se tienen los conocimientos necesarios


----------



## callecuatro1976 (Dic 15, 2018)

Si venia usando el adc pero use el on off del lm2576  para controlar el encendido y apagado de mi fuente y me di cuenta que no puedo setear el voltaje al estar apagado,  entonces tengo que cambiar el sistema de poder cambiar voltaje siempre y cuando piso el pedal y enciendo el integrado que este lo más parecido al valor que tenia el adc!


----------



## pandacba (Dic 15, 2018)

Cuando se apaga tu fuente se apaga el display?, dame más   datos tal vez pueda ayudarte


----------



## callecuatro1976 (Dic 16, 2018)

No sólo se apaga la muestra de tensión, se pone en cero,  aprieto los pulsadores para poner una tensión y no marca nada pero esta funcionando,  se ve recién cuando aprieto el pedal y enciendo el Lm2576.


----------



## pandacba (Dic 16, 2018)

Podes poner un esquema de lo que estas haciendo?


----------



## callecuatro1976 (Dic 16, 2018)

Si, lo voy a buscar o tendría que hacelo otra vez, ya hace bastante que hice ésta fuente,  quería cambiar lo de la muestra del voltaje en el lcd,  si mantengo el pedal apretado y activo el Lm2576adj se ven voltaje y lo puedo modificar,  cuando le saco masa al lm y lo apagó ahi tengo el problema de la muestra,  por eso quería ya mostrarlo en el lcd directamente sin tomar la lectura del adc! Y no me queda, siempre se me pasa,  no se como mover el ciclo activo y mostrar una tensión sin usar el adc !


----------



## D@rkbytes (Dic 23, 2018)

¿Y el esquema que te pidieron?


----------



## callecuatro1976 (Dic 25, 2018)

Lo estoy armando otra vez,  ésta fuente la hicimos hace bastante tiempo y no encuentro los esquemas,  tengo el programa y la fuente armada,  en breve voy a subir el esquema en Proteus!

Aquí está el esquema y lo que voy haciendo del programa, felicidades para todos.

Consulta, se puede tomar la medición,  ejemplo adc con un optoacoplador?


----------



## callecuatro1976 (Ene 15, 2019)

Hola miembros del grupo,  pude hacer lo más cercano la medición sin adc,  lo único que puedo hacer es que corra cuando dejo apretado el botón!


```
void establecer_ciclo (int8 ciclo)
{
  


   set_pwm1_duty(ciclo);   // Establecer el ciclo activo
    lcd_gotoxy(1,2);
  
    porcentaje2 =(float) (ciclo * 70.0) / 1023;

   printf(lcd_putc," %.1f ",(double)porcentaje2);
}
```

ahí pude avanzar un poco en lo que estoy haciendo , me falta que lo que muestra en pantalla vaya con el voltaje y porque me lo da invertido en cero es el máximo , pero bueno gracias por la ayuda.


----------



## callecuatro1976 (Jun 28, 2019)

Hola grupo !! tengo un problema que no puede resolver no me da el conocimiento para hacerlo y no me doy la idea de como implementarlo, quiero hacer que el ciclo activo de mi fuente muestre el valor en pantalla del lcd sin usar el adc como medición, ya probé todas las formas y siempre me mete ruidos por el adc , puse todo los capacitores que hay !! le dejo el código y proteus en el archivo , mil gracias al que me pueda ayudar , busque algún ingeniero que me ayude y nada , saludos

cambien a usar el adc y lo estabilice bastante bien ahora cambie el display al Nokia 5110 y se me tilda cuando quiero usar las memorias del pic 18f2550 , dejo simulación y código !!!


----------



## hell_fish (Ene 6, 2021)

Buenas noches, estamos pasando por momentos difíciles, espero todos estén bien.

Hace algún tiempo estoy haciendo estabilizadores de tensión de red usando lectura ADC de un pic, resulta que me encontré un par de estabilizadores averiados y estos usaban un pequeño Pic12f508 para medir la tension y elegir la derivación correcta. Me di cuenta que este Pic NO tiene ADC me preguntaba cómo puede medirse la tensión sin ADC . 

Pdt:el Pic12f508 tiene protección de lectura. :-\


----------



## DJ T3 (Ene 7, 2021)

Sin circuito donde ver, se hace imposible.
Para mi que lee 2 o 3 puertos donde tiene colocado una par de zener, si uno de los zener sobrepasa X voltaje, conduce y el PIC interpreta como voltaje elevado. Si el otro zener deja de conducir, entonces interpreta como bajo voltaje...
Es lo que se me ocurre


----------



## hell_fish (Ene 7, 2021)

DJ T3 dijo:


> Sin circuito donde ver, se hace imposible.
> Para mi que lee 2 o 3 puertos donde tiene colocado una par de zener, si uno de los zener sobrepasa X voltaje, conduce y el PIC interpreta como voltaje elevado. Si el otro zener deja de conducir, entonces interpreta como bajo voltaje...
> Es lo que se me ocurre


Es algo difusa mi pregunta, invariablemente de los miles de circuitos que podrían funcionar en mi caso, diré de formaas específica.... Se puede medir y tension solo con el Pic antes mencionado? Si fuere así explicar la forma de hacerlo...,...

	Mensaje automáticamente combinado: Ene 7, 2021



DJ T3 dijo:


> Sin circuito donde ver, se hace imposible.
> Para mi que lee 2 o 3 puertos donde tiene colocado una par de zener, si uno de los zener sobrepasa X voltaje, conduce y el PIC interpreta como voltaje elevado. Si el otro zener deja de conducir, entonces interpreta como bajo voltaje...
> Es lo que se me ocurre


Pdt:no no tiene más que un puerto para lectura


----------



## Scooter (Ene 7, 2021)

¿Esto es una broma, un concurso de adivinanzas...?
No lo entiendo.


hell_fish dijo:


> Es algo difusa mi pregunta, invariablemente de los miles de circuitos que podrían funcionar en mi caso, diré de formaas específica.... Se puede medir y tension solo con el Pic antes mencionado? Si fuere así explicar la forma de hacerlo...,...
> 
> Mensaje automáticamente combinado: Ene 7, 2021
> 
> ...


No,tu pregunta es absolutamente difusa.
¿Un puerto de ocho pines o un GPIO de un pin?. El 12f508 tiene ocho pines, será un GPIO, osea un pin.

¿Se puede leer una tensión analógica con un pin digital sin mas? *NO, NO SE PUEDE*.
¿Y haciendo cosas ingeniosas?, si que se puede.
Básicamente implementando un ADC en el sentido amplio del término, no necesariamente un flash ni un sigma delta ni un... hay bastantes enfoques para conseguirlo.

Ahora bien ¿Cual es la pregrunta? ¿Que adivinemos que hizo nosequien en noseque circuito montado nosecomo que no podemos ni ver?
Si tienes dudas de un circuito, postea el circuito, saca el esquema, pon fotos, no sé preguntar por preguntar me parece absurdo.

Este hilo es de hace tiempo pero me parece recordar que en él hay comentados posibles métodos de leer un valor digital sin un "ADC al uso".
Por ejemplo un generador de rampa, un comparador y midiendo el tiempo. Osea implementando un conversor ADC de rampa.


----------



## cosmefulanito04 (Ene 7, 2021)

Probablemente usen comparadores y el indicador sea de nivel mediante algún arreglo de leds.


----------



## DJ T3 (Ene 7, 2021)

Me fije antes de realizar mi respuesta, y el dicho PIC no tiene comparadores, es bastaaante basico.


----------



## Scooter (Ene 8, 2021)

Se me ocurre algún arreglo conversor tensión frecuencia o cualquier cosa similar... Llegados a ese punto se pone un pic un poco mejor que cuesta menos.


----------



## cosmefulanito04 (Ene 8, 2021)

DJ T3 dijo:


> Me fije antes de realizar mi respuesta, y el dicho PIC no tiene comparadores, es bastaaante basico.



Sin esquema es todo suposición.

Usando operacionales como comparadores, tal vez el PIC solo está para tomar decisiones un poco más complejas que un simple arreglo de transistores + reles, por ej. algo relacionado al tiempo.


----------



## Eduardo (Ene 9, 2021)

El viejo gameport de las PC incluia la lectura de la resistencia de un potenciómetro y lo hacía sin usar ADC.  El principio de funcionamiento era simplemente medir el tiempo de carga de un condensador.

No es un ADC como se puede llegar a pensar, la lectura no es lineal , depende fuertemente de las variaciones de la tensión de umbral y de las variaciones por temperatura de la capacidad del condensador.  Pero como es algo muy sencillo, para aplicaciones de baja resolución como es un estabilizador donde solamente hay que ver en qué rango se está para conmutar los relays --> sirve.

Con microcontroladores lo que se puede hacer es programar un puerto como salida para descargar un condensador y luego reprogramarlo como entrada para medir el tiempo que demora en cargarse hasta leer un '1' 
No está en el ejemplo, pero luego se debe comparar la lectura con valores de una tabla para saber en rango se está y actuar en consecuencia.



En el ejemplo el programa del micro es:

```
#include <12f508.h>
#FUSES NOWDT          //No Watch Dog Timer
#FUSES NOMCLR         //Master Clear pin used for I/O
#use delay(internal=4MHz)
#use FAST_IO(all)

#bit pinB0 = getenv("SFR:PORTB").0

int16 N  ;
//-----------------------------------
int16 Tcarga(){
int16 k ;

    set_tris_b(1) ;
    for(k=0 ; pinB0 == 0 ; k++);

    set_tris_b(0) ;
    pinB0=0 ;

    return k ;
}
//-----------------------------------

void main(void){

    set_tris_b(0) ;
    pinB0 = 0 ;

    while(1){

        N = Tcarga() ;    // Leo el tiempo de carga
                          // del condensador
/*
    Otras operaciones dentro del bucle ppal
.........
.........
*/
        delay_ms(200) ;  // Un retardo cualquiera para este ejemplo
    }
}
```


Hay que tener cuidado con la simulación porque al menos Proteus usa un modelo de entrada que llama "Digital" y vaya uno a saber por qué pero no mantiene constante el umbral donde la entrada pasa de detectar '0' a '1' y* en consecuencia la lectura durante la simulación es inestable*

Con compuertas, *Proteus* tiene la opción de *usar un modelo 'Analógico" o 'Digital' para las entradas* (obviamente el que funcionaría en este ejemplo es el 'Analógico')  pero para micros NO.


----------



## Scooter (Ene 9, 2021)

@Eduardo: Eso que tu has definido es un ADC, de rampa concretamente. Pero no sabemos si es eso lo que usa.
Lo puedes hacer incluso "automático" usando interrupciones para medir el tiempo.





						Google Sites: Sign-in
					

Access Google Sites with a personal Google account or Google Workspace account (for business use).



					sites.google.com
				




Normalmente se usan conversores de "doble rampa" porque son menos sensibles a si la señal de entrada se modifica mientras se está efectuando la conversión.

La ventaja es que son muy baratos y muy precisos. La desvantaja es que son muy lentos.

Hay vida mas allá de los conversores de aproximaciones sucesivas:


			http://ario.webs.uvigo.es/docencia/sad/SADGRADO_3.pdf
		

Este pdf está pero que muy bien, lo acabo de encontrar por casualidad.


----------



## Eduardo (Ene 9, 2021)

No me refería a la definición de ADC sino a lo que uno espera de un ADC "normal", que es una lectura proporcional a la tensión.  Esto te devuelve un número proporcional al tiempo transcurrido ligeramente no lineal respecto a la tensión.

El 12F508 solamente tiene 25 bytes de RAM, un timer de 8bits, solo 2 niveles de stack y* no soporta interrupciones*, lo que hagas tiene que ser en el bucle principal y no anidar subrutinas ni ser ambicioso con la RAM.


----------



## Scooter (Ene 9, 2021)

Creo entonces que se han pasado de ahorradores eligiendo el micro.


----------



## DJ T3 (Ene 10, 2021)

Como bien dicen, existen otros metodos, pero yo sigo esperando las fotos del circuito para saber cuál usaron.

Para agregar a la lista de opciones, se podria usar un ADC externo...


----------



## Scooter (Ene 10, 2021)

DJ T3 dijo:


> Como bien dicen, existen otros metodos, pero yo sigo esperando las fotos del circuito para saber cuál usaron.
> 
> Para agregar a la lista de opciones, se podria usar un ADC externo...


Y yo también, lo mismo es un método ingenioso.
El convertidor de rampa es "gratis" si lo usas con un potenciometro, pero si lo usas comparando con una tensión entonces necesitas un comparador y ya no es "gratis", llegados a ese punto que lleve ADC el micro.


----------



## D@rkbytes (Ene 10, 2021)

hell_fish dijo:


> Hace algún tiempo estoy haciendo estabilizadores de tensión de red usando lectura ADC de un PIC.
> Resulta que me encontré un par de estabilizadores averiados y estos usaban un pequeño PIC12F508 para medir la tensión y elegir la derivación correcta.
> Me dí cuenta que este PIC no tiene ADC y me preguntaba cómo puede medirse la tensión sin ADC.


Tal vez el truco de ese circuito es usar el clásico TL431


----------



## hell_fish (Ene 20, 2021)

D@rkbytes dijo:


> Tal vez el truco de ese circuito es usar el clásico TL431


Buenas noches de hecho solo usa el Pic y un capacitor, resistencia, luego hago un esquema de esa parte.

Son excelentes sus respuestas me inclino por lo que dijo el compañero carga y descarga ese capacitor, mide el tiempo y compara con los datos en su programación.

@Scooter la pregunta concreta era como puede ese Pic medir tensión de red sin ADC y ya fue contestada o por lo menos una forma de hacerlo.

Gracias bendiciones


----------



## DJ T3 (Ene 20, 2021)

Lo interesante y certero seria ver ese diagrama.
Trata de dibujarlo completo, no debe ser mucho


----------



## callecuatro1976 (Jul 23, 2021)

Hola, necesito de su ayuda nuevamente, no puedo hacer que esto funcione correctamente, subo archivo y simulación, estoy tratando que el pwm vaya de la mano del contador cuando esté en 5 Volt el pwm del pic el lcd muestre 17 Volt , gracias

Ahi pude hacer que estén parejos solo tengo un problema, como guardo los dos datos en la memoria, para que cuando se apague y se encienda se muestren los datos en el lcd, gracias por leer


----------



## Scooter (Jul 23, 2021)

Como no, donde: En la eeprom


----------



## callecuatro1976 (Jul 23, 2021)

Scooter dijo:


> Como no, donde: En la eeprom


No logro guardar los datos del lcd del contador, los datos pwm los guarda, no la muestra ejemplo 12 volt me arranca el contador de 0 y el pwm en 12


----------



## Scooter (Jul 23, 2021)

¿Cual es el que guardas primero en la eeprom?


----------



## callecuatro1976 (Jul 23, 2021)

Scooter dijo:


> ¿Cual es el que guardas primero en la eeprom?


El pwm el ciclo activo.


----------



## Scooter (Jul 23, 2021)

Para programar la eeprom has de esperar a que se grabe el dato anterior mirando un flag, para leer se lee libremente. ¿Has verificado eso?


----------



## callecuatro1976 (Jul 24, 2021)

Si lo verifique, pero tengo varios problemas con el código completo ya llevo varios años tratando de que funcione y me falta  bastante.


----------



## DJ T3 (Jul 24, 2021)

Mire "*Nueva Carpeta(2).rar*", muy por arriba, y minimamente lo que veo es que estas intentando guardar un *float* en la *eeprom*, ademas no se por qué usas ese float, si con un *int* va bien.
Insisto, lo vi por arriba y sin formateado visual (colores para las funciones y eso)


----------



## callecuatro1976 (Jul 24, 2021)

Si, también se me esta dando vuelta el ciclo activo, tengo que llamar un programador


----------



## DJ T3 (Jul 25, 2021)

Te la estas complicando mucho, asi que si, seria lo ideal alguien que se dedique a la programacion.
No se porqué no usas el ADC, pero seria lo ideal


----------



## unmonje (Jul 26, 2021)

callecuatro1976 dijo:


> Si, también se me esta dando vuelta el ciclo activo, tengo que llamar un programador


Me parece que si, viene siendo hora.
 Leí su tópico desde que empezo hace 3 años ó mas y hubiera intentado ayudarle, pero la mayor traba para mi, era usted, porque lamentablemente no entendía la redacción, de lo que usted intentaba explicar, su redacción era confusa y cuando le pedian documentación concreta los colegas, usted subía los esquemas en un archivo de una aplicación indirecta, es decir que se necesitaban emuladores. Hubiera bastado con una buena FOTO del circuito para ayudarle y ayudarnos. Nunca me quedo claro, por donde leia los datos, ni como los quería representar con la PIC.
 Programé muchos años las PICs o los PLCs de varios tipos y marcas para cosas complicadas, pero en assembler o Ladder, no en C.
Usar demoras en la programación no es un buen método, hay otras técnicas mas pícaras, que usted deberia conocer para sobrellevar el proyecto.     Y si, hay maneras elegantes para mostrar 0 a 18 volts de tensión de la salida de un ADC de 0 a 5 inestable, pero son métodos pícaros que se usan en lenguaje ensamblador del fabricante, mucho mas complicado es en lenguaje C. Saludos


----------



## callecuatro1976 (Jul 26, 2021)

Voy a usar un lm2596 y lo enciendo y apago del on off si no uso algún sistema para mostrar el voltaje cuando el integrado está apagado muestra 0 en el lcd por eso el adc no me funciona, el resto funciona bien lo único que no puedo hacer es ese bendito contador que mueva también el ciclo activo. Gracias por leer


----------



## unmonje (Jul 26, 2021)

callecuatro1976 dijo:


> Voy a usar un lm2596 y lo enciendo y apago del on off si no uso algún sistema para mostrar el voltaje cuando el integrado está apagado muestra 0 en el lcd por eso el adc no me funciona, el resto funciona bien lo único que no puedo hacer es ese bendito contador que mueva también el ciclo activo. Gracias por leer


El LM2596 es un regulador de fuente con un encendido y apagado remoto, pero eso no me explica que cosa quiere usted hacer con el proyecto.
Se que lo queria mostrar por la puerta C del PIC a un  VISOR  de LCD y lo comandaba con otros pines, como es lógico, pero no llegue a entender que cosa queria leer y por donde.
Aparentemente en el programa en C que lei, usted configuraba un PWM y pretendia controlar el ancho del pulso,  pero se me escapaba el motivo concreto. y si lo comparaba con otro origen de dato ó que ?
Es decir :
1-De donde toma el dato que quiere mostrar en LCD ( pin , puerta, periferico interno, etc)
2-Su naturaleza (AC,DC ó que otra cosa),
3-Su rango ( de *x* volt  a * x+n* volts/ corriente )
Resumiendo , el destino del dato sería claro. Lo que no es claro es el ORIGEN, NATURALEZA  y PROPOSITO.
(programar PICs en Lenguaje C es muy  rápido, pero se pierde mucho del potencial de la PIC programada en asembler, porque lo limita)
Saludos


----------



## callecuatro1976 (Jul 26, 2021)

Es una fuente de 0 a 17 volt de dc con visualización en un lcd, te agradezco el interés


----------



## unmonje (Jul 26, 2021)

¿ Algo como esto ? --> https://http2.mlstatic.com/D_NQ_NP_627142-MLA42637653461_072020-O.webp
Ya está hecho.


----------



## Dr. Zoidberg (Jul 26, 2021)

Bueee.....pero si lo quiere hacer para aprender, está OK.
En cualquier otro caso es una pérdida de tiempo.


----------



## callecuatro1976 (Jul 26, 2021)

unmonje dijo:


> ¿ Algo como esto ? --> https://http2.mlstatic.com/D_NQ_NP_627142-MLA42637653461_072020-O.webp
> Ya está hecho.


Si algo así pero manejo el voltaje con el pic, porque no se puede hacer diferente? El proyecto funciona lo único que quería era aprender a controlar y mostrarlo de otra manera y todos quieren que use el adc, si serviría como lo pensé! Porque no se puede ?


----------



## DJ T3 (Jul 26, 2021)

callecuatro1976 dijo:


> Voy a usar un lm2596 y lo enciendo y apago del on off


Acá otro como vos; PWM LM2596 buck converter?
No se qué tan rapido es ese pin, y mucho menos qué tan rapido reacciona el LM. Ademas ese pin no es para esa finalidad.

Te conviene, como dice al final, usar el PWM del microcontrolador, y reemplazar el potenciometro, pasando a analógico al PWM.
O usar algun potenciometro digital y controlar via I2C o SPI.
Luego con un ADC del mismo microcontrolador realizas la lectura del voltaje.


callecuatro1976 dijo:


> todos quieren que use el adc


Porque no te aclaras.
El ADC (Analog Digital Converter, Conversor Analógico Digital), sirve para obtener una señal analógica (tu voltaje), y convertirlo en digital (lo que entiende el microcontrolador).
Lo que necesitas es el contrario para controlar, osea DAC (Digital Analog Converter, Conversor Digital Analógico), que convierte datos digitales (desde tu microcontrolador), a analógicos (voltaje de salida variable).
Lee cómo usar el PWM como DAC. Y si quieres, en vez de usar el módulo PWM (que seria lo lógico y conveniente), puedes crear mediante código tu propio PWM (problemas de retardo, desincronizacion, etc)


----------



## unmonje (Jul 26, 2021)

¿Para aprender ? buenisimo, nunca me quedo claro ESO.
Entendía que era para un trabajo o un berretin personal.
Como sea, si se puede con una PIC, pero no lo recomiendo en  lenguaje "C" , si en *assembler* del fabricante.
Primero hay que escribir la rutina interrupcion de *refresco del display* para que *no parpadee* nunca y refreque a 50Hrtz
Ademas hay que usar un *watch dog *para que el ciclo no varie y funcione por RAFAGAS.
En el funcionamiento por RAFAGA, se hace *un ciclo* completo con todas las tareas necesarias y se descanza en un bucle INFINITO al final del ciclo.
De ese bucle infinito lo saca la INTERRUPCION , en el bucle se leen los teclados pulsados que ocurran o de algun otro evento o variable a controlar.
La rutina  de teclado se programa como sigue :
1-Se espera un cambio de estado de tecla de 0  a 1.
2-Se entra  en un bucle de espera a que retorne de 1 a 0 para dar por concluida la pulsación.
(No hacerlo de esta manera induce a errores y reniegos por parte del usuario)
3- recien se procede a cumplir con la orden.
Un ser humano tarda como mínimo 10 milsegundos en pulsar una tecla y liberarla.Es importante para programar teclados y no llorar.
El programa debe HACER todo A LA VEZ sin parar. Lo dificil es coordinar todo eso adecuadamente. Haga un *plan* no escriba a tontas y a locas.

_*Algo a tener en cuenta en la PICS es NO hacer abuso de la EPPROM interna. Su vida útil es limitada. Sirve para datos a largo plazo calibración anual, no para grabar datos a cada rato porque termina rompiendose.*_

Le adjunto en este* .rar *un sistema operativo que hice por 2004, que simula un PLC , funciona y hace bastante de lo que le escribo en este topico. No es el definitivo pero le va a dar una idea de como se hace ciertas cosas. (No es fácil le adelanto)


----------



## callecuatro1976 (Jul 26, 2021)

Si fuera un trabajo ya me hubieran echado como 2 años que estoy con esto, busque programadores en Argentina para que me orienten pero.... en fin sin palabras ahora estoy haciendo un curso por Internet para mejorar y volví con esta idea, se que va salir, gracias a todos por contestar


----------



## Scooter (Jul 26, 2021)

Usa un divisor de tensión y el convertidor ADC que ya estás usando actualmente.


----------



## callecuatro1976 (Jul 26, 2021)

Scooter dijo:


> Usa un divisor de tensión y el convertidor ADC que ya estás usando actualmente.


Si así me funciona bien, pero pasa que quiero encender y apagar la fuente del pin on/off y cuando la apago no muestra valor en el lcd, tengo que encender para que se vea, por eso pensé un contador de 0 a 17 y que vayan concatenado con el ciclo activo, si es 5 volr=17 volt, tendría que funcionar no estaría 100% precisó pero andaría bien


----------



## Scooter (Jul 27, 2021)

callecuatro1976 dijo:


> Si así me funciona bien, pero pasa que quiero encender y apagar la fuente del pin on/off y cuando la apago no muestra valor en el lcd, tengo que encender para que se vea, por eso pensé un contador de 0 a 17 y que vayan concatenado con el ciclo activo, si es 5 volr=17 volt, tendría que funcionar no estaría 100% precisó pero andaría bien


No entiendo absolutamente nada.
Si la fuente está apagada mostrará 0, suponiendo que el indicador se alimente de otro sitio.
Lo del contador y todo eso, no lo entiendo.


----------



## callecuatro1976 (Jul 27, 2021)

Ok, se que hay miembros del grupo que esto es una pavada y lo hacen con los ojos cerrados, para otros es todo un reto, seguiré trabajando gracias 🙂


----------



## el_patriarca (Jul 27, 2021)

En estos tiempos donde la electrónica se ha convertido en una especie de ensamblaje de legos, no le veo sentido el tener a disposición todas las herramientas para un propósito,  y no querer usarlas. Yo lo veo como querer sacar un tornillo sin usar destornillador y querer darse golpes en el pecho por ser el primero que lo hizo.

Ojalá tengas éxito en tu proyecto, de todo corazón.


----------



## DJ T3 (Jul 28, 2021)

Pero como ya te puse, NO está pensado ese pin para ese uso, por eso al apagar obtienes los 0V.
Aparte de eso, seguro ni siquiera tienes un capacitor a la salida del LM, porque con carga puede ser, pero sin carga deberia marcarte algo superior a 0.
Haz lo que te dije, controla el pin que llevaria el potenciometro, o usa otro método con otros componentes que estén mas adecuado para eso (transistores varios, bobinas, diodos, etc).
Mira en el foro, que hay mucho material. Busca una fuente regulable digital


----------



## unmonje (Jul 28, 2021)

Si entendí bien o se explico bien el asunto, para que el display LCD, muestre el último valor leido de la fuente
despues de apagarse, hay 2 opciones básicas que no son ningun secreto.
1- El LCD debe tener su propia fuente o batería que lo alimente, a pesar de apagar la fuente ó el PIC  ó
2- Hay  que desconectar el bus del LCD , antes de apagar la fuente para que conserve el dato y ademas éste último siga recibiendo alimentación de algun origen (bateria , o lo que sea) ( No puedo creer que ésdte tópico tenga ya 7 páginas)     😝


----------



## callecuatro1976 (Jul 29, 2021)

unmonje dijo:


> Si entendí bien o se explico bien el asunto, para que el display LCD, muestre el último valor leido de la fuente
> despues de apagarse, hay 2 opciones básicas que no son ningun secreto.
> 1- El LCD debe tener su propia fuente o batería que lo alimente, a pesar de apagar la fuente ó el PIC  ó
> 2- Hay  que desconectar el bus del LCD , antes de apagar la fuente para que conserve el dato y ademas éste último siga recibiendo alimentación de algun origen (bateria , o lo que sea) ( No puedo creer que ésdte tópico tenga ya 7 páginas)     😝


Poneme un ejemplo de cómo sería? Así acordamos las páginas, no es así, el ciclo activo tiene que ir con lo que muestro en el lcd, esta el adjunto para verlo! Gracias

Ahí pude hacerlo funcionar, lo único no se porque cuando presiono el pulsador el el primer pulso se va al máximo, subo el archivo con el código y la simulación en proteus , gracias


----------



## MaShicO (Jul 29, 2021)

callecuatro1976 dijo:


> Ahí pude hacerlo funcionar, lo único no se porque cuando presiono el pulsador el el primer pulso se va al máximo, subo el archivo con el código y la simulación en proteus , gracias


Porque cuando presionas ingresa al *while(!input_state(pin_incr)) *y aquí mientras sigas presionando se va a ejecutar lo que hay dentro de ese while y viendo tu código lo que haces es incrementar tu variable.
Prueba y déjalo así: *while(input_state(pin_incr))* {...};


----------



## unmonje (Jul 29, 2021)

callecuatro1976 dijo:


> Poneme un ejemplo de cómo sería? Así acordamos las páginas, no es así, el ciclo activo tiene que ir con lo que muestro en el lcd, esta el adjunto para verlo! Gracias


Se lo que es un ciclo activo en general, pero en vuestro proyecto, hace hojas que me pregunto a que le llama usted el ciclo activo. 
Si hay un ciclo activo para usted,¿a que le llama ciclo pasivo  en su proyecto ?   Así terminamos con los neologismos. 😝  ... y avanzamos


----------



## callecuatro1976 (Jul 30, 2021)

Lo hace solo al inicio después no, el ciclo activo es el pwm, igual ya estoy por abandonar tengo que estudiar mucho más se me complico!


----------



## Scooter (Jul 30, 2021)

Así desde afuera es un sinsentido de la A a la Z.
El único sentido que tenía era estudiar por aprender aunque no tuviera sentido el resultado, si aprender y distraerse no es el objetivo, entonces ya...


----------



## callecuatro1976 (Jul 30, 2021)

Scooter dijo:


> Así desde afuera es un sinsentido de la A a la Z.
> El único sentido que tenía era estudiar por aprender aunque no tuviera sentido el resultado, si aprender y distraerse no es el objetivo, entonces ya...



Si, pero la frustración de que no ande a veces te gana.


----------



## DJ T3 (Jul 30, 2021)

callecuatro1976 dijo:


> Si, pero la frustración de que no ande a veces te gana.


Eso no es motivo para abandonar, al contrario para aprender mas


----------



## hell_fish (May 21, 2022)

Eduardo dijo:


> El viejo gameport de las PC incluia la lectura de la resistencia de un potenciómetro y lo hacía sin usar ADC.  El principio de funcionamiento era simplemente medir el tiempo de carga de un condensador.
> 
> No es un ADC como se puede llegar a pensar, la lectura no es lineal , depende fuertemente de las variaciones de la tensión de umbral y de las variaciones por temperatura de la capacidad del condensador.  Pero como es algo muy sencillo, para aplicaciones de baja resolución como es un estabilizador donde solamente hay que ver en qué rango se está para conmutar los relays --> sirve.
> 
> ...


Buena tarde.
Dónde puedo encontrar el voltaje umbral de los pines configurados como entradas para ser leídos como 1? En cada pic es diferente ? Depende de la temperatura? 

En lenguaje de bajo nivel una orden se ejecuta a la misma velocidad que uno de bajo nivel? Es para calcular el valor de K en el ejemplo. 

Gracias.


----------



## unmonje (May 21, 2022)

hell_fish dijo:


> Buena tarde.
> Dónde puedo encontrar el voltaje umbral de los pines configurados como entradas para ser leídos como 1? En cada pic es diferente ? Depende de la temperatura?
> 
> En lenguaje de bajo nivel una orden se ejecuta a la misma velocidad que uno de bajo nivel? Es para calcular el valor de K en el ejemplo.
> ...


Por diversas razones, en lenguaje de alto nivel, se suele llegar a tardar mas, pero ésta aseveración, no es absoluta de ninguna manera, es una tendencia lógica no mas.
No confundir_ *tiempo de instrucción*_ con _*ejecución de comando*_. Para mi, son cosas distintas. La primera es de HARDWARE la segunda es de SOFTWARE


----------



## Eduardo (May 21, 2022)

hell_fish dijo:


> Dónde puedo encontrar el voltaje umbral de los pines configurados como entradas para ser leídos como 1? En cada pic es diferente ? Depende de la temperatura?


En ningún lado, en una entrada digital lo que se te dan son dos niveles de tensión donde se garantiza que por encima o por debajo se leerá un 1 o un 0,  entre medio no se asegura nada. A su vez estos niveles dependen del pin y como esté configurado.

Obviamente que en cada pin existe un umbral, pero  pero lo tenés que sacar experimentalmente con una rutina de calibración.  A fines de dimensionar podés usar un valor de 2V (Vdd=5V)



hell_fish dijo:


> En lenguaje de bajo nivel una orden se ejecuta a la misma velocidad que uno de bajo nivel? Es para calcular el valor de K en el ejemplo.


Supongo que la pregunta era *"En lenguaje de alto nivel una orden se ejecuta a la misma velocidad que uno de bajo nivel?"*
Ni cerca, salvo casualidades de compilación.

Siendo que usas Proteus, la manera mas fácil es poner breakpoints y que el mismo Proteus te dé el tiempo transcurrido.


----------



## DJ T3 (May 21, 2022)

hell_fish dijo:


> Dónde puedo encontrar el voltaje umbral de los


Nadie te dio la respuesta, la respuesta correcta a esta pregunta es en el datasheet.
Allí encontrarás todos los datos, incluidos los del umbral o histeresis


----------



## switchxxi (May 21, 2022)

Igual, dependiendo del microcontrolador, se puede realizar un ADC mediante un comparador si es que lo trae internamente.

Como el mismo puede conectar una de sus entradas a una tensión externa precisa o a una referencia interna estable no hace falta hacer cálculos raros para saber si varia de un microcontrolador al otro. Y en el caso de necesitar precisión se usa una referencia externa.

Si no hace falta mucha precisión, que el umbral esté 100mV mas arriba o mas abajo no va a variar mucho la situación.


----------



## hell_fish (May 21, 2022)

Buenas noches. 

El pic que estoy usando es el 12f508 que es el más económico, el voltimetro que uso es básico simplemente son 4 led que me indiquen si sube o baja conmutados por los pines libres del pic.  

La primera imagen es la el tiempo de carga cuando el voltaje está bajo y la segunda imagen es cuando el voltaje está alto, de lo anterior he notado que el tiempo no varía linealmente con el voltaje esto es problemático al intentar mostrar en los led que voltaje aprox que hay.

Pienso que para hacer lineal el tiempo de carga de acuerdo al voltaje puedo usar una fuente de corriente constante con un par de bjt?  

 Pdt: la imagen final es el circuito para que tenga una idea de que hice.


----------



## Eduardo (May 22, 2022)

hell_fish dijo:


> ...
> El pic que estoy usando es el 12f508 que es el más económico,


No sé en Colombia, pero acá en Argentina podés conseguir a menor precio el 12F1571 , también de 8 pines y con sus limitaciones de memoria, pero al lado del 12F508 es un cohete a la Luna. Soporta interrupciones, tiene timers de 8 y 16bit, PWM , comparador, ADC y DAC.



hell_fish dijo:


> el voltimetro que uso es básico simplemente son 4 led que me indiquen si sube o baja conmutados por los pines libres del pic.
> 
> La primera imagen es la el tiempo de carga cuando el voltaje está bajo y la segunda imagen es cuando el voltaje está alto, de lo anterior he notado que el tiempo no varía linealmente con el voltaje esto es problemático al intentar mostrar en los led que voltaje aprox que hay.
> 
> Pienso que para hacer lineal el tiempo de carga de acuerdo al voltaje puedo usar una fuente de corriente constante con un par de bjt?



Con 4 niveles de tensión la alinealidad la corregís con una tabla (si es que realmente hace falta)
También, si la tensión a medida es bastante superior a 5V, usás una resistencia+zener de protección en lugar de un divisor de tensión --> te queda mucho mas lineal.



hell_fish dijo:


> Pdt: la imagen final es el circuito para que tenga una idea de que hice.


Sinceramente me dá poca idea. Un circuito vale mas que mil fotos.


----------



## switchxxi (May 22, 2022)

Si te quieres complicar un poco puedes usar la formula de carga del capacitor y calcular los puntos de tu interés, en tu caso serían 4. Una vez tenido los cuatro tiempos es solo cuestión de cronometrar y comparar.

La fórmula es:  T = R * C * ln (VCC / (VCC - VD))

Donde R es la resistencia de carga, C el capacitor, VCC la tensión de alimentación (5V) y VD la tensión del punto que estas calculando.

De todas formas hay que saber bien el valor de C, ademas que en general no se usa del tipo electrolítico sino de poliéster ya que son mas estables.


----------



## hell_fish (May 22, 2022)

Eduardo dijo:


> No sé en Colombia, pero acá en Argentina podés conseguir a menor precio el 12F1571 , también de 8 pines y con sus limitaciones de memoria, pero al lado del 12F508 es un cohete a la Luna. Soporta interrupciones, tiene timers de 8 y 16bit, PWM , comparador, ADC y DAC.
> 
> 
> 
> ...


Buena tarde el circuito que uso está en la foto adjunta. Muchas gracias por la ayuda de verdad es que he podido dilucidar como hacer la lectura de forma más económica pues acá es el pic más económico el siguiente más económico es el 12f675 pero vale más del triple del 508



switchxxi dijo:


> Si te quieres complicar un poco puedes usar la formula de carga del capacitor y calcular los puntos de tu interés, en tu caso serían 4. Una vez tenido los cuatro tiempos es solo cuestión de cronometrar y comparar.
> 
> La fórmula es:  T = R * C * ln (VCC / (VCC - VD))
> 
> ...


Hola que tal, hermano gracias muchas gracias por tu ayuda. Esa fórmula era exactamente lo que buscaba pues no tengo mucho conocimiento sobre el cálculo.

La verdad es que gracias a todos me han ayudado enormemente les envío un gran abrazo..


----------



## switchxxi (May 22, 2022)

Ojo que la formula que puse es para cargar el capacitor siempre desde 5V y usar esa rampa para comparar con la tensión a medir.

Para tu circuito, VCC, en la formula, vendría a ser la tensión de entrada (la que se quiere medir) y VD la tensión a la que cambia de estado el pin.


----------



## unmonje (May 22, 2022)

hell_fish dijo:


> Buena tarde el circuito que uso está en la foto adjunta. Muchas gracias por la ayuda de verdad es que he podido dilucidar como hacer la lectura de forma más económica pues acá es el pic más económico el siguiente más económico es el 12f675 pero vale más del triple del 508
> 
> 
> Hola que tal, hermano gracias muchas gracias por tu ayuda. Esa fórmula era exactamente lo que buscaba pues no tengo mucho conocimiento sobre el cálculo.
> ...


Yo creo que le está errando al blanco...
Su programa tendría que tener 2 partes bien independientes a mi entender :

-Una que se dedica a capturar los datos y ponerlos en un registro apropiado hasta el momento correcto y
- Otra dedicada al muestreo equidistante en el tiempo y en las salidas, de manera que, no importe la cadencia de captura de los datos de entrada, siempre pueda hacer las muestras de los valores a la misma cadencia que a usted le importe mostrar, independientemente de si pierde alguna lectura o no.
Eso no es crítico a la velocidad que todo ocurre. Esto se hace con interrupciones, que deberías aprender a usar correctamente.


----------



## hell_fish (May 22, 2022)

unmonje dijo:


> Yo creo que le está errando al blanco...
> Su programa tendría que tener 2 partes bien independientes a mi entender :
> 
> -Una que se dedica a capturar los datos y ponerlos en un registro apropiado hasta el momento correcto y
> ...


Hola, no te sigo, no te entiendo muy bien. podrías explicar de forma más sencilla ?

En el pic 12f508 no se puede hacer interrupciones


----------



## Eduardo (May 23, 2022)

En ese circuito de prueba la alinealidad se da porque la tensión es baja, con tensiones del orden de los 100V (y *cambiando la R10k por una del orden de 150k*  + zener de protección por las dudas) , en el rango de interés te va a quedar prácticamente lineal.
De todas maneras, cuando se trata de discriminar pocos niveles se usa una tabla o una cadena de IFs

```
#include <12f508.h>
#FUSES NOWDT        
#FUSES NOMCLR      
#use delay(internal=4MHz)
#use FAST_IO(all)
                                 
                                 
// Umbral para diferentes voltajes
#define N1 90
#define N2 120
#define N3 150
#define N4 180  

//-----------------------------------

void main(void){
int8 N  ;

    #asm
        movlw 0xC0
        option
    #endasm  
       
    set_tris_b(0) ;
    output_b(0) ;

    while(1){

//-----------------------------------
//--    Lee el tiempo de carga     --
        set_tris_b(1) ;
        for(N=0 ; !input(pin_B0) ; N++)
            delay_us(20) ;   // delay para que N resulte menor de 256
        set_tris_b(0) ;
        output_b(0) ;
//-----------------------------------
       
        if(N>N4)        output_high(PIN_B5) ;
        else if(N>N3)   output_high(PIN_B4) ;
        else if(N>N2)   output_high(PIN_B2) ;
        else if(N>N1)   output_high(PIN_B1) ;

        delay_ms(200) ;
    }
}
```

*Este es un ejemplo de como hacer la comparación, porque debe realizarse una calibración para determinar los umbrales N1..4  y el programa incluir una histéresis.*


----------

