Skip to content

brayanftobonc/purificador-de-agua-via-ubidots

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 

Repository files navigation

Overview

Purpose and Scope

This document provides a high-level introduction to the water purification control system implemented in the Arduino-based codebase. The system monitors water quality and manages the transfer of water between two tanks using automated pump control. This overview covers the system's purpose, key components, operational flow, and how the software architecture maps to physical hardware.

For detailed information about specific subsystems, refer to:

  • Hardware pin assignments and electrical connections: Hardware Architecture
  • Software implementation details: Hardware Components
  • Software architecture and design patterns: Software Architecture
  • Configuration parameters and calibration: Configuration Reference

Sources: purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 1-345

System Purpose

The water purification control system automates the operation of a dual-tank water management system with the following objectives:

  1. Water Quality Monitoring: Continuously measures pH to ensure water quality remains within safe parameters (7.5-9.0 pH)
  2. Automated Pump Control: Manages water transfer from Tank 1 (source) to Tank 2 (storage) based on level sensors
  3. Safety Enforcement: Implements turbid water override that disables pumping when pH is out of acceptable range
  4. Real-time Monitoring: Provides local LCD display and cloud telemetry via Ubidots IoT platform
  5. Flow Measurement: Tracks water flow rate and frequency for system performance monitoring

The system executes as a single Arduino sketch on an Arduino Mega, interfacing with multiple sensors, a relay-controlled pump, an LCD display, and an external WiFi telemetry gateway.

Sources: purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 198-248

Key Components and Code Entities

The following table maps physical system components to their corresponding code entities in the implementation:

Componente Code Entity Type Purpose
pH Sensor A1 pin, ph variable Analog Input Water quality measurement (7.5-9.0 range)
Tank 1 Upper Float FLOTADOR_ALTO (D7) Digital Input Tank 1 high water level detection
Tank 1 Lower Float FLOTADOR_BAJO (D6) Digital Input Tank 1 low water level detection
Tank 2 Lower Float Nivel_T2 (A0), lvltanque Analog Input Continuous Tank 2 fill level (0-100%)
Flow Sensor YF-S201 sensorPin (D3), ISRCountPulse() Interrupt Input Water flow frequency measurement
Motor Relay MOTOR_RELAY (D4), M variable Digital Output Pump ON/OFF control
Status LED ledverde1 (D5) Digital Output Visual operation indicator
LCD Display u8g2 object, draw() function SPI Interface Local real-time data visualization
WiFi Telemetry Serial1, Ubidots protocol UART Interface Cloud data transmission

Sources: purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 18-22 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 27-28 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 42-47

System Architecture with Code Mapping

