Tutorial – Part 3 – Using an Analog to Digital Converter with your Raspberry Pi

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 Pi

The Software

Raspberry Pi ADCThis 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
--------------------

 

Raspberry Pi 3

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:

  1. 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.

  2. 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.

Analog to Digital

 

Analog to Digital

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!