Heladera Lauckner Lipari

Dependencies:   DS1820 TextLCD mbed

Fork of DS1820_HelloWorld by Erik -

main.cpp

Committer:
juanlipari
Date:
2018-05-23
Revision:
6:b2a27e6f6195
Parent:
5:838bc36ed9e4

File content as of revision 6:b2a27e6f6195:

#define CANT_SAMPLES    10  //Constante que se define por si se quiere agregar mas mediciones al promedio 

#include "mbed.h"
#include "DS1820.h"
#include "TextLCD.h"

#define MAX_PROBES      2  //Constante que se define para la cant de sensores DS1820 (Lo requiere la lib)

enum {DEMORA, CONTROL,  MODO,  OFF, SET, UP, DOWN,                //Estados de la ME de Interrupciones
      MODO_HELADERA, SET_HELADERA, MODO_FREEZER, SET_FREEZER,     //Estados de la ME de LCD
      CERO, ESPERANDO, UNO,                                       //Estados de la ME de antirebotes
      ADC_FRZ, SAMPLES};                                          //Estados de la ME de Mediciones del ADC

Ticker timer1;  //Timer para controlar los tiempos de pulsadores  1mSeg
Ticker timer2;  //Timer para controlar los tiempos del sensor DS1820 200mSeg
InterruptIn modo(PTD5);   //Pin de entrada del Pulsador de Modo
InterruptIn set(PTD0);    //Pin de entrada del Pulsador de Set
InterruptIn up(PTD2);     //Pin de entrada del Pulsador de UP
InterruptIn down(PTD3);   //Pin de entrada del Pulsador de DOWN
DS1820 probe1(A0);        //Pin asociado al sensor DS1820
AnalogIn LM35(A1);        //Pin de entrada analogico del LM35
DigitalOut salida_frz(PTC2);  //Salida activada para enfriar el freezer
DigitalOut salida_hel(PTC1);  //Salida activada para enfriar la heladera

// I2C Communication
I2C i2c_lcd(PTC9,PTC8); // SDA, SCL


// LCD instantiation
TextLCD_I2C lcd(&i2c_lcd, 0x4E, TextLCD::LCD16x2);  //Se indica que sera por I2C, la address del modulo y tipo de LCD


unsigned char puls_modo = 0, puls_set = 0, puls_up = 0, puls_down = 0, set_hel = 8, set_frz = 16; //Variables de los pulsadores y el valor seteado
short PULS_tic;

unsigned char  ADC_CONV_state = ADC_FRZ, cuentaFrz = 0, cuentaHel = 0; //Variables usadas en las mediciones de los sensores
float acumHel = 0, acumFrz  = 0, resHel = 0, resFrz = 0, resADC;       //Variables usadas en las mediciones de los sensores

//Variables usadas en los pulsadores
char habilitacion = 0, valor_puls_modo, valor_puls_set, valor_puls_up, valor_puls_down, anti_rebote_state, hab_antirrebote; 
short espera_tic = 50; //Variable de tiempo


//Prototipos 
void ADC_CONV_Step(void);
void ADC_CONV_TIEMPO (void);
void timer_init(void);
void anti_rebote_step (char hab);
void flanco_modo (void);
void flanco_set (void);
void flanco_up (void);
void flanco_down (void);
void Interrupciones(void);
void TIEMPOS(void);
void LCD_init(void);
void LCDStep(void);
void HeladeraStep(void);
void Activacion_frio(void);


int main()                                                               
{
    probe1.convertTemperature(false, DS1820::all_devices);  //Iniciacion del sensor DS1820 (Lo requiere la lib)
    timer_init();  //Funcion que configura los timers
    LCD_init();    //Funcion que configura e inicia el LCD
    while(1) {
        ADC_CONV_Step();   //Maquina de estados de medicion del ADC
        Interrupciones();  //Maquina de estados de interrupciones de los pulsadores
        LCDStep();         //Maquina de estados que controla el LCD
        Activacion_frio(); //Maquina de estados que controla la activacion de las salidas 
    }

}