flowchart LR
 subgraph PL["Physical Layer"]
        T1["Tank 1 (Source Water)"]
        T2["Tank 2 (Purifier Storage)"]
        n1["Water Pump"]
  end
 subgraph SL["Sensor Layer (Pin Assignaments)"]
        FLS1["FLOTADOR_BAJO- Pin D6"]
        FLS2["FLOTADOR_ALTO - Pin D7"]
        pHSensor["pH Sensor Pin A1 buffer_arr[10]"]
        FlowSensor["Nivel_T2 Pin A0 CANTIDAD variable"]
        NexT_DS["Flow Sensor Pin D3 ISRCountPulse()"]
  end
 subgraph AL["Actuator Layer"]
        Relay["MOTOR_RELAY - Pin D4"]
        Pump["ledverde1 Pin D5"]
  end
 subgraph PC["Processing Core"]
        DataAcq["digitalRead()[165-166] FLOTADOR_A/B"]
        TankStatus["pH Median Filter [136-162] avgval calculation"]
        Validation["pH Validation [198] 7.5 < ph < 9"]
        ControlLogic["Turbid Override [242-248] T=000, M=000"]
        OutputMgmt["Tank Level States [200-240] 6 decision branches"]
        Debug["digitalWrite(MOTOR_RELAY) [202-239] M variable"]
        n2["sprintf(command)[261-270] POST format"]
        n3["draw() Function [305-345] u8g2 rendering"]
        n4["analogRead(nivel_T2) [167-172] porcentajet1"]
        n5["GetFrequency() [175-178] frequency, flow_Lmin"]
        n6["loop() Function[121-303]"]
  end
 subgraph CL["Communication Layer"]
        WiFiMod["Serial1 (Telemetry) 115200 baud"]
        MQTT["Serial (USB) 115200 baud"]
        HTTP["u8g2 Object U8G2_ST920_128X64 SPI Pins 10,8"]
  end
 subgraph EXT["External Systems / Cloud"]
        SmartDashboard["WiFi Gateway Command Parser"]
        IoTCloud["Ubidots Cloud DEVICE_LABEL: IOT_Control"]
  end
    T1 --> FLS1 & FLS2 & pHSensor
    FLS1 --> DataAcq
    FLS2 --> DataAcq
    pHSensor --> TankStatus
    DataAcq --> OutputMgmt
    TankStatus --> n2 & Validation & n3
    Validation -- Invalid --> ControlLogic
    Validation -- Valid --> OutputMgmt
    ControlLogic --> Debug
    OutputMgmt --> Debug & n2
    Debug --> n3 & n2 & Relay
    Relay --> n1
    n1 --> T2
    n1 -.-> NexT_DS
    T2 -.-> FlowSensor
    FlowSensor --> n4
    NexT_DS --> n5
    n5 --> n3 & n2
    n4 --> n2 & n3 & OutputMgmt
    n2 --> WiFiMod
    n3 --> HTTP
    MQTT -.-> n6
    IoTCloud <-- HTTP POST --> SmartDashboard
    SmartDashboard <-- flow_control flag --> WiFiMod
    n1@{ shape: rect}
    n2@{ shape: rect}
    n3@{ shape: rect}
    n4@{ shape: rect}
    n5@{ shape: rect}
    n6@{ shape: rect}
Loading

Sources: purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 121-303 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 18-22 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 42-47

Main Execution Flow

The system operates in a continuous cycle within the loop() function. The following diagram illustrates the execution sequence with specific function calls and code references:

flowchart LR

loopEntryLine121[loop Entry Line 121]
digitalWriteledverde1,HIGH123[digitalWrite ledverde1, HIGH Line 123]
delay3000124[delay 3000 Line 124]
digitalWriteledver1LOW125[digitalWrite ledver1, LOW Line 125]
flow_controltrue132{flow_control = true Line 132}


    subgraph Sensor Acquisition Block
        direction TB
        forloop:10samples136-140analogReadA1[for loop: 10 samples Lines 136-140 analogRead A1]
        Bubblesortbuffer_arr141-152[Bubble sort buffer_arr Lines 141-152]
        CalculatepH154-159-5.7*volt+calibration_value[Calculate pH Lines 154-159 -5.7*volt + calibration_value]        
        digitalReadFLOTADOR_ALTO/BAJO165-166[digitalRead FLOTADOR_ALTO/BAJO Lines 165-166]        
        analogReadNivel_T2167porcentajet1CANTIDAD/1023*100[analogRead Nivel_T2 Line 167 porcentajet1 = CANTIDAD/1023*100]        
        GetFrecuency1752.5sinterruptcount[GetFrecuency Line 175 2.5s interrupt count]        
        flow_Lminfrequency/factorK176[flow_Lminfrequency/factorK176]
    end

