Lectura de un potenciometro en LCD.(PIC16F628A)

Para que entiendas la idea de la histéresis llevado a la programación en un sistema de control simple.

Supongamos que tenés un sistema de refrigeración que debe activarse cuando la ºT supera un cierto umbral (llamémosle temp_max) y debe desactivarse cuando se alcance otro umbral del ºT (llamémosle temp_min). Entonces la idea sería saber en que estado actual está tu control para tomar una decisión según la ºT actual, ej:

C:
...
temp_actual=lectura_temp();
...
if(refrigeracion_on<1) //Pregunto si el sistema de refrigeración se encuentra apagado
{
    if(temp_actual>=temp_max) //Pregunto si se alcanzó la temperatura max con el sistema de refrigeración apagado
    {
        refrigeracion_on=1;    //Enciendo el sistema de refrigeración
    }
}// Sistema de refrigeración apagado
else
{
    if(temp_actual<=temp_min)
    {
        refrigeracion_on=0;    //Apago el sistema de refrigeración
    }
}// Sistema de refrigeración encendido
....

Entonces la idea de separar temp_max de temp_min, es evitar que el control de refrigeración oscile entre 1 y 0 cuando este cerca de esos valores en el corto plazo. Mientras más cerca esten esos valores, mayor es la probabilidad de esa oscilación y cuando temp_min y temp_max son iguales, es muy probable que el sistema oscile. Obviamente en el funcionamiento normal, vas a tener una oscilación, de encendido y apagado, pero más espaciado en el tiempo, al igual que funciona un aire acondicionado.
 

Adjuntos

  • unnamed.jpg
    unnamed.jpg
    24.8 KB · Visitas: 2
C:
//Código de D@arkbyte
...
   
while (TRUE)
{
    valor_adc = read_adc();                // Leer al ADC
    voltaje = (valor_adc / 1023.0) * 5;    // Convertir a voltaje.
    porcentaje = (voltaje / 5.0) * 100;    // Convertir a porcentaje.

    #ifdef DEBUG
    printf("Voltaje: %0.2f V\rPorcentaje: %0.2f %c\r\n", voltaje, porcentaje, 0x25);
    delay_ms(500);
    #endif
    // Establecer un rango de actuación con histéresis por software.
    if (porcentaje > 48.5 && porcentaje < 51.0)
        output_high(pin_relay);
    else if (porcentaje < 48.0 || porcentaje > 51.0)
        output_low(pin_relay);
}

D@rk, eso más que histéresis sería implementar un rango de valores por el cual se considera la salida en alto y todo fuera de ese rango considerar la salida en 0.
 
Busca en el foro, se ha hablado bastantes veces de eso.

Puedes también aplicar un control proporciona que para muchos casos es suficiente.
 
Otro ejemplo adjunto.
Muchas gracias por tomarse la molestia en responder :) .
Primero quiero comentarles lo que deseo realizar en mi proyecto.
Programacion en Pic Basic Pro - Pic 16f628A
1. Inicio con retardo de dos minutos, una vez pasado ese tiempo encender Motor1.
2. Que permanezca encendido por 6 horas. Una vez que hayan pasado las 6 horas, que recien empiece a sensar. Para efectos de simulacion estoy usando un potenciometro de 50k, en la vida real es un sensor ptc de 5 a 50 k. Aumenta su ohmeaje cuando la temperatura baja.
3. que el sensor haga lo siguiente:
cuando este por debajo del 70% de su valor de reistencia encienda el Motor1
o cuando este por encima del 90% de su valor active la Resistencia1
4 y que empiece a trabajar oscilando en esos valores.

Ahora mi problema es que cuando coloco en simulacion el potenciometro de 10k funciona correctamente, sin embargo cuando coloco el potenciometro de 50k , el programa no lee correctamente los valores y en pantalla no aparecen los vlores q deberian ser.

Les voy adjuntar parte de mi programa.
Espero me puedan ayudar. Muchas gracias.



Código:
@ DEVICE INTRC_OSC_NOCLKOUT,PROTECT_OFF,WDT_OFF,PWRT_ON,MCLR_ON,BOD_OFF,LVP_OFF,CPD_OFF

