UnifiedWater v1 – Kit completo de sensor de calidad de agua con Arduino
Componentes y suministros
| Arduino MKR GSM 1400 | ×1 |
| Anillo NeoPixel Adafruit: WS2812 5050 RGB LED | ×1 |
| GY21 Temperatura y Humedad | ×1 |
| Sensor de Turbidez, Salida Fototransistor | ×1 |
| Sensor de temperatura digital DS18B20 a prueba de agua (Adafruit) | ×1 |
| DFRobot Gravity: Kit Sensor pH Analógico Punta de Lanza / Medidor | ×1 |
| Interruptor pulsador SparkFun 12mm | ×1 |
| Cables jumper (genéricos) | ×1 |
| Resistencia 220 ohm | ×1 |
Herramientas necesarias
- Soldador (genérico)
Aplicaciones y servicios en línea
- Arduino Web Editor
- SORACOM Air Plataforma de Conectividad IoT
- SORACOM Harvest
- SORACOM Lagoon
Sobre este proyecto
Visión general
Los ríos. Esenciales para nuestra supervivencia, comercio, etc. En la última década se han hecho grandes esfuerzos para reducir la contaminación de las masas de agua del mundo. Los ríos son la fuente de la contaminación, ya que la gente no va al mar a tirar su basura. La tiran en los ríos.
Estos ríos desembocan en el mar, el océano y así el cepillo de dientes que una vez se tiró en un río recorre el mundo y llega al otro lado.
En un mundo que intenta combatir la contaminación, los datos son cruciales. Debe ser fácil para empresas y negocios colaborar en un proyecto global para reducir la contaminación del agua. Aquí es donde entra UnifiedWater.
Un dispositivo lo bastante barato y escalable que pueda recopilar y analizar fácilmente estos datos, tan necesarios para saber cuán contaminado está un río. WaterAid viene en 2 modos: uno para empresas y otro para particulares.
Múltiples dispositivos pueden funcionar juntos, colocados en diferentes puntos de un arroyo o en diferentes masas de agua. Estos dispositivos recopilan datos a intervalos de tiempo y los envían a la misma base de datos. Esto permite a la empresa comprobar el estado del río o lago monitorizado con un clic.
También hay una versión portátil. En esta versión, el particular lleva el dispositivo y cuando quiere tomar una muestra de agua, pulsa el botón del dispositivo y lo sumerge 30 segundos. Los datos estarán disponibles en un panel online.
Al recopilar temperatura del agua, pH y humedad, así como temperatura y humedad atmosféricas, WaterAid incluye todos los sensores necesarios para monitorizar la contaminación del río.
Vídeo
Imágenes


Funcionalidad
UnifiedWater permite al usuario, empresa o particular recopilar datos de forma segura y precisa y visualizarlos todos en un solo lugar gracias a la nube de Soracom. El proyecto consta de frontend y backend.
Frontend
El frontend es el dispositivo físico que recopila los datos y los envía a la nube. El dispositivo puede ponerse en modo 1 o 2. En modo 1, el dispositivo registra un conjunto de datos al pulsar un botón, útil para monitorización ocasional. El modo 2 configura el dispositivo para tomar lecturas a intervalos definidos y enviar esos datos a la nube.
Se usa un MKR GSM por ser fácil de usar y fiable. También puede acceder a Soracom mediante GSM. A continuación, los pasos que sigue el dispositivo al recopilar datos.


Batería
El dispositivo puede alimentarse de varias formas: batería LiPo mediante el puerto del dispositivo, power bank, o conectando una batería al puerto VIN.
La duración depende mucho de la capacidad de la batería. El dispositivo entra en modo suspensión entre lecturas para ahorrar energía.
Anillo LED
El dispositivo lleva un anillo LED que da feedback al usuario sobre lo que está haciendo. Tres modos:
- Multicolor: el dispositivo se está configurando o procesando datos
- Parpadeo rojo: advertencia, normalmente significa que el dispositivo debe sumergirse en agua, aunque también puede indicar error
- Progresión azul o verde: el dispositivo está tomando una muestra y debe estar en el agua

Tomar una muestra
Todos los sensores deben estar sumergidos al tomar una muestra. Hay un retraso de 6 segundos antes de la muestra para calentar los sensores. Para mejores resultados, los sensores deben estar sumergidos durante el calentamiento.