u8g2.firstPagedo-whileloop190-194callsdraw[u8g2.first Page do-while loop Lines 190-194 calls draw]
ph750&&ph918{ph > 750 > && < ph Line 918}

    subgraph Tank Level Decision Tree
        direction TB
        FLOTADOR_A0FLOTADOR_B0200{FLOTADOR_A = 0 FLOTADOR_B = 0 Line 200}
        FLOTADOR_A0FLOTADOR_B1207CANTIDAD110{FLOTADOR_A = 0 FLOTADOR_B = 1 CANTIDAD < 110 Line 207}
        FLOTADOR_A0FLOTADOR_B1214CANTIDAD500{FLOTADOR_A = 0 FLOTADOR_B = 1 CANTIDAD > 500 Line 214}
        FLOTADOR_A1FLOTADOR_B0221{FLOTADOR_A = 1 FLOTADOR_B = 0 Line 221}
        FLOTADOR_A1FLOTADOR_B1228CANTIDAD500{FLOTADOR_A = 1 FLOTADOR_B = 1 CANTIDAD > 500 Line 228}
        FLOTADOR_A1FLOTADOR_B1235CANTIDAD110{FLOTADOR_A = 1 FLOTADOR_B = 1 CANTIDAD < 110 Line 235}

        digitalWriteMOTOR_RELAY,1T0/1,M0[digitalWrite MOTOR_RELAY, 1 T = 0/1, M = 0]
        digitalWriteMOTOR_RELAY,0T0/1,M1[digitalWrite MOTOR_RELAY, 0 T = 0/1, M = 1]
        digitalWriteMOTOR_RELAY,1T0,M0[digitalWrite MOTOR_RELAY, 1 T = 0, M = 0]
    end

TurbidWaterMode242-248digitalWriteMOTOR_RELAY,1T000,M000[Turbid Water Mode Lines 242-248 digitalWrite MOTOR_RELAY, 1 T = 000,M = 000]
dtostrfconvertions252-257floattostr_sensor1-6[dtostrf convertions Lines 252-257 float to str_sensor 1-6]
sprintfcommandchain261-270init#...USER_AGENT...end#final[sprintfcommand chain Lines 261-270 init#...USER_AGENT...end#final]
Serial.printlncommand274[Serial.println command Line 274]
Serial1.printlncommand277[Serial1.println command Line 277]
freecommand280[freecommand Line 280]
Serial1.availableloop289-294readtelemetry_unit[Serial1.available loop Lines 289-294 read telemetry_unit]
Endofloop303[End of loop Line 303]