//Funcion que se ejecuta cada 1mSeg
void TIEMPOS (void)                                                           
{
    if(PULS_tic > 0)
        PULS_tic--;
    if(espera_tic > 0)
        espera_tic--;
}


void timer_init (void)
{
    timer1.attach(&TIEMPOS, 0.001);         //TIMER cada 1mSeg
    timer2.attach(&ADC_CONV_TIEMPO, 0.2);   //TIMER cada 200mSeg (sensor DS1820)
}

//Maquina que controla las mediciones del ADC y calcula un promedio 
void ADC_CONV_Step(void)
{
    switch(ADC_CONV_state) {
        default:        //Si no se definio estado, es ADC_FRZ
        case ADC_FRZ:   //Estado ADC_FZR
            resADC = 3.3 * LM35.read();   //Se lee la entrada y se la multiplica segun la ganancia requerida
            resADC = (resADC *26)/3.3;   //Se hace regla de tres para la ganancia requerida
            acumFrz = acumFrz + resADC;  //El valor medido se le suma al acumulado para luego calcular el promedio
            cuentaFrz++;                 //La variable que guarda la cant de mediciones aumenta 1

            ADC_CONV_state = SAMPLES;    //Proximo estado
            break;

        case SAMPLES:   //Estado Samples
            if(cuentaHel >= CANT_SAMPLES) //Si cant de mediciones es > 0 = a la cant de samples definida...
            {
                resHel = acumHel/ CANT_SAMPLES;  //Calcula el promedio y lo guarda en resHel
                acumHel = 0;                     //Reinicia la variable que acumula los resultados
                cuentaHel = 0;                   //Reinicia la variable que cuenta la cant de mediciones
            }
            
            if(cuentaFrz >= CANT_SAMPLES) //Si cant de mediciones es > 0 = a la cant de samples definida... 
            {
                resFrz = acumFrz/ CANT_SAMPLES;  //Calcula el promedio y lo guarda en resFrz
                acumFrz = 0;                     //Reinicia la variable que acumula los resultados
                cuentaFrz = 0;                   //Reinicia la variable que cuenta la cant de mediciones
            }
                       
            ADC_CONV_state = ADC_FRZ;  //Proximo estado
            break;
    }
}

//Funcion que se repite cada 200mSeg
void ADC_CONV_TIEMPO (void)
{
    probe1.convertTemperature(false, DS1820::all_devices);  //Prepara al sensor para la medicion (lo requiere la lib)
    acumHel =  (probe1.temperature() + acumHel);            //Se guarda la medicion y se le suma al acumulado
    cuentaHel++;                                            //La variable que guarda la cant de mediciones aumenta 1
}