DEFINE OSC 4

 DEFINE  LCD_DREG    PORTB      ; define pines del LCD  B4  a  B7
 DEFINE  LCD_BITS    4
 DEFINE  LCD_DBIT    4          ; empezando desde el Puerto B4 hasta el B7
 DEFINE  LCD_RSREG   PORTA      ;define el puerto B para conectar el bit RS
 DEFINE  LCD_RSBIT   0          ;este es el puerto B3
 DEFINE  LCD_EREG    PORTA      ;define el puerto B para conectar el bit Enable
 DEFINE  LCD_EBIT    1          ;este es el puerto B2     
 
 CMCON = 7                ; Entradas Analogicas del Puerto A Como Digitales
 TRISA = $FC            ; %11111100
 TRISB = $F                ; %00001111 (POT hace bidireccional al pin RB0)
 B0 VAR word            ; Variable para almacenar el dato de POT
 dato var word
 
 SYMBOL  POTE      = PORTA.2
 SYMBOL  LED1      = PORTB.1
 SYMBOL  LED2      = PORTB.2
 symbol  HORAS     = PORTA.3
 SYMBOL  MINUTOS   = PORTA.4
 
 hora    VAR BYTE : minut   VAR BYTE : segun VAR BYTE                   
 cuenta  VAR BYTE : actual  VAR BYTE : x     VAR BYTE             
 cuenta  = 0 : actual  = 1
 
 CLEAR

eeprom 0,[00,00,00]
READ 0,hora : READ 1,minut : READ 2,segun

      ;setea TMR0 de interrupción cada 32768 microsegundos
OPTION_REG = %1010110   ;setea TMR0 configurando y habilita PORTB pullups
INTCON = %10100000      ;hablilita TMR0 interrupción interna
ON INTERRUPT GOTO interrup

pause 200
    
INICIO:
    IF MINUTOS = 0 THEN gosub incmin                ;botón para igualar minutos
    IF hORAS   = 0 THEN gosub inchr                 ;botón para igualar horas
    IF actual = 1 THEN                              ;chequea si hay que actualizar LCD
    gosub Mostrar
    actual = 0                  ;pantalla actualizada
    ENDIF
GOTO INICIO

Mostrar:
                                    
    POT POTE,127,B0                 ;127 para 10K - 31 para 50K
    B0 = b0*100/255                 ; elvalor sale en porcentaje
    LCDOUT $FE,1," ",dec2 hora,":",dec2 minut,":",DEC2 segun
    LCDOUT  $FE,$C0,"POT= ",dec b0,"%"
    if (hora <= 5) and (minut = 2) then gosub Motor_On
    if hora >= 6 then gosub Sensar
    
    return
      
; ***********************para igualar la hora *****************

  incmin: minut = minut + 1
    IF minut >= 60 THEN minut=0
    gosub Pausa
    return
    
  inchr: hora = hora + 1
    IF hora >= 24 THEN hora=0
    gosub Pausa
    return
    
  Pausa:
  FOR x = 1 TO 25 ; retardo de 200 mls
    PAUSE 10 ;pasos de 10 mls para no perder interrupciones
    NEXT x
    actual = 1 ;indica actualizar pantalla LCD
  return
;************** Handler de interrupciones para incrementar contador ***************

DISABLE             ;deshabilita interrupciones durante el proceso

interrup:
    cuenta = cuenta + 1 ;cuenta las interrupciones del TMR0
    TMR0 = 4 ;resta 4 al contador de 256 del TMR0
    
    IF cuenta < 31 THEN reset ;31 cuentas (32256ms = 999936uS)
    cuenta = 0
    segun = segun + 1
    
    IF segun >= 60 THEN
    segun = 0
    minut = minut + 1
    
    IF minut >= 60 THEN
    minut = 0
    hora = hora + 1
    
    IF hora >= 24 THEN
    hora = 0
    
    ENDIF
    ENDIF
    ENDIF
    WRITE 0, HORA : READ 0,hora : WRITE 1,MINUT : READ 1,minut
    
    actual = 1 ;actualizar LCD
    
reset:
    INTCON.2 = 0 ;resetea la bandera de interrupción del TMR0
    RESUME

Sensar:
   if B0 >= 90 then
        gosub resis_on
   else
   if B0 <= 75 then
        gosub Motor_on
   endif
   endif
return

Motor_On:
    high led1 : low led2
return

Resis_On:
     low led1 : high led2
return

END
 