%%Direcionamientos
loopEntryLine121 --> digitalWriteledverde1,HIGH123
digitalWriteledverde1,HIGH123 --> delay3000124
delay3000124 --> digitalWriteledver1LOW125
digitalWriteledver1LOW125 --> flow_controltrue132
flow_controltrue132 --false--> Serial1.availableloop289-294readtelemetry_unit
flow_controltrue132 --true--> forloop:10samples136-140analogReadA1
forloop:10samples136-140analogReadA1 --> Bubblesortbuffer_arr141-152
Bubblesortbuffer_arr141-152 --> CalculatepH154-159-5.7*volt+calibration_value
CalculatepH154-159-5.7*volt+calibration_value --> digitalReadFLOTADOR_ALTO/BAJO165-166
digitalReadFLOTADOR_ALTO/BAJO165-166 --> analogReadNivel_T2167porcentajet1CANTIDAD/1023*100
analogReadNivel_T2167porcentajet1CANTIDAD/1023*100 --> GetFrecuency1752.5sinterruptcount
GetFrecuency1752.5sinterruptcount --> flow_Lminfrequency/factorK176
flow_Lminfrequency/factorK176 --> u8g2.firstPagedo-whileloop190-194callsdraw
u8g2.firstPagedo-whileloop190-194callsdraw --> ph750&&ph918
ph750&&ph918 --false--> TurbidWaterMode242-248digitalWriteMOTOR_RELAY,1T000,M000
TurbidWaterMode242-248digitalWriteMOTOR_RELAY,1T000,M000 --> dtostrfconvertions252-257floattostr_sensor1-6
ph750&&ph918 --true--> FLOTADOR_A0FLOTADOR_B0200
FLOTADOR_A0FLOTADOR_B0200 --match--> digitalWriteMOTOR_RELAY,1T0,M0
digitalWriteMOTOR_RELAY,1T0,M0 --> dtostrfconvertions252-257floattostr_sensor1-6
FLOTADOR_A0FLOTADOR_B0200 --no match-->  FLOTADOR_A0FLOTADOR_B1207CANTIDAD110
FLOTADOR_A0FLOTADOR_B1207CANTIDAD110 --match--> digitalWriteMOTOR_RELAY,0T0/1,M1
digitalWriteMOTOR_RELAY,0T0/1,M1 --> dtostrfconvertions252-257floattostr_sensor1-6
FLOTADOR_A0FLOTADOR_B1207CANTIDAD110 --no match--> FLOTADOR_A0FLOTADOR_B1214CANTIDAD500
FLOTADOR_A0FLOTADOR_B1214CANTIDAD500 --match--> digitalWriteMOTOR_RELAY,1T0/1,M0
digitalWriteMOTOR_RELAY,1T0/1,M0 --> dtostrfconvertions252-257floattostr_sensor1-6
FLOTADOR_A0FLOTADOR_B1214CANTIDAD500 --no match--> FLOTADOR_A1FLOTADOR_B0221
FLOTADOR_A1FLOTADOR_B0221 --match--> digitalWriteMOTOR_RELAY,1T0/1,M0
FLOTADOR_A1FLOTADOR_B0221 --no match--> FLOTADOR_A1FLOTADOR_B1228CANTIDAD500
FLOTADOR_A1FLOTADOR_B1228CANTIDAD500 --match--> digitalWriteMOTOR_RELAY,1T0/1,M0
FLOTADOR_A1FLOTADOR_B1228CANTIDAD500 --no match--> FLOTADOR_A1FLOTADOR_B1235CANTIDAD110
FLOTADOR_A1FLOTADOR_B1235CANTIDAD110 --match--> digitalWriteMOTOR_RELAY,0T0/1,M1
dtostrfconvertions252-257floattostr_sensor1-6 --> sprintfcommandchain261-270init#...USER_AGENT...end#final
sprintfcommandchain261-270init#...USER_AGENT...end#final --> Serial.printlncommand274
Serial.printlncommand274 --> Serial1.printlncommand277
Serial1.printlncommand277 --> freecommand280
freecommand280 --> Serial1.availableloop289-294readtelemetry_unit
Serial1.availableloop289-294readtelemetry_unit --> Endofloop303
Endofloop303 --> loopEntryLine121
Loading

Sources: purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 121-303 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 61-70

Subsystem Overview

The codebase is organized into several functional subsystems, each implemented as code blocks within the main sketch:

Subsystem Code Location Key Functions/Variables Purpose
pH Sensing 136-162 buffer_arr[10], avgval, calibration_value 10-sample median-filtered pH measurement
Float Switches 165-166 FLOTADOR_ALTO, FLOTADOR_BAJO, digitalRead() Binary Tank 1 level detection
Analog Level 167-172 Nivel_T2, CANTIDAD, porcentajet1 Binary Tank 1 level detection
Flow Sensor 61-70 175-178 GetFrequency(), ISRCountPulse(), pulseConter Interrupt-driven flow rate calculation

Control Subsystem

The motor control logic (198-248) implements a safety-first decision tree:

  1. Primary Gate: pH validation (7.5 < pH < 9.0) - invalid pH forces turbid water mode
  2. Tank State Evaluation: Six distinct float switch combinations determine pump operation
  3. Tank 2 Threshold Logic: Analog level sensor (CANTIDAD) uses thresholds of 110 (empty) and 500 (full)
  4. Output Variables: M (motor state: 0=OFF, 1=ON), T (Tank 1 status)

Output Subsystems

Subsystem Code Location Key Entities Purpose
Motor Relay 202-243 digitalWrite(MOTOR_RELAY), M variable Controls pump via relay on pin D4
LCD Display 190-194 305-345 u8g2 object, draw() function Renders 128x64 display with 4 data rows
Telemetry 261-294 Serial1, sprintf(command), Ubidots protocol Binary Tank 1 level detection

Sources: purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 136-294 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 305-345

Ubidots Cloud Integration