unsigned char LCDState = MODO_HELADERA;  //Variable de estado del LCD
//Maquina de estado que escribe en el LCD el modo en el que se está
void LCDStep(void)
{
    switch(LCDState) {                                                          
        default:            //Si no se definio estado, es MODO_HELADERA
        case MODO_HELADERA: //Estado MODO_HELADERA         
            lcd.printf("Temp Hel: %2.1f", resHel);  //Escribe en el LCD Temp Hel: y el valor del promedio del sensor con 1 decimal de precision
            lcd.putc(0);                            //Escribe en el LCD el simbolo de º
            lcd.printf("C");                        //Escribe en el LCD una C, terminando el espacio en esa fila
            lcd.printf("Temp Set: 0%d.0",set_hel);  //Escribe en el LCD Temp Set: y el valor seteado por el usuario
            lcd.putc(0);                            //Escribe en el LCD el simbolo de º
            lcd.printf("C");                        //Escribe en el LCD una C, terminando el espacio en esa fila
            lcd.locate(0,0);                        //Coloca al cursor en la primera posicion del LCD
            break;

        case SET_HELADERA:   //Estado SET_HELADERA  
            lcd.printf("Hel set:  %d",set_hel);  //Escribe en el LCD Set Hel: y el valor actual seteado
            lcd.putc(0);                         //Escribe en el LCD el simbolo de º
            lcd.printf("C\n");                   //Escribe en el LCD una C y baja al proximo renglon
            lcd.printf("  UP ");                 //Escribe en el LCD UP 
            lcd.putc(3);                         //Escribe en el LCD el simbolo de una flecha hacia arriba
            lcd.printf("   DOWN ");              //Escribe en el LCD DOWN 
            lcd.putc(4);                         //Escribe en el LCD el simbolo de una flecha hacia abajo
            lcd.locate(0,0);                     //Coloca al cursor en la primera posicion del LCD
            break;

        case MODO_FREEZER:      //Estado MODO_FREEZER
            lcd.printf("Temp FRZ:-");                 //Escribe en el LCD Temp FRZ:- 
            if(resFrz < 10)   //Si la medicion es menor a 10...
                lcd.printf("0%2.1f", resFrz);         //Escribe el valor del promedio del sensor con 1 decimal de precision, con un cero delante
            else
                lcd.printf("%2.1f", resFrz);          //Si no escribe el valor del promedio del sensor con 1 decimal de precision
            lcd.putc(0);                              //Escribe en el LCD el simbolo de º
            lcd.printf("C");                          //Escribe en el LCD una C, terminando el espacio en esa fila
            lcd.printf("Temp Set:-%d.0",set_frz);     //Escribe en el LCD Temp Set:- y el valor seteado por el usuario  
            lcd.putc(0);                              //Escribe en el LCD el simbolo de º
            lcd.printf("C");                          //Escribe en el LCD una C, terminando el espacio en esa fila
            lcd.locate(0,0);                          //Coloca al cursor en la primera posicion del LCD
            break;

        case SET_FREEZER:     //Estado SET_FREEZER 
            lcd.printf("FRZ set: -%d",set_frz);         //Escribe en el LCD FRZ set:-
            lcd.putc(0);                                //Escribe en el LCD el simbolo de º
            lcd.printf("C\n");                          //Escribe en el LCD una C y baja al proximo renglon
            lcd.printf("  UP ");                        //Escribe en el LCD UP
            lcd.putc(3);                                //Escribe en el LCD el simbolo de una flecha hacia arriba
            lcd.printf("   DOWN ");                     //Escribe en el LCD DOWN 
            lcd.putc(4);                                //Escribe en el LCD el simbolo de una flecha hacia abajo
            lcd.locate(0,0);                            //Coloca al cursor en la primera posicion del LCD
            break;
    }
}

//Funcion que inicializa el LCD
void LCD_init(void)                                                          
{
    lcd.setBacklight(TextLCD::LightOn);             //Se enciende el BackLight
    lcd.setCursor(TextLCD::CurOff_BlkOff);          //Se desactiva el cursor y el parpadeo de este
    lcd.setUDC(0, (char *) udc_degr);               //Se crea el simbolo de grado asociandolo al caracter 0
    lcd.setUDC(3, (char *) udc_uparrow);            //Se crea el simbolo de flecha UP asociandolo al caracter 3
    lcd.setUDC(4, (char *) udc_downarrow);          //Se crea el simbolo de flecha DOWN sociandolo al caracter 4
}

//Maquina de estado antirrebote del pulsador de MODO
void anti_rebote_step_modo(void)                                                
{
    switch(anti_rebote_state) {
        case CERO:                  //Estado de que el pulsador quedo en cero (presionado)
            puls_modo = 0;          //iguala variable a como quedo el pulsador de modo
            habilitacion = 0;       //deshabilita la maquina (se vuelve a habilitar con interrupin)
            break;

        case ESPERANDO:             //estado de espera para sacar el rebote
            if(espera_tic >0)       //si no paso la espera termina aca la maquina
                return;             
            valor_puls_modo = modo.read();      //si paso la espera, iguala una variable a lo que lee en la entrada del pulsador

            if(valor_puls_modo == 0) {          //si esa variable es 0, cambia el estado de la maquina a CERO
                anti_rebote_state = CERO;

                switch (LCDState) {             //Si estaba  en modo heladera pasa a freezer
                    case MODO_HELADERA:
                        lcd.cls();
                        LCDState = MODO_FREEZER;
                        break;

                    case MODO_FREEZER:          //Si estaba en modo freezer pasa a heladera
                        lcd.cls();
                        LCDState = MODO_HELADERA;
                        break;

                    default:
                        break;
                }

            } else
                anti_rebote_state = UNO;        //si la variable no es 0 (es 1), cambia el estado de la maquina a UNO
            break;

        case UNO:                   //Estado de que el pulsador quedo en cero (presionado)
            puls_modo = 1;          //iguala variable a como quedo el pulsador de modo
            habilitacion = 0;       //deshabilita la maquina (se vuelve a habilitar con interrupin)
            break;
    }
}