Adjuntos

  • Proyecto Pic16f628A.rar
    59.8 KB · Visitas: 6
Hola....Tenes la opción de cambiar el valor RC para que siga tu programa(cuentas) o cambias las cuentas en el programa para que siga a tu cambio RC.
ca.JPG
Un ejemplo de que funciona si se adapta el valor del C cuando se cambia R.

No tengo el PBP instalado y si bien tengo el Proton o Positron, no tienen exactamente la misma sintaxis.


Saludos.
 
Para empezar, si requiero lecturas análogas, cambiaría el microcontrolador por uno con ADC, por ejemplo: el PIC16F88
Para el conteo de las horas usaría un RTC como el DS1307 o implementaría uno interno con algún timer.
Y si quiero programar en Basic, cambiaría de entorno, el Basic de Proton es mejor que el de MicroCode.
 
Muchas gracias por tomarse la molestia en responder :) .
Primero quiero comentarles lo que deseo realizar en mi proyecto.
Programacion en Pic Basic Pro - Pic 16f628A
1. Inicio con retardo de dos minutos, una vez pasado ese tiempo encender Motor1.
2. Que permanezca encendido por 6 horas. Una vez que hayan pasado las 6 horas, que recien empiece a sensar. Para efectos de simulacion estoy usando un potenciometro de 50k, en la vida real es un sensor ptc de 5 a 50 k. Aumenta su ohmeaje cuando la temperatura baja.
3. que el sensor haga lo siguiente:
cuando este por debajo del 70% de su valor de reistencia encienda el Motor1
o cuando este por encima del 90% de su valor active la Resistencia1
4 y que empiece a trabajar oscilando en esos valores.

Ahora mi problema es que cuando coloco en simulacion el potenciometro de 10k funciona correctamente, sin embargo cuando coloco el potenciometro de 50k , el programa no lee correctamente los valores y en pantalla no aparecen los vlores q deberian ser.

Les voy adjuntar parte de mi programa.
Espero me puedan ayudar. Muchas gracias.



Código:
@ DEVICE INTRC_OSC_NOCLKOUT,PROTECT_OFF,WDT_OFF,PWRT_ON,MCLR_ON,BOD_OFF,LVP_OFF,CPD_OFF

DEFINE OSC 4

 DEFINE  LCD_DREG    PORTB      ; define pines del LCD  B4  a  B7
 DEFINE  LCD_BITS    4
 DEFINE  LCD_DBIT    4          ; empezando desde el Puerto B4 hasta el B7
 DEFINE  LCD_RSREG   PORTA      ;define el puerto B para conectar el bit RS
 DEFINE  LCD_RSBIT   0          ;este es el puerto B3
 DEFINE  LCD_EREG    PORTA      ;define el puerto B para conectar el bit Enable
 DEFINE  LCD_EBIT    1          ;este es el puerto B2   
 
 CMCON = 7                ; Entradas Analogicas del Puerto A Como Digitales
 TRISA = $FC            ; %11111100
 TRISB = $F                ; %00001111 (POT hace bidireccional al pin RB0)
 B0 VAR word            ; Variable para almacenar el dato de POT
 dato var word
 
 SYMBOL  POTE      = PORTA.2
 SYMBOL  LED1      = PORTB.1
 SYMBOL  LED2      = PORTB.2
 symbol  HORAS     = PORTA.3
 SYMBOL  MINUTOS   = PORTA.4
 
 hora    VAR BYTE : minut   VAR BYTE : segun VAR BYTE                 
 cuenta  VAR BYTE : actual  VAR BYTE : x     VAR BYTE           
 cuenta  = 0 : actual  = 1
 
 CLEAR

eeprom 0,[00,00,00]
READ 0,hora : READ 1,minut : READ 2,segun

      ;setea TMR0 de interrupción cada 32768 microsegundos
OPTION_REG = %1010110   ;setea TMR0 configurando y habilita PORTB pullups
INTCON = %10100000      ;hablilita TMR0 interrupción interna
ON INTERRUPT GOTO interrup

pause 200
  
INICIO:
    IF MINUTOS = 0 THEN gosub incmin                ;botón para igualar minutos
    IF hORAS   = 0 THEN gosub inchr                 ;botón para igualar horas
    IF actual = 1 THEN                              ;chequea si hay que actualizar LCD
    gosub Mostrar
    actual = 0                  ;pantalla actualizada
    ENDIF
