From a4dd3116817f35220dd2c616e78fa12ec8293b4e Mon Sep 17 00:00:00 2001 From: Jesenrique <117788977+Jesenrique@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:34:29 -0500 Subject: [PATCH 1/5] TP1 --- .mbed | 1 + README.md | 37 +++++- README.md.bak | 3 + main.cpp | 340 +++++++++++++++++++++++++++++++++++++++++++++++++- mbed-os.lib | 2 +- 5 files changed, 377 insertions(+), 6 deletions(-) create mode 100644 .mbed create mode 100644 README.md.bak diff --git a/.mbed b/.mbed new file mode 100644 index 0000000..e87b56d --- /dev/null +++ b/.mbed @@ -0,0 +1 @@ +ROOT=. diff --git a/README.md b/README.md index 6113ab9..326ca98 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,38 @@ # ArmBookCurso2024 -Primer ejemplo básico para aprender a usar las herramientas + +**Título:** Control de Sistema de Tratamiento de Agua + +**Alumno:** Jesús García + +**Objetivo:** Desarrollar un sistema que monitorice y controle un proceso de tratamiento de agua. + +**Descripción:** + +El sistema controlará el suministro y la producción de agua ultrapura a través de un sistema de tratamiento mediante ósmosis inversa. + +El usuario podrá: +- Encender y apagar el sistema. +- Controlar las presiones de corte mínimas y máximas para el encendido de las bombas de abastecimiento principal. +- Ajustar la frecuencia de funcionamiento de la bomba que proporciona presión a las membranas de filtración. + +Cuando el sistema está encendido, las bombas P1 y P2 funcionarán en condiciones normales. +- La bomba P1 está controlada por presiones mínima y máxima de funcionamiento. +- La bomba P2 está controlada por una presión mínima para evitar que funcione en vacío. + +La bomba P2 impulsa agua a presión a través de membranas para purificarla, y el agua tratada se almacena en un tanque con tres interruptores de nivel: +- **Level high:** Cuando se activa, indica que el tanque está lleno y apaga todas las bombas hasta que el nivel disminuya. +- **Level medium:** Permite iniciar la producción de agua desde este nivel. +- **Level low:** También permite iniciar la producción de agua desde este nivel. + +**Plataforma de desarrollo:** NUCLEO-144 + +**Periféricos a utilizar:** +- **USER BUTTON:** Para iniciar o apagar el sistema. +- **LED 1:** Indica el estado de funcionamiento del sistema. +- **ANALOG IN 1:** Emula un sensor de presión. +- **UART:** Se utiliza para enviar información sobre el estado del sistema a una PC. +- **DIGITAL IN:** Emula el interruptor de nivel alto ("level high"). +- **DIGITAL IN:** Emula el interruptor de nivel medio ("level medium"). +- **DIGITAL IN:** Emula el interruptor de nivel bajo ("level low"). + diff --git a/README.md.bak b/README.md.bak new file mode 100644 index 0000000..6113ab9 --- /dev/null +++ b/README.md.bak @@ -0,0 +1,3 @@ +# ArmBookCurso2024 + +Primer ejemplo básico para aprender a usar las herramientas diff --git a/main.cpp b/main.cpp index 21eabd5..fe40328 100644 --- a/main.cpp +++ b/main.cpp @@ -1,12 +1,344 @@ +//=====[Libraries]============================================================= #include "mbed.h" +//=====[Defines]=============================================================== +#define TIME_INCREMENT_MS 10 +#define TIME_BLINK_LED_SISTEM 1000 +#define TIME_CHECK_PRESSURE 1500 +#define TIME_SEND_DATA 3000 +#define DEBOUNCE_BUTTON_TIME_MS 40 +#define KEYPAD_NUMBER_OF_ROWS 4 +#define KEYPAD_NUMBER_OF_COLS 3 + +//=====[Declaration and initialization of public global objects]=============== +DigitalIn onOffButton(BUTTON1); +DigitalIn upButton(D0); +DigitalIn downButton(D1); +DigitalIn levelHighSensor(D2); +DigitalIn levelMediumSensor(D3); +DigitalIn levelLowSensor(D4); + +DigitalOut ledSistem(LED1); +DigitalOut pumpP1(LED2); +DigitalOut pumpP2(LED3); +DigitalOut buzzer(D7); + +UnbufferedSerial uartUsb(USBTX, USBRX, 115200); + +AnalogIn potentiometer(A0); + + +//=====[Declaration of public data types]====================================== + +typedef enum { + BUTTON_UP, + BUTTON_DOWN, + BUTTON_FALLING, + BUTTON_RISING +} onOffButtonState_t; + +typedef enum { + MATRIX_KEYPAD_SCANNING, + MATRIX_KEYPAD_DEBOUNCE, + MATRIX_KEYPAD_KEY_HOLD_PRESSED +} matrixKeypadState_t; + +//=====[Declaration and initialization of public global variables]============= +bool onOffStatus = false; +bool onOffStatusLed = false; +bool evento_boton = false; +int blinkLedSistem = 0; + +int timeCheckPressure=0; +int counterEventsBtnOff = 0; +int accumulatedDebounceButtonTime = 0; +int numberOfEnterButtonReleasedEvents = 0; +int timeAccumulatedSendData=0; +int timeAccumulatedCheckPressure=0; + + +onOffButtonState_t enterButtonState; + + +char buffer[50]; + +DigitalOut keypadRowPins[KEYPAD_NUMBER_OF_ROWS] = {PE_5, PE_6, PE_3, PF_8}; +DigitalIn keypadColPins[KEYPAD_NUMBER_OF_COLS] = {PF_7, PF_9, PG_1}; + +int accumulatedDebounceMatrixKeypadTime = 0; +char matrixKeypadLastKeyPressed = '\0'; +char matrixKeypadIndexToCharArray[] = { + '1', '2', '3', + '4', '5', '6', + '7', '8', '9', + '*', '0', '#', +}; +matrixKeypadState_t matrixKeypadState; + + +//=====[Declarations (prototypes) of public functions]========================= + +void inputsInit(); +void outputsInit(); + +void statusSistem(); +void statusLed(); +void debounceButtonInit(); +bool debounceButtonUpdate(); +float readPressureM1(); +void checkpressure(); +void statePump1(); + +void sendData(); +void availableCommands(); + +void matrixKeypadInit(); +char matrixKeypadScan(); +char matrixKeypadUpdate(); + +//=====[Main function, the program entry point after power on or reset]======== + int main() { - DigitalIn B1_USER(BUTTON1); + inputsInit(); + outputsInit(); + while (true) { + statusSistem(); + statusLed(); + checkpressure(); + sendData(); + HAL_Delay(TIME_INCREMENT_MS); + } +} - DigitalOut LD1(LED1); +//=====[Implementations of public functions]=================================== - while (true) { - LD1 = B1_USER; +void inputsInit() +{ + onOffButton.mode(PullDown); + upButton.mode(PullDown); + downButton.mode(PullDown); + levelHighSensor.mode(PullDown); + levelMediumSensor.mode(PullDown); + levelLowSensor.mode(PullDown); + debounceButtonInit(); + matrixKeypadInit(); +} + +void outputsInit() +{ + ledSistem = 0; + pumpP1 = false; + pumpP2 = 0; + buzzer =0; +} + +void statusSistem() +{ + evento_boton=debounceButtonUpdate(); + if (evento_boton){ + onOffStatus=!onOffStatus; + } + +} + +void statusLed() +{ + if (onOffStatus) + { + if(blinkLedSistem <= TIME_BLINK_LED_SISTEM){ + blinkLedSistem = blinkLedSistem+TIME_INCREMENT_MS; + } + else{ + blinkLedSistem=0; + ledSistem=!ledSistem; + } + } + else{ + ledSistem=0; + } +} + + +void sendData() +{ + if (timeAccumulatedSendData <= TIME_SEND_DATA){ + timeAccumulatedSendData=timeAccumulatedSendData+TIME_INCREMENT_MS; + } + else{ + int length = snprintf(buffer, sizeof(buffer), "La presión de entrada es: %.2f psi, ", readPressureM1()); + uartUsb.write(buffer, length); + int length1 = snprintf(buffer, sizeof(buffer), "el sistema esta: %s, \n\r", pumpP1 ? "encendido" : "apagado"); + uartUsb.write(buffer, length1); + timeAccumulatedSendData=0; + } +} + +void debounceButtonInit() +{ + if( onOffButton == 1) { + enterButtonState = BUTTON_DOWN; + } else { + enterButtonState = BUTTON_UP; + } +} + +bool debounceButtonUpdate() +{ + bool enterButtonReleasedEvent = false; + switch( enterButtonState ) { + + case BUTTON_UP: + if( onOffButton ) { + enterButtonState = BUTTON_FALLING; + accumulatedDebounceButtonTime = 0; + } + break; + + case BUTTON_FALLING: + if( accumulatedDebounceButtonTime >= DEBOUNCE_BUTTON_TIME_MS ) { + if( onOffButton ) { + enterButtonState = BUTTON_DOWN; + } else { + enterButtonState = BUTTON_UP; + } + } + accumulatedDebounceButtonTime = accumulatedDebounceButtonTime + + TIME_INCREMENT_MS; + break; + + case BUTTON_DOWN: + if( !onOffButton ) { + enterButtonState = BUTTON_RISING; + accumulatedDebounceButtonTime = 0; + } + break; + + case BUTTON_RISING: + if( accumulatedDebounceButtonTime >= DEBOUNCE_BUTTON_TIME_MS ) { + if( !onOffButton ) { + enterButtonState = BUTTON_UP; + enterButtonReleasedEvent = true; + } else { + enterButtonState = BUTTON_DOWN; + } + } + accumulatedDebounceButtonTime = accumulatedDebounceButtonTime + + TIME_INCREMENT_MS; + break; + + default: + debounceButtonInit(); + break; + } + return enterButtonReleasedEvent; + +} + + +void matrixKeypadInit() +{ + matrixKeypadState = MATRIX_KEYPAD_SCANNING; + int pinIndex = 0; + for (pinIndex = 0; pinIndex < KEYPAD_NUMBER_OF_COLS; pinIndex++) { + (keypadColPins[pinIndex]).mode(PullUp); + } +} + +char matrixKeypadScan() +{ + int row = 0; + int col = 0; + int i = 0; + + for( row=0; row= + DEBOUNCE_BUTTON_TIME_MS ) { + keyDetected = matrixKeypadScan(); + if( keyDetected == matrixKeypadLastKeyPressed ) { + matrixKeypadState = MATRIX_KEYPAD_KEY_HOLD_PRESSED; + } else { + matrixKeypadState = MATRIX_KEYPAD_SCANNING; + } + } + accumulatedDebounceMatrixKeypadTime = + accumulatedDebounceMatrixKeypadTime + TIME_INCREMENT_MS; + break; + + case MATRIX_KEYPAD_KEY_HOLD_PRESSED: + keyDetected = matrixKeypadScan(); + if( keyDetected != matrixKeypadLastKeyPressed ) { + if( keyDetected == '\0' ) { + keyReleased = matrixKeypadLastKeyPressed; + } + matrixKeypadState = MATRIX_KEYPAD_SCANNING; + } + break; + + default: + matrixKeypadInit(); + break; + } + return keyReleased; +} + + +float readPressureM1() { + float analogValue = potentiometer.read(); + float voltagePsi= (analogValue * 3.3)*30; + float pressureM1=voltagePsi; + + return pressureM1; +} + +void checkpressure() { + //verifica presion cada 1.5 seg + if (timeAccumulatedCheckPressure <= TIME_CHECK_PRESSURE){ + timeAccumulatedCheckPressure=timeAccumulatedCheckPressure+TIME_INCREMENT_MS; + } + else{ + int valuePressureM1 = readPressureM1(); + + if (valuePressureM1 <= 5) { + pumpP1 = false; + } else if (valuePressureM1 >= 6 && valuePressureM1 <= 75) { + pumpP1 = true; + } else { + pumpP1 = false; + } + timeAccumulatedCheckPressure=0; } } diff --git a/mbed-os.lib b/mbed-os.lib index 27e1338..91bb263 100644 --- a/mbed-os.lib +++ b/mbed-os.lib @@ -1 +1 @@ -https://github.com/ARMmbed/mbed-os.git#26606218ad9d1ee1c8781aa73774fd7ea3a7658e +https://github.com/ARMmbed/mbed-os.git#17dc3dc2e6e2817a8bd3df62f38583319f0e4fed \ No newline at end of file From ca1d2dbd5b0b44d0dc10f31c406f9b523abfc39b Mon Sep 17 00:00:00 2001 From: Jesenrique <117788977+Jesenrique@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:43:25 -0500 Subject: [PATCH 2/5] Update README.md --- README.md | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 326ca98..27a51d2 100644 --- a/README.md +++ b/README.md @@ -11,19 +11,12 @@ El sistema controlará el suministro y la producción de agua ultrapura a través de un sistema de tratamiento mediante ósmosis inversa. -El usuario podrá: -- Encender y apagar el sistema. -- Controlar las presiones de corte mínimas y máximas para el encendido de las bombas de abastecimiento principal. -- Ajustar la frecuencia de funcionamiento de la bomba que proporciona presión a las membranas de filtración. +Entrega TP1 +- Encender y apagar el sistema, en este caso ya se habia implementado maquina de estado para ese control por que se evidenció problema de rebote y era muy dificil poder prender o apagar el sistema. el Led1 es el indicador de este servicio. +- Controlar las presiones de corte mínimas y máximas para el encendido de las bombas de abastecimiento principal, este item se esta emulando con un potenciometro y se realiza una conversión sencilla que me permite obtener la presión de entrada en PSI y prender o apagar la bomba P1 según la presiones altas y bajas configuradas para apagar el sistema, el monitoreo se realiza cada 1.5 segundos, evitando ser bloqueante. +- Ajustar la frecuencia de funcionamiento de la bomba que proporciona presión a las membranas de filtración. Se ha implementado una maquina de estado para el manejo de un teclado 4x3, todavia no se ha implementado. +- Envio por UART, de momento se esta enviando cada 3 segundos el estado del sistema y la presión actual del sistema. -Cuando el sistema está encendido, las bombas P1 y P2 funcionarán en condiciones normales. -- La bomba P1 está controlada por presiones mínima y máxima de funcionamiento. -- La bomba P2 está controlada por una presión mínima para evitar que funcione en vacío. - -La bomba P2 impulsa agua a presión a través de membranas para purificarla, y el agua tratada se almacena en un tanque con tres interruptores de nivel: -- **Level high:** Cuando se activa, indica que el tanque está lleno y apaga todas las bombas hasta que el nivel disminuya. -- **Level medium:** Permite iniciar la producción de agua desde este nivel. -- **Level low:** También permite iniciar la producción de agua desde este nivel. **Plataforma de desarrollo:** NUCLEO-144 @@ -32,7 +25,5 @@ La bomba P2 impulsa agua a presión a través de membranas para purificarla, y e - **LED 1:** Indica el estado de funcionamiento del sistema. - **ANALOG IN 1:** Emula un sensor de presión. - **UART:** Se utiliza para enviar información sobre el estado del sistema a una PC. -- **DIGITAL IN:** Emula el interruptor de nivel alto ("level high"). -- **DIGITAL IN:** Emula el interruptor de nivel medio ("level medium"). -- **DIGITAL IN:** Emula el interruptor de nivel bajo ("level low"). + From 4254e000513550ab9447bd8049e8067334248c70 Mon Sep 17 00:00:00 2001 From: Jesenrique <117788977+Jesenrique@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:13:42 -0500 Subject: [PATCH 3/5] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 27a51d2..1600271 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,13 @@ El sistema controlará el suministro y la producción de agua ultrapura a través de un sistema de tratamiento mediante ósmosis inversa. Entrega TP1 -- Encender y apagar el sistema, en este caso ya se habia implementado maquina de estado para ese control por que se evidenció problema de rebote y era muy dificil poder prender o apagar el sistema. el Led1 es el indicador de este servicio. -- Controlar las presiones de corte mínimas y máximas para el encendido de las bombas de abastecimiento principal, este item se esta emulando con un potenciometro y se realiza una conversión sencilla que me permite obtener la presión de entrada en PSI y prender o apagar la bomba P1 según la presiones altas y bajas configuradas para apagar el sistema, el monitoreo se realiza cada 1.5 segundos, evitando ser bloqueante. -- Ajustar la frecuencia de funcionamiento de la bomba que proporciona presión a las membranas de filtración. Se ha implementado una maquina de estado para el manejo de un teclado 4x3, todavia no se ha implementado. -- Envio por UART, de momento se esta enviando cada 3 segundos el estado del sistema y la presión actual del sistema. +- Encender y apagar el sistema: en este caso ya se habia implementado maquina de estado para ese control por que se evidenció problema de rebote y era muy dificil poder prender o apagar el sistema. el Led1 es el indicador de este servicio. +- Controlar las presiones de corte mínimas y máximas para el encendido de las bombas de abastecimiento principal: este item se esta emulando con un potenciometro y se realiza una conversión sencilla que me permite obtener la presión de entrada en PSI y prender o apagar la bomba P1 según la presiones altas y bajas configuradas para apagar el sistema, el monitoreo se realiza cada 1.5 segundos, para evitar que sea bloqueante se uso un retardo de 10 milisegundos y se usó una variable de acumulación de tiempo hasta legar a los 1.5 segundos. +- Ajustar la frecuencia de funcionamiento de la bomba que proporciona presión a las membranas de filtración: se ha implementado una maquina de estado para el manejo de un teclado 4x3, todavia no se ha implementado. +- Envío por UART: de momento se esta enviando cada 3 segundos el estado y la presión actual del sistema. -**Plataforma de desarrollo:** NUCLEO-144 +**Plataforma de desarrollo:** NUCLEO-F767ZI **Periféricos a utilizar:** - **USER BUTTON:** Para iniciar o apagar el sistema. From f75aca38068a5e21e02eeba5c3b3e602bd02abf8 Mon Sep 17 00:00:00 2001 From: Jesenrique <117788977+Jesenrique@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:15:31 -0500 Subject: [PATCH 4/5] correcciones sugeridas --- main.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/main.cpp b/main.cpp index fe40328..e34cdab 100644 --- a/main.cpp +++ b/main.cpp @@ -3,12 +3,12 @@ //=====[Defines]=============================================================== #define TIME_INCREMENT_MS 10 -#define TIME_BLINK_LED_SISTEM 1000 +#define TIME_BLINK_LED_SYSTEM 1000 #define TIME_CHECK_PRESSURE 1500 #define TIME_SEND_DATA 3000 #define DEBOUNCE_BUTTON_TIME_MS 40 -#define KEYPAD_NUMBER_OF_ROWS 4 -#define KEYPAD_NUMBER_OF_COLS 3 +#define KEYPAD_NUMBER_OF_ROWS 4 +#define KEYPAD_NUMBER_OF_COLS 3 //=====[Declaration and initialization of public global objects]=============== DigitalIn onOffButton(BUTTON1); @@ -18,7 +18,7 @@ DigitalIn levelHighSensor(D2); DigitalIn levelMediumSensor(D3); DigitalIn levelLowSensor(D4); -DigitalOut ledSistem(LED1); +DigitalOut ledSystem(LED1); DigitalOut pumpP1(LED2); DigitalOut pumpP2(LED3); DigitalOut buzzer(D7); @@ -47,7 +47,7 @@ typedef enum { bool onOffStatus = false; bool onOffStatusLed = false; bool evento_boton = false; -int blinkLedSistem = 0; +int blinkLedSystem = 0; int timeCheckPressure=0; int counterEventsBtnOff = 0; @@ -56,6 +56,9 @@ int numberOfEnterButtonReleasedEvents = 0; int timeAccumulatedSendData=0; int timeAccumulatedCheckPressure=0; +int pressureCutIn_P1 = 5; +int pressureCutOff_P1 = 80; + onOffButtonState_t enterButtonState; @@ -81,7 +84,7 @@ matrixKeypadState_t matrixKeypadState; void inputsInit(); void outputsInit(); -void statusSistem(); +void statusSystem(); void statusLed(); void debounceButtonInit(); bool debounceButtonUpdate(); @@ -103,7 +106,7 @@ int main() inputsInit(); outputsInit(); while (true) { - statusSistem(); + statusSystem(); statusLed(); checkpressure(); sendData(); @@ -127,13 +130,13 @@ void inputsInit() void outputsInit() { - ledSistem = 0; + ledSystem = 0; pumpP1 = false; pumpP2 = 0; buzzer =0; } -void statusSistem() +void statusSystem() { evento_boton=debounceButtonUpdate(); if (evento_boton){ @@ -146,16 +149,16 @@ void statusLed() { if (onOffStatus) { - if(blinkLedSistem <= TIME_BLINK_LED_SISTEM){ - blinkLedSistem = blinkLedSistem+TIME_INCREMENT_MS; + if(blinkLedSystem <= TIME_BLINK_LED_SYSTEM){ + blinkLedSystem = blinkLedSystem+TIME_INCREMENT_MS; } else{ - blinkLedSistem=0; - ledSistem=!ledSistem; + blinkLedSystem=0; + ledSystem=!ledSystem; } } else{ - ledSistem=0; + ledSystem=0; } } @@ -168,7 +171,7 @@ void sendData() else{ int length = snprintf(buffer, sizeof(buffer), "La presión de entrada es: %.2f psi, ", readPressureM1()); uartUsb.write(buffer, length); - int length1 = snprintf(buffer, sizeof(buffer), "el sistema esta: %s, \n\r", pumpP1 ? "encendido" : "apagado"); + int length1 = snprintf(buffer, sizeof(buffer), "el Systema esta: %s, \n\r", pumpP1 ? "encendido" : "apagado"); uartUsb.write(buffer, length1); timeAccumulatedSendData=0; } @@ -332,9 +335,9 @@ void checkpressure() { else{ int valuePressureM1 = readPressureM1(); - if (valuePressureM1 <= 5) { + if (valuePressureM1 <= pressureCutIn_P1) { pumpP1 = false; - } else if (valuePressureM1 >= 6 && valuePressureM1 <= 75) { + } else if (valuePressureM1 > pressureCutIn_P1 && valuePressureM1 <= pressureCutOff_P1) { pumpP1 = true; } else { pumpP1 = false; From 4bbb03d4be183819a239e42978f9849a13675bf3 Mon Sep 17 00:00:00 2001 From: Jesenrique <117788977+Jesenrique@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:15:57 -0500 Subject: [PATCH 5/5] correcciones sugeridas