void anti_rebote_step_set(void)                                                 //PULSADOR DE SET
{                                //TODOS LOS PULSADORES SON IGUALES, SOLO CAMBIAN LOS NOMBRES DE LAS VARIABLES PARA DIFERENCIARLOS
    switch(anti_rebote_state) {
        case CERO:
            puls_set = 0;
            habilitacion = 0;
            break;

        case ESPERANDO:
            if(espera_tic >0)
                return;
            valor_puls_set = set.read();

            if(valor_puls_set == 0) {
                anti_rebote_state = CERO;

                switch (LCDState) {                                             //LO QUE HACE
                    case MODO_HELADERA:
                        lcd.cls();
                        LCDState = SET_HELADERA;
                        break;

                    case MODO_FREEZER:
                        lcd.cls();
                        LCDState = SET_FREEZER;
                        break;

                    case SET_HELADERA:
                        lcd.cls();
                        LCDState = MODO_HELADERA;
                        break;

                    case SET_FREEZER:
                        lcd.cls();
                        LCDState = MODO_FREEZER;
                        break;
                    default:
                        break;
                }
            } else
                anti_rebote_state = UNO;
            break;

        case UNO:
            puls_set = 1;
            habilitacion = 0;
            break;
    }
}

void anti_rebote_step_up(void)                                                  //PULSADOR DE UP
{                                //TODOS LOS PULSADORES SON IGUALES, SOLO CAMBIAN LOS NOMBRES DE LAS VARIABLES PARA DIFERENCIARLOS
    switch(anti_rebote_state) {
        case CERO:
            puls_up = 0;
            habilitacion = 0;
            break;

        case ESPERANDO:
            if(espera_tic >0)
                return;
            valor_puls_up = up.read();

            if(valor_puls_up == 0) {
                anti_rebote_state = CERO;

                switch (LCDState) {   //En el caso de los pulsadore UP y DOWN, lo que hacen es aumentar/disminuir en 1 la variable set que corresponda

                    case SET_HELADERA:
                        if(set_hel<8)       //Si no se llegó al limite, aumenta 1
                            set_hel++;
                        else
                            set_hel = 2;    //Vuelve al valor minimo
                        break;

                    case SET_FREEZER:

                        if(set_frz < 24) //Si no se llegó al limite, aumenta 1
                            set_frz++;
                        else
                            set_frz = 16;  //Vuelve al valor minimo
                        break;

                    default:
                        break;
                }

            } else
                anti_rebote_state = UNO;
            break;

        case UNO:
            puls_up = 1;
            habilitacion = 0;
            break;
    }
}

void anti_rebote_step_down(void)                                                //PULSADOR DE DOWN
{                                //TODOS LOS PULSADORES SON IGUALES, SOLO CAMBIAN LOS NOMBRES DE LAS VARIABLES PARA DIFERENCIARLOS
    switch(anti_rebote_state) {
        case CERO:
            puls_down = 0;
            habilitacion = 0;
            break;

        case ESPERANDO:
            if(espera_tic >0)
                return;
            valor_puls_down = down.read();

            if(valor_puls_down == 0) {
                anti_rebote_state = CERO;

                switch (LCDState) {   //En el caso de los pulsadore UP y DOWN, lo que hacen es aumentar/disminuir en 1 la variable set que corresponda                                   

                    case SET_HELADERA:

                        if(set_hel > 2) //Si no se llegó al limite, disminuye 1
                            set_hel--;
                        else
                            set_hel = 8; //Vuelve al valor maximo
                        break;

                    case SET_FREEZER:

                        if(set_frz > 16) //Si no se llegó al limite, disminuye 1
                            set_frz--;
                        else
                            set_frz = 24;  //Vuelve al valor maximo
                        break;

                    default:
                        break;
                }

            } else
                anti_rebote_state = UNO;
            break;

        case UNO:
            puls_down = 1;
            habilitacion = 0;
            break;
    }
}