GOTO INICIO

Mostrar:
                                  
    POT POTE,127,B0                 ;127 para 10K - 31 para 50K
    B0 = b0*100/255                 ; elvalor sale en porcentaje
    LCDOUT $FE,1," ",dec2 hora,":",dec2 minut,":",DEC2 segun
    LCDOUT  $FE,$C0,"POT= ",dec b0,"%"
    if (hora <= 5) and (minut = 2) then gosub Motor_On
    if hora >= 6 then gosub Sensar
  
    return
    
; ***********************para igualar la hora *****************

  incmin: minut = minut + 1
    IF minut >= 60 THEN minut=0
    gosub Pausa
    return
  
  inchr: hora = hora + 1
    IF hora >= 24 THEN hora=0
    gosub Pausa
    return
  
  Pausa:
  FOR x = 1 TO 25 ; retardo de 200 mls
    PAUSE 10 ;pasos de 10 mls para no perder interrupciones
    NEXT x
    actual = 1 ;indica actualizar pantalla LCD
  return
;************** Handler de interrupciones para incrementar contador ***************

DISABLE             ;deshabilita interrupciones durante el proceso

interrup:
    cuenta = cuenta + 1 ;cuenta las interrupciones del TMR0
    TMR0 = 4 ;resta 4 al contador de 256 del TMR0
  
    IF cuenta < 31 THEN reset ;31 cuentas (32256ms = 999936uS)
    cuenta = 0
    segun = segun + 1
  
    IF segun >= 60 THEN
    segun = 0
    minut = minut + 1
  
    IF minut >= 60 THEN
    minut = 0
    hora = hora + 1
  
    IF hora >= 24 THEN
    hora = 0
  
    ENDIF
    ENDIF
    ENDIF
    WRITE 0, HORA : READ 0,hora : WRITE 1,MINUT : READ 1,minut
  
    actual = 1 ;actualizar LCD
  
reset:
    INTCON.2 = 0 ;resetea la bandera de interrupción del TMR0
    RESUME

Sensar:
   if B0 >= 90 then
        gosub resis_on
   else
   if B0 <= 75 then
        gosub Motor_on
   endif
   endif
return

Motor_On:
    high led1 : low led2
return

Resis_On:
     low led1 : high led2
return

END
Ni se moleste en poner potes de alto valor de resistencia para leer entradas analógicas, porque se le va a venir la relación señal ruido hasta el piso y se le vá a meter señal de alterna de 50 hertz de la red domiciliaria, en rigor evite pasarse de 10 o 20 kohms . Si esta al limite , ponga un capacitor que atenúe todo los de AC y despues rece para que funcione. Yo lloré mucho hasta resolverlo. :ROFLMAO:
Si tuvieran algún ejemplo estimados seria excelente.
Gracias.
¿Ejemplo de histéresis ? mmmmm veamos :
Supongamos que quiero que mi heladera deje de enfriar a los -10 grados y entonces apague el moto compresor.
Supongamos que llega a los -10 grados y se apaga tal como quería.
5 segundos después de apagarse la temperatura sube a -9, 99 grados por ende el motor enciende de nuevo.
5 segundos despues vuelve a -10 grados y se apaga el motor.
Con este esquema método , la heladera pareceria un árbol de navidad y duraría muy poco innecesariamente.
Para eso se inventó el control de histéresis , para que el motor no se convierta en un histérico asunto.
Dicho en castellano se le llama control de umbral o ventana, es decir que se apagará en -10 grados, pero que su re encendido, será en 0 grados, es decir mas lejos del punto límite , lo que da un tiempo razonable de pausa , para que el motocompresor no sufra y ademas se descomprima. ;)
 
Última edición:
Tengo un problema con esta misma practica; lo que me sucede a mi es que pese a funcionar correctamente, me surge el mismo error una y otra vez en proteus y no entiendo a que se deba, espero que puedan ayudarme. Les adjunto evidencia, gracias.
 

Adjuntos

  • Captura 5.PNG
    Captura 5.PNG
    13.1 KB · Visitas: 12
  • Captura 6.PNG
    Captura 6.PNG
    19.1 KB · Visitas: 12
  • Captura 7.PNG
    Captura 7.PNG
    60 KB · Visitas: 12
Atrás
Arriba