# Monitoring of wastewater treatment plant **Andreas Hedlund, ah225ms** This IoT application aims to monitor a wastewater treatment plant for single households. According to the manufacture of the treatment plant, some components needs to be monitored manually to prevent overheating and a barrel with flocculation liquid need to always have sufficient amount of liquid in it. Instead of checking this manually, this will be automatically monitored in this project. Estimated time: 5 hours Estimated price: 113$ ![](https://i.imgur.com/xbB4MvV.jpg) ## Objective Reasons why I chose to do this application: - Save time when I don't need to check the treatment plant manually. - Quicker detect that something is wrong with the treatment plant and take faster action to fix it to prevent costly damages. - Learn IoT development with Python and send data with LoraWAN. ## Material ### Micro computer For this application I used a **Pycom LoPy4** manly because it was the standard unit for this course, but I also liked that is could send data over LoraWAN and was programmed with Python. Together with the LOPY4 I used an **expansion board V3** from Pycom. This expansion board made it possible to easily power the LOPY4 board and to connect different sensors. ![](https://i.imgur.com/jmi496o.jpg) ### Sensors I used these sensors: - 1 x **DHT11** for reading ambient temperature and humidity. I used a 3-pin model. - 2 x **DS18B20** mounted on cables for reading the air pumps temperatures. - 1 x **4.7kΩ Resistor** to use with the DS18B20 sensors. - 1 x **XKC-Y25-V** for reading liquid level in flocculation barrel. DHT11 | DS18B20 | XKC-Y25-V | | - | - | - | ![](https://i.imgur.com/k2SOyX6.jpg) | ![](https://i.imgur.com/xx7BxYN.jpg) | ![](https://i.imgur.com/CDHc8Nw.jpg) ### Other material I also used the things below to build the application: - 1 x **Breadboard** for easy prototyping. - 10 x **Connection leads** to connect the sensors. - 1 x **USB Cable** to connect the Pycom device to a computer. - 1 x **TTI Indoor gateway** to communicate with the The Things Network (optional if you already have coverage in your area). You also need a computer to program the micro computer. ### Links to material The material can be fund on the links: | Product | Link | Price $ (roughly) | | - | - | - | | Pycom LoPy4 | [Pycom](https://pycom.io/product/lopy4/) | 47 USD | | Pycom Expansion Board 3.0 | [Pycom](https://pycom.io/product/expansion-board-3-0/) | 22 USD | | DHT11 | [Elektrokit](https://www.electrokit.com/produkt/digital-temperatur-och-fuktsensor-dht11/) | 5 USD | | DS18B20 | [Elektrokit](https://www.electrokit.com/produkt/temperatursensor-vattentat-metallholje-ds18b20/) | 10 USD / each | | XKC-Y25-C | [Aliexpress](https://www.aliexpress.com/item/4001245646772.html?spm=a2g0o.productlist.0.0.90a3214020pHt9&algo_pvid=64b50f5a-717e-4e62-8d18-095705fbde48&algo_exp_id=64b50f5a-717e-4e62-8d18-095705fbde48-0) | 5 USD | | Breadboard | [Elektrokit](https://www.electrokit.com/produkt/kopplingsdack-400-anslutningar/) | 6 USD | | Connection leads | [Elektrokit](https://www.electrokit.com/produkt/kopplingstrad-byglar-for-kopplingsdack-mjuka-65st/) | 4 USD for 65 pieces | | USB-cable | [Elektrokit](https://www.electrokit.com/produkt/usb-kabel-a-hane-micro-b-5p-hane-1-8m/) | 4 USD | | TTI Gateway | [RS Components](https://se.rs-online.com/web/p/communication-wireless-development-tools/1843981) | 90 USD (optional) | | **Total** | | 113 USD / 203 USD w. optional ## Computer setup For this project I chose to use VS Code as the IDE to program the micro computer. I also tried Atom but I went with VS Code because I have used is before in other projects. I run the software on my Apple MacBook with Mac OS operating system. In the following steps below you find how to install and program the micro computer. In my case it was pretty straight forward without any problem with extra drivers etc. ### Flashing the Pycom micro computer and expansion board Before you begin you need to mount the Pycom LoPy4 on the expansion board and then connect the USB-cable. The correct way to mount it is to **align the circular LED light on the LoPy4 with the USB-port on the expansion board** as shown in the picture below. You also need to **attach the Lora antenna**. If you don't connect an antenna and start the Lora transmission the chip can take damage. The antenna should be connected to one of the gold-plated connectors in the upper part of the LoPy4 board. In Europe it is the the one on the right side. ![](https://i.imgur.com/EVYt9dU.png) As a first step it is good to flash the Pycom LoPy4 with the latest firmware. I followed the tutorial on the link below. [https://docs.pycom.io/updatefirmware/device/](https://docs.pycom.io/updatefirmware/device/) If you purchased an old Expansion Board you also need to upgrade the firmware on that. I did not need to do that but if you need to do it, you can follow the tutorial on the link below. [https://docs.pycom.io/updatefirmware/expansionboard/](https://docs.pycom.io/updatefirmware/expansionboard/) ### Installing the IDE To install the IDE I followed the link below. In the tutorial you will be downloading and install the IDE [VS Code](https://code.visualstudio.com/). You also need to download and install [NodeJS](https://nodejs.org/). After you installed VS Code you download the [Pymakr VSCode Extension](https://marketplace.visualstudio.com/items?itemName=pycom.Pymakr) in the extensions page in VS Code. [https://docs.pycom.io/gettingstarted/software/vscode/](https://docs.pycom.io/gettingstarted/software/vscode/) ### Upload the code to the micro computer If you completed the steps above and connected the LoPy4 to your computer you should see the Pymakr console in the bottom of VS Code. If you click the download button the computer should download the main.py file from the LoPy4. ![](https://i.imgur.com/6TxAZIv.png) This file is the main file to run the code on the micro computer. If you replace the code in main.py with the on below and then click on the Upload button, the led on the LoPy4 should blink I different colors. ``` python= # Source: https://hackmd.io/@lnu-iot/rk4qNlajd import pycom import time pycom.heartbeat(False) while True: #Forever loop pycom.rgbled(0xFF0000) # Red time.sleep(1) #sleep for 1 second pycom.rgbled(0xFF3300) # Orange time.sleep_ms(1000) #sleep for 1000 ms pycom.rgbled(0x00FF00) # Green time.sleep(1) ``` If you got the led to blink like the GIF below you have successfully uploaded and run the code on the micro computer. ![](http://hlund.se/gifs/EndResultGif.gif) ## Connecting the sensors to the micro computer The sensors should be connected as described in the schematic below. This is a development setup for proof of concept. In a production setup a special designed expansion board with screw terminals to connect the sensors, an integrated DHT11 sensor and integrated resistor for DS18B20 would be more suitable. #### Main positive and negative - 3.3 V from expansion board to positive rail on the breakout board. - GND from expansion board to negative rail on the breakout board. #### DHT11 - Ambient temperature and humidity - \+ from DHT11 sensor to positive rail on breadboard. - \- from DHT11 sensor to negative rail on breadboard. - Signal pin from DHT11 sensor to P23 on the expansion board. #### DS18B20 - Air pump temperature - Red wire from DS18B20 to positive rail on breadboard. - Black wire from DS18B20 to negative rail on breadboard. - Orange wire from DS18B20 to signal rail on breadboard. - 4.7kΩ resistor from signal rail to positive rail on breadboard. - Signal rail on breadboard to P9 on expansion board. #### XKC-Y25-V - Flocculation level sensor - \+ (5-24V) on XKC-Y25-V to positive rail on breadboard. - \- (GND) on XKC-Y25-V to negative rail on breadboard. - Out on XKC-Y25-V to P11 on expansion board. ![](https://i.imgur.com/FoxeBpl.png) ### Battery backup calculations According to [Pycom](https://pycom.io/wp-content/uploads/2018/08/lopy-specsheet.pdf) the LoPy4 draws the following current in it's different power modes in 5V. If we calculate what is draws in watt we get (5V x 37mA = 185mW) when it is in idle and (5V x 92.6mA = 463mW) when transmitting with LoRa. ![](https://i.imgur.com/DnFRn4z.png) In our case we would like to wait about 30 seconds if the power cuts out before we send a message that the power is lost in case it's only a miner outage. If we use a [150mAh 3.7 V battery](https://www.electrokit.com/produkt/batteri-lipo-3-7v-150mah/) we can calculate how many mA the LoPy4 draws at 3V which is the lowest voltage that the battery operate at. We get (185mW / 3V = 61.7mA) when idle and (463mW / 3V = 154.4mA) when transmitting over LoRa. So we would get about nearly 60 minutes of continues transmission of data or about 150 minutes in idle mode. If we take height for that the sensors draw some power and that the battery will decrease over time we still got sufficient time for transmitting one or more last messages with battery power. ### Platform When developing this project I tested Pybytes and Datacake to receive, present and analyzing the created data. I chose the free version of Datacake to be the final choice because it could provide the needed functions to get this proof of work running, but also because it could be white-labeled so it could be used in production environments is this project would end there later. I did not elaborate on installing a TIG-stack but have used InfluxDB and Grafana in previous projects and that could be an alternative to do self-hosting of the services. If this project would later end in a production environment I think Datacake would suite the needs but it would need more investigating of how they handle batch registration of multiple units and how the registration process can be streamlined. Lets say a technician on the field install a unit it should be easy to add it to Datacake. It would also be necessarily to be added to a global dashboard automatically for monitoring by a support team. And also give access to the customer if they also want to check the temperatures and get early warnings before they are sent to the support team. ### The Code The code for this project can be found on [GitHub](https://github.com/moorgrove/wastewater-treatment-plant-monitor/). Download the code as I ZIP file to your computer and open the folder in VS Code. Click on the Upload button in the bottom of the screen to upload the code to the micro computer. To use the LoraWAN function you need to define variables in keys.py that we will cover later. ![](https://i.imgur.com/XHJBrrd.png) #### main.py Main.py contains the following code: - Import libraries that is needed to run the program. - Disable heartbeat on the built in led. The led will instead be used for display a warning that the flocculation level is to low. - Definition of the different pins that will be used by the sensors. With the pins defined in variables it was easy to edit the used pin for debugging purposes. - Initialization of the three different sensor: ```python= # Initialize DS18X20 air pump temperature sensors. oneWire = OneWire(Pin(pinOneWire)) time.sleep(1) oneWireSensors = oneWire.scan() airPumpTemp = DS18X20(oneWire) print('OneWire scan', oneWireSensors) # Initialize DHT 11 Ambient Temperature and humidity sensors. ambientTempHumidity = DHT(Pin(pinAmbientTempHumidity, mode=Pin.OPEN_DRAIN), 0) # Initialize Flocculation fluid level. flocculationFluidLevel = Pin(pinFlocculationFluidLevel, mode=Pin.IN, pull=Pin.PULL_DOWN) ``` - Definition of global variables that will be used in the functions and in the main loop. - Functions that read and store the data in variables from the different sensors. - Functions to join and send data with LoraWAN. - Startup of sensor reading and LoraWAN in threaded functions. This allows the micro controller to read and send data in parallel without halting the program: ```python= # Start threads that collect sensor data. _thread.start_new_thread(readAirPumpTemp, ()) _thread.start_new_thread(readAmbientTempHumidity,()) _thread.start_new_thread(readFlocLevel, ()) # Sleep to let the sensors collect their first value. time.sleep(5) # Join the LoraWan network. _thread.start_new_thread(joinLoraWan, ()) # Start thread that sends data with LoraWAN. _thread.start_new_thread(sendDataLoraWan, ()) ``` - Main loop to print sensor readout in console for debugging purposes. ```python= # Main thread while True: # Print values for debugging purpose. print('Floc level:', flocculationFluidLevelValue) print('Ambient Temp:', ambientTempValue, '| Humidity:', ambientHumidityValue) print('Air pump temp:', list(airPumpsTempValue.values())[0], '|', list(airPumpsTempValue.values())[1]) # Sleep 1 minute before values are printed again. time.sleep(60) ``` #### keys.py The keys file is used to store Lora chip keys. In this file you will later define the device app_eui, app_eui and dev_eui information. #### /lib folder The libraries folder contains the two files that is needed to read the data from DHT11 and DS18B20 sensors. ## Connect the device to The Things Network We will use The Things Network to transmit the data over LoraWAN from the device to a gateway in the The Things Network. I chose this method because the wastewater treatment plant is often located in the countryside and a bit away from the house. Therefore I could not rely on WiFi coverage and LoraWAN with is't long range coverage should be a good fit for this type of project. Another alternative could be NB-IoT from cellular providers but that was not an alternative in this project as I did not have a Pycom device with those functions. The unit will send ambient temperature and humidity, air pump temperature for the two pumps and flocculation status every 30 minutes. In further development some degree of monitoring could be done on locally on the unit itself and send update as soon as trigger points is reached. As 30 minutes is much more often than every week, that the treatment plant should be monitored according to the manufacture, i'm satisfied to get the data every 30 minutes for now. Right now the code is set to transmit with data rate 5 which is equal to SF7, the type with shortest range. One improvement in the could could be to get receive confirmation and if the message did not get to the gateway the device tries again with a higher SF mode with longer transmission range. If WiFi is present in future deployments it could also be possible to send data in real time, lets say every 5 seconds, because WiFi does not have the transmit limitations that LoraWAN has. This would be possible because the unit is power by mains power and don't rely on battery. While battery backup could be an option to send messages that the treatment plant has power issues. This could also be achieved if Datacake doesn't receive any messages in one or two hours. To get the device registered and connected to The Things Network you follow this steps: #### VS Code - In VS Code you create a new file and paste the following code: ```python= from network import LoRa import binascii print(binascii.hexlify(LoRa().mac()).upper()) ``` - Click somewhere inside the console with your mouse. - Press the "Ctrl" and "C" keys on your keyboard a couple of times to exit any code that is already running on your LoPy4. - Press the "Run" button on the bottom of the screen. - You should get a string stat is something like "70B3D5499585FCA1". We will use this later so copy and save it. #### The Things Network - First you need to register an account at [The Things Network using this link](https://account.thethingsnetwork.org/register). - After that you sign in to the [console and chose your region](https://console.cloud.thethings.network/). - You then go to "Applications" and "Add application" in the top right corner of the screen. - Enter a name in the field for "Application ID" and click "Create Application". - Click on "Add end device" on the right side of the webpage. - Select "Manually" in the top menu bar. - In "LoraWAN version" you select "Mac V1.0.3" and for "Frequency plan" you chose the region your located in. In my case "Europe 868-870 MHz (SF9 for RX2 - recommended)" - Insert "DevEUI" with the string that you got earlier in VS Code. Also paste it in the keys.py file. - In "AppEUI" you click on "Fill with zeros" - For "AppKey" you click "Generate" and copy the generated values and paste it in the keys.py file. - Click on "Register device" ![](https://i.imgur.com/UQejRV6.png) After you entered the data in keys.py you save the file, click inside the console and then press "Ctrl" and "C" on the keyboard to exit any running code. Then press the "upload" button and you should see in the console that the code is being uploaded and you should see a text declaring that the unit waiting to join LoraWAN. After a while the unit should join if you have The Things Network coverage in your area. If you go to the page where you registered your device on thethings.network and click on "Live Data" you should see that the unit has joined the network and sent it's first message. ![](https://i.imgur.com/3vM9fxV.png) ## Transmitting the data to Datacake We now need to transfer the incoming data from The Things Network to Datacake. To setup the communication between the networks you follow the guide on the link below. In the guide you will setup web-hook communication from The Things Network to Datacake. Do the steps down to "Scheduling Downlinks", you can skip the rest after that headline. [https://www.thethingsindustries.com/docs/integrations/cloud-integrations/datacake/](https://www.thethingsindustries.com/docs/integrations/cloud-integrations/datacake/) When the communication is established it is time to add the device and configure the dashboard. Start by follow the tutorial on the link below. [https://docs.datacake.de/lorawan/get-started](https://docs.datacake.de/lorawan/get-started) When you come to the options below, skip the section of "Add your Device using a Template" and continue below the headline "[Create your own Device](https://docs.datacake.de/lorawan/get-started#create-your-own-device)": > You now have two options. - You already own a LoRaWAN device and want to add it to Datacake - You create your own LoRaWAN device on Datacake When you configure the "Create Payload Decoder" use the following code for the payload. You find the decoder option in "Configuration" in the device settings. ```javascript= function Decoder(payload, port) { return [ { field: "FLOC_LEVEL", value: payload[0] }, { field: "AMBIENT_TEMP", value: payload[1] }, { field: "AMBIENT_HUMIDITY", value: payload[2] }, { field: "AIR_PUMP_1_TEMP", value: payload[3] }, { field: "AIR_PUMP_2_TEMP", value: payload[4] } ]; } ``` The "Create Database Fields" information should be configured as the picture below. Be careful to select the correct "type" according to the picture. You find this settings in the "Configuration" menu in the device settings. ![](https://i.imgur.com/jVG1aqf.png) ## Presenting the data The [last step](https://docs.datacake.de/lorawan/get-started#create-dashboard) in the tutorial above is to create the dashboard itself for displaying the data. I chose to present it like the picture below. When the screenshot was taken the Flocculation warning is activated as you see in the top left side of the picture. Below that we see the last transmitted values from the different sensors. On the right side we see a chart showing the last two days of temperatures. This gives us a graphical way to see if the temperatures reached abnormal temperatures compared to the ambient temperature. You add widgets by selecting edit slider on the top right side of the screen. You then select "Add Widget" and select "Boolean" for the Flocculation level, "Value" for the other current state values and a "Chart" for the chart with the temperatures. Name the different widgets and select corresponding value in "Device and Fields". ![](https://i.imgur.com/bUkNZky.png) ### Rules To monitor the different values I added two rules. These are Air Pump monitor and Flocculation level monitor. You add a rule by click in "Add Rule" in the top right corner. #### Air pumps ![](https://i.imgur.com/N6KkIGp.png) The Air Pumps is set the sending an e-mail if any of the two pumps average temperature for the last 120 minutes reaches above 60 degrees celsius. ![](https://i.imgur.com/iMI0vYv.png) ![](https://i.imgur.com/diI1yAL.png) #### Flocculation level The Flocculation level is set to send an e-mail if the state changes to "false". ![](https://i.imgur.com/dnz6rMn.png) ### Data retention As this is a proof of concept I went with the "Free" plan in Datacake when adding the sensor and it allows me to have: - 7 days data retention - 500 data points / day - Max. 2 per workspace As we only send values every 30 minutes the data points does not reach the maximum allowed amount and 7 days retention is plenty enough for this test. If this should evolve in I production setup the light package for 1 EUR / month should be sufficient. I chose Datacake as my database as describes before because it could be white-labeled and it also fit the needs for this project very well. ### Conclusion of this project #### The final result I'm very satisfied with the result. The monitoring and the warnings is working but there is also room for further development. In the code I would like to add local detection of abnormal temperatures and low liquid level. And directly send information to Datacake so it can send out e-mail directly. I't would also be possible to do machine learning algorithms to detect if the treatment plants cycles for emptying wastewater is done on regular basis by monitor the air pumps working schedule. If the cycles happens to often the treatment plant is overloaded if there fore example is to many flushes from the toilets. This could also result in a warning. The hardware could also be developed with a special expansion board with screw terminals for the sensors. This would replace the breadboard. Also a case for the unit that make it possible to mount is on one of the sides of the cabinet would be much needed. Link to video with presentation of the project: https://www.youtube.com/watch?v=RsQb2KirnLk ![](https://i.imgur.com/9x90Mfd.jpg) And a video of the result. ![](http://hlund.se/gifs/wastewater-treatment-plant.gif) #### Air pump sensors The temperature sensor attached to one of the air pumps. ![](https://i.imgur.com/jh9ULAH.jpg) #### Liquid level sensor The level sensor attached to the barrel with liquid. This is actually placed under ground down in the treatment but I spare you the pictures with the sewage water. ![](https://i.imgur.com/Abn45Ui.jpg) Simulating the liquid level in barrel with my fingers. The led show red when no liquid is detected: ![](http://hlund.se/gifs/liquid-level.gif) The Pycom LoPy4 and the breadboard. ![](https://i.imgur.com/ZfGwFF9.jpg)