Riviergezondheidsmonitor: Arduino-gebaseerd Waterkwaliteitssysteem
Onderdelen en Benodigdheden
| Arduino MKR1000 | × | 1 |
| Waterpeilsensor | × | 1 |
| pH-sensor | × | 1 |
| LED (wit, indien mogelijk) | × | 1 |
| Weerstand 221 ohm | × | 2 |
| Fotoweerstand (LDR) | × | 1 |
| Jumper wires (algemeen) | × | 1 |
Benodigde Tools en Machines
- Soldeerbout (algemeen)
- Metaalzaag
Apps en Online Services
- Arduino Web Editor
- Sigfox
- Wia
Over dit Project
Overzicht
Een rivier of meer kan een geweldige bron van plezier en ontspanning zijn. Maar als de rivier vervuild en gecontamineerd raakt, is al het plezier voorbij. Veel mensen zijn afhankelijk van rivierwater om hun vee te voeren en kunnen het zich niet veroorloven om hun dieren vuil water te geven.
Stel je voor dat je recht naast een rivier woont (als dat niet al het geval is), je zou niet willen wakker worden in het midden van de met je huis overstort door de rivier. Of wat als je buurman besluit om een beetje benzine in de rivier te dumpen, je zou niet willen dat je dieren ziek worden.
MyRiver lost al die problemen op. Het kan werken in geïsoleerde gebieden dankzij Sigfox, zodat iedereen toegang heeft tot het apparaat. Het apparaat meet de pH van het water, het vervuilingsniveau met een innovatieve methode, en het waterpeil. Je kunt de rivier live monitoren op je telefoon of computer overal ter wereld dankzij Wia. Op die manier weet je of er een probleem is met de stroom en kun je handelen voordat het te laat is. Het stuurt je een melding als er een probleem is met de rivier.
Functionaliteit
Het apparaat is gebaseerd op de Arduino MKR FOX, ontworpen voor remote gebruik. De gebruiker kan het apparaat in een rivier of meer plaatsen en het van overal monitoren. Dankzij de lage-standby-modus van de SAM D, kan het apparaat langdurig werken op 2 AA-batterijen.
Het apparaat neemt elke 30 minuten metingen, waarna het in slaapstand gaat. De slaapperiode kan worden aangepast, maar de minimume slaaptijd moet 20 minuten zijn.
De MKR FOX meet de pH van de rivier met een pH-sensor, meet het waterpeil met een waterpeilsensor, en detecteert of het vervuild is met onoplosbare stoffen door een LED te laten schijnen op een fotoweerstand. Als de meting van de fotoweerstand laag is, betekent dat dat een vaste stof (olie, benzine, kwik, etc.) in de rivier aanwezig is. Het apparaat stuurt vervolgens alle data naar Sigfox, waar deze wordt doorgestuurd naar Wia, verwerkt en gevisualiseerd. De gebruiker wordt op de hoogte gesteld van de staat van de rivier.
De buffer wordt naar Sigfox gestuurd gecodeerd als HEX. Sigfox stuurt de data door naar Wia, de data passeert vervolgens een flow, wordt terug geconverteerd naar string en vervolgens naar de sensorwaarden. Deze worden verwerkt en de gebruiker wordt gewaarschuwd als de waarden buiten de grenzen vallen.
Read Sensorsleest de pH-, waterpeil- en fotoweerstandsensorwaarden en slaat ze op in variabelen.Format Buffervoegt alle waarden samen in een 12-byte buffer die naar Sigfox gestuurd kan worden.Parse Datastuurt de buffer naar Sigfox.
De MKR FOX kan slechts 12 bytes via Sigfox sturen. Dit betekent dat alle sensorwaarden samengevoegd moeten worden in de 12 bytes. De maximale ruwe waarde van elke sensor is 1024 (aangezien ze allemaal analoog zijn), dus elke sensor vertegenwoordigt een derde van de buffer (4 bytes). De Arduino moet de waarden samenvoegen en nullen toevoegen aan het begin van elke waarde tot de waarde 4 bytes is. De onderstaande afbeelding illustreert dit proces.
De Arduino ontvangt de sensorwaarden als integers, converteert de integers naar strings en voegt nullen toe aan het begin van elke waarde tot deze 4 bytes is. Bijvoorbeeld, als de fotoweerstandswaarde 620 is, wordt één nul toegevoegd: 0620. Maar als de waterpeilsensor gelijk is aan 24, worden twee nullen toegevoegd: 0024. Het apparaat voegt de waarden samen tot een 12-byte buffer en stuurt de data naar Sigfox.
Het Apparaat in Actie
Hieronder een aantal foto's die de functionaliteit van het project tonen. Voor een beter overzicht, verwijzen we naar de video bovenaan.
Voordelen
De gebruiker van dit project zal profiteren van:
- Gemakkelijk monitoren van waterpeil, pH en vervuilingsgraad van een rivier van overal en op elk moment.
- Een melding ontvangen als de rivier vervuild is door oplosbare of onoplosbare stoffen, of overstort.
- Gemak van gebruik en montage.
- Werkt in elk land met Sigfox-dekking.
Het Project Bouwen
Stap 1: Benodigde Apparatuur
Dit project vereist dat alle componenten met elkaar gesoldeerd worden. Er zijn niet veel dingen nodig naast de sensoren. De materialenlijst staat hieronder.
- 1× Arduino MKR FOX 1200
- 1× pH-sensor
- 1× Waterpeilsensor
- 1× Fotoweerstand
- 1× Witte LED
- 2× Weerstanden (220Ω)
- Jumper wires
Stap 2: De Schakeling Aansluiten
Het schakelingsschema van het project kan een beetje verwarrend zijn omdat de componenten niet op een breadboard geplaatst zijn. Als je er moeite mee hebt, probeer dan het Fritzing-bestand hieronder te downloaden en de draden op je computer te verplaatsen.
De onderstaande afbeeldingen laten zien hoe de schakeling eruit moet zien wanneer deze voltooid is.
De MKR FOX Voorbereiden
De onderstaande afbeeldingen begeleiden je bij het aansluiten van de batterijhouder en antenne aan de MKR FOX. Let op: de batterijhouder moet worden aangesloten nadat de sensoren zijn aangesloten. Overige bedrading en setup vind je onder het project bouwen / Final.
Stap 3: De Code Begrijpen
Er zijn 3 hoofdonderdelen in de code:
- Read Sensors
- Format Buffer
- Parse Data
Deze secties worden hieronder uitgelegd.
Read Sensors
struct GetValue // Structuur om lussen te vereenvoudigen
{
int riverLevel() // waterpeil ophalen
{
const int val = analogRead(A2);
if(proDebug) {
Serial.print(" River Level ");
Serial.println(val);
}
return val;
}
int riverPh() // pH ophalen
{
const int val = (analogRead(A1) / 5 * 3.3);
if(proDebug) {
Serial.print(" River Ph ");
Serial.println(val);
}
return val;
}
int riverPol() // vervuilingsgraad ophalen
{
const int val = analogRead(A3);
if(proDebug) {
Serial.print(" River Pollution ");
Serial.println(val);
}
return val;
}
};
De bovenstaande structuur bevat lussen die elke sensorwaarde lezen. Er is een afzonderlijke lus voor elke waarde.
Format Buffer
String data(int level, int ph, int pol) // sensorwaarden samenvoegen in buffer
{
int values[3] = {level, ph, pol};
String newValues;
for(int i = 0; i < 3; i++) // loopt door alle waarden, voegt 0's toe aan het begin
{
if(values[i] < 10) {
newValues += "000";
Serial.println("Option 1");
} else if(values[i] < 100) {
newValues += "00";
Serial.println("Option 2");
} else if(values[i] < 1000) {
newValues += "0";
Serial.println("Option 3");
};
newValues += values[i];
Serial.print(" Run ");
Serial.print(i);
Serial.print("/3 ");
Serial.println(newValues);
}
return newValues;
}
De bovenstaande lus neemt de 3 sensorwaarden en plaatst ze in een array. Vervolgens loopt het door elke waarde, voegt nullen toe aan het begin van elke waarde tot de waarde 4 bytes is, en voegt elke waarde toe aan een string die vervolgens wordt teruggegeven.
Parse Data
void parseData(String data) // buffer naar SigFox sturen
{
SigFox.beginPacket();
SigFox.print(data);
int ret = SigFox.endPacket();
}
Deze sectie neemt de string om te parsen en stuurt de waarde naar Sigfox.
Stap 4: Wia Sigfox-integratie Instellen
Deze stap laat zien hoe Wia in te stellen om berichten van Sigfox te ontvangen. Wia is een professioneel IoT-platform dat de gebruiker in staat stelt om data te visualiseren met widgets op het web of in de mobiele app. Het stelt de gebruiker ook in staat om een blokcode genaamd een flow te maken, waarmee de data verwerkt kan worden. Data wordt voorgesteld door een event.
Om te beginnen, zorg dat je een Sigfox-account en een Wia-account hebt. Download ook de Wia-app op iOS of Android om meldingen te ontvangen. De onderstaande afbeeldingen illustreren het koppelen van Sigfox en Wia.
Instellingen voor de Sigfox-callback:
- Stel Type in op
Data Uplink - Stel Channel in op
URL - Er is geen behoefte aan Custom Payload Configuration
- Stel URL patroon in op "https://api.wia.io/v1/events"
- Stel HTTPMethod in op
POST - Maak een header genaamd
Authorisationmet waardeBearer(deze waarde wordt later bewerkt) - Stel ContentType in op
application/json - Kopieer de code van deze link in de body van de webhook.
- Klik ten slotte op OK en je bent klaar.
Stap 5: De Wia Flow Instellen
Deze sectie duurt iets langer. De flow converteert de ontvangen data van HEX naar String, parseert de string in de 3 sensorwaarden en converteert ze naar integers. Vervolgens converteert het de waarde van riviervervuiling en waterpeil naar een "High" of "OK" descriptor en de ruwe pH-waarde naar de daadwerkelijke pH-waarde. Tot slot stuurt het een melding als de waarde buiten de grenzen valt.
De onderstaande handleiding illustreert dit proces stap voor stap. Je wordt gevraagd om bepaalde stukken code in Wia Functions in te voegen. Deze stukken code staan hieronder, kopieer en plak ze in de functie. De data voor de e-mails staan ook hieronder, werk ermee alsof het functies zijn.
Wia Functions
processPayload
if(input.body) {
output.body.name = "value";
output.body.data = toByteArrayStr(input.body.data.sigfoxData);
}
function toByteArrayStr(sigfoxData) {
let result = Buffer(sigfoxData, 'hex');
return result.toString('utf8');
}
processPollution
if(input.body.data) {
let data = input.body.data;
if(data == "POLLUTED") {
output.body.name = "waterLevel";
output.body.data = data;
} else {
while(1);
}
}
processPh
let minVal = 6.5;
let maxVal = 8.5;
if(input.body.data) {
let data = input.body.data;
if(data > maxVal || data < minVal) {
output.body.name = "waterPh";
output.body.data = data;
} else {
while(1);
}
}
processLevel
if(input.body.data) {
let data = input.body.data;
if(data == "HIGH") {
output.body.name = "waterLevel";
output.body.data = data;
} else {
while(1);
}
}
riverPollution
let minVal = 200;
let maxVal = 0;
if(input.body.data.sigfoxData) {
let data = input.body.data.sigfoxData;
let processedData = toByteArrayStr(data);
let newData = cutString(processedData);
output.body.name = "waterPollution";
output.body.data = processData(newData);
}
function toByteArrayStr(sigfoxData) {
let result = Buffer(sigfoxData, 'hex');
return result.toString('utf8');
}
function cutString(data) {
let newVal = data[8];
newVal += data[9];
newVal += data[10];
newVal += data[11];
let finalVal = parseInt(newVal);
return finalVal;
}
function processData(data) {
if(data < minVal) {
return "POLLUTED";
} else {
return "OK";
}
}
riverPh
let minVal = 300;
let maxVal = 600;
if(input.body.data.sigfoxData) {
let data = input.body.data.sigfoxData;
let processedData = toByteArrayStr(data);
let newData = cutString(processedData);
let finalVal = (newData / 73.1428571);
let valueToSend = finalVal.toFixed(2);
output.body.name = "waterPh";
output.body.data = valueToSend;
}
function toByteArrayStr(sigfoxData) {
let result = Buffer(sigfoxData, 'hex');
return result.toString('utf8');
}
function cutString(data) {
let newVal = data[4];
newVal += data[5];
newVal += data[6];
newVal += data[7];
let finalVal = parseInt(newVal);
return newVal;
}
riverLevel
let minVal = 0;
let maxVal = 200;
if(input.body.data.sigfoxData) {
let data = input.body.data.sigfoxData;
let processedData = toByteArrayStr(data);
let newData = cutString(processedData);
output.body.name = "waterLevel";
output.body.data = processData(newData);
}
function cutString(data) {
let newVal = data[0];
newVal += data[1];
newVal += data[2];
newVal += data[3];
let finalVal = parseInt(newVal);
return finalVal;
}
function toByteArrayStr(sigfoxData) {
let result = Buffer(sigfoxData, 'hex');
return result.toString('utf8');
}
function processData(data) {
if(data > maxVal) {
return "HIGH";
} else {
return "OK";
}
}
Wia E-mails
riverPollutionEmail
Automatic Messaging System Data Warning - myWater device ${trigger.source.device.id} detected a problem in the stream.
Warning - Water Is Polluted by Insoluble Substances.
Information Device ${trigger.source.device.id} Raw Data ${input.body.data}
riverPhEmail
Automatic Messaging System Data Warning - myWater device ${trigger.source.device.id} detected a problem in the stream.
Warning - Water Ph is not Appropriate. Water is Contaminated.
Information Device ${trigger.source.device.id} Raw Data ${input.body.data}
riverLevelEmail
Automatic Messaging System Data Warning - myWater device ${trigger.source.device.id} detected a problem in the stream.
Warning - Water Level is too High, River may be flooding.
Information Device ${trigger.source.device.id} Raw Data ${input.body.data}
Variabelen Instellen
Wanneer de data door Wia ontvangen wordt, moet het verwerkt worden. Als de data tussen een minimum en maximum waarde ligt, is de waarde veilig. De grenzen voor de pH- en waterpeilsensor zijn ingesteld, maar de gebruiker moet de limiet van de fotoweerstand handmatig instellen. Er moet een test gedaan worden om deze waarde te bepalen. De onderstaande stappen leggen uit hoe je dit doet.
void setup() {
pinMode(1, OUTPUT);
Serial.begin(9600);
while(!Serial) {};
digitalWrite(1, HIGH);
}
void loop() {
const int val = analogRead(A3);
Serial.println(val);
delay(5000);
}
Er is nog een variabele die de gebruiker moet instellen: proDebug. Als deze ingeschakeld is, vereist de Arduino verbinding via USB met een computer en moet de Serial Monitor open zijn. De Arduino print dan naar de Serial Monitor, ideaal voor troubleshooting. proDebug staat standaard op false voor gebruik in het veld.
Bibliotheken
- Sigfox - copyright (c) 2016 Arduino LLC GNU Lesser General Public Licence - deze bibliotheek is in het publieke domein
- ArduinoLowPower (c) 2016 Arduino LLC GNU Lesser General Public Licence - deze bibliotheek is in het publieke domein
Final
De laatste stap is je Arduino met een PC/Mac te verbinden en de sketch te uploaden. Zorg ervoor dat de batterijhouder aan de Arduino is verbonden en de schakeling in orde is. De volgende stappen begeleiden je bij het maken van een behuizing voor het project.
Ik heb ervoor gekozen om mijn behuizing te maken uit een waterfles. Ik vind dat een geweldige en ecologische manier om het project in te verpakken. Het apparaat ziet er als de onderstaande afbeelding uit.
Als je het idee van de behuizing leuk vindt, kun je door de onderstaande afbeeldingen scrollen, die illustreren hoe de behuizing gemaakt werd. Voel je vrij om er zelf een te maken.
Het laatste wat te doen is, is het apparaat in de rivier plaatsen. Ga hiervoor naar de rivier waar je MyRiver wilt implementeren tijdens hoogwater. Dit is essentieel om te zorgen dat het apparaat niet waarschuwt dat de rivier overstort terwijl het eigenlijk alleen de getij is.
Plak wat tape op de bovenkant van de waterfles om te voorkomen dat water in de fles zakt en alles vernietigt.
We gingen naar een lokale, vuile rivier om het project te testen. Alle alarmen gingen correct af.
Bij het plaatsen van de meetstaf in het water, zorg ervoor dat het water aan de onderkant van de waterpeilsensor is, maar de fotoweerstand volledig bedekt. Bevestig het project aan de oever met tape of een hamer en schroeven, en het zou er zo uit moeten zien (of beter).
Achtergrond
Ontspannen in je huis, naar buiten kijken naar de eens zo mooie en heerlijke rivier die voor je huis stroomt. Maar in plaats van de mooie verse rivier, zie je een groene slijmerige. In dat geval wil je misschien wel verhuizen.
En als de rivier besluit je huis in het midden van de nacht te overstorten terwijl je slaapt, zul je zeker besluiten te verhuizen.
Ik dacht over deze problemen en hoe ze allemaal in één apparaat op te lossen, en bedacht MyRiver.
Als je in de stad woont naast een rivier, waarschuwt het je op tijd als de rivier besluit je dag te verpesten op welke manier dan ook, of als je buurman olie in de rivier dumpt. Of als je op een boerderij zit, waarschuwt MyRiver je dat de rivier vuil is voordat je het water aan je dieren geeft, en geeft je tijd om de dieren binnen te halen voordat de rivier overstort.
Maar alleen de pH van de rivier meten was niet genoeg, omdat onoplosbare stoffen zoals kwik of andere metalen de pH van het water niet beïnvloeden. Dus we bedachten een nieuwe methode om die stoffen te detecteren, uniek voor dit project: een fotoweerstand die het licht van een LED meet dat het water doordringt. Op deze manier kan elke waterverontreiniging gedetecteerd worden.
Code
MyRiver - Volledige Code
De volledige code is beschikbaar in de projectbestanden.
Schema's
schematics_lXO5SiusZO.fzz
Productieproces
- Een Raspberry Pi thuistemperatuurmonitor bouwen met MCP9808, InfluxDB & Grafana
- Emotiesensor & EEG: Goedkope Hardware voor Real-time Emotiedetectie
- Precisie druk- en luchtstroommeting met analoge sensor en Arduino
- DHT11 Temperatuur- & Vochtigheidsensor Project met LED-indicatoren en Piezo-luidspreker
- UnifiedWater v1 – Complete Arduino Waterkwaliteit Sensor Kit
- 3D RGB Arduclock – Bluetooth LED Tijdstuk met Real-Time Clock
- Een eenvoudige obstakelsensor bouwen met Arduino – IR LED & Fotodiodo Tutorial
- Interactieve Joystick Game met Arduino en LED Feedback
- Find Me: Slimme Item Locator met Arduino en Bluetooth
- Arduino-aangedreven mini-rover: Bouw je eigen autonome robot
- De zuurstofsensor (O2) begrijpen: functie, plaatsing en defectherkenning