Autor Tema: Lectura ADC en dos canales - Simulacion Proteus - Manejo de Funciones  (Leído 147 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Fabri Olivari

  • PIC10
  • *
  • Mensajes: 16
Hola sigo trabajando en un proyecto para hacer un termostato con seteo y autonivelacion de tempertarura, en este momento tengo varios problemas, estoy simulando con proteus y tambien en una placa de desarrollo para PIC. Estoy trabando con un display LCD 16x2, hay dos menus, el primero, que seria el estado normal, es asi, solo muestra la temperatura medida y la seteada. Cuando presiono un pulsador, entra a otro menu, que me permite setear la temperatura con un potenciometro.

Hice una lista de problemas que tengo en el entrenador y en el simulador:
1-La temperatura que muestra el LCD en la simulación da saltos incorrectos, cosa que en el entrenador no pasa. En el entrenador la temperatura aumenta bien, en pasos de 0,5 grados, pero en la simulación, hace saltos de 1 grado en algunas situaciones, por ejemplo cuando pasa los 22°C, pasa a 22,5°, pero de ahí pasa a 23,5° y después a 24,5° y así.   
2-Si saco la parte de redondear, y quiero que me muestre la temperatura del sensor con todos los decimales, en el entrenador funciona pero en la simulación no. Por ejemplo, en la simulación, seteo el sensor en 0,7° y me marca 1°, cuando estoy en 25,0° me marca 25,4°, en el entrenador no pasa eso.
Hasta ahora, esos problemas los considero del simulador, no de software.
3-Pero hay algo que pasa en los dos, en la simulación y en el entrenador. La temperatura medida y seteada, se mezclan. Es asi, cuando yo presiono el pulsador para setear la temperatura, y no muevo el pote, pero si el trimmer (que simula el LM35), y vuelvo a presionar el pulsador para salir del modo set up, me aparecen como si la temperatura seteada y la medida fueran la misma, hasta que mueva el trimmer, ahí es cuando se “actualiza” y muestra el valor correcto de temperatura medida.
También pasa cuando presiono para setear, dejo el valor que esta y vuelvo a presionar. La temp. seteada y temp. medida aparecen iguales.
Eso pasa cuando la función de redondeo esta activa. Probando sin hacer el redondeo, las temperaturas no se mezclan, asique el problema tiene que estar en el redondeo o en algo similar.
Cuando pongo para redondear solo la temp set, y dejo que la temperatura media muestre los decimales, no pasa esto, no se mezclan los valores. Asique el problema debe estar en que cuando pongo para setear la temperatura, se mezclan los datos de medidos y seteados.

Estoy programando en el PIC16F1519, con MPLABX y XC8

Quisiera ver si me pueden ayudar en el tema de las lecturas ADC,que se mezclan.

ADJUNTO MI CODIGO:
Código: [Seleccionar]
/*
 * File:   codigo.c
 * Author: MR X
 *
 * Termosatato con seteo y autonivelacion de temperatua
 *
 *
 */

#include <xc.h>
#include "Ejercicio7.h"
#include "drv_lcd.h"

//Definición de E/S
#define calefactor  RD0         //RD0
#define enfriador   RD1         //RD1
#define pote        RA0         //Potenciometro
#define lm35        RA1         //Sensor de Temperatura LM35     
#define button_set  RB0         //Pulsador para Setear Temperatura

//Variables Boton Set
int t_antirrebote = 0;          //Tiempo para antirrebote
int flag_modosetup = 0;         //Activa/Desactiva el modo set up

//Varibles Potenciometro Set
float temp_set = 25.0;          //Temperatura a setear //Inicia a una temp default de 25.0 °C 
char vector_set [16];       

//Redondeo
float temp_round = 0.0;         //Redondeo de temperatura

//Sensor LM35
float temp_med = 0.0;           //Temperatura medida (LM35)
int time_muestreo = 0;          //Tiempo de muestreo (100ms)
int flag_temp = 0;              //Avisa cuando realizar la medicion


//Variables LCD
char vector1 [16];              //Contiene el valor de Tset y Tmed

//Funciones
int lectura_ADC();              //Canal a leer
int visualLCD();                //Visualizacion LCD
float redondeo(float temp);     //Redondeo pasos de 0,5°C

void main(void)
{
//Oscilador
    OSCCON = 0x6A;              //4MHz
//Puertos
    ANSELA = 0x03;              //RA0 y RA1 Analogico 
    ANSELB = 0x00;
    ANSELC = 0x00;
    ANSELD = 0x00; 
    ANSELE = 0x00; 
   
    TRISA = 0x03;               //RA0 y RA1 Entrada   
    TRISB = 0x03;               //RB0 y RB1 Entrada
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;
   
    PORTA = 0x00;               //Limpiar Puertos
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
//LCD Configuracion
    LCD_init();                 //Inicializar LCD
    __delay_ms(10);
//Interrupcion     
    INTCON = 0xB0;              //0b10110000
    OPTION_REG = 0x01;          //PS 1:4 //T=(4/Fosc)*Prescaler*(255-TMR0)
    TMR0 = 5;                   //(255-5) -> Interrupcion cada 1 ms
   
    while(1)
    {
    //Lectura Temperatura - Sensor LM35
        if(flag_temp == 1)                                  //Bandera leer temperatura
        {
            if(flag_modosetup == 0)                         //Modo setup desactivado
            {
                temp_med = (lectura_ADC(1)*5.001/1023)*100; //Formula convercion
//                redondeo(temp_med);                         //Pasos 0,5°C
//                temp_med = (float)temp_round;               //Temp redondeada
            }
        }
        visualLCD();                                        //Visualizacion LCD
    }
}
int lectura_ADC(int canal)                          //Seleccion de Canal
{
    if(canal == 0){ADCON0 = 0x01;}                  //Lectura del Canal 0
    if(canal == 1){ADCON0 = 0x05;}                  //Lectura del Canal 1
   
    ADCON1 = 0x80;                                  //Configuracion ADC
    ADCON0bits.GO_nDONE = 1;                        //Iniciamos Conversion
    while(ADCON0bits.GO_nDONE == 1){}               //Conversion
    flag_temp = 0;                                  //Bajo bandera lectura sensor
    return ((ADRESH<<8) + ADRESL);                  //Resultado
}
visualLCD()
{
    if(flag_modosetup == 0)                         //Modo setup desactivado
    {
        LCD_setCursor(0,0);                         //Ubicacion de Cursor
        LCD_print("                ");              //16 Espacios limpian el LCD - BORRAR - provisorio
        LCD_setCursor(0,1);                         
        sprintf(vector1,"Temp: %.1f/%.1f   ", temp_med, temp_set);
        LCD_print(vector1);                         
    }
    if(flag_modosetup == 1)                         //Modo setup activado
    {
        flag_temp = 0;                              //Deshabilito lectura temperatura
        temp_set = (lectura_ADC(0)*30.001/1023.0);  //Formula Conversion
        redondeo(temp_set);                         //Pasos 0,5°C
        temp_set = (float)temp_round;               //Temp redondeada
       
        LCD_setCursor(0,0);                         //LCD
        LCD_print("  Setear Temp   ");
        sprintf(vector_set,"  Temp: %.1f      ",temp_set);
        LCD_setCursor(0,1);
        LCD_print(vector_set);
    }
}
float redondeo(float temp)
{
    int trunk = temp;                  //Truncar decimales de temperatura
    float digito = temp - trunk;       //Devuelve la diferencia de los decimales
    if((digito > 0.0)&&(digito < 0.4)) //Rango 0
    {
        temp_round = trunk;   
    }
    if((digito > 0.4)&&(digito < 0.7))  //Rango 0,5
    {
        temp_round= (trunk + 0.5);     
    }
    if(digito >= 7)                     //Rango 1
    {
        temp_round=(trunk + 1.0);
    }
    return (float)temp_round;           //Devuelve temperatura redondeada
}
void __interrupt() isr(){ 
//Interrupcion Externa - RB0
    if(INTF == 1)
    {
        INTE = 0;                       //Deshabilito Int. Externa
    } 
//Interrupcion por Timer
    if(TMR0IF == 1)
    {
    //Configuracion Pulsador Set Up
        if(INTE == 0)                                       //Int. Externa Deshabilitada
        {
            t_antirrebote++;                                //Tiempo de espera
            if(t_antirrebote == 100)                        //150ms
            {
                if(button_set == 0)                         //RB0 - Pull Down
                {
                    flag_modosetup = !flag_modosetup;       //Activa/Desactiva modo Set Up
                    INTE = 1;                               //Habilita Int. Externa
                    INTF = 0;                               //Baja bandera de Int. Externa
                    t_antirrebote = 0;                      //Limpia tiempo antirrebote
                }
                if(button_set == 1){t_antirrebote = 90;}    //Error - Reinicia tiempo
            }
        }
    //Lectura Sensor LM35
        time_muestreo++;
        if(time_muestreo == 100)                            //Timer para muestreo de LM35 - 100 ms
        {
            flag_temp = !flag_temp;                         //Des/Habilita lectura
            time_muestreo = 0;                              //Reinicio tiempo
        }
        TMR0IF = 0;                                         //Bajo bandera Timer0
    }
}
//Fin del Codigo


SIMULACION PROTEUS

Cualquier consulta sobre el codigo, me avisan y si me pueden dar una mano se los voy a agradecer. :-/

Desconectado Fabri Olivari

  • PIC10
  • *
  • Mensajes: 16
Re:Lectura ADC en dos canales - Simulacion Proteus - Manejo de Funciones
« Respuesta #1 en: 21 de Junio de 2020, 18:16:11 »
Si se fijan en el codigo, comente la parte del redondeo para la temperatura medida del sensor LM35. Cuando hago eso si funciona, relativamente bien, pero Proteus no me muestra bien la temperatura, va de saltos de 0,4° a pesar de que no este redondeando. Asique el problema debe estar en el redondeo o la forma en que cambio los canales de ledctura ADC.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 7802
Re:Lectura ADC en dos canales - Simulacion Proteus - Manejo de Funciones
« Respuesta #2 en: 22 de Junio de 2020, 20:31:00 »
No veo donde puede estar el error pero proba cambiando la funcion redondeo:

Código: C
  1. void redondeo(float *temp)
  2. {
  3.     int trunk = *temp;                  //Truncar decimales de temperatura
  4.     float digito = *temp - trunk;       //Devuelve la diferencia de los decimales
  5.     if((digito > 0.0)&&(digito < 0.4)) //Rango 0
  6.     {
  7.         *temp = (float)trunk;  
  8.         return;
  9.     }
  10.     if((digito > 0.4)&&(digito < 0.7))  //Rango 0,5
  11.     {
  12.         *temp= (float)(trunk + 0.5);
  13.         return;
  14.     }
  15.     if(digito >= 7)                     //Rango 1
  16.     {
  17.         *temp = (float)(trunk + 1.0);
  18.         return;        
  19.     }
  20. }

Y lo usas asi:

Código: C
  1.         temp_set = (lectura_ADC(0)*30.001/1023.0);  //Formula Conversion
  2.         redondeo(&temp_set);                         //Pasos 0,5°C

Ya temp_set queda redondeado... Por si las dudas el valor global en algun momento queda para los 2.
Que es lo unico que unia las dos temperaturas.

Desconectado Fabri Olivari

  • PIC10
  • *
  • Mensajes: 16
Re:Lectura ADC en dos canales - Simulacion Proteus - Manejo de Funciones
« Respuesta #3 en: 24 de Junio de 2020, 23:49:40 »
Probe el hacer el redondeo de esa forma, pero no me deja poner return en cada if. Igual, lo aplique de una manera parecida:
Código: [Seleccionar]
float redondeo(float temp)
{
    int trunk = temp;                  //Truncar decimales de temperatura
    float digito = temp - trunk;       //Devuelve la diferencia de los decimales
    if((digito > 0.0)&&(digito < 0.4)) //Rango 0
    {
        temp_round = (float)trunk;
    }
    if((digito > 0.4)&&(digito < 0.7))  //Rango 0,5
    {
        temp_round = (float)(trunk + 0.5);
    }
    if(digito >= 7)                     //Rango 1
    {
        temp_round = (float)(trunk + 1.0);
    }
    return (float)temp_round; //Devuelve temperatura redondeada
}

Pero aun asi, tengo el problema de que al presionar el pulsador para leer el potenciometro en RA0, y muevo el Potenciometro (que simula LM35) en el pin RA1, y vuelvo a presionar el pulsador (para salir del modo set up), las temperaturas se igualan, hasta que mueva de vuelta el potenciometro en RA1 y se actualiza.


 

anything