diff --git a/README.md b/README.md index 41ef5d64be99db3c31d84fef9c0e8691295dd3b3..7353c58d3db38ddee9ffdea98715d608ffdf23af 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # Medidor UV-C ## Requerimientos funcionales -Punteo de ideas. - ### Para prototipo 0 - medir radiación - reportar radiación instantanea @@ -14,18 +12,55 @@ Punteo de ideas. - switch para indicar presencia de bandeja con máscaras - leb blanco que enciende y apaga y buzzer para indicar fin de tiempo de desinfección - si se usa display 7 segmentos: - - normalmente muestra información relacionada con la desinfección: - - rayitas en el centro ----- si no se detecta la bandeja con máscaras - - cuenta regresiva con tiempo faltante para terminar desinfección - - un botón muestra la radiación instantanea medida al ser presionada. - - un botón reinicia la cuenta regresiva de desinfección. + - en una parte muestra información indicando si no hay bandeja o la cuenta regresiva + - en otra parte se muestra la radiación instantanea - si se usa un diplay tipo matriz de puntos - en una fila muestra información indicando si no hay bandeja o la cuenta regresiva - en otra fila se muestra la radiación instantanea - - un botón reinicia la cuenta regresiva de desinfección. -El funcionamiento es simple, cuando se detecta que se acciona el switch de presencia de mascara, calcula el tiempo necesario de desinfección de acuerdo a la radiación medida y +## Diagrama flujo prototipo 0 +''' +0. POWER_UP + Mide radiación + + Disp_power: <potencia_medida> + Disp_remain: <apagado> + -> Bandeja no presente: 1 + +1. NO_LOAD_PRESENT + Mide radiación (mW/cm2) + + Disp_power: <potencia_medida> + Disp_remain: <apagado> + + -> Insertan bandeja: 2 + +2. DOSE_CALCULATION + Tiempo dosis (s) = Dosis_objetivo (mJ/cm2) / radiación medida (mW/cm2) + + Disp_power: <potencia_medida> + Disp_remain: <apagado> + + -> Pasa a 3 + +3. DOSE_APPLY + Cuenta regresiva de tiempo transcurrido + + Disp_power: <potencia_medida> + Disp_remain: <cuenta_regresiva> + + -> Sacan bandeja : 1 + -> Cuenta llega a 0 : 4 + +4. DOSE_END + Alarma sonora y visual. + + Disp_power: <potencia_medida> + Disp_remain: <alterna entre 0000 y 8888> + + -> Sacan bandeja: 1 +''' ### Para versión con leds @@ -41,22 +76,29 @@ El funcionamiento es simple, cuando se detecta que se acciona el switch de prese ### Caja ### Plataforma - Arduino mini o ESP32 Pico + Arduino mini o ESP32 ### Sensor UV -#### Sensores que se consiguen en Uruguay. +#### Sensores que existen en Uruguay. -Interfaz analógico: ML8511 +Interfaz analógico: ML8511 **No hay stock*** https://www.robotec.com.uy/productos/S168 -Interfaz digital: VEML6075 +Interfaz digital: VEML6075 **No hay stock*** https://www.robotec.com.uy/productos/S281 #### Opciones a nivel mundial -GUVA-S12SD +Interfaz analógica: GUVA-S12SD +https://www.digikey.com/product-detail/en/genicom-co-ltd/GUVA-S12SD/2096-GUVA-S12SDCT-ND/9960959 ### Display +### Sensores de bandeja + +Magneticos para evitar roturas mecánicas. + +https://articulo.mercadolibre.com.uy/MLU-444040526-sensores-magneticos-para-puertas-ventanas-o-portones-_JM?quantity=1#position=2&type=item&tracking_id=e96d47ce-e028-47d7-acd5-4289fe7948e9 + ## Otros proyectos HYJEIA WIRELESS DOSIMETER: diff --git a/arduino/prototipo_0/uv_meter/uv_meter.ino b/arduino/prototipo_0/uv_meter/uv_meter.ino new file mode 100644 index 0000000000000000000000000000000000000000..4263c276697245fd82641b299f515c45528ff4ec --- /dev/null +++ b/arduino/prototipo_0/uv_meter/uv_meter.ino @@ -0,0 +1,313 @@ +/* Prototipo de medidor de radiación UV + * Sebastian Fernandez + * sebfer@fing.edu.uy + * + * Plataformas: + * - ESP32 de ESPRESSIF + * + * v0.1 + * + * + * LedControl library + * Instalarla y editar + * #include <avr/pgmspace.h> + * https://github.com/wayoda/LedControl + * + */ + +#include <pgmspace.h> + + +/* +Editar "LedControl.h" y cambiar +# include <avr\pgmspace.h> +por +#if (defined(__AVR__)) +# include <avr\pgmspace.h> +# else +# include <pgmspace.h> +# endif +*/ +#include "LedControl.h" // 8 digit 7 segment. MAX + +#include <WiFi.h> // WiFi control for ESP32 + + +/**************************************** + * Aplication parameters + ****************************************/ +// WiFi access point +#define WIFI_AP_NAME "este" +#define WIFI_PASSWORD "lapropia" + +// UV metering +int radiation_power_theorical = 20; // mW/cm2 +//int target_dose = 2500; // mJ/cm2 +int target_dose = 200; // mJ/cm2 + +// Main application loop delay +int quant = 100; //ms + +// Period of sending information +//int send_delay = 600000; //10min = 10*60*1000 ms +int send_delay = 1000; //1seg = 1000 ms + + +/**************************************** + * Platform parameters + ****************************************/ +// Main application loop timers +int quant_passed = 0; +//const int quants_per_sec = 1000 / quant; +const int quants_per_sec = 1000 / quant; + +// Baud rate for debug serial +#define SERIAL_DEBUG_BAUD 115200 + +// the Wifi radio's status +int status = WL_IDLE_STATUS; + +// 7 segment +LedControl lc=LedControl(12,27,14,1); +// pin 12 is connected to the DIN pin +// pin 27 is connected to the CLK pin +// pin 14 is connected to the CS pin +// 1 as we are only using 1 MAX7219 +char digitos_disp1[4] = {}; +char digitos_disp2[4] = {}; + +// alarma +const int alarm_led_pin = 26; +const int alarm_buz_pin = 25; +int alarm_state = LOW; + +// load detection +const int load_status_pin = 33; +int load_present = LOW; + +// Period of sending information +int send_passed = 0; // Time passed after data was sent, milliseconds. + + +// UV metering +int radiation_power = radiation_power_theorical; +int total_desinfection_time = target_dose/radiation_power ; // seconds +int remaining_desinfection_time = total_desinfection_time; + +// States +enum State_enum {POWER_UP, NO_LOAD_PRESENT, DOSE_CALCULATION, DOSE_APPLY, DOSE_END}; +uint8_t state = POWER_UP; + +/**************************************** + * SETUP + ****************************************/ +void setup() { +// Initialize serial for debugging + Serial.begin(SERIAL_DEBUG_BAUD); + +// the zero refers to the MAX7219 number, it is zero for 1 chip + lc.shutdown(0,false);// turn off power saving, enables display + lc.setIntensity(0,10);// sets brightness (0~15 possible values) + lc.clearDisplay(0);// clear screen + +// initialize alarm pins +pinMode(alarm_led_pin, OUTPUT); +ledcSetup(0,1E5,12); +ledcAttachPin(alarm_buz_pin,0); + +// init load sensor pin +pinMode(load_status_pin, INPUT); + +// Initialize Wifi +// Serial.println("==== wifi setup ===="); +// WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD); +// InitWiFi(); + +} + +/**************************************** + * MAIN LOOP + ****************************************/ + +void loop() { + delay(quant); + +switch(state) + { + /////////////////////////////////////// + case POWER_UP: + Serial.println("state: POWER_UP"); + if(loadPresent()==LOW){ + state = NO_LOAD_PRESENT; + } + + lc.clearDisplay(0); + // Get radiation power and show it. + radiation_power = getRadiationPower(); + snprintf(digitos_disp1,5,"%04d", radiation_power); + displayRadiationPower(digitos_disp1); + + break; + + /////////////////////////////////////// + case NO_LOAD_PRESENT: + Serial.println("state: NO_LOAD_PRESENT"); + if(loadPresent()==HIGH){ + state = DOSE_CALCULATION; + } + + lc.clearDisplay(0); + // Get radiation power and show it. + radiation_power = getRadiationPower(); + snprintf(digitos_disp1,5,"%04d", radiation_power); + displayRadiationPower(digitos_disp1); + + break; + + /////////////////////////////////////// + case DOSE_CALCULATION: + Serial.println("state: DOSE_CALCULATION"); + state = DOSE_APPLY; + + quant_passed = 0; + remaining_desinfection_time = total_desinfection_time; + + break; + + /////////////////////////////////////// + case DOSE_APPLY: + Serial.println("state: DOSE_APPLY"); + + quant_passed += 1; + + if (quant_passed >= quants_per_sec){ + remaining_desinfection_time -=1; + quant_passed = 0; + } + + if(loadPresent()==LOW){ + state = NO_LOAD_PRESENT; + } else if (remaining_desinfection_time == 0){ + state = DOSE_END; + quant_passed = 0; + alarm_state = LOW; + } + + // Get radiation power and show it. + radiation_power = getRadiationPower(); + snprintf(digitos_disp1,5,"%04d", radiation_power); + displayRadiationPower(digitos_disp1); + // Show remaining time + snprintf(digitos_disp2,5,"%04d", remaining_desinfection_time); + displayRemainingDesinfectionTime(digitos_disp2); + + break; + + /////////////////////////////////////// + case DOSE_END: + Serial.println("state: DOSE_END"); + + quant_passed += 1; + + if (quant_passed >= quants_per_sec){ + quant_passed = 0; + alarm_state = not(alarm_state); + + digitalWrite(alarm_led_pin, alarm_state); + if (alarm_state) { + ledcWriteTone(0,800); + snprintf(digitos_disp2,5,"%04d", 0); + displayRemainingDesinfectionTime(digitos_disp2); + } + else { + ledcWriteTone(0,0); + snprintf(digitos_disp2,5,"%04d", 8888); + displayRemainingDesinfectionTime(digitos_disp2); + } + + + } + + if(loadPresent()==LOW){ + state = NO_LOAD_PRESENT; + ledcWriteTone(0,0); + digitalWrite(alarm_led_pin, 0); + + } + + break; + } + // Reconnect to WiFi, if needed + /* + if (WiFi.status() != WL_CONNECTED) { + reconnect(); + return; + } + */ +} + + +/**************************************** + * AUX FUNCTIONS + ****************************************/ + +int loadPresent() +{ + // HIGH if load to germinize present + return digitalRead(load_status_pin); +} + +int getRadiationPower() +{ + return radiation_power_theorical; +} + +void displayRadiationPower(const char *chars4) { + //lc.clearDisplay(0); + //for (int i = 0; i < 5 && chars4[i] != 0; i++) { + for (int i = 0; i < 4; i++) { + lc.setChar(0, 7 - i, chars4[i], false); + } +} + +void displayRemainingDesinfectionTime(const char *chars4) { + //lc.clearDisplay(0); + for (int i = 0; i < 4; i++) { + Serial.print(i); + Serial.print("-->"); + Serial.println(chars4[i]); + lc.setChar(0, 3 - i, chars4[i], false); + } +} + + +void InitWiFi() +{ + Serial.println("Connecting to AP ..."); + // attempt to connect to WiFi network + + WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println("Connected to AP"); +} + +void reconnect() { + // Loop until we're reconnected + status = WiFi.status(); + if ( status != WL_CONNECTED) { + WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println("Connected to AP"); + } +} + +/**************************************** + * Trash + ****************************************/ +//lc.setRow(0,0,B00000001); // on g segment (center) diff --git a/hojas_datos/display_7seg/MAX7219-MAX7221.pdf b/hojas_datos/display_7seg/MAX7219-MAX7221.pdf new file mode 100644 index 0000000000000000000000000000000000000000..dd7a52ae090c02802e30d5875a280af3cfee79e7 Binary files /dev/null and b/hojas_datos/display_7seg/MAX7219-MAX7221.pdf differ diff --git a/hojas_datos/esp32_DevKit_v4/esp32_DevKit_v4-pinout.jpg b/hojas_datos/esp32_DevKit_v4/esp32_DevKit_v4-pinout.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2daca0d22607f32bf9c694bf71431c5ada66cd33 Binary files /dev/null and b/hojas_datos/esp32_DevKit_v4/esp32_DevKit_v4-pinout.jpg differ diff --git a/hojas_datos/nodemcu_esp32s/nodemcu_esp32_pin.jpg b/hojas_datos/nodemcu_esp32s/nodemcu_esp32_pin.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f817c5ebfc91070305d1b7deecee692d04416c80 Binary files /dev/null and b/hojas_datos/nodemcu_esp32s/nodemcu_esp32_pin.jpg differ diff --git a/recursos/esp-32s_pinout.jpg b/recursos/esp-32s_pinout.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fbc12b7910b2a5e613330f606b3e5998dcaa9e5b Binary files /dev/null and b/recursos/esp-32s_pinout.jpg differ