TP01-SE2018-PUNTO3

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
KilianPolkov
Date:
Tue Jun 05 00:18:10 2018 +0000
Commit message:
Version 1

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jun 05 00:18:10 2018 +0000
@@ -0,0 +1,696 @@
+/* BOTON ARRIBA: 2do izquierda, BOTON ABAJO: 3ero izquierda, BOTON OK/STOP: 1ero derecha*/
+
+/* consola */
+/* pc.printf("TEMP: %d\n", temperaturaActual);
+   pc.printf("TIME: %d\n", tiempoActual);
+   pc.printf("MOTOR: %d\n", MOTOR_estado);
+*/
+
+#include "mbed.h"
+#include <string.h>
+
+/* -----definiciones----- */
+#define DATA                1   // para mandar caracter al display LCD
+#define CMND                0   // para configurar registro al display LCD
+#define APRETADO            0   // para indicar el apretado del pulsador
+#define NO_APRETADO         1   // para indicar el no apretado del pulsador
+
+/* -----enumeraciones----- */
+enum{MENU_MODO, MENU_TEMPERATURA, MENU_CENTRIFUGADO, MENU_TIEMPO, MENU_ENJUAGUE, MENU_LAVADO, CONFIG_MODO, CONFIG_TEMPERATURA, CONFIG_CENTRIFUGADO, CONFIG_TIEMPO, CONFIG_ENJUAGUE, LAVANDO, PAUSADO}; // SELECTOR_Step
+enum{OFF, ENJUAGADO, ENJABONADO, SUAVIZADO, DESAGOTE, CENTRIFUGADO};                                                                                        // LAVADO_Step
+enum{ALGODON, SINTETICO, PROGRAMA_BEBE, PESADO, RAPIDO};                                                                                                    // MODO_Step
+enum{RPM_OFF = 0, RPM_MIN = 3, RPM_NORMAL = 6, RPM_MAX = 9};                                                                                                // CENTRIFUGADO_Step
+enum{TEMP_MIN = 10, TEMP_BAJA = 20, TEMP_NORMAL = 30, TEMP_ALTA = 40, TEMP_MAX = 50};                                                                       // TEMP_Step
+enum{TIEMPO_FINAL_MIN = 30, TIEMPO_FINAL_BAJO = 40, TIEMPO_FINAL_NORMAL = 50, TIEMPO_FINAL_MEDIO = 60, TIEMPO_FINAL_ALTO = 70, TIEMPO_FINAL_MAX = 80};      // TIEMPO_Step
+enum{TIEMPO_OFF = 0, TIEMPO_MIN = 5, TIEMPO_NORMAL = 10, TIEMPO_MAX = 15};                                                                                  // ENJUAGUE_Step y variables tiempo
+enum{PULS_NO_APRETADO, PULS_FLANCO_1, PULS_APRETADO, PULS_FLANCO_2};                                                                                        // PULS_Step
+enum{NO_CALENTAR = 1, CALENTAR = 0};                                                                                                                        // ACTUADOR_Step
+enum{NO_GIRAR = 0, GIRAR = 1};                                                                                                                              // MOTOR_Step
+
+/* -----clases----- */
+/* entradas */
+DigitalIn PULSDOWN(PTB0);       // boton abajo
+DigitalIn PULSUP(PTB1);         // boton arriba
+DigitalIn PULSOK(PTB3);         // boton aceptar
+AnalogIn LM35(PTC1);            // sensor de temperatura analogico
+/* salidas */
+DigitalOut CALENTADOR(LED1);    // es un led para indicar el encendido/apagado del CALENTADOR
+DigitalOut MOTOR(PTC9);         // es el enable para el driver del MOTOR
+PwmOut pwm(PTA5);               // es la señal para variar la velocidad del MOTOR
+/* objetos */
+Ticker timerMili;               // instancia de la clase Ticker
+Ticker timerSeg;                // instancia de la clase Ticker
+Serial pc(USBTX, USBRX);        // instancia de la clase Serial
+I2C i2c(PTE0, PTE1);            // instancia de la clase I2C - PTEO: SDA (data), PTE1: SCL (clock)
+
+typedef unsigned char BYTE;     // sirve para escribir "BYTE" en ves de "unsigned char" que es mas largo
+
+/* -----variables globales----- */
+/* modulo i2c */
+const int address = 0x7E;       // address de 8bits I2C
+int i2c_error = 0;              // si hay error en el ACK se pone en 1, sino en 0
+char fila1[17];
+char fila2[17];
+/* sensor LM35 */
+char i = 0;
+float sensado[10], promedio;
+/* estados de funciones */
+BYTE SELECTOR_estado;           // SELECTOR_Step
+BYTE LAVADO_estado;             // LAVADO_Step
+BYTE LAVADO_ultimoEstado;       // LAVADO_Step
+BYTE MODO_estado;               // MODO_Step
+BYTE CENTRIFUGADO_estado;       // CENTRIFUGADO_Step
+BYTE TEMP_estado;               // TEMP_Step
+BYTE TIEMPO_estado;             // TIEMPO_Step
+BYTE ENJUAGUE_estado;           // ENJUAGUE_Step
+BYTE PULS_tout;                 // PULS_Step
+BYTE ACTUADOR_estado;           // ACTUADOR_Step
+BYTE MOTOR_estado;              // MOTOR_Step
+/* estados de pulsadores */
+BYTE PULSOK_estado, PULSUP_estado, PULSDOWN_estado; //variables utilizadas en la maquina de estados
+/* variables maquinas de estados */
+char temperaturaSeteada, temperaturaActual, rpmSeteado, vecesEnjuagado;
+char tiempoActual, tiempoDiferido, tiempoSeteado, tiempoEnjuague, tiempoEnjabonado, tiempoSuavizado, tiempoDesagote, tiempoCentrifugado; // tiempos
+    
+/* -----prototipos funciones----- */
+/* funciones generales */
+void miliSegundo(void);                     // se ejecuta cada milisegundo
+void segundo(void);                         // se ejecuta cada segundo
+void initMCU(void);                         // se ejecuta una sola vez al inicializar el microcontrolador
+void showTimeNow(void);                     // imprime en pantalla el tiempo actual
+void detectForBack(void);                   // vuelve al menu principal MENU_MODO
+void readSensor(void);                      // lee 10 valores y saca el promedio del sensor LM35
+char isWashing(void);                       // devuelve true si esta lavando, sino false
+/* funciones maquina de estados */
+void SELECTOR_Step(void);                   // maquina de estados principal
+void LAVADO_Step(void);                     // maquina de estados lavado
+void MODO_Step(void);                       // maquina de estados para setear modo o programa (algodon, sintetico)
+void CENTRIFUGADO_Step(void);               // maquina de estados para setear centrifugado (configura las RPM, si esta en 0 RPM es que no centrifuga)
+void TEMP_Step(void);                       // maquina de estados para setear temperatura (para configurar manualmente la temperatura en vez de utilizar los modos o programas)
+void TIEMPO_Step(void);                     // maquina de estados para setear el tiempo diferido (cuando finaliza el ciclo de lavado)
+void ENJUAGUE_Step(void);                   // maquina de estados para setear ciclos de enjuague
+void ACTUADOR_Step(void);                   // maquina de estados para activar/desactivar el calentador
+void MOTOR_Step(void);                      // maquina de estados para activar/desactivar el motor
+BYTE PULS_Step(BYTE PULSADOR, BYTE& estado);// maquina de estados para detectar el flanco de los pulsadores
+/* funciones I2C */
+void LCD_wr( BYTE dato );                   // funcion para escritura de un byte
+/* funciones display LCD */
+void LCD_init(void);                        // inicializacion del display LCD
+void LCD_send(BYTE data, BYTE reset);       // manda 4 bits mas significativos, despues 4 bits menos significativos
+void printstr(char* s);                     // muestra en el display LCD un string
+void LCD_print(void);                       // muestra el display LCD       
+    
+int main() {
+    LCD_init();
+    initMCU();
+    while(1) {
+        /* ejecuta */
+        SELECTOR_Step();     // maquina de estados principal
+        LCD_print();         // printea en el LCD
+        
+        /* girar o no girar el motor */
+        if(LAVADO_estado == ENJUAGADO || LAVADO_estado == CENTRIFUGADO) 
+            MOTOR_estado = GIRAR;
+        else 
+            MOTOR_estado = NO_GIRAR;
+            
+        /* activa o desactiva el motor dependiendo de MOTOR_estado */
+        MOTOR_Step();
+            
+        /* si esta lavando */
+        if(isWashing()) {    // si no para de girar cuando esta pausado, CAMBIAR ACA
+            showTimeNow();
+            ACTUADOR_Step(); // maquina de estados para activar/desactivar el calentador
+        }
+    }
+}
+
+/* -----contador que se decrementa cada milisegundo----- */
+void miliSegundo() {
+    if(PULS_tout > 0) PULS_tout--;
+}
+
+/* -----cada segundo se decrementa el valor del temporizador(si no esta pausado) y tambien se lee el valor de temperatura del LM35----- */
+void segundo() {
+    readSensor();
+    if(isWashing()) tiempoActual--;
+}
+
+/* -----guarda en el vector de la fila1 el tiempoActual----- */
+void showTimeNow() {
+    strcpy(fila1, "TIME ACTUAL:xxs ");
+    fila1[12] = (tiempoActual / 10) + 0x30;
+    fila1[13] = (tiempoActual % 10) + 0x30;    
+}
+
+/* -----vuelve al menu principal MENU_MODO----- */
+void detectForBack() {
+    if(PULS_Step(PULSOK, PULSOK_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_MODO; // cuando se presiona el pulsador vuelve al menu principal
+}
+
+/* -----lee 10 valores y saca el promedio del sensor LM35----- */
+void readSensor(void) {
+    promedio = 0;
+    for(i = 0; i < 10; i++){
+        sensado[i] = LM35.read(); 
+    }
+    for(i = 0; i < 10; i++){
+        promedio += sensado[i]/10;
+    }
+    temperaturaActual = (promedio*3.25*100);
+}
+
+/* -----devuelve true si esta lavando, sino false----- */
+char isWashing() {
+   if(LAVADO_estado == ENJUAGADO || LAVADO_estado == ENJABONADO || LAVADO_estado == SUAVIZADO || LAVADO_estado == DESAGOTE || LAVADO_estado == CENTRIFUGADO) return 1; // devuelve true
+   return 0; // si no se cumple la sentencia if, devuelve false
+}
+
+/* -----se ejecuta una sola vez al inicializar el microcontrolador----- */
+void initMCU(void) {
+    pc.printf("PROGRAMA INICIALIZADO\n");
+    
+    /* PWM */
+    pwm.period_ms(10);
+    pwm.pulsewidth_ms(RPM_OFF);
+    pc.printf("pwm set to %.2f %%\n", pwm.read() * 100);
+    
+    /* TIMER */
+    PULS_tout = TIEMPO_OFF;
+    timerMili.attach(&miliSegundo, 0.001);  // timer en 1ms
+    timerSeg.attach(&segundo, 1);           // timer en 1s
+    
+    /* SELECTOR_Step */
+    SELECTOR_estado = MENU_MODO;
+    
+    /* LAVADO_Step */
+    LAVADO_estado = OFF;
+    tiempoCentrifugado = TIEMPO_OFF;    // se inicializa en 0s por si no se configura el centrifugado, se puede modificar
+    tiempoEnjuague = TIEMPO_MIN;        // se inicializa en 5s, se puede modificar
+    tiempoEnjabonado = TIEMPO_MIN;      // se inicializa en 5s, se puede modificar
+    tiempoSuavizado = TIEMPO_MIN;       // se inicializa en 5s, se puede modificar
+    tiempoDesagote = TIEMPO_MIN;        // se inicializa en 5s, se puede modificar
+    vecesEnjuagado = 1;                 // se inicializa en 1, despues se incrementa hasta 3 porque es la cantidad maxima de enjuagues
+    
+    /* MODO_Step */
+    MODO_estado = ALGODON;
+    
+    /* CENTRIFUGADO_Step */
+    CENTRIFUGADO_estado = RPM_OFF;
+    rpmSeteado = RPM_OFF; // se inicializa en 0rps, se puede modificar
+    
+    /* TEMP_Step */
+    TEMP_estado = TEMP_MIN;
+    
+    /* TIEMPO_Step */
+    TIEMPO_estado = TIEMPO_FINAL_BAJO;
+    tiempoActual = tiempoDiferido = tiempoSeteado = TIEMPO_FINAL_BAJO; // se inicializa en 40s, se puede modificar
+    
+    /* PULSADORES */
+    PULSOK_estado = PULS_NO_APRETADO;
+    PULSUP_estado = PULS_NO_APRETADO;
+    PULSDOWN_estado = PULS_NO_APRETADO;
+    
+    /* ACTUADOR_Step */
+    ACTUADOR_estado = NO_CALENTAR;
+    CALENTADOR = NO_CALENTAR;
+    
+    /* MOTOR_Step */
+    MOTOR_estado = NO_GIRAR;
+    
+    /* ENJUAGUE_Step */
+    ENJUAGUE_estado = TIEMPO_MIN;
+} 
+
+/* -----maquina de estados principal----- */
+void SELECTOR_Step() {
+    switch(SELECTOR_estado) {
+        default:
+        case MENU_MODO:
+            strcpy(fila1, "MENU:           ");
+            strcpy(fila2, "CONFIG MODE     ");
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_LAVADO;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_TEMPERATURA;
+            if(PULS_Step(PULSOK, PULSOK_estado) == PULS_FLANCO_1) SELECTOR_estado = CONFIG_MODO;
+            break;
+        case MENU_TEMPERATURA:
+            strcpy(fila2, "CONFIG TEMP     ");
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_MODO;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_CENTRIFUGADO;
+            if(PULS_Step(PULSOK, PULSOK_estado) == PULS_FLANCO_1) SELECTOR_estado = CONFIG_TEMPERATURA;
+            break;
+        case MENU_CENTRIFUGADO:
+            strcpy(fila2, "CONFIG RPM      ");
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_TEMPERATURA;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_TIEMPO;
+            if(PULS_Step(PULSOK, PULSOK_estado) == PULS_FLANCO_1) SELECTOR_estado = CONFIG_CENTRIFUGADO;
+            break;
+        case MENU_TIEMPO:
+            strcpy(fila2, "CONFIG TIME     ");
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_CENTRIFUGADO;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_ENJUAGUE;
+            if(PULS_Step(PULSOK, PULSOK_estado) == PULS_FLANCO_1) SELECTOR_estado = CONFIG_TIEMPO;
+            break;
+        case MENU_ENJUAGUE:
+            strcpy(fila2, "CONFIG ENJUAGUE ");
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_TIEMPO;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_LAVADO;
+            if(PULS_Step(PULSOK, PULSOK_estado) == PULS_FLANCO_1) SELECTOR_estado = CONFIG_ENJUAGUE;
+            break;
+        case MENU_LAVADO:
+            strcpy(fila2, "COMENZAR          ");
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_ENJUAGUE;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) SELECTOR_estado = MENU_MODO;
+            if(PULS_Step(PULSOK, PULSOK_estado) == PULS_FLANCO_1) {
+                SELECTOR_estado = LAVANDO;
+                LAVADO_estado = ENJUAGADO;
+                tiempoSeteado -= tiempoEnjuague; //primer ciclo de lavado
+            }
+            break;
+        case CONFIG_MODO:
+            MODO_Step();
+            detectForBack();
+            break;
+        case CONFIG_TEMPERATURA:
+            TEMP_Step();
+            detectForBack();
+            break;
+        case CONFIG_CENTRIFUGADO:
+            CENTRIFUGADO_Step();
+            detectForBack();
+            break;
+        case CONFIG_TIEMPO:
+            TIEMPO_Step();
+            detectForBack();
+            break;
+        case CONFIG_ENJUAGUE:
+            ENJUAGUE_Step();
+            detectForBack();
+            break;
+        case LAVANDO:
+            LAVADO_Step();
+            if(PULS_Step(PULSOK, PULSOK_estado) == PULS_FLANCO_1) {
+                LAVADO_estado = OFF;        // pone en OFF, es decir, deja de lavar en LAVADO_Step
+                SELECTOR_estado = PAUSADO;  // va al estado PAUSADO del SELECTOR_Step
+            }
+            break;
+        case PAUSADO:
+            strcpy(fila2, "PAUSADO...      ");
+            if(PULS_Step(PULSOK, PULSOK_estado) == PULS_FLANCO_1){ 
+                LAVADO_estado = LAVADO_ultimoEstado; // vuelve al ultimo estado de LAVADO_estado
+                SELECTOR_estado = LAVANDO;  // vuelve al estado LAVANDO del SELECTOR_Step
+            }
+            break;
+    }
+}
+
+/* -----maquina de estados lavado----- */
+void LAVADO_Step() {
+    switch(LAVADO_estado) {
+        default:
+        case OFF:
+            tiempoSeteado = tiempoActual = tiempoDiferido;
+            vecesEnjuagado = 1;
+            CALENTADOR = NO_CALENTAR;
+            SELECTOR_estado = MENU_MODO;
+            break;
+        case ENJUAGADO:
+            strcpy(fila2, "ENJUAGANDO...   ");
+            /* finaliza tiempo enjuagado */ 
+            if(tiempoActual == tiempoSeteado) {
+                switch(vecesEnjuagado) {
+                    case 1: /* finaliza primer enjuague */ 
+                        tiempoSeteado -= tiempoEnjabonado; // segundo ciclo de lavado
+                        LAVADO_estado = ENJABONADO;
+                        break;
+                    case 2: /* finaliza segundo enjuague, despues del enjabonado */
+                        tiempoSeteado -= tiempoSuavizado; // cuarto ciclo de lavado
+                        LAVADO_estado = SUAVIZADO;
+                        break;
+                    case 3: /* finaliza tercer enjuague, despues del suavizado */
+                        tiempoSeteado -= tiempoDesagote; // sexto ciclo de lavado
+                        LAVADO_estado = DESAGOTE;
+                        break;
+                }
+            }
+            LAVADO_ultimoEstado = ENJUAGADO;
+            break;
+        case ENJABONADO:
+            strcpy(fila2, "ENJABONANDO...  ");
+            /* finaliza tiempo enjabonado */ 
+            if(tiempoActual == tiempoSeteado) {
+                vecesEnjuagado++;
+                tiempoSeteado -= tiempoEnjuague; // tercer ciclo de lavado
+                LAVADO_estado = ENJUAGADO;
+            }
+            LAVADO_ultimoEstado = ENJABONADO;
+            break;
+        case SUAVIZADO:
+            strcpy(fila2, "SUAVIZANDO...   ");
+            /* finaliza tiempo suavizado */ 
+            if(tiempoActual == tiempoSeteado) {
+                vecesEnjuagado++;
+                tiempoSeteado -= tiempoEnjuague; // quinto ciclo de lavado
+                LAVADO_estado = ENJUAGADO;
+            }
+            LAVADO_ultimoEstado = SUAVIZADO;
+            break;
+        case DESAGOTE:
+            strcpy(fila2, "DESAGOTANDO...  ");
+            /* finaliza tiempo desagote */
+            if(tiempoActual == tiempoSeteado && rpmSeteado != RPM_OFF) {
+                tiempoSeteado -= tiempoCentrifugado; // septimo ciclo de lavado, se ejecuta solo si queres centrifugar
+                LAVADO_estado = CENTRIFUGADO;
+            }
+            LAVADO_ultimoEstado = DESAGOTE;
+            if(tiempoActual == 0) LAVADO_estado = OFF;
+            break;
+        case CENTRIFUGADO:
+            strcpy(fila2, "CENTRIFUGANDO...");
+            LAVADO_ultimoEstado = CENTRIFUGADO;
+            if(tiempoActual == 0) LAVADO_estado = OFF;
+            break;
+    }
+}
+
+/* -----maquina de estados para setear modo o programa (algodon, sintetico, etc)----- */
+void MODO_Step() {
+    strcpy(fila1, "CONFIG:         ");
+    switch(MODO_estado) {
+        default:
+        case ALGODON:
+            strcpy(fila2, "MODO:ALGODON   ");
+            temperaturaSeteada = TEMP_BAJA;
+            tiempoEnjuague = TIEMPO_MAX; //15s tiempo enjuague
+            if(rpmSeteado)
+                tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_ALTO; //70s tiempo total, 10s tiempo centrifugado  
+            else
+                tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_MEDIO; //60s tiempo total, 0s tiempo centrifugado
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) MODO_estado = PESADO;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) MODO_estado = SINTETICO;
+            break;
+        case SINTETICO:
+            strcpy(fila2, "MODO:SINTETICO ");
+            temperaturaSeteada = TEMP_NORMAL;
+            tiempoEnjuague = TIEMPO_NORMAL; //10s tiempo enjuague
+            if(rpmSeteado)
+                tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_MEDIO; //60s tiempo total, 15s tiempo centrifugado
+            else
+                tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_NORMAL; //50s tiempo total, 0s tiempo centrifugado
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) MODO_estado = ALGODON;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) MODO_estado = RAPIDO;
+            break;
+        case RAPIDO:
+            strcpy(fila2, "MODO:RAPIDO    ");
+            temperaturaSeteada = TEMP_NORMAL;
+            tiempoEnjuague = TIEMPO_MIN; //5s tiempo enjuague
+            if(rpmSeteado)
+                tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_BAJO; //40s tiempo total, 10s tiempo centrifugado
+            else
+                tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_MIN; //30s tiempo total, 0s tiempo centrifugado
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) MODO_estado = SINTETICO;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) MODO_estado = PROGRAMA_BEBE;
+            break;
+        case PROGRAMA_BEBE:
+            strcpy(fila2, "MODO:BEBE      ");
+            temperaturaSeteada = TEMP_MAX;
+            tiempoEnjuague = TIEMPO_MAX; //15s tiempo enjuague
+            tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_MAX; //80s tiempo total, 20s tiempo centrifugado
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) MODO_estado = RAPIDO;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) MODO_estado = PESADO;
+            break;
+        case PESADO:
+            strcpy(fila2, "MODO:PESADO    ");
+            temperaturaSeteada = TEMP_NORMAL;
+            tiempoEnjuague = TIEMPO_MIN; //5s tiempo enjuague
+            tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_NORMAL; //50s tiempo total, 20s tiempo centrifugado
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) MODO_estado = PROGRAMA_BEBE;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) MODO_estado = ALGODON;
+            break;
+    }
+}
+
+/* -----maquina de estados para setear centrifugado (configura las RPM, si esta en 0 RPM es que no centrifuga)----- */
+void CENTRIFUGADO_Step() {
+    strcpy(fila1, "CONFIG:         ");
+    strcpy(fila2, "RPM SET:xx      ");
+    fila2[8] = (rpmSeteado / 10) + 0x30;
+    fila2[9] = (rpmSeteado % 10) + 0x30; 
+    switch(CENTRIFUGADO_estado) {
+        default:
+        case RPM_OFF:
+            rpmSeteado = RPM_OFF;
+            pwm.pulsewidth_ms(RPM_OFF);
+            tiempoCentrifugado = TIEMPO_OFF;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) CENTRIFUGADO_estado = RPM_MAX;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) CENTRIFUGADO_estado = RPM_MIN;
+            break;
+        case RPM_MIN:
+            rpmSeteado = RPM_MIN;
+            pwm.pulsewidth_ms(RPM_MIN);
+            tiempoCentrifugado = TIEMPO_MIN;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) CENTRIFUGADO_estado = RPM_OFF;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) CENTRIFUGADO_estado = RPM_NORMAL;
+            break;
+        case RPM_NORMAL:
+            rpmSeteado = RPM_NORMAL;
+            pwm.pulsewidth_ms(RPM_NORMAL);
+            tiempoCentrifugado = TIEMPO_MIN;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) CENTRIFUGADO_estado = RPM_MIN;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) CENTRIFUGADO_estado = RPM_MAX;
+            break;
+        case RPM_MAX:
+            rpmSeteado = RPM_MAX;
+            pwm.pulsewidth_ms(RPM_MAX);
+            tiempoCentrifugado = TIEMPO_MIN;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) CENTRIFUGADO_estado = RPM_NORMAL;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) CENTRIFUGADO_estado = RPM_OFF;
+            break;
+    }
+}
+
+/* -----maquina de estados para setear temperatura (para configurar manualmente la temperatura en vez de utilizar los modos o programas)----- */
+void TEMP_Step() {
+    strcpy(fila1, "TEMP NOW:xxg    ");
+    fila1[9] = (temperaturaActual / 10) + 0x30;
+    fila1[10] = (temperaturaActual % 10) + 0x30;
+    fila1[11] = 0xDF; // para el simbolo de grado
+    strcpy(fila2, "TEMP SET:xxg    ");
+    fila2[9] = (temperaturaSeteada / 10) + 0x30;
+    fila2[10] = (temperaturaSeteada % 10) + 0x30;
+    fila2[11] = 0xDF; // para el simbolo de grado
+    switch(TEMP_estado) {
+        default:
+        case TEMP_MIN:
+            temperaturaSeteada = TEMP_MIN;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) TEMP_estado = TEMP_MAX;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) TEMP_estado = TEMP_BAJA;
+            break;
+        case TEMP_BAJA:
+            temperaturaSeteada = TEMP_BAJA;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) TEMP_estado = TEMP_MIN;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) TEMP_estado = TEMP_NORMAL;
+            break;
+        case TEMP_NORMAL:
+            temperaturaSeteada = TEMP_NORMAL;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) TEMP_estado = TEMP_BAJA;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) TEMP_estado = TEMP_ALTA;
+            break;
+        case TEMP_ALTA:
+            temperaturaSeteada = TEMP_ALTA;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) TEMP_estado = TEMP_NORMAL;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) TEMP_estado = TEMP_MAX;
+            break;
+        case TEMP_MAX:
+            temperaturaSeteada = TEMP_MAX;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) TEMP_estado = TEMP_ALTA;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) TEMP_estado = TEMP_MIN;
+            break;
+    }
+}
+
+/* -----maquina de estados para setear el tiempo diferido (cuando finaliza el ciclo de lavado)----- */
+void TIEMPO_Step() {
+    strcpy(fila1, "CONFIG:         ");
+    strcpy(fila2, "TIME SET:x      ");
+    fila2[9] = (tiempoDiferido / 10) + 0x30;
+    fila2[10] = (tiempoDiferido % 10) + 0x30; 
+    switch(TIEMPO_estado) {
+        default:
+        case TIEMPO_FINAL_BAJO:
+            tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_BAJO;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) TIEMPO_estado = TIEMPO_FINAL_NORMAL;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) TIEMPO_estado = TIEMPO_FINAL_MAX;
+            break;
+        case TIEMPO_FINAL_NORMAL:
+            tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_NORMAL;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) TIEMPO_estado = TIEMPO_FINAL_MEDIO;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) TIEMPO_estado = TIEMPO_FINAL_BAJO;
+            break;
+        case TIEMPO_FINAL_MEDIO:
+            tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_MEDIO;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) TIEMPO_estado = TIEMPO_FINAL_ALTO;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) TIEMPO_estado = TIEMPO_FINAL_NORMAL;
+            break;
+        case TIEMPO_FINAL_ALTO:
+            tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_ALTO;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) TIEMPO_estado = TIEMPO_FINAL_MAX;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) TIEMPO_estado = TIEMPO_FINAL_MEDIO;
+            break;
+        case TIEMPO_FINAL_MAX:
+            tiempoSeteado = tiempoActual = tiempoDiferido = TIEMPO_FINAL_MAX;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) TIEMPO_estado = TIEMPO_FINAL_BAJO;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) TIEMPO_estado = TIEMPO_FINAL_ALTO;
+            break; 
+    }
+}
+
+/* -----maquina de estados para setear ciclos de enjuague----- */
+void ENJUAGUE_Step() {
+    strcpy(fila1, "CONFIG:         ");
+    strcpy(fila2, "TIME ENJUAGUE:xx");
+    fila2[14] = (tiempoEnjuague / 10) + 0x30;
+    fila2[15] = (tiempoEnjuague % 10) + 0x30;
+    switch(ENJUAGUE_estado) {
+        default:
+        case TIEMPO_MIN:
+            tiempoEnjuague = TIEMPO_MIN;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) ENJUAGUE_estado = TIEMPO_NORMAL;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) ENJUAGUE_estado = TIEMPO_MAX;
+            break;
+        case TIEMPO_NORMAL:
+            tiempoEnjuague = TIEMPO_NORMAL;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) ENJUAGUE_estado = TIEMPO_MAX;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) ENJUAGUE_estado = TIEMPO_MIN;
+            break;
+        case TIEMPO_MAX:
+            tiempoEnjuague = TIEMPO_MAX;
+            if(PULS_Step(PULSUP, PULSUP_estado) == PULS_FLANCO_1) ENJUAGUE_estado = TIEMPO_MIN;
+            if(PULS_Step(PULSDOWN, PULSDOWN_estado) == PULS_FLANCO_1) ENJUAGUE_estado = TIEMPO_NORMAL;
+            break;
+    }
+}
+
+/* -----maquina de estados para activar/desactivar el calentadorl----- */
+void ACTUADOR_Step() {
+    switch(ACTUADOR_estado) {
+        default:
+        case NO_CALENTAR:
+            CALENTADOR = NO_CALENTAR;
+            if(temperaturaActual < temperaturaSeteada) ACTUADOR_estado = CALENTAR;
+            break;
+        case CALENTAR:
+            CALENTADOR = CALENTAR;
+            if(temperaturaActual >= temperaturaSeteada) ACTUADOR_estado = NO_CALENTAR;
+            break;
+    }
+}
+
+/* -----maquina de estados para activar/desactivar el motor----- */
+void MOTOR_Step() {
+    switch(MOTOR_estado) {
+        default:
+        case NO_GIRAR:
+            MOTOR = NO_GIRAR;
+            break;
+        case GIRAR:
+            MOTOR = GIRAR;
+            break;
+    }
+}
+
+/* -----maquina de estados para detectar el flanco de los pulsadores----- */
+BYTE PULS_Step(BYTE PULSADOR, BYTE& estado) {
+    switch(estado){
+        default:
+        case PULS_NO_APRETADO:
+            if(PULSADOR == APRETADO && PULS_tout == 0){
+                estado = PULS_FLANCO_1;
+                PULS_tout = 5; // 5ms de espera
+            }
+            break;
+        case PULS_FLANCO_1:
+            if(PULSADOR == APRETADO && PULS_tout == 0){
+                estado = PULS_APRETADO;
+                PULS_tout = 5; // 5ms de espera
+            }
+            if(PULSADOR == NO_APRETADO && PULS_tout == 0){
+                estado = PULS_NO_APRETADO;
+                PULS_tout = 5; // 5ms de espera
+            }
+            break;  
+        case PULS_APRETADO:
+            if(PULSADOR == NO_APRETADO && PULS_tout == 0){
+                estado = PULS_NO_APRETADO;
+                PULS_tout = 5; //5ms de espera
+            }
+            break;  
+    }
+    return estado;
+}
+
+/* -----escribe un byte----- */
+void LCD_wr( BYTE dato ) {
+    dato = dato & 0xF0; // hace una mascara con 0b11110000 para que queda los 4 MSB
+    do{
+        i2c.start();
+        i2c_error = i2c.write( address );
+    }while( i2c_error == 0 ); /* espera fin ciclo escritura (ACK polling) */
+    /* Primero mando los 4 bits mas significativos */
+    i2c.write( dato | 0x09 );  // esta mascara pone BACKLIGHT = 1, ENABLE = 0, RW = 0, RESET = 1
+    i2c.write( dato | 0x0D );  // esta mascara pone BACKLIGHT = 1, ENABLE = 1, RW = 0, RESET = 1
+    i2c.write( dato | 0x09 );  // esta mascara pone BACKLIGHT = 1, ENABLE = 0, RW = 0, RESET = 1
+    /* Mando STOP */
+    i2c.stop();
+}
+
+/* -----escribe 4 MSB, luego 4 LSB, si reset = 1 es porque manda un caracter, si reset = 0 configura registro----- */
+void LCD_send(BYTE data, BYTE reset) {
+    BYTE DataHIGH, DataLOW;
+    DataHIGH = data & 0xF0;         // hace una mascara con 0b11110000 para que queda los 4 MSB
+    DataLOW = ( data << 4 ) & 0xF0; // mueve los 4 LSB a la izquierda
+    do{
+        i2c.start();
+        i2c_error = i2c.write( address );
+    }while( i2c_error == 0 ); /* espera fin ciclo escritura (ACK polling) */
+    /* primero mando los 4 bits mas significativos */
+    i2c.write( DataHIGH | ( 0x0C | reset ) );   // esta mascara pone BACKLIGHT = 1, ENABLE = 1, RW = 0, RESET = X
+    i2c.write( DataHIGH | ( 0x08 | reset ) );   // esta mascara pone BACKLIGHT = 1, ENABLE = 0, RW = 0, RESET = X
+    /* despues mando los 4 bits menos significativos */
+    i2c.write( DataLOW | ( 0x0C | reset ) );    // esta mascara pone BACKLIGHT = 1, ENABLE = 1, RW = 0, RESET = X
+    i2c.write( DataLOW | ( 0x08 | reset ) );    // esta mascara pone BACKLIGHT = 1, ENABLE = 0, RW = 0, RESET = X
+    i2c.write( DataLOW | 0x0C );                // esta mascara pone BACKLIGHT = 1, ENABLE = 1, RW = 0, RESET = 0
+    /* mando STOP */
+    i2c.stop(); 
+}
+
+/* -----inicializacion LCD----- */
+void LCD_init() {
+    i2c.frequency(300000);
+    wait(0.4);
+    LCD_wr( 0x30 );
+    LCD_wr( 0x30 );
+    LCD_wr( 0x30 );
+    LCD_wr( 0x20 );             /* --- modo 4 bit --- */
+    LCD_send( 0x28 , CMND );    /* --- modo 4b - 2 lin - car 5x7 --- */
+    LCD_send( 0x08 , CMND );    /* --- apaga display --- */
+    LCD_send( 0x01 , CMND );    /* --- clear --- */
+    wait(0.2);
+    LCD_send( 0x0C , CMND );    /* --- disp on - cur off - blink off --- */
+    LCD_send( 0x06 , CMND );    /* --- inc - no scroll --- */
+    pc.printf("DISPLAY INICIALIZADO\n");
+}
+
+/* -----muestra string en el display LCD----- */
+void printstr(char* s) {
+    /* recorre el vector s (el string parametro de la funcion), hasta que llega al final "\0" */
+    for (char i = 0; s[i] != '\0'; i++) LCD_send(s[i], DATA);
+}
+
+/* -----muestra en el display LCD los vectores fila1 y fila2----- */
+void LCD_print() {
+    LCD_send( 0x80 , CMND );    // posiciona en columna de arriba, y en la primer linea
+    printstr(fila1);            // una vez posicionado, muestra el texto en la fila 1
+    LCD_send( 0xC0 , CMND );    // posiciona en columna de abajo, y en la segunda linea
+    printstr(fila2);            // una vez posicionado, muestra el texto en la fila 2
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Jun 05 00:18:10 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/5aab5a7997ee
\ No newline at end of file