Procesar datos
Los datos deben enviarse a Soracom como cadena JSON. Esto da valor a todas las claves usadas. Los datos serán fáciles de interpretar por el backend. Ejemplo de payload:
{
"Latitude":53.3474617,
"Longitude":-6.2514529,
"waterpH":7.30,
"waterTurbidity":94,
"waterTemp":12.10,
"atmoTemp":14.50,
"atmoHum":82,
"deviceID":1,
"deviceName":"device1",
"epoch":1559392636,
"mode":2
}
Backend
El backend se refiere a Soracom. Los datos se recopilan y visualizan en paneles creados con Soracom Lagoon.

El Panel
El panel resume todos los datos del dispositivo. Marca en un mapa los lugares donde se recogieron datos, el color varía según el nivel de contaminación. Los datos se grafican en gráficos de líneas y se resumen en una tabla.
El usuario recibe alertas por email si el pH o la turbidez son anormales. Capturas del panel:


Escalabilidad
El dispositivo es fácilmente escalable y todos los datos se recopilan e ilustran en el mismo panel. Múltiples dispositivos pueden enviar datos a Soracom y visualizarse en el panel.
El precio del dispositivo y la facilidad extrema para construirlo y programarlo facilitan el uso de flotas. Estos dispositivos también se registran fácilmente en Soracom con herramientas como Soracom Krypton.
Cada empresa o particular tendrá su panel personalizado. Esperamos que en el futuro se pueda colaborar en el mismo panel y compartir datos.
Beneficios
- Costes operativos reducidos: el dispositivo es muy autónomo.
- Fácilmente escalable, funciona solo o en flotas de decenas.
- Recopilación rápida de datos, enviados a la nube y visualizados en tiempo real.
- Visualización fácil: datos accesibles desde cualquier lugar y momento vía panel online.
Construcción del proyecto
Paso 1: Material necesario
El proyecto requiere muchos sensores para monitorizar parámetros del agua y la atmósfera. Lista completa:
- 1 Arduino MKR GSM
- 1 Anillo LED RGB de 16 LEDs
- 1 Módulo temperatura y humedad GY-21
- 1 Sensor de turbidez
- 1 Sensor de temperatura a prueba de agua
- 1 Sensor pH y módulo
- 1 Pulsador
- 1 Resistencia (220Ω)
- Cables jumper

Paso 2: Conectar el circuito
Los componentes deben soldarse. Para facilitar la comprensión de los esquemáticos, se ha usado una protoboard. Los esquemáticos están abajo.

Preparar el MKR GSM
Tras soldar los sensores, hay que colocar la tarjeta SIM, antena GSM y batería. Alimento la placa con 2 pilas AA por el puerto VIN. Pasos:









