![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
Version Final
Diff: main.cpp
- Revision:
- 5:f12c0d64518f
- Parent:
- 3:f483abe4bc57
- Child:
- 6:75b0f24dad9b
--- a/main.cpp Fri Jan 13 18:30:37 2017 +0000 +++ b/main.cpp Wed Jun 05 01:27:43 2019 +0000 @@ -1,49 +1,645 @@ -#define MULTIPLE_PROBES -#define DATA_PIN A0 +/* +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 -#ifdef MULTIPLE_PROBES +*/ +/*Librerias*/ #include "mbed.h" #include "DS1820.h" -#define MAX_PROBES 16 - -DS1820* probe[MAX_PROBES]; - -int main() { - // Initialize the probe array to DS1820 objects - int num_devices = 0; - while(DS1820::unassignedProbe(DATA_PIN)) { - probe[num_devices] = new DS1820(DATA_PIN); - num_devices++; - if (num_devices == MAX_PROBES) + +/*Definicion Pines*/ +#define EN_COOLER PTB0 +#define DS18B20_PIN PTB1 +#define VELOCIDAD D3 +#define PULSADOR A5 +#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 RISE_1 1 +#define FALL_1 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 (LAZO ABIERTO)*/ + +#define INICIO_CM 0 +#define CAMBIO_MAYOR 1 +#define CAMBIO_MENOR 2 +#define INICIO_CAMBIO_MENOR 5 +#define ESPERA_DECREMENTO 3 +#define ESPERA_FINAL 4 + +int tcd = 0; //Acumulador de tiempo +int ECM = 0; //Guardo el estado de la maquina +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 +float DAN = 0.5f;//Duty Anterior + +void cambio_duty_pwm(float nuevoDuty); //Funcion que engloa la maquina + + +/*MAQUINA DE ESTADOS LAZO CERRADO (DUTY EN FUNCION DE TEMPERATURA)*/ + +#define INCIO_LAZOCERRADO 0 +#define MEDICION_TEMPERATURA 1 +#define MEDICION_RPM 2 +#define CAMBIO_PWM 3 +#define ESPERA_CAMBIOS_PWM 4 +#define ESPERA_ENTRE_MODIFICACIONES 5 + +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 + +/*SubMaquina utilizada para modificar el duty*/ +int FTR = 0; //Control de estados de la submaquina +bool tdm = 0; //Flag que me notifica cuando termine de cambiar el duty.. + +float NuevoDuty = 0; //Duty que voy enviando a forma de prueba y error.. + +/*VALORES DE CONFIGURACION LAZO CERRADO*/ +#define DEFINICION_CAMBIO_PWM 0.02f //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 +*/ + +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 + + +/*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_duty_pwm(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; } - - printf("Found %d device(s)\r\n\n", num_devices); - while(1) { - probe[0]->convertTemperature(true, DS1820::all_devices); //Start temperature conversion, wait until ready - for (int i = 0; i<num_devices; i++) - printf("Device %d returns %3.1foC\r\n", i, probe[i]->temperature()); - printf("\r\n"); - wait(1); +} + +//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; + } + tp = 0; + break; + case RISING_P: + estado = RETENCION_P; + tp = 0; + return 1; + case RETENCION_P: + if((tp >= 2) && (lectura == 0)) { + estado = INICIO_P; + } + break; } - + lecant = lectura; + return 0; +} + +//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 } -#else -#include "mbed.h" -#include "DS1820.h" - -DS1820 probe(DATA_PIN); - -int main() { - while(1) { - probe.convertTemperature(true, DS1820::all_devices); //Start temperature conversion, wait until ready - printf("It is %3.1foC\r\n", probe.temperature()); - wait(1); +//Funcion del timmer dos, es llamada cada 0.05 segundos +void tiempo_rapido() +{ + tcd ++;//Acumulador Cambio de Duty(Lazo Abierto) + ty ++; //Acumulador Cambio de Duty(Lazo Cerrado) +} + +//Funcion dedicada a controlar el pulsador y analizar los cambios de modo.. +void CambioDeModo() +{ + if(antirrebote(P)) { + Modo ++; + if(Modo > 2) { + Modo = 1; + printf("Lazo Abierto!!\r\n"); + } + } +} + +//Inicio la medicion del tiempo de On del pulso +void R_ton() +{ + switch(EMV) { + case INCIO_V: + ap.reset(); + ap.start(); + em = 1; + tmv = 0; + EMV = RISE_1; + break; + + case RISE_1: + printf("ERROR MIDIENDO VELOCIDAD, EMV = %d!!\r\n", EMV); + break; + + case FALL_1: + ap.stop(); + tmv = 1; + em = 0; + tv = 0; + EMV = ESPERA_V; + break; + } } -#endif \ No newline at end of file +void F_ton() +{ + if(em) { + switch(EMV) { + case INCIO_V: + printf("ERROR MIDIENDO VELOCIDAD, EMV = %d!!\r\n", EMV); + break; + case RISE_1: + EMV = FALL_1; + break; + case FALL_1: + printf("ERROR MIDIENDO VELOCIDAD, EMV = %d!!\r\n", EMV); + break; + } + } + +} + +void cambio_duty_pwm(float nuevoDuty) +{ + static float ND = 0; + + switch(ECM) { + case INICIO_CM: + + ND = nuevoDuty; + Azul = 1; //Apago el indicador de LazoCerrado + + //Me fijo si estoy por poner mas o menos el mismo duty para evitar el proceso + if(abs(ND * 100.00f - DAN * 100.00f ) < 2) { + //printf("El duty es el mismo del ciclo previo...\r\n"); + tcd = 0; + ECM = ESPERA_FINAL; + break; + } + + printf("Inicio el cambio de duty....\r\n"); + Rojo = 0; + tcd = 0; + if(ND < 0.07f) { + Cooler.write(0); + duty = 0; + printf("Cooler APAGADO!\r\n"); + tcd = 0; + DAN = 0.5f; + ECM = ESPERA_FINAL; + Rojo = 1; + break; + } + if(ND >= 0.5f) { + ECM = CAMBIO_MAYOR; + } else + ECM = INICIO_CAMBIO_MENOR; + break; + case CAMBIO_MAYOR: + Cooler.write(ND); + printf("\tNuevo Duty = %f%\r\n", ND* 100); + DAN = ND; + tcd = 0; + ECM = ESPERA_FINAL; + break; + case INICIO_CAMBIO_MENOR: + cantv = abs( (int(DAN*100)) - (int(ND*100))); + printf("\tVoy a hacer %.0f pasos intermedios desde %.0f para llegar a %.0f%\r\n", cantv, DAN*100, ND * 100); + ECM = CAMBIO_MENOR; + jv = 0; + D = DAN; + break; + case CAMBIO_MENOR: + if(cantv >= jv) { + Cooler.write(D); + printf("\t\tEtapa intermedia en %.0f%\r\n", D * 100.00f); + /*Si quiero alcanzar un duty inferior*/ + if(ND < DAN) + D -= 0.01f; //Decremeto 1% + /*Si quiero alcanzar un duty superior*/ + if(ND > DAN) + D += 0.01f; //Incremento 1% + tcd = 0; + ECM = ESPERA_DECREMENTO; + jv++; + break; + } else { + tcd = 0; + ECM = ESPERA_FINAL; + printf("\t\tNuevo Duty = %.0f\r\n", floor(ND*100.00f)); + DAN = ND; + } + break; + case ESPERA_DECREMENTO: + if(tcd >= 2) { + ECM = CAMBIO_MENOR; + tcd = 0; + } + break; + case ESPERA_FINAL: + Rojo = 1; + if(tcd >= 100) { + ECM = INICIO_CM; + tcd = 0; + } + break; + } + +} + +//Maquina LazoCerrado +void control_PWM_Temp(void) +{ + static float temperatura = 0; + float val = 0; + switch(CPT) { + case INCIO_LAZOCERRADO: + ECM = 0; //Reincio la maquina de cambio de duty de lazo abierto.. + 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 = MEDICION_TEMPERATURA; + break; + + case MEDICION_TEMPERATURA: + probe.convertTemperature(false, DS1820::all_devices); + temperatura = probe.temperature(); + printf("La temperatura es de %3.1foC\r\n",temperatura ); + /*Reinicio la medicion de RPM*/ + CPT = MEDICION_RPM; + tv = 0; + 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 + 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_ENTRE_MODIFICACIONES; + break; + + } + + } + } + /*Verifico que no se me apago el motor...*/ + if(IM > 10) { + printf("El cooler estaba apagadoo!!..Reiniciando Lazo cerrado..\r\n"); + EMV = INCIO_LAZOCERRADO; + IM = 0; + } + + break; + + case CAMBIO_PWM: + cambio_gradual_duty(NuevoDuty); + /*Si termine de modificar el duty*/ + if(tdm) { + IM = 0; + CPT = ESPERA_CAMBIOS_PWM; + } + break; + + case ESPERA_CAMBIOS_PWM: + /*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_ENTRE_MODIFICACIONES: + if(IM >= 1) + CPT = MEDICION_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_DECREMENTO; //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_DECREMENTO: + /*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; + } +} + +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"); + } + } +} \ No newline at end of file