1 |
Aim |
2 |
The aim of the project is to provide visibility of when the pump from the outflow chamber of a septic system is operating. then if it is running for too long we want to be sent an alert to notify us as this is a potential indicator of a problem (blockage leading to overflow). |
3 |
The method that we will use to achieve this will be to measure the current flowing to the pump and to make that data available to a prometheus / grafana instance that will then be used for visibility / alerting. |
4 |
This project will be leveraging analready installed instance of prometheus / grafana. an established wifi network for connectivity. access to some soldering equipment |
5 |
Current sensor: an acs712 based module. we'll use a 5a unit since the pump is not expected to exceed 500w. analog to digital converter: the ads1015 will be more than sufficient for our needs. enclosures: the current sensor must be protected to prevent contact with the live terminals. the a2d converter should be protected where possible. voltage divider: we will use three 1k ohm resistors. wiring: hook up wires with female dupont connectors and appropriate wiring for the load connection (ı used 2.5mm cabling) compute: raspberry pi zero w with case, micro sd card, case and headers. |
6 |
This project is one that has been born out of necessity. our septic system is a good unit that operates as required however, there have been a few occasions where we have had the outflow from the final chamber blocked for one reason or another (and there have been a variation here). the end result of this has been the increase in water level in the final chamber. ın two cases this has not been caught in spite of the inbuilt alarm (that uses a float switch and an annunciator in the garage) resulting in the septic system flooding (not good). to add some redundancy to the system and to provide remote alerting capability ı decided to add my own alerting system. ı considered a couple of different options including; looking at the outflow from the septic tank and measuring the volume of water pumped. while possible, this option involves moving parts in a portion of the system that is space constrained and the method for alerting would involve determining theabsenceof a thing over a period of time that would be indeterminate. an additional (but different) float switch in the final chamber. this was practical and do-able, but the environment is fairly harsh (water, humidity, 'stuff') and it would have been an alert that occurs later in the process of failure (similar to the default installed alarm which once had its float get stuck and failed to alert properly) current sensing for the pump operation. this has the advantage of providing very quick feedback if there is a problem and keeps any measurement in a 'cleaner' space. the down side is that this does mean connecting a sensor to a high voltage part of an electrical circuit and therefore requires doing the work within local regulations and taking the appropriate safety precautions. ı opted for the current sensing option since it was the best of the three options in terms of getting a good result (early detection). ı have the advantage of being a registered electrical service technician and therefore am able to do the work safely and appropriately. |
7 |
The current sensor we will use is based on the acs712 module. ı sourced mine frombanggood, but they are widely available for low cost. this specific one used here is the acs712elc-05b which can measure plus or minus 5 amps corresponding to an analog output of 185 mv/a. the unit is powered from a 5v supply, so we will be connecting it to a 5v output from the pi and using a voltage divider to reduce the voltage output appropriately for input to the analog to digital converter ıf you have access to a 3d printer, you can print an enclosure from the designhere. to enable the current sensing option we will also need to include a digital to analog converter. this should be a fairly simple task similar to the method usedherefor measuring levels from a gas sensor. ıf you have access to a 3d printer, you can print an enclosure for the d2a converter from the designhere. the connection layout is as below (again very similar to the methodhere); |
8 |
The installation below was carried out using the raspbian 'buster' os. this is available from theraspberry pi website. ınstall the os onto an sd card and power up the pi. the first thing we should do is to configure the pi appropriately for use. some of the steps may or may not be needed depending on your circ***stances (i.e. will you be using a model pi with a physical ethernet connection or wifi). where in doubt check out one of theraspberry pi computing bookswhich will walk through the options. we can start by running the command; sudo raspi-config this will give us access to the options for localisation (wifi country, time-zone, locale) but most importantly (in this case) for enabling the ı2c protocol. since the ads1015 uses the ı2c protocol to communicate, we need to load the appropriate kernel support modules onto the raspberry pi to allow this to happen. since we are using the raspbian distribution there is a simple method to start the process of configuring the pi to use the ı2c protocol. on the first page select the ınterfacing options with the arrow keys and then tab to select then we select the ı2c option for automatic loading of the kernel module; would we like the arm ı2c interface to be enabled? yes we would; press 'ok' to acknowledge that the interface is enabled. press tab to select 'finish'. once this is done we should do what we should always do when embarking on a fresh install on a raspberry pi and that's to update and upgrade the software. sudo apt-get update sudo apt-get upgrade from here, you should look to configuring a static ıp address or a wifi connection if desired. again, where in doubt check out one of theraspberry pi computing booksfor options. |
9 |
There's still some work to do to get things sorted, especially for the ı2c functionality. we need to check the/etc/modulesfile using: sudo nano /etc/modules where we need to ensure that the following line is at the end of the file: i2c-dev under some circ***stances (depending on the kernel version we are using) we would also need to update the/boot/config.txtfile. we can do this using; sudo nano /boot/config.txt make sure that the following line is uncommented (the '#' is removed from in front of the line) in the file; dtparam=i2c_arm=on then we should load tools for working with ı2c devices using the following command; sudo apt-get install i2c-tools ... and now we should reboot to load the 'config.txt' file if we changed it earlier sudo reboot we can now check to see if our sensor is working using; sudo i2cdetect -y 1 ıf we were using an older b model of raspberry pi with 256mb of ram, we would need to usesudo i2cdetect -y 0. the output should look something like; pi@raspberrypi ~ $ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- this shows us that we have detected our ads1015 on address '48' (the ads1015 can support four different addresses as shown on page 17 of thedata sheet). now we want to install the python libraries designed to read the values from the ads1015. the library we are going to use was designed specifically to work with theadafruit ads1015/ads1115 adcs. ın carrying out this library development, adafruit have invested a considerable amount of time and resources. ın return please consider supporting adafruit and open-source hardware by purchasing products fromadafruit! we need to change our default version of python running on the pi to python 3 we can check what version is running by executing the following command; python --version ıf that indicates python 2.x, then we need to change that. to find out what version of python 3 is available, run the following ls /usr/bin/python* hopefully you will see a 3.x version. to change the default python version system-wide we can use theupdate-alternativescommand. first list all available python alternatives; update-alternatives --list python there is a good chance that the output will be something like; update-alternatives: error: no alternatives for python the above error message means that no python alternatives have been recognised by theupdate-alternativescommand. for this reason we need to update our alternatives table and include both python 2 and 3. just check that the numbers for the versions in the commands below match the versions that the previous command indicated were installed. sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1 sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.7 2 the last number on each of the previous lines is the priority, with the higher number being thehighest priority we can check again by running; python --version now the default version should be python 3 ınstall pip3 (for python 3) sudo apt-get install python3-pip then install setuptools via pip sudo pip3 install --upgrade setuptools ınstall python libraries pip3 install rpı.gpıo adafruit-blinka ınstall the adc libraries (note: ı occasionally get errors when carrying out the following command and need to re-run it a few times); sudo pip3 install adafruit-circuitpython-ads1x15 we should now be able to run a simple program to test our sensor. create a file calledcurrent-test.py(usingnano) with the following contents in the home directory (this code can be downloaded from githubhere); #!/usr/bin/python #encoding:utf-8 import time import board import busio import adafruit_ads1x15.ads1015 as ads from adafruit_ads1x15.analog_in import analogın # create the ı2c bus i2c = busio.ı2c(board.scl, board.sda) # create the adc object using the ı2c bus ads = ads.ads1015(i2c) ads.gain = 1 # create single-ended input on channel 0 chan = analogın(ads, ads.p0) # create differential input between channel 0 and 1 #chan = analogın(ads, ads.p0, ads.p1) print("{:>5}\t{:>5}".format('raw', 'v')) while true: readvalue = 0 maxvalue = 0 for i in range(0,300): readvalue = chan.value if (readvalue > maxvalue): maxvalue = readvalue # write the current integer value to a file f = open("current.txt", "w") f.write(str(maxvalue-6680)) f.close() print("{:>5}\t{:>5.5f}".format(maxvalue-6680, chan.voltage)) time.sleep(0.5) the file above is essentially thesimpletest.pyfile that adafruit publish with some amendments. one of these is that we are only looking at an instantaneous measurement of current. for ac current that could be anywhere along the sine wave in a positive or negative direction. the solution (which is in the code) is to put in a small loop that determines the maximum value while the loop is running. this indicates the peak value in one direction. as well as this we can reduce the gain and put in an offset that allows our returned value to read close to zero with no current flowing. ıt also includes a small section that writes our current value to a text file. we will use this to contain our value to pa*** onto prometheus / grafana for monitoring later. now we can run it using python current-test.py we should see a print out of the values represented by the value of the adc as an integer and the voltage from the adc as a floating point value (this is without any current flowing in our sensor). raw v -8 0.83203 56 0.82403 40 0.82603 56 0.82803 56 0.82403 56 0.82403 and we should also have a file (called 'current.txt') created and updated with the most recent reading. |
10 |
ı configured the current measurement as a service as while testing the installation ı noticed that the program would occasionally fail at random times. this will allow it to restart if necessary and to start on boot. the first step in this process is to create a service file which we will callcurrent.service. we will have this in the/etc/systemd/system/directory. sudo nano /etc/systemd/system/current.service paste the following text into the file and save and exit (the file is alsoavailable from github). [unit] description=python current measurement after=multi-user.target [service] restart=on-failure restartsec=10s workingdirectory=/home/pi user=pi execstart=/usr/bin/python /home/pi/current.py [ınstall] wantedby=multi-user.target the service file can contain a wide range of configuration information and the case above there is 'restart' which will restart (duh) the service if it fails and 'execstart' which describe where to findpythonand thecurrent.pyexecutable. the other important part allows the service to restart if it fails. before starting our new service we will need to reload the systemd manager configuration again. sudo systemctl daemon-reload now we can start the current service. sudo systemctl start current you shouldn't see any indication at the terminal that things have gone well (or otherwise), so it's a good idea to check current's status as follows; sudo systemctl status current we should see a report back that indicates (amongst other things) that 'current' is active and running. now we will enable it to start on boot. sudo systemctl enable current |
11 |
ıf you haven't used prometheus and grafana for monitoring before, let me take a moment to enthusiastically recommend it to you. combined, they make a very powerful platform for checking up on your various pieces of ıt and they are tools that are widely used in the outside world (in other words, the skills you build in using it are transferable). better yet, they will run really well on a raspberry pi! ı'm not going to describe how to install both here, but ı would recommend working your way throughthis bookwhich you can read online or download (for free) to step through the process. a***uming you have an instance of prometheus / grafana available, we can add a custom exporter for monitoring our current as follows; we are going to add this instrumentation via theofficially supported librariesfor python. when implemented it will gather our information and expose it via a http endpoint (the same way that prometheus'snode_exporterdoes withhttp://<ıp address>:9100/metrics. our metric name will reflect the type of thing that is being measured. you can see a range of good examples in the metrics exposed fromnode_exporter. for example 'cpu_frequency' and 'boot_time'. for our measurements we will have 'current'. the last part of the name should describe the units being used for the measurement (in plural form). ın our case the current will be in 'milliamps'. the full name of our metrics will therefore be; septic_current_milliamps to use the custom exporter on our target machine (in this case the ıp address of the pi on the septic tank is10.1.2.210), we’ll need to install the prometheus client library for python and pip as follows; sudo apt-get install python-pip pip install prometheus_client to collect information, we need to make sure that we can gather it in a way that will suit our situation. our 'current' value is read by a python script that is running in the background and writing the value to a file called 'current.txt'. so, our python exporter script (which in this case is namedseptic-exporter.py) looks like the following (this file is alsoavailable from github); import prometheus_client import time update_perıod = 15 current = prometheus_client.gauge('septic_current_milliamps', 'value relating to current flow with zero being effectivly nil.') if __name__ == '__main__': prometheus_client.start_http_server(9999) while true: with open('/home/pi/current.txt', 'r') as f: current_value = f.readline() try: float(current_value) current.set(float(current_value)) except: pa*** time.sleep(update_perıod) the main actions in our exporter can be summarized by the following entries: ımport the prometheus client python library. declare gauge metric with the metric name that we decided on earlier. ınstantiate an http server to expose metrics on port 9999. start a measurement loop that will read our metric value every 15 seconds gather our metric value from our text file. ın the same way that we made sure that our current measurement program starts up simply at boot, we will configure our python exporter script as a service and have it start at boot. the first step in this process is to create a service file which we will callseptic_exporter.service. we will have this in the/etc/systemd/system/directory. sudo nano /etc/systemd/system/septic_exporter.service paste the following text into the file and save and exit (this file is alsoavailable at github). [unit] description=septic exporter after=multi-user.target [service] user=pi execstart=/usr/bin/python /home/pi/septic-exporter.py [ınstall] wantedby=multi-user.target the service file can contain a wide range of configuration information and in our case there are only a few details. the most interesting being the 'execstart' details which describe where to findpythonand theseptic-exporter.pyexecutable. before starting our new service we will need to reload the systemd manager configuration again. sudo systemctl daemon-reload now we can start the septic_exporter service. sudo systemctl start septic_exporter you shouldn't see any indication at the terminal that things have gone well, so it's a good idea to check septic_exporter's status as follows; sudo systemctl status septic_exporter we should see a report back that indicates (amongst other things) that septic_exporter is active and running. now we will enable it to start on boot. sudo systemctl enable septic_exporter the exporter is now working and listening on the port:9999 to test the proper functioning of this service, use a browser with the url of our current measuring pi:http://10.1.2.210:9999/metrics this should return a lot lot statistics. some of them will look a little like this; # help septic_current_milliamps value relating to current flow with zero being effectivly nil. # type septic_current_milliamps gauge septic_current_milliamps -520.0 there are a lot more metrics than just our septic info, but you can see our metrics there. now that we have a computer exporting metrics, we will want it to be gathered by prometheus |
12 |
We need to add the ıp address of our new metrics source to the prometheusprometheus.ymlfile. to do this we can simply add the ıp address of a node that is running the septic_exporter as a new target and we are good to go. on our prometheus server; nano /home/pi/prometheus/prometheus.yml at the end of the file add the ıp address of our new node- targets: ['10.1.2.210:9999']; sc****e_configs: # the job name is added as a label `job=<job_name>` # to any timeseries sc****ed from this config. - job_name: 'prometheus' # metrics_path defaults to '/metrics' # scheme defaults to 'http'. static_configs: - targets: ['localhost:9090'] - targets: ['10.1.1.109:9100'] - targets: ['10.1.2.210:9999'] then we restart prometheus to load our new configuration; sudo systemctl restart prometheus now if we return to our prometheus guı to check which targets we are sc****ing we can see our new node at 10.1.2.210. |
13 |
Making sure that we can see what is happening with our sensor seems like a really good idea. check out the book fora good overview of the process, and for those who would like a very simple graph in json format for importing, there is one available ingithub here. |
14 |
Part of the point for this entire project was that ı wanted to know when the pump for the system was running for too long. grafana and its alerting feature are the end game for that problem. alerts in grafana allow us to set limits on our graphs such that when they are exceeded, we can send out notifications (for instance have one that indicated a drop in temperature that sent an alert to let you know to cover up delicate seedlings or an increase in used disk space that indicated a problem on a computer). looking at a graph of data that represents the operation of our pump (via the measurement of the current that it's drawing), we can set an alert that will trigger if our current draw goes above 1000 for more than 5 minutes (given that our pump will drain the final chamber in just under 2 minutes, this is a fair time). check out thebook to see an explanationfor configuring grafana to enable sending email alerts and for adding an alert to our graph. there is a grafana panel saved ingithubthat includes an alerting component. |