Nicolas Fernandez Sanz
/
TP1_EJER01
Version Final
main.cpp
- Committer:
- NIcolasFernandezSanz
- Date:
- 2019-06-16
- Revision:
- 10:d0d3e0429c6f
- Parent:
- 9:56bfbc0947af
File content as of revision 10:d0d3e0429c6f:
/* FERNANDEZ-CLERICI EJER01 - TP01 PTB0 -- Habilitacion Cooler PTB1 -- DS18B20 (Data) (4K7 PullUp) D3 -- Sensor Efecto de Hall --> PullUp 4k7 PTB3 -- Pulsador --> 0 = Nada || 1 = Pulsado PTC2 -- Preset A3 -- Pin Para Probar que el programa no retiene */ /*Librerias*/ #include "mbed.h" #include "DS1820.h" /*Definicion Pines*/ #define EN_COOLER PTB0 #define DS18B20_PIN PTB1 #define VELOCIDAD D3 #define PULSADOR PTC1 #define PRESET PTC2 /*Definicion de Elementos*/ DS1820 probe(DS18B20_PIN); DigitalOut Rojo(LED1); DigitalOut Verde(LED2); DigitalOut Azul(LED3); DigitalOut RET(A3); PwmOut Cooler(EN_COOLER); InterruptIn velocidad(VELOCIDAD); AnalogIn Preset(PRESET); DigitalIn P(PULSADOR); /*MAQUINA DE ESTADOS CENTRAL*/ #define InicioSistema 0 #define LazoAbierto 1 #define LazoCerrado 2 #define VelocidadMaxima 3 /*Variables maquina de estado lazos*/ int Modo = 0; //Me avisa en que modo estoy : Lazo Abierto , Lazo Cerrado, Inicio Sistema y Velocidad maxima int ta = 0; //Acumulador de tiempo del Inicio Sistema void medicion_velocidad(void); int VMAX = 0; //Velocidad maxima del Cooler /*MAQUINA DE ESTADOS ANTI REBOTE*/ #define INICIO_P 0 #define RISING_P 1 #define RETENCION_P 2 bool antirrebote(bool lectura); int estado = 0;//Variable que guaarda el estado de la maquina de estados int tp = 0;//Acumulador de tiempo de la maquina void CambioDeModo(); //Funcion que me sirve para switchear entre los dos modos /*MAQUINA DE ESTADOS MEDICION VELOCIDAD*/ #define INCIO_V 0 #define V_1 1 #define V_2 2 #define ESPERA_V 3 //Interrupciones de deteccion de cambios en pin de medicion de valocidad void R_ton(); //Funcion relacionada a la interrupcion de deteccion de flancos ascendentes void F_ton(); //Funcion relacionada a la interrupcion de deteccion de flancos descendentes //Flags medicion de ancho de pulso bool em = 0; //Estoy midiendo bool tmv = 0; //Termine de medir int tv = 0; //Acumulacion de tiempo maquina control velocidad int EMV = 0; //Guardar estado medicion de velocidad float RPM = 0; //Guardo la velocidad /*MAQUINA DE ESTADOS CAMBIO DE DUTY */ #define INICIO_CM 0 #define CAMBIO_MAYOR 1 #define CAMBIO_MENOR 2 #define INICIO_CAMBIO_MENOR 5 #define ESPERA 3 #define ESPERA_FINAL 4 void cambio_gradual_duty(float obj);//Funcion que engloba la maquina de modificacion del duty , en especial la zona que no puedo enviar directamente.. int ty = 0; //Acumulador de tiempo int FTR = 0; //Control de estados de la submaquina bool tdm = 0; //Flag que me notifica cuando termine de cambiar el duty.. float cantv = 0; //Cantidad de veces que debo modificar el duty (funciona como entero) char jv = 0; //Cantidad de veces que modifique el duty float D = 1.00f; //Duty Actual void cambio_duty_pwm(float nuevoDuty); //Funcion que engloa la maquina /*MAQUINA DE ESTADOS LAZO CERRADO (DUTY EN FUNCION DE TEMPERATURA)*/ #define INICIO_LC 0 #define TEMPERATURA 1 #define MEDICION_RPM 2 #define CAMBIO_PWM 3 #define ESPERA_CPWM 4 #define ESPERA_LC 5 float NuevoDuty = 0; //Duty que voy enviando a forma de prueba y error.. void control_PWM_Temp(void); //Funcion que engloba la maquina de estados int CPT = 0; //Guardo el estado de la maquina int IM = 0; //Acumulador de tiempo base float duty = 0; //Guardo el duty actual /*VALORES DE CONFIGURACION LAZO CERRADO*/ #define DEFINICION_CAMBIO_PWM 0.01f //Resolucion de barrido, valores altos agilizan el cambio pero pueden hacer que nunca se alcance lo pedido.. #define MinRPM 500.0f //Minima velocidad establecida por el Cooler #define ToleranciaRPM 100.0f //Tolerancia de calculos en torno a la velocidad (Cuanto me puedo desviar de la regla de tres simple y considerarlo verdadero) /*RELACION DE REVOLUCIONES POR MINUTO EN FUNCION DE LA TEMPERATURA*/ /* 20ºC ==> 500rpm x ºC ==> x rpm */ /*ELEMENTOS GENERALES DEL SISTEMA*/ void leds(int num); /*Tickers*/ Ticker TiempoBase; Ticker TiempoRapido; void base_de_tiempo(); void tiempo_rapido(); /*Timmers*/ Timer ap; int main() { /*Apago Todos los LEDS*/ leds(0); printf("TRABAJO PRACTICO 1 : MAQUINAS DE ESTADO\r\n EJERCICIO 1\r\n ALUMNOS: FERNANDEZ SANZ Y CLERICI \r\n INICIANDO.............\r\n"); /*Attach Timmers*/ TiempoBase.attach(&base_de_tiempo, 0.5f); TiempoRapido.attach(&tiempo_rapido, 0.05f); /*Inicio PWM*/ Cooler.period(0.01f); //Establezco un periodo de 100mS para el PWM while(1) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /*Maquina de Estados Central del Sistema*/ switch(Modo) { //La primera vez arranco el motor al maximo y inicializo la medicion de velocidad.. case InicioSistema: Cooler.write(1); //Espero un tiempo para q arranque el motor if(ta > 5) { ta = 0; /*Attach Pin Interrupt del medidor de velocidad*/ velocidad.rise(&R_ton); velocidad.fall(&F_ton); printf("Termine de incializar....\r\n"); Modo = VelocidadMaxima; } break; //Mido la velocidad maxima del Cooler.. Lo setie al meximo en "InicioSistema" case VelocidadMaxima: medicion_velocidad(); break; //Mido el Preset y seteo el duty del Cooler en funcion de la lectura case LazoAbierto: float lec = Preset; cambio_gradual_duty(lec); break; //Mido la temperatura y establezco la velocidad del Cooler case LazoCerrado: control_PWM_Temp(); break; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Actualizo el pulsador... CambioDeModo(); RET = !RET; //Cambio el estado del pin de verificacion.. } } //Funcion utilizada para controlar los Leds On Board //IN ==> Combinacion Binaria de estados || OUT ==> Actualizacion estado de leds void leds(int num) { switch(num) { case 0: Rojo = 1; Verde = 1; Azul = 1; break; case 4: Rojo = 0; Verde = 1; Azul = 1; break; case 2: Rojo = 1; Verde = 0; Azul = 1; break; case 1: Rojo = 1; Verde = 1; Azul = 0; break; case 7: Rojo = 0; Verde = 0; Azul = 0; break; } } //Maquina de estados que elimina el Rebote de los pulsadores //IN ==> DigitalIn || OUT ==> Detector de flancos ascendentes del pulsador bool antirrebote(bool lectura) { static bool lecant = 0; switch(estado) { case INICIO_P: //Si tengo un flanco ascendente if((lectura == 1) && (lecant == 0)) { estado = RISING_P; } break; case RISING_P: /*Devuelvo el estado uno , una unica vez (Saco el rebote)*/ estado = RETENCION_P; tp = 0; return 1; //Devuelvo el estado alto ya que tuve un flanco case RETENCION_P: /*Durante un segundo y siempre que la lectura siga siendo alta retengo*/ if((tp >= 2) && (lectura == 0)) { estado = INICIO_P; } break; } lecant = lectura; //Asigno el estado previo para el proximo ciclo.. return 0; //Devuelvo el estado nulo o cero } //Funcion relacionada al timmer , es llamada cada 0.5 segundos void base_de_tiempo() { tp ++; //Acumulador Antirebote tv ++; //Acumulador Mediciond de velocidad ta ++; //Acumulador Inicio del sistema.. IM++; //Acumulador Lazo Cerrado } //Funcion del timmer dos, es llamada cada 0.05 segundos void tiempo_rapido() { ty ++; //Acumulador Cambio de Duty(Lazo Cerrado) } //Funcion dedicada a controlar el pulsador y analizar los cambios de modo.. void CambioDeModo() { /*Si tengo un flanco ascendente en el pulsador (Apretaron)*/ if(antirrebote(P)) { /*Switcheo entre MODO = 1 y MODO = 2 (LazoAbierto | LazoCerrado)*/ Modo ++; if(Modo > 2) { Modo = 1; printf("Lazo Abierto!!\r\n"); } FTR = 0; } } ///////////////////////////////////////////////////////////////////////////ETAPAS DE MEDICION DE VELOCIDAD/////////////////////////////////////////////////////////////////////////// /* UN PERIODO ==> RISE - FALL - RISE 2 PERIODOS ==> Una vuelta 60 seg ==> 1 minuto / tiempo que tardo en dar una vuelta ==> RPM */ /*LA MAQUINA DE ESTADOS SE SUBDIVIDE EN TRES FUNCIONES (2 INTERRUPCIONES + 1 FUNCION EN LA MAQUINA PRINCIPAL)*/ //Interrupcion relacionada al Rising.. void R_ton() { switch(EMV) { case INCIO_V: ap.reset(); //Reseteo el timmer ap.start(); //Inicio la cuenta em = 1; //Aviso que estoy midiendo tmv = 0; //Aviso que no termine de medir EMV = V_1; break; case V_1: printf("ERROR MIDIENDO VELOCIDAD, EMV = %d!!\r\n", EMV); break; case V_2: ap.stop(); //Freno el timmer tmv = 1; //Aviso que termine de medir em = 0; //Ya no estoy midiendo tv = 0; //Reinicio el acumulador de tiempo EMV = ESPERA_V; break; } } //Interrupcion relacionada a el falling.. void F_ton() { if(em) { switch(EMV) { case INCIO_V: printf("ERROR MIDIENDO VELOCIDAD, EMV = %d!!\r\n", EMV); break; case V_1: EMV = V_2; break; case V_2: printf("ERROR MIDIENDO VELOCIDAD, EMV = %d!!\r\n", EMV); break; } } } //Estado final de la maquina de estados //Aqui genero la cuenta de donde obtengo las RPM y espero el tiempo prudencial.. void medicion_velocidad(void) { if(EMV == ESPERA_V) { if(tv >= 1) { RPM = 60.00 / (ap.read() * 2); printf("Velocidad maxima = %f RPM\r\n",RPM); VMAX = RPM; tv = 0; EMV = INCIO_V; Modo = LazoAbierto; printf("Modo Lazo Abierto...!\r\n"); } } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Maquina LazoCerrado void control_PWM_Temp(void) { static float temperatura = 0; float val = 0; static bool suptempmax = 0; //Flag que me indica si ya puse al maximo el duty switch(CPT) { case INICIO_LC: Rojo = 1;//Apago el Led rojo.. Azul = 0;//Prendo el Led azuil... /*Fijo el duty en 50%*/ Cooler.write(0.5f); duty = 0.5f; printf("Lazo Cerrado!!\r\n"); CPT = TEMPERATURA; break; case TEMPERATURA: probe.convertTemperature(false, DS1820::all_devices); //Le digo que convierta la temperatura del sensor, false ==> No retiene || True ==> Retiene temperatura = probe.temperature(); //Guardo la temperatura printf("La temperatura es de %3.1foC\r\n",temperatura ); /*Si tengo mas de 70 grados directamente pongo la maxima velocidad*/ if(temperatura >= 70.00f) { /*Aviso que supere los 70ºC*/ if(!suptempmax) { printf("Supere los 70oC... Pongo el duty al maximo.. Dejo de medir RPM momentaneamente..\r\n"); suptempmax = 1; //Seteo el flag de superar los 70ºC } duty = 1.00f; //Registro el cambio de duty al maximo Cooler.write(1); //Ejecuto el cambio de duty al maximo IM = 0; //Reinicio el acumulador para tener el tiempo entre modificaciones.. CPT = ESPERA_LC; break; } else { /*Aviso que baje de los 70ºC*/ if(suptempmax) { printf("Baje de los 70oC... duty dinamico.. Vuelvo a medir RPM ..\r\n"); Cooler.write(0.5f); duty = 0.5f; CPT = ESPERA_LC; suptempmax = 0; //Reinicio el flag de superar los 70ºC } /*Reinicio la medicion de RPM*/ tv = 0; //Reinicio el acumulador de tiempo de la maquina de estados que mide velocidad EMV = INCIO_V; //Pongo en el estado inicial la maquina de medicion de velocidad IM = 0; //Pongo en cero el acumulador para darle un TimeOut a la medicion de velocidad CPT = MEDICION_RPM; //Paso a medir la velocidad del Cooler break; } case MEDICION_RPM: /*Si termine de medir la velocidad...*/ if(EMV == ESPERA_V) { if(tv >= 1) { RPM = 60.00 / (ap.read() * 2); //printf("Velocidad = %f RPM\r\n",RPM); tv = 0; EMV = INCIO_V; val = floor(temperatura * MinRPM / 20); printf("Deberia tener %f RPM y tengo %f RPM\r\n", val, RPM); /*Aca me fijo si debo modificar el duty*/ if(abs(RPM - val) > ToleranciaRPM) { /*Miro que duty debo enviar...*/ if(val < RPM) NuevoDuty = duty - DEFINICION_CAMBIO_PWM; if(val > RPM) NuevoDuty = duty + DEFINICION_CAMBIO_PWM; IM = 0; CPT = CAMBIO_PWM; break; } else { printf("EL duty es correcto! Estoy en %0.1f% :D\r\n", floor(duty * 100.0f)); IM = 0; CPT = ESPERA_LC; break; } } } /*Verifico que no se me apago el motor...*/ if(IM > 10) { printf("El cooler estaba apagadoo!!..Reiniciando Lazo cerrado..\r\n"); EMV = INICIO_LC; IM = 0; } break; case CAMBIO_PWM: cambio_gradual_duty(NuevoDuty); //Actualizo el duty, si el valor es menor a 50% hago un proceso especial.. /*Si termine de modificar el duty*/ if(tdm) { IM = 0; CPT = ESPERA_CPWM; } break; case ESPERA_CPWM: /*Si se cumplio un tiempo prudencial.. El motor se debe adecuar a la nueva velocidad*/ if(IM >= 2) { tdm = 0; //Reinicio el flag de cambio de duty EMV = 0; //Reinico la maquina de medicion de velocidad.. IM = 0; //Reinicio el acumulador de tiempo CPT = MEDICION_RPM; //Mido nuevamente la velocidad y me fijo si debo modificar denuevo break; } break; case ESPERA_LC: /*Si se cumplio el tiempo..*/ if(IM >= 1) CPT = TEMPERATURA; break; } } //Maquina de cambio de duty gradual.... void cambio_gradual_duty(float obj) { static float dtf = 0; //Variable que va a guardar durante todo el proceso el objetivo, es estatico... lo modifico en el estado inicial solamente.. switch(FTR) { case INICIO_CM: dtf = obj; //Fijo el nuevo objetivo... tdm = 0; //Aviso que estoy modificando el duty... //printf("Inicio el cambio de duty....\r\n"); //Rojo = 0; /*Si estoy por debajo del minimo del Cooler directamente lo apago...*/ if(dtf < 0.07f) { /*Apago el PWM*/ Cooler.write(0); duty = 0; //printf("Cooler APAGADO!\r\n"); /*Voy al final de la maquina*/ ty = 0; //Reinicio el acumulador de tiempo final... FTR = ESPERA_FINAL; Rojo = 1; break; } if(dtf >= 0.5f) { FTR = CAMBIO_MAYOR; } else FTR = INICIO_CAMBIO_MENOR; break; case CAMBIO_MAYOR: Cooler.write(dtf); //Coloco el nuevo valor en el PWM de una.. //printf("\tNuevo Duty = %f%\r\n", dtf * 100); duty = dtf; //Actualizo el duty actual.. ty = 0; //Reinicio el acumulador de tiempo base FTR = ESPERA_FINAL; break; case INICIO_CAMBIO_MENOR: cantv = abs( (int(duty*100)) - (int(dtf*100))); //Me fijo cuantos pasos intermedios voy a dar... //printf("\tVoy a hacer %.0f pasos intermedios desde %.0f para llegar a %.0f%\r\n", cantv, duty*100, dtf * 100); D = duty; //Parto desde el PWM actual jv = 0; //Reinico el acumulador de veces FTR = CAMBIO_MENOR; break; case CAMBIO_MENOR: /*La cantidad de pasos intermedios calculados en el estado anterior...*/ if(cantv >= jv) { Cooler.write(D); //Pongo el duty //printf("\t\tEtapa intermedia en %.0f%\r\n", D * 100.00f); /*Si quiero alcanzar un duty inferior*/ if(dtf < duty) D -= 0.01f; //Decremeto 1% /*Si quiero alcanzar un duty superior*/ if(dtf > duty) D += 0.01f; //Incremento 1% if(D < 0 || D > 1) { //Si estoy en valores no logicos... //printf("Valores de duty no logicos... ERORR!!!! D:\r\n"); FTR = INICIO_CM; break; } jv++; //Acumulo el paso realizo en la variable(Lo cuento).. ty = 0; //Reinicio el acumulador de tiempo FTR = ESPERA; //Espero un tiempo para que se ajuste la salida.. break; } /*Si termine con las modificaciones de duty..*/ else { //printf("\t\tNuevo Duty = %.0f\r\n", (D+0.01f)*100); duty = dtf; //Guardo el nuevo valor de duty ty = 0; //Reinicio el acumulador de tiempo base FTR = ESPERA_FINAL; //Paso a la espera final... } break; case ESPERA: /*Si se cumplio el tiempo*/ if(ty >= 1) { ty = 0; //Reinico el acumulador de tiempo FTR = CAMBIO_MENOR;//Paso al nuevo paso } break; case ESPERA_FINAL: /*Termine el proceso de cambio de duty*/ Rojo = 1; //Apago el led modificador.. tdm = 1; //Notifico a las otras maquinas de estado que termine de modificar el duty.. /*Si se cumplio el tiempo*/ if(ty >= 1) { ty = 0; //Reinicio el acumulador de tiempo FTR = INICIO_CM; //Vuelvo al estado inicial del proceso.. } break; } }