The estacion-meteorologica repository implements a complete Arduino-based meteorological station system that collects environmental sensor data, displays it in real-time on an OLED screen, logs it to local SD card storage, and transmits it to the Ubidots IoT cloud platform for remote monitoring and analysis.
This system is designed as a single, self-contained Arduino sketch running on an Arduino Mega 2560 microcontroller. It operates autonomously using a hardware timer interrupt to trigger periodic data acquisition cycles, ensuring precise timing without blocking operations.
This page provides a high-level overview of the system architecture, components, and operation. For detailed information about specific subsystems, see:
- Hardware components and wiring: Hardware Components
- Sensor implementation details: Sensor Integration
- Display, storage, and cloud integration: System Operation
- Timing and execution flow: Data Flow & Protocols
- Configuration and deployment: Configuration and Setup
Sources: est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 1-322
The meteorological station consists of the following primary components:
| Componente | Type | Interface | Purpose |
|---|---|---|---|
| Arduino Mega 2560 | Microcontroller | ---- | Main controller and data processor |
| DHT22 | Digital Sensor | Pin 2 (One-Wire) | Temperature and humidity measurement |
| UV Sensor | Analog Sensor | A0 (UVOUT), A1 (REF_3V3) | UV intensity measurement |
| LDR | Analog Sensor | A3 (SENSORLUZ) | Ambient light level measurement |
| SSD1306 OLED | Display | I2C (0x3C) | Real-time data visualization |
| SD Card Module | Storage | SPI (CS Pin 53) | Local data logging to Datos.txt |
| ESP8266/Telemetry Unit | WiFi Module | Serial1 (115200 baud) | Cloud data transmission |
| Status LED's | Indicators | Pins 3, 7 | Visual feedback for light level and transmission |
The system integrates these components through multiple communication protocols (I2C, SPI, Serial, One-Wire, analog) coordinated by the Arduino Mega's ATmega2560 processor.
Sources:
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 5-48
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 75-124
flowchart LR
subgraph est_meteorologica_via_ubidots.ino
direction TB
setupLines75-125[setup Lines 75-125]
loopLines127-12[loop Lines 127-12]
ISRTIMER3_COMPA_vectLines312-321[ISR TIMER3_COMPA_vect Lines312-321]
datosServerLines150-309[datosServer Lines 150-309]
averageAnologReadLines132-142[averageAnologRead Lines 132-142]
mapfloatLines144-147[mapfloat Lines 144-147]
end
subgraph External Library Objects
direction TB
dhtLine29[dht Line 29]
displayAdafruit_SSD1306Line48[display Adafruit_SSD1306 Line 48]
myFileLine14[myFile Line 14]
Serial1HardwareUART[Serial1 Hardware UART]
end
subgraph Global State Variables
direction TB
Contador1Line7Timercounter[Contador1 Line 7 Timer counter]
flow_controlLine54Request-responsesync[flow_control Line 54 Request-response sync]
TEMPERATURAHUMEDADVALORPWM[TEMPERATURA HUMEDAD VALOR PWM]
TOKENDEVICE_LABELVARIABLE_LABELs[TOKEN DEVICE_LABEL VARIABLE_LABEL's]
end
%% Direccionamientos
setupLines75-125 --Initialize--> dhtLine29
setupLines75-125 --Initialize--> displayAdafruit_SSD1306Line48
setupLines75-125 --Configure--> ISRTIMER3_COMPA_vectLines312-321
setupLines75-125 --Initialize SD--> myFileLine14
loopLines127-12 -.Empty, all work done in ISR.-> ISRTIMER3_COMPA_vectLines312-321
ISRTIMER3_COMPA_vectLines312-321 --Every 4s Calls--> datosServerLines150-309
ISRTIMER3_COMPA_vectLines312-321 --Increments--> Contador1Line7Timercounter
datosServerLines150-309 --Calls--> averageAnologReadLines132-142
datosServerLines150-309 --Calls--> mapfloatLines144-147
datosServerLines150-309 --Reads--> dhtLine29
datosServerLines150-309 --Updates--> displayAdafruit_SSD1306Line48
datosServerLines150-309 --Writes--> myFileLine14
datosServerLines150-309 --Transmits via--> Serial1HardwareUART
datosServerLines150-309 --Uses--> flow_controlLine54Request-responsesync
datosServerLines150-309 --Uses--> TOKENDEVICE_LABELVARIABLE_LABELs
The system employs a monolithic single-file architecture where all functionality resides in est_meteorologica_via_ubidots.ino. The loop() function is intentionally empty, as all operational logic is triggered by the Timer3 interrupt service routine ISR(TIMER3_COMPA_vect).
Sources:
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 75-125
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 127-128
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 312-321
flowchart LR
subgraph Timer 3 Configuration in setup
direction TB
TCCR3A0Line95[TCCR3A = 0 Line 95]
TCCR3BWGM32bitLine104CTCMode[TCCR3 BWGM32 bit Line 104 CTC Mode]
TCCR3BCS32CS30Line106Prescaler1024[TCCR3B CS32 CS30 Line 106 Prescaler 1024]
OCR3A31249Line992speriod[OCR3A = 31249 Line 99 2s period]
TIMSK3OCIE3ALine108Enableinterrupt[TIMSK3 OCIE3A Line 108 Enable interrupt]
end
subgraph Runtine Operation
direction TB
HardwareTimer316MHz1024[Hardware Timer3 16MHz / 1024]
ComparetoOCR34Every2second[Compare to OCR34 Every 2 second]
ISRTIMER3_COMPA_vectLine312[ISR TIMER3_COMPA_vect Line 312]
Contador1++Line313[Contador1++ Line 313]
ifContador12Line314[if Contador1 = 2 Line 314]
datosServerLine319[datosServer Line 319]
end
TCCR3A0Line95 --> HardwareTimer316MHz1024
TCCR3BWGM32bitLine104CTCMode --> HardwareTimer316MHz1024
TCCR3BCS32CS30Line106Prescaler1024 --> HardwareTimer316MHz1024
OCR3A31249Line992speriod --> HardwareTimer316MHz1024
TIMSK3OCIE3ALine108Enableinterrupt --> HardwareTimer316MHz1024
HardwareTimer316MHz1024 --Every 2s--> ComparetoOCR34Every2second
ComparetoOCR34Every2second --> ISRTIMER3_COMPA_vectLine312
ISRTIMER3_COMPA_vectLine312 --> Contador1++Line313
Contador1++Line313 --> ifContador12Line314
ifContador12Line314 --False: Return--> ISRTIMER3_COMPA_vectLine312
ifContador12Line314 --True: 4s elapse--> datosServerLine319
The system uses Timer3 in CTC mode (Clear Timer on Compare Match) with a prescaler of 1024 and compare value of 31249 to generate interrupts every 2 seconds. The ISR maintains a counter Contador1 that triggers the main data acquisition function datosServer() every 4 seconds (when counter reaches 2).
Sources: - est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 90-111
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 312-321
flowchart LR
subgraph interrupt Trigger Every 4s
direction TB
ISRTIMER3_COMPA_vectLine312[ISR TIMER3_COMPA_vect Line 312]
Contador12Line314[Contador1 = 2 Line 314]
datosServerLine319[datosServer Line 319]
end
subgraph Flow Control Check
direction TB
flow_controlflagLine54,160[flow_control flag Line 54, 160]
flow_controltrue?{flow_control = true?}
end
subgraph Response Handling
direction TB
Serial1.availableLine295[Serial1.available Line 295]
Readtelemetry_unitLines296-298[Read telemetry_unit Lines 296-298]
flow_controltrueLine298[flow_control true Line 298]
end
subgraph Sensor Reading
direction TB
dht.readTemperaturedht.readHumidityLines161-162[dht.readTemperatured ht.readHumidity Lines 161-162]
averageAnalogReadUVOUTaverageAnalogReadREF_3V3Lines164-165[averageAnalogRead UVOUT average AnalogRead REF_3V3 Lines 164-165]
outputVoltagecalculationmapfloattouvIntensityLines167-169[outputVoltage calculation mapfloat to uvIntensity Lines 167-169]
analogReadSENSORLUZmaptoPWMLines215-216[analogReadSENSORLUZ map to PWM Lines 215-216]
end
subgraph Data Processing y Display
direction TB
display.clearDisplaydisplay.printlnLines172-233[display.clearDisplay display.println Lines 172-233]
dtostrfconversionsLines236-239[dtostrf conversions Lines 236-239]
sprintfUbidotscommandLines242-249[sprint fUbidots command Lines 242-249]
end
subgraph Output Operations
direction TB
SD.openDatos.txtmyFile.printLines264-276[SD.openDatos.txt myFile.print Lines 264-276]
Serial1.printcommandLine256[Serial1.printcommand Line 256]
flow_controlfalseLine262[flow_control = false Line 262]
end
ISRTIMER3_COMPA_vectLine312 --> Contador12Line314
Contador12Line314 --Yes--> datosServerLine319
datosServerLine319 --> flow_controlflagLine54,160
flow_controlflagLine54,160 --> flow_controltrue?
flow_controltrue? --No: Read response --> Serial1.availableLine295
Serial1.availableLine295 --> Readtelemetry_unitLines296-298
Readtelemetry_unitLines296-298 --> flow_controltrueLine298
flow_controltrueLine298 -.Next cycle.-> flow_controlflagLine54,160
flow_controltrue? --> dht.readTemperaturedht.readHumidityLines161-162
dht.readTemperaturedht.readHumidityLines161-162 --> averageAnalogReadUVOUTaverageAnalogReadREF_3V3Lines164-165
averageAnalogReadUVOUTaverageAnalogReadREF_3V3Lines164-165 --> outputVoltagecalculationmapfloattouvIntensityLines167-169
outputVoltagecalculationmapfloattouvIntensityLines167-169 --> analogReadSENSORLUZmaptoPWMLines215-216
analogReadSENSORLUZmaptoPWMLines215-216 --> display.clearDisplaydisplay.printlnLines172-233
display.clearDisplaydisplay.printlnLines172-233 --> dtostrfconversionsLines236-239
dtostrfconversionsLines236-239 --> sprintfUbidotscommandLines242-249
sprintfUbidotscommandLines242-249 --> SD.openDatos.txtmyFile.printLines264-276
SD.openDatos.txtmyFile.printLines264-276 --> Serial1.printcommandLine256
Serial1.printcommandLine256 --> flow_controlfalseLine262
flow_controlfalseLine262 -.Next cycle.-> flow_controlflagLine54,160
The data pipeline implements a request-response flow control mechanism using the flow_control boolean flag:
-
When
flow_controlisTrue: The system reads all sensors, processes data, updates the OLED display, logs to SD card, transmits to Ubidots via Serial1, and setsflow_controltofalse -
When
flow_controlisFalse: The system waits for a response from the telemetry unit on Serial1, and upon receiving data, setsflow_controlback toTrue
This prevents command queue overflow in the ESP8266 telemetry unit by ensuring only one command is in flight at a time.
Sources: - est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 150-309
| Sensor | Reading Method | Processing | Output Format |
|---|---|---|---|
| DHT22 Temperature | dht.readTemperature() |
Direct read, stored inTEMPERATURA |
Integer °C, converted to string via dtostrf() |
| DHT22 Humidity | dht.readHumidity() |
Direct read, stored inHUMEDAD |
Integer %, converted to string via dtostrf() |
| UV Sensor | averageAnalogRead(UVOUT)8 samples |
Voltage calculation, mapfloat()to 0.0-15.0 scale |
uvLevel raw value, categorized text display |
| LDR Light | analogRead(SENSORLUZ) |
map()to PWM 0-255, threshold at 80 |
VALOR raw value, ON/OFF LED control |
All analog sensors use noise reduction techniques: the UV sensor employs averageAnalogRead() which takes 8 samples and returns the average, while the LDR uses direct reading with PWM mapping for LED brightness control.
Sources: - est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 161-169
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 215-216
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 132-147
flowchart LR
subgraph Arduino Mega ATmega2560
direction TB
SerialUART0115200baudLine76[Serial UART0 115200 baud Line 76]
Serial1UART1115200baudLine77[Serial1 UART1 115200 baud Line 77]
SPILines10,13[SPI Lines 10, 13]
WireLines17,48[Wire I2C Lines 17, 48]
GPIOPinsDigitalyAnalog[GPIO Pins Digital and Analog]
end
SerialUART0115200baudLine76 --Debug output--> PC/SerialMonitor[PC/Serial Monitor]
Serial1UART1115200baudLine77 --Ubidots commands telemetry_unit array--> ESP8266WiFiModuleTelemetryUnit[ESP8266 WiFi Module Telemetry Unit]
ESP8266WiFiModuleTelemetryUnit --Wifi HTTP POST--> UbidotsCloudDevice:Mega1[Ubidots Cloud Device: Mega1]
SPILines10,13 --CS Pin 53 myFile object--> SDCardModuleDatos.txt[SDCard Module Datos.txt]
WireLines17,48 --0x3c address display object--> SSD1306OLEDDisplay128x64[SSD1306 OLED Display 128x64]
GPIOPinsDigitalyAnalog --Pin 2 dht object--> DHT22Sensor[DHT22 Sensor]
GPIOPinsDigitalyAnalog --Pin's A0, A1--> UVSensor[UV Sensor]
GPIOPinsDigitalyAnalog --Pin A3--> LDRSensor[LDR Sensor]
GPIOPinsDigitalyAnalog --Pin's 3, 7--> StatusLED's[Status LED's]
The system employs four distinct communication protocols coordinated by the Arduino Mega:
- UART0 (Serial): Debug output to PC at 115200 baud
- UART1 (Serial1): Bidirectional communication with ESP8266 telemetry unit for cloud transmission
- I2C (Wire): Communication with SSD1306 OLED display at address 0x3C
- SPI: High-speed data transfer to SD card module with chip select on pin 53
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 76-77
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 13-48
The system constructs custom protocol commands for transmission to Ubidots via the ESP8266 telemetry unit. The command format follows this structure:
init#UbidotsESP8266Mega1/1.0|POST|TOKEN=>DEVICE_LABEL=>variable:value,variable:value|end#final
Example command built in datosServer():
init#UbidotsESP8266Mega1/1.0|POST|BBFF-Uya1LL5n6F8Jn62mthoTfNI2Qd8VuW|Mega1=>Temperatura:25.00,Humedad:60.00,lUZ:512.00,Uv:227.00|end#final
This command is constructed using multiple sprintf() calls
est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 242-249 and transmitted via Serial1.print(command)
est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 256 The telemetry unit parses this command and executes an HTTP POST request to the Ubidots API.
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 50-65
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 236-262
Local data persistence is achieved through the SD card module using the Arduino SD library. Data is appended to a file named Datos.txt in CSV-like format:
TEMPERATURA:25°C,HUMEDAD:60%,INTENSIDAD LUZ:512,RANGO:227
The file operations occur within datosServer()
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 264-280
- Open file in write mode: ``` myFile = SD.open("Datos.txt", FILE_WRITE)``
- Write sensor data with labels
- Close file:
myFile.close()
Error handling is implemented to detect file operation failures, with error messages printed to the Serial port.
Sources: - est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 9-14
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 113-123
- est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 264-280
The meteorological station provides the following capabilities:
| Capability | Implementation | Update Frequency |
|---|---|---|
| Environmental monitoring | DHT22, UV sensor, LDR | Every 4 seconds |
| Real-time display | SSD1306 OLED with live readings and status | Every 4 seconds |
| Local data logging | SD card CSV append operations | Every 4 seconds |
| Cloud telemetry | Ubidots HTTP POST via ESP8266 | Every 4 seconds (with flow control) |
| UV categorization | Threshold-based classification (8 levels) | Real-time |
| Automatic light control | PWM-based LED dimming based on ambient light | Real-time |
| Interrupt-driven timing | Timer3 hardware interrupts for precise scheduling | 2-second ISR, 4-second data cycle |
The system operates autonomously and continuously once powered on, with all operations coordinated by the Timer3 interrupt mechanism. No manual intervention is required for normal operation, and the empty loop() function ensures minimal overhead between interrupt cycles.
Sources: - est_meteorologica_via_ubidots/est_meteorologica_via_ubidots.ino 1-322