Paso 3: Entender el código
Hay 4 secciones principales en el código:
- Recopilar datos de sensores
- Obtener hora y fecha
- Procesar datos
- Enviar datos
Recopilar datos de sensores
Serial.println("Taking Sample");
Serial.println("________________________________________");
Serial.println("Taking Sample");
Serial.println(" OK - Warming Up");
delay(6000); // delay para calibración de sensores
colourLED(50);
Serial.println(" OK - Taking Sample");
Serial.print(" ");
for (int i = 0; i < 16; i++)
{
if (mode == 1)
{
strip.setPixelColor(i, strip.Color(0, 255, 0));
strip.show();
}
else
{
strip.setPixelColor(i, strip.Color(0, 0, 255));
strip.show();
}
// múltiples muestras de agua - sensores no muy precisos
waterTurbidity += getWaterTurbidity();
waterPh += getWaterPh();
if (i > 14)
{
// una sola muestra para sensores de alta precisión
waterTemperature = getWaterTemp();
atmoTemperature = getAtmoTemp();
atmoHumidity = getAtmoHumidity();
}
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println(" Success - Samples Taken");
for (int i = 0; i <= 16; i++)
{
strip.setPixelColor(i, strip.Color(0, 0, 0));
strip.show();
delay(30);
}
Serial.println("________________________________________");
Serial.println("");
delay(500);
El código espera 6 segundos para calibrar sensores en el agua. Luego itera 16 veces, encendiendo un LED del anillo por vuelta. Los datos de sensores fluctuantes se recogen 16 veces y se promedian. Los sensores de alta precisión se leen en la última vuelta.
Obtener hora y fecha
void getCredentials()
{
Serial.println(" [1/2] Time");
Serial.println(" OK - Getting Time from RTC");
currentEpoch = processTime();
colourLED(50);
Serial.println(" [2/2] Geolocation");
Serial.println(" OK - Getting Geolocation from GPRS");
while (!getLocation());
Serial.print(" Success - Geolocation is "); Serial.print(latitude, 7); Serial.print(", "); Serial.println(longitude, 7);
colourLED(50);
}
bool getLocation()
{
if (location.available())
{
latitude = location.latitude();
longitude = location.longitude();
delay(500);
return true;
}
else
{
delay(500);
return false;
}
}
El primer bucle gestiona credenciales. La hora se extrae del RTC interno (sincronizado con la red GSM en setup). La geolocalización se extrae de GPRS.
Procesar datos
void processData()
{
Serial.println(" OK - Getting Mean of Water pH and Turbidity");
waterPh = (waterPh / 16);
waterTurbidity = (waterTurbidity / 16);
Serial.println(" OK - Dumping Data to Serial");
Serial.println("");
Serial.print(" [Water] pH "); Serial.println(waterPh);
Serial.print(" [Water] Turbidity "); Serial.println(waterTurbidity);
Serial.print(" [Water] Temperature "); Serial.println(waterTemperature);
Serial.print(" [Atmo] Temperature "); Serial.println(atmoTemperature);
Serial.print(" [Atmo] Humidity "); Serial.println(atmoHumidity);
Serial.println("");
Serial.println(" Success - Data Processed");
colourLED(50);
}
String makeLine()
{
Serial.println(" OK - Making String");
String dataReturned; dataReturned += "{"; dataReturned += " \n";
dataReturned += "\"Latitude\":" + String(latitude, 7); dataReturned += ", \n";
dataReturned += "\"Longitude\":" + String(longitude, 7); dataReturned += ", \n";
dataReturned += "\"waterpH\":" + String(waterPh); dataReturned += ", \n";
dataReturned += "\"waterTurbidity\":" + String(waterTurbidity); dataReturned += ", \n";
dataReturned += "\"waterTemp\":" + String(waterTemperature); dataReturned += ", \n";
dataReturned += "\"atmoTemp\":" + String(atmoTemperature); dataReturned += ", \n";
dataReturned += "\"atmoHum\":" + String(atmoHumidity); dataReturned += ", \n";
dataReturned += "\"deviceID\":" + String(deviceID); dataReturned += ", \n";
dataReturned += "\"deviceName\":"; dataReturned += String("\""); dataReturned += String(deviceName); dataReturned += String("\""); dataReturned += ", \n";
dataReturned += "\"epoch\":" + String(currentEpoch); dataReturned += ", \n";
dataReturned += "\"mode\":" + String(mode); dataReturned += " \n";
dataReturned += "}";
Serial.println(" OK - Data is below");
Serial.println("");
Serial.println(dataReturned);
Serial.println("");
Serial.println(" Success - String is Ready");
colourLED(50);
return dataReturned;
}
processData() calcula la media de datos fluctuantes y vuelca todo al Monitor Serie. makeLine() compila todos los datos en la cadena JSON que se envía a Soracom.
Enviar datos
void parseData(String dataToSend)
{
Serial.println(" OK - Setting Up Connection");
if(client.connect(url, 80))
{
Serial.println(" OK - Connection Established, Parsing Data");
client.println("POST / HTTP/1.1");
client.println("Host: harvest.soracom.io");
client.println("User-Agent: Arduino/1.0");
client.println("Connection: close");
client.print("Content-Length: ");
client.println(dataToSend.length());
client.println("");
client.println(dataToSend);
Serial.println(" OK - Data Parsed");
}
Serial.println(" OK - Getting Responce");
Serial.println("");
while(1)
{
if(client.available())
{
char c = client.read();
Serial.print(c);
}
if(!client.connected())
{
break;
}
}
Serial.println(" Success - Data is Parsed");
}
Finalmente, los datos se envían a Soracom. El dispositivo establece conexión, prepara credenciales, envía datos y muestra la respuesta en el Monitor Serie. Luego entra en suspensión hasta el siguiente disparador.
Paso 4: Configurar variables
Variables a editar antes de usar:
mode: modo del dispositivo. 1 = muestras por botón; 2 = muestras periódicas.deviceID y deviceName: identificadores únicos si usas flota de dispositivos.sleepTime: tiempo de suspensión entre lecturas. 5 segundos en código (para pruebas), cambiar a 15 min en campo.proDebug: depuración.falseen código; sitrue, el dispositivo no arranca sin monitor serie abierto.
Paso 5: Subir el código
Conecta tu MKR GSM al ordenador y sube el código, asegurando mode = 1 para la configuración. Tras subir, sumerge todos los sensores en agua. Pulsa el botón y espera a que recoja y envíe datos. Repite varias veces para poblar Soracom Air.
Paso 6: Configurar Soracom
Dos secciones: crear cuenta y registrar SIM, y configurar Soracom Harvest. Si ya tienes cuenta, salta a la sección 2.
Sección 1: Crear cuenta




















Sección 2: Grupos y Harvest


















Paso 7: Configurar Lagoon
Lo último en Soracom es Lagoon, para visualizar datos y crear alertas por email si los datos son anómalos.




































Problemas de calibración
Los sensores de turbidez y pH deben calibrarse para precisión. Si la turbidez marca 105% o el pH del agua da 3, hay que calibrar:
- Sensor pH: Usa los potenciómetros del módulo. Sumerge la sonda en agua embotellada quieta de pH 7 durante 5 min. Crea código que imprima pH en monitor serie. Ajusta potenciómetro hasta leer 7.
- Sensor turbidez: No es muy preciso, se toma porcentaje relativo vs agua pura. Si lecturas superan 100%, sumerge sensor en agua pura y crea código que imprima voltaje en pin analógico del sensor pH en monitor serie. En
sensors.hhay variablecalibration, cámbiala al voltaje leído en agua pura.
Librerías
- ArduinoLowPower (c) 2016 Arduino LLC LGPL
- Adafruit_Neopixel (c) Phil Burges LGPL
- MKRGSM (c) 2016 Arduino AG LGPL
- Wire (c) 2006 Nicholas Zambetti LGPL
- OneWire (c) 2007 Jim Studt GPL
- DallasTemperature GPL
- RTCZero (c) 2015 Arduino LLC LGPL
Final
Finalmente hice una carcasa portable que puede fijarse para recoger muestras en ambos modos. Pasos:










Asegúrate que el modo está configurado correctamente y empieza a usar el dispositivo en campo. Revisa tu río o lago local y comprueba su limpieza. Juega con el panel y descubre sus widgets.
Contexto
Hoy, los datos son la nueva moneda y recopilarlos fácil y eficientemente es clave para un mejor entorno. Midiendo la contaminación de ríos y lagos colectivamente, podemos concienciar de que las aguas se ensucian y hay que actuar.
Pensaba en una idea para el concurso de Soracom y sentí que debía hacer algo beneficioso para el medio ambiente. La idea de gente y empresas trabajando juntas en paneles colectivos para visualizar el estado de ríos y lagos globalmente me inspiró.
¿Qué harás tú para frenar la contaminación del agua? Porque la acción debe ser hoy, y mañana es un día demasiado tarde.



Código
Código
Repositorio del proyecto: GitHub UnifiedWater-v1
Esquemáticos

Proceso de manufactura
- Controle un LED con Sensor PIR de Movimiento en Raspberry Pi
- Construya un Sensor de Humedad de Suelo de Bajo Coste para Riego Inteligente con Raspberry Pi
- Prueba del Sensor de Temperatura DS18B20 en Raspberry Pi
- Monitor de temperatura casero con Raspberry Pi, MCP9808, InfluxDB y Grafana
- Sensor Telemetry 2.0.1 – Monitorización Avanzada de Temperatura con Azure IoT Hub
- Sensor de Emociones y EEG: Hardware de Bajo Coste para Detección de Emociones en Tiempo Real
- Envío de Datos IMU Adafruit 10DOF desde Raspberry Pi 2 a Azure Event Hubs con Windows 10 IoT Core
- Monitor de Salud Fluvial: Sistema de Calidad de Agua con Arduino
- Construye una Torre de Sensores con Arduino Cloud: Temperatura, Movimiento y Gas
- Jukebox Moderna: Reproductor Musical Raspberry Pi + Arduino con LEDs Reactivos
- Entendiendo el sensor de oxígeno (O2): función, ubicación y señales de fallo