void flanco_modo (void)                             //Si se detecto un flanco ascendente o descendente del pulsador de modo
{
    PULS_tic = 40; // Demora de Puls es 40mSeg, demora para evitar el rebote
    hab_antirrebote = MODO;                 //eligue que pulsador habilitar
    anti_rebote_state = ESPERANDO;          //modifica el estado de la maquina antirrebote a ESPERANDO
    habilitacion = 1;                       //habilita la maquina de antirrebote
}

void flanco_set (void)
{                                                   //TODOS LOS DETECTORES DE FLANCO SON IGUALES, SOLO CAMBIA QUE MAQUINA SE HABILITA DE LAS 4 OPCIONES DE PUILSADORES
    PULS_tic = 40; // Demora de Puls es 40mSeg
    hab_antirrebote = SET;
    anti_rebote_state = ESPERANDO;
    habilitacion = 1;
}

void flanco_up (void)
{                                                   //TODOS LOS DETECTORES DE FLANCO SON IGUALES, SOLO CAMBIA QUE MAQUINA SE HABILITA DE LAS 4 OPCIONES DE PUILSADORES
    PULS_tic = 40; // Demora de Puls es 40mSeg
    hab_antirrebote = UP;
    anti_rebote_state = ESPERANDO;
    habilitacion = 1;
}

void flanco_down (void)
{                                                   //TODOS LOS DETECTORES DE FLANCO SON IGUALES, SOLO CAMBIA QUE MAQUINA SE HABILITA DE LAS 4 OPCIONES DE PUILSADORES
    PULS_tic = 40; // Demora de Puls es 40mSeg
    hab_antirrebote = DOWN;
    anti_rebote_state = ESPERANDO;
    habilitacion = 1;
}


void Interrupciones(void)                                                       //HABILITA INTERRUPCIONES DE PULSADORES
{

    modo.fall(&flanco_modo); //Habilita interrupción MODO 
    modo.rise(&flanco_modo);
    set.fall(&flanco_set);   //Habilita interrupción SET
    set.rise(&flanco_set);
    up.fall(&flanco_up);     //Habilita interrupción UP
    up.rise(&flanco_up);
    down.fall(&flanco_down); //Habilita interrupción DOWN
    down.rise(&flanco_down);

    if(habilitacion == 1) {                 //si se detecto un flanco en alguna de las entradas de los pulsadores
        switch (hab_antirrebote) {          //dependiendo de que pulsador se toco, eligue que maquina debe ejecutar
            case MODO:                      
                anti_rebote_step_modo();    //maquina modo
                break;
            case SET:
                anti_rebote_step_set();     //maquina set
                break;
            case UP:
                anti_rebote_step_up();      //maquina up
                break;
            case DOWN:
                anti_rebote_step_down();    //maquina down
                break;
        }
    }
}

//Funcion que controla las salidas
void Activacion_frio(void)                                                     
{
    if(resHel < (set_hel - 1))   //Si el promedio de las mediciones es menor al valor seteado menos un grado de margen...
        salida_hel = 0;          // No hay que enfriar, se desactiva la salida
    else if(resHel > (set_hel + 1))  //Si el promedio de las mediciones es mayor al valor seteado mas un grado de margen...
        salida_hel = 1;              //Se debe enfriar, se activa la salida
        
//Como el valor seteado se toma como positivo para la funcion de los pulsadores up y down, al compararlos se debe tomar como negativos

    if(resFrz < ((set_frz * -1) - 1))  //Si el promedio de las mediciones es menor al valor seteado menos un grado de margen...
        salida_frz = 0;                // No hay que enfriar, se desactiva la salida
    else if(resFrz  > ((set_frz * -1) + 1))  //Si el promedio de las mediciones es mayor al valor seteado mas un grado de margen...
        salida_frz = 1;                      //Se debe enfriar, se activa la salida
}