Tutorial – Part 3 – Using an Analog to Digital Converter with your Raspberry Pi
Did you ever want to read a voltage (rather than a 1 or 0) on your Raspberry Pi? You can do this with an Analog to Digital Converter (ADC).
Have you ever wanted to read analog (voltage level) levels and sensors on your Raspberry Pi? While you can read digital sensors with the Raspberry Pi, there is no built in analog to digital converter on your Raspberry Pi.
In this Tutorial, you will learn how use an 4 Channel 16 bit Analog to Digital Converter (ADC) on your Raspberry Pi.
In This Tutorial
We are going to show you how to read these four sensors:
- An O2 (Oxygen Gas Sensor)
- An analog light sensor (light variable resistor)
- An analog air quality sensor
- A voltage divider connected to 5V on the Raspberry Pi
In part 1 to this tutorial, we discussed each of the various parts used to build this project.
The Four Parts to this Tutorial
Part 1 - Overview of the ADC Raspberry Pi Project Part 2 - Hooking up the Hardware Part 3 - The ADC Raspberry Pi Project Software Part 4 - Two Really Cool Experiments with the ADC Raspberry PiThe Software
This ADC board is based on the TI ADS1115 16 bit 4 channel I2C ADC. Any software that supports the ADS1116 will work (either Arduino or Raspberry Pi) and this board supports 3.3V and 5V power supplies. We are going to use two examples of Python Software to read the ADC devices. The first is a simple test of the ADS1115 board, reading all the values, doing a little math and then printing the values out to the screen. This test program is included in the Raspberry Pi DataLogger shown below.
The second piece of software is the Raspberry Pi DataLogger software that periodically samples all four channels and then builds graphs that can be displayed in a browser.
Installing the Raspberry Pi DataLogger
In order to run the testADS115.py program, we need to first install the Raspberry Pi DataLogger. We will do this in four steps. First, we will install the github archive of the DataLogger. Secondly, we will run the testADS1115.py program. Thirdly, we will install the rest of the DataLogger software, and finally, we will run the DataLogger to generate graphs for all four of the ADS1115 channels for our test project.
DataLogger Python Software
To install the DataLogger software do the following:
cd git clone https://github.com/switchdoclabs/SDL_Pi_DataLogger.git
This installs the DataLogger software which includes the testADS1115.py software. We will come back and install the rest of the DataLogger support software later.
Running the First Test of the ADS1115 setup
In a terminal window on the Raspberry Pi, type the following:
cd cd SDL_Pi_DataLogger
Then, type the following command:
sudo python testADS1115.py
Remember in Part 2, we hooked up the following sensors:
- – Channel 0 – Air Quality Sensor
- – Channel 1 – Oxygen Sensor
- – Channel 3 – Light Sensor
- – Channel 4 – Voltage Divider hooked up to 5V on the Pi
If you have hooked up all the hardware correctly as in Part 2 of this tutorial, you should see something very similar to this:
-------------------- Channel 0 =0.171187V raw=914 raw=0x 392 Channel 1 =2.436375V raw=0x32C2 O2 Percent= 22.05 Channel 2 =2.577750V raw=0x35B6 Channel 3 =0.484875V raw=0x A1B -------------------- -------------------- Channel 0 =0.171187V raw=911 raw=0x 38F Channel 1 =2.436375V raw=0x32C2 O2 Percent= 22.05 Channel 2 =2.570625V raw=0x35B4 Channel 3 =0.484125V raw=0x A1A -------------------- -------------------- Channel 0 =0.170813V raw=908 raw=0x 38C Channel 1 =2.436375V raw=0x32C1 O2 Percent= 22.05 Channel 2 =2.574000V raw=0x360D Channel 3 =0.483375V raw=0x A20 -------------------- -------------------- Channel 0 =0.171187V raw=908 raw=0x 38C Channel 1 =2.436375V raw=0x32C2 O2 Percent= 22.05 Channel 2 =2.590500V raw=0x35E3 Channel 3 =0.485250V raw=0x A1F -------------------- -------------------- Channel 0 =0.171750V raw=917 raw=0x 395 Channel 1 =2.436187V raw=0x32C1 O2 Percent= 22.05 Channel 2 =2.573437V raw=0x3611 Channel 3 =0.478875V raw=0x A1F --------------------
Installation of the Raspberry Pi Software
We will need to install the following three major software packages. MySQL/phpMyAdmin/Apache web server, apscheduler, MatPlotLib and then the DataLogging Python software itself.
MySQL/phpMyAdmin/Apache
MySQL is used to store the data from the DataLogger software to provide a database that can be used for later analysis and graphing. The phpMyAdmin software is used to setup and control the MySQL database server and finally Apache is used to serve phpMyAdmin webpages and the DataLogger graphs.
Installing MySQL/phpMyAdmin/Apache – Use the following excellent tutorial: https://pimylifeup.com/raspberry-pi-mysql-phpmyadmin/
Apscheduler
apscheduler is a very good Python package that is used to schedule events from within a main Python program that run in different threads. One good thing about running tasks like this in another thread, is that a hang in one of the threads does not stop the whole system. Just that thread.
sudo pip install setuptools --upgrade sudo pip install apscheduler
MatPlotLib
MatPlotLib is a python library for making publication quality plots using methods similar to MATLIB on the Raspberry Pi. You can output formats such as PDF, Postscript, SVG, and PNG.
Install the following packages (This will take quite a while)
$ sudo apt-get install libblas-dev ## 1-2 minutes $ sudo apt-get install liblapack-dev ## 1-2 minutes $ sudo apt-get install python-dev ## Optional $ sudo apt-get install libatlas-base-dev ## Optional speed up execution $ sudo apt-get install gfortran ## 2-3 minutes $ sudo apt-get install python-setuptools ## ? $ sudo easy_install scipy ## 2-3 hours $ sudo apt-get install python-matplotlib ## 1 hour
Now you have all the required software installed.
Two last things:
- If you have phpMyAdmin, go to the SQL Tab and copy the contents of DataLogger.sql into the MySQL Box and hit “Go” to build the database. If not, use the following commands:
example: mysql -u root -p < DataLogger.sql user: root password: password
Obviously with these credentials, don’t connect port 3306 to the Internet. Change them if you aren’t sure.
- Copy DataLogger.html to /var/www/html:
sudo cp DataLogger.html /var/www/html
Now you are ready to go.
Running the ADC DataLogger
Now we are ready to run the full Analog to Digital DataLogger and look at some graphs of our data.
In a terminal window on the Raspberry Pi, type the following:
cd cd SDL_Pi_DataLogger
Then, let’s start the DataLogger.
sudo python DataLogger.py
The you should see something similar to this. If you have errors, go back and check your setup.
SDL_Pi_Datalogger Will work with the INA3221 SwitchDoc Labs Breakout Board Will work with the ADS1115 SwitchDoc Labs Breakout Board Will work with OurWeather - Complete Weather Kit Will work with SwitchDoc Labs WxLink Wireless LInk Program Started at:2017-01-03 09:14:07 readADS1115Data - The time is: 2017-01-03 09:14:07.021874 ------------------------------ writing SQLdata query=INSERT INTO ADS1115Table(timestamp, deviceid, channel0_voltage, channel0_raw, channel1_voltage, channel1_raw, channel2_voltage, channel2_raw, channel3_voltage, channel3_raw) VALUES(CURRENT_TIMESTAMP(), 0, 0.166, 885, 2.440, 13014, 2.592, 13870, 0.485, 2588) buildADS1115Graph0 - The time is: 2017-01-03 09:14:07.099378 2000 query= (SELECT timestamp, deviceid, channel0_voltage, channel0_raw, channel1_voltage, channel1_raw, channel2_voltage, channel2_raw, channel3_voltage, channel3_raw, id FROM ADS1115Table ORDER BY id DESC LIMIT 2000) ORDER BY id ASC (datetime.datetime(2017, 1, 1, 22, 40, 17), 0L, 0.196, 1046L, 2.419, 12899L, 0.645, 3429L, 0.486, 2589L, 391L) ('count of t=', 2000) ------ADS1115Graph0 finished now buildADS1115Graph1 - The time is: 2017-01-03 09:14:11.459563 2000 query= (SELECT timestamp, deviceid, channel0_voltage, channel0_raw, channel1_voltage, channel1_raw, channel2_voltage, channel2_raw, channel3_voltage, channel3_raw, id FROM ADS1115Table ORDER BY id DESC LIMIT 2000) ORDER BY id ASC (datetime.datetime(2017, 1, 1, 22, 40, 17), 0L, 0.196, 1046L, 2.419, 12899L, 0.645, 3429L, 0.486, 2589L, 391L) ('count of t=', 2000) ------ADS1115Graph1 finished now buildADS1115Graph2 - The time is: 2017-01-03 09:14:14.952826 2000 query= (SELECT timestamp, deviceid, channel0_voltage, channel0_raw, channel1_voltage, channel1_raw, channel2_voltage, channel2_raw, channel3_voltage, channel3_raw, id FROM ADS1115Table ORDER BY id DESC LIMIT 2000) ORDER BY id ASC (datetime.datetime(2017, 1, 1, 22, 40, 17), 0L, 0.196, 1046L, 2.419, 12899L, 0.645, 3429L, 0.486, 2589L, 391L) ('count of t=', 2000) ------ADS1115Graph2 finished now buildADS1115Graph3 - The time is: 2017-01-03 09:14:19.056077 2000 query= (SELECT timestamp, deviceid, channel0_voltage, channel0_raw, channel1_voltage, channel1_raw, channel2_voltage, channel2_raw, channel3_voltage, channel3_raw, id FROM ADS1115Table ORDER BY id DESC LIMIT 2000) ORDER BY id ASC (datetime.datetime(2017, 1, 1, 22, 40, 17), 0L, 0.196, 1046L, 2.419, 12899L, 0.645, 3429L, 0.486, 2589L, 391L) ('count of t=', 2000) ------ADS1115Graph3 finished now Jobstore default: readADS1115Data (trigger: interval[0:01:00], next run at: 2017-01-03 09:15:23 PST) tick (trigger: interval[0:01:00], next run at: 2017-01-03 09:15:23 PST) doAllGraphs (trigger: cron[minute='*/2'], next run at: 2017-01-03 09:16:00 PST) killLogger (trigger: interval[6 days, 22:40:00], next run at: 2017-01-10 07:54:23 PST) Press Ctrl+C to exit readADS1115Data - The time is: 2017-01-03 09:15:23.564634 ------------------------------ Tick! The time is: 2017-01-03 09:15:23.582201 writing SQLdata query=INSERT INTO ADS1115Table(timestamp, deviceid, channel0_voltage, channel0_raw, channel1_voltage, channel1_raw, channel2_voltage, channel2_raw, channel3_voltage, channel3_raw) VALUES(CURRENT_TIMESTAMP(), 0, 0.170, 905, 2.438, 13003, 2.605, 13846, 0.485, 2585) buildADS1115Graph0 - The time is: 2017-01-03 09:16:00.006283 2000 query= (SELECT timestamp, deviceid, channel0_voltage, channel0_raw, channel1_voltage, channel1_raw, channel2_voltage, channel2_raw, channel3_voltage, channel3_raw, id FROM ADS1115Table ORDER BY id DESC LIMIT 2000) ORDER BY id ASC (datetime.datetime(2017, 1, 1, 22, 41, 17), 0L, 0.197, 1049L, 2.419, 12903L, 0.647, 3438L, 0.486, 2590L, 392L) ('count of t=', 2000) ------ADS1115Graph0 finished now buildADS1115Graph1 - The time is: 2017-01-03 09:16:03.053961 2000 query= (SELECT timestamp, deviceid, channel0_voltage, channel0_raw, channel1_voltage, channel1_raw, channel2_voltage, channel2_raw, channel3_voltage, channel3_raw, id FROM ADS1115Table ORDER BY id DESC LIMIT 2000) ORDER BY id ASC (datetime.datetime(2017, 1, 1, 22, 41, 17), 0L, 0.197, 1049L, 2.419, 12903L, 0.647, 3438L, 0.486, 2590L, 392L) ('count of t=', 2000) ------ADS1115Graph1 finished now buildADS1115Graph2 - The time is: 2017-01-03 09:16:06.501289 2000 query= (SELECT timestamp, deviceid, channel0_voltage, channel0_raw, channel1_voltage, channel1_raw, channel2_voltage, channel2_raw, channel3_voltage, channel3_raw, id FROM ADS1115Table ORDER BY id DESC LIMIT 2000) ORDER BY id ASC (datetime.datetime(2017, 1, 1, 22, 41, 17), 0L, 0.197, 1049L, 2.419, 12903L, 0.647, 3438L, 0.486, 2590L, 392L) ('count of t=', 2000) ------ADS1115Graph2 finished now buildADS1115Graph3 - The time is: 2017-01-03 09:16:09.982362 2000 query= (SELECT timestamp, deviceid, channel0_voltage, channel0_raw, channel1_voltage, channel1_raw, channel2_voltage, channel2_raw, channel3_voltage, channel3_raw, id FROM ADS1115Table ORDER BY id DESC LIMIT 2000) ORDER BY id ASC (datetime.datetime(2017, 1, 1, 22, 41, 17), 0L, 0.197, 1049L, 2.419, 12903L, 0.647, 3438L, 0.486, 2590L, 392L) ('count of t=', 2000) ------ADS1115Graph3 finished now readADS1115Data - The time is: 2017-01-03 09:16:23.568773 ------------------------------ Tick! The time is: 2017-01-03 09:16:23.580755 writing SQLdata query=INSERT INTO ADS1115Table(timestamp, deviceid, channel0_voltage, channel0_raw, channel1_voltage, channel1_raw, channel2_voltage, channel2_raw, channel3_voltage, channel3_raw) VALUES(CURRENT_TIMESTAMP(), 0, 0.169, 903, 2.438, 13001, 2.617, 13879, 0.486, 2592)
And after a few minutes, open up a browser to:
https:///DataLogger.html and you will see graphs
Note: Replace with your local IP Number. You can find your local IP number by typing:
ifconfig
Then you can read your IP number from the appropriate interface (the wlan0 in our case – 192.168.1.62 as below).
eth0 Link encap:Ethernet HWaddr b8:27:eb:2c:33:13 inet6 addr: fe80::b6db:516d:7659:b6f9/64 Scope:Link UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:121546 errors:0 dropped:0 overruns:0 frame:0 TX packets:121546 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1 RX bytes:12010576 (11.4 MiB) TX bytes:12010576 (11.4 MiB) wlan0 Link encap:Ethernet HWaddr b8:27:eb:79:66:46 inet addr:192.168.1.62 Bcast:192.168.1.255 Mask:255.255.255.0 inet6 addr: fe80::ba27:ebff:fe79:6646/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:1418961 errors:0 dropped:122860 overruns:0 frame:0 TX packets:781759 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:240284835 (229.1 MiB) TX bytes:386959850 (369.0 MiB)
Here are our graphs after running overnight. Note that the Air Quality varies, the O2 is flat (as expected), you can see the lights being turned on and off in the Laboratory and you can see the Voltage divider switch being moved from divide by 10 to divide by 3 and back again.
Coming In Part 4
In part 4, we will show some results of two really cool experiments. One with the Air Quality sensor and the other with the Oxygen sensor. Stay tuned!