The system transmits telemetry to Ubidots IoT platform using a custom text-based protocol over Serial1:

Transmitted Variables

Variable Code Symbol Ubidots Label Description
1 ph ph Water pH value (float)
2 T Tanque1 Tank 1 status (0, 1, or 000 for turbid)
3 lvltanque Tanque2 Tank 2 level percentage (0-100)
4 frecuencia frecuencia Flow frequency in Hz
5 M Motor Motor state (0=OFF, 1=ON, 000=turbid)
6 flujocaudal caudal Flow rate in L/min

Flow Control Mechanism

The flow_control flag lines (77, 132, 293) implements a simple handshake:

  • Set to false after command transmission
  • Reset to true when Serial1.available() > 0 (gateway responds)
  • Prevents command overflow when gateway is processing previous request

Sources: purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 76-89 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 261-294

Hardware Configuration Summary

Pin Assignments

Pin Type Purpose Code Constant
D3 Interrupt Input Flow sensor pulse sensorPin
D4 Digital Output Motor relay control MOTOR_RELAY
D5 Digital Output Status LED ledverde1
D6 Digital Input Tank 1 lower float FLOTADOR_BAJO
D7 Digital Input Tank 1 upper float FLOTADOR_ALTO
D8 Digital Output LCD reset u8g2 reset parameter
D10 Digital Output LCD chip select u8g2 CS parameter
A0 Analog Input Tank 2 level sensor Nivel_T2
A1 Analog Input pH sensor pH measurement

Communication Interfaces

Interface Baud Rate Purpose Code Reference
Serial (USB) 115200 Debug output 104
Serial1 (UART1) 115200 Telemetry gateway 105
SPI Hardware LCD display 15 U8G2_ST7920

Sources: purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 18-22 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 42 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 104-105

Key Design Patterns

Safety-First Architecture

The pH validation check (198) acts as a primary safety gate. When pH is outside the 7.5-9.0 range:

  • Motor is forced OFF regardless of tank levels
  • Variables T and M are set to 000 (turbid water indicator)
  • All subsequent motor control logic is bypassed

This ensures that only clean water (within acceptable pH range) is pumped to Tank 2.

Median Filtering for Noise Reduction

The pH sensor uses a 10-sample median filter (136-162):

  1. Collects 10 analog readings with 30ms delay between samples
  2. Performs bubble sort on buffer_arr[10]
  3. Averages middle 6 values (indices 2-7), discarding outliers
  4. Converts to voltage and applies calibration formula

This approach eliminates sensor noise and provides stable pH readings.

Interrupt-Driven Flow Measurement

The GetFrequency() function (61-70) uses hardware interrupts for accurate flow measurement:

  1. Resets pulseConter to 0
  2. Enables interrupts for 2.5 seconds (measureInterval)
  3. ISRCountPulse() increments counter on each sensor pulse
  4. Calculates frequency: pulseConter * 1000 / measureInterval

The interrupt service routine (56-59) is lightweight, ensuring no pulses are missed during high flow rates.

Sources: purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 56-70 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 136-162 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 198-248

Getting Started

To begin working with this system:

  1. Hardware Setup: Review pin assignments and connect sensors/actuators as documented in Hardware Architecture
  2. Library Installation: Install U8g2 graphics library via Arduino Library Manager (see Installation and Setup Guide)
  3. Configuration: Set Ubidots credentials in TOKEN and DEVICE_LABEL constants (see Ubidots Configuration)
  4. Calibration: Adjust calibration_value for pH sensor and factorK for flow sensor model (see Sensor Calibration)
  5. Deployment: Upload sketch to Arduino Mega and monitor Serial output for debug information

Sources: purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 33 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 47 purificador_agua_via_ubidots/purificador_agua_via_ubidots.ino 81-82

About

Automated purifying system that controls the levels of two tanks, closing a solenoid valve and pausing against possible spills. It resumes when levels allow it. It integrates with Ubidots for real-time remote monitoring and control (on/off) from anywhere, ensuring efficiency and safety.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages