In this revamped tutorial we are going to go over the basics of using both versions of our Raspberry Pi 16 Channel Analog Input HAT. These boards are designed to give the Raspberry Pi analog read capabilities similar to those found on the Arduino. Our boards can provide 16 channels of analog input at 10 bit resolution using two onboard MCP3008 Analog to Digital Converters (ADCs). The tutorial will start with the very basics including soldering the header, configuring the Raspberry Pi’s operating system, how to connect different analog sensors to the board, the pull up/pull down resistor options, and how to read each channel using Python.
About The Boards:
The 16 Channel Analog Input HAT was designed right here at BC Robotics – it isn’t the most complicated board out there – just a few components and two MCP3008 ADCs. It is common to see the MCP3008 chipset used with the Raspberry Pi – in this case we have just made it into a finished board – something a little more suited to permanent applications. The board uses both SPI channels on the Pi (one per MCP3008 chip) and features 10 bit resolution, 0 – 3.3V range, and integrated resistor pads for creating voltage dividers with basic resistive sensors. The board is available unassembled (no headers installed) and fully assembled (no soldering required).
This tutorial will be requiring a few common parts depending on which version of the board you are using:
This board is offered in both an assembled and “bare bones” version. The assembled version ships fully assembled and requires no soldering under most circumstances.
The bare bones version is intended for users wishing to solder their own preferred connectors or for custom integrations. For those using the bare bones version: we will start with a quick look at assembling the board. If you are using the assembled version of this board, feel free to skip ahead to Step 6.
First we need to solder the header that allows this board to plug into the Raspberry Pi. We recommend using this header, but any compatible Raspberry PI GPIO header will work. If you haven’t soldered before, or want a quick refresher course, have a look at this awesome comic: Soldering Is Easy! https://mightyohm.com/…/FullSolderComic_EN.pdf
Start by Tacking two opposite corners of the connector in place and checking the connector alignment. We do this to ensure the connector is sitting correctly before soldering all 40 pins; once these have all been soldered, it is very difficult to adjust the alignment.
Next, we are going to solder in the headers for each of the ADC inputs. The holes are 2.54mm (O.100″) pitch and will fit any standard breakaway headers. Alternatively, if you know this board is going to be stacked with another board on top (or clearance is an issue), these 4 x 3 Right Angle headers will also work. For this example, we are using standard 40 pin breakaway headers.
Just like the other header, tack one pin in place for each piece, check the alignment, and solder the remaining pins.
Before we get the Pi powered up, you should have a microSD card pre-installed with Raspberry Pi OS. We used the most current version available at the time of writing this tutorial. If you do not have it installed – head over to the Raspberry Pi Foundation website to get that sorted.
Once this has been completed, we are going to insert the microSD card into the Pi. Your keyboard, mouse and monitor should also be connected at this time. Power up the Pi by plugging in the Power Supply. Once the Pi has done its initial boot of the operating system you should arrive at a desktop. A dialogue should appear for initial configuration – we will take care of this in the next step.
In recent versions of Raspbian, most initial setup can be done by following the dialogue that pops up on first boot up. However, we do need to set up a few additional things once this is initial configuration is completed. Follow through the initial setup, if prompted to reboot – go ahead and do that as well.
Once all of that has been completed, we can go ahead and configure a few more things. Click the Raspberry Logo in the top left corner, scroll down to Preferences, and select “Raspberry Pi Configuration”.
On the third tab we are going to want to enable the SPI interface. This is the interface our ADCs are connected to.
If prompted to reboot, click yes. Once the Pi boots back up we can proceed.
Before we can install the library and set up the ADCs, we need internet connectivity. If you are using WiFi, this was probably already set up during the initial configuration. If it isn’t working, or you skipped that step, it can be accessed by clicking the connectivity logo (located beside the Volume control in the top right corner of the screen).
Ethernet is as simple as plugging it into the Pi – if you are planning to use ethernet, go ahead and plug this in if you haven’t already.
To read each of the MCP3008 ADC chips we will be using a simple Python 3 library we have put together. The library can be added by typing a couple of commands into the terminal window:
Run each of these commands (in order!) by typing them in and hitting enter:
sudo apt-get update
pip3 install bcr-libraries
We are ready to write some code – start up your favorite Python editor and let’s go! We aren’t going to write anything too complicated – just a basic bit of code to read a channel from either of the ADCs we have on board. This code can then be used going forwards to work this ADC board into your project!
import time
interval = 1 #How long we want to wait between loops (seconds)
while True:
time.sleep(interval)
Before we can read either of the ADCs, we will need to create the basic framework of the program. This means we need to import the time library, create our loop, and set the interval we want to pause the code each time the loop has completed. For those unfamiliar with Python, note that the white spaces (tabs and spaces) are very important in this language so be sure to format exactly as shown in the example.
Libraries are added to the project using the import command. On the first line we are importing the time library. On line 3 we define a variable to store the length of time in seconds that we want to sleep the program during each loop of the code. Next, we want to create the loop itself – in Python this can be done in a variety of ways; “While true:” works well. Note that when you press “Enter” the next line becomes indented. Finally, on line 8 we “sleep” or pause our program using the variable we set above. The end result is a program that starts, and then runs whatever code we stick in the loop once a second.
Note: Because we are going to be adding code over the next few steps, each new line we add will be highlighted in the example code and the line number will correspond to notes below the code.
import time
from bcr_mcp3008 import MCP3008
adc0 = MCP3008(device = 0)
adc1 = MCP3008(device = 1)
interval = 1 # How long we want to wait between loops (seconds)
while True:
time.sleep(interval)
Before we can read either of the ADCs, we will need to create the basic framework of the program. This means we need to import the time library, create our loop, and set the interval we want to pause the code each time the loop has completed. For those unfamiliar with Python, note that the white spaces (tabs and spaces) are very important in this language so be sure to format exactly as shown in the example.
Libraries are added to the project using the import command. On the first line we are importing the time library. On line 3 we define a variable to store the length of time in seconds that we want to sleep the program during each loop of the code. Next, we want to create the loop itself – in Python this can be done in a variety of ways; “While true:” works well. Note that when you press “Enter” the next line becomes indented. Finally, on line 8 we “sleep” or pause our program using the variable we set above. The end result is a program that starts, and then runs whatever code we stick in the loop once a second.
Note: Because we are going to be adding code over the next few steps, each new line we add will be highlighted in the example code and the line number will correspond to notes below the code.
import time
from bcr_mcp3008 import MCP3008
adc0 = MCP3008(device = 0)
adc1 = MCP3008(device = 1)
interval = 1 # How long we want to wait between loops (seconds)
while True:
#Each ADC device has 8 channels (0 to 7)
#Chip 0, Channel 0 (0-0)
value0 = adc0.readData(0)
print(value0) #print the result from Channel 0 on Chip 0
#Chip 1, Channel 7 (1-7)
value1 = adc1.readData(7)
print(value1) #print the result from Channel 7 on Chip 1
time.sleep(interval)
Using this MCP3008 library to get a reading from one of the channels is really easy – just one line of code! The addresses of each input are printed on the board; so if you have connected a sensor to input 1-5, you would use “adc1” and “5” as the channel. Connected to input 0-3, you would use “adc0” and “3” as the channel. Each of the two chips has 8 channels (0 – 7).
If we were to run this code, it would simply read the two requested channels once a second and print the value for each. The value returned is a number between 0 and 1023. If you prefer to work with the voltage, simply divide the reading by 310 .
Now that we have some basic code to read sensors, let’s hook up a few and get a reading. We don’t want to be messing around with electrical connections while the Pi is on so save you work, close everything, and shutdown. Once the Pi is shutdown, grab your breadboard and set up a few sensors in the breadboard. We will go through the proper connection of a basic resistive sensor (normally used with a voltage divider circuit) and an analog output sensor with a specific analog output pin.
In this case we are going to use a CDS photocell and a Potentiometer. With the CDS photocell we will also need a 10K Ohm resistor to create the voltage divider. Connect each sensor up as shown:
Wiring for the Potentiometer:
Red is 3.3V Power (To “+”)
Blue is the analog signal to the board (To: “SIG”)
Black is the Ground (To “GND”)
Wiring for the CDS Photocell:
Red is 3.3V Power (To: “+”)
Green is the analog signal to the board (To: “SIG”)
Black is the Ground (To “GND”)
10K Resistor between Green and Black (On Breadboard)
Double check all of your connections, and once satisfied they are correct, boot up the Pi. Load up your Python program again and try it out. You should see the sensor readings correspond to your analog sensors!
Finally, we are going to take a look at what all these onboard jumpers and solder pads are for. As you may have noticed in Step 14, we have to add a resistor along with the CDS photocell to get a useable reading. This is the same for all basic resistive sensors. On this board we have added solder pads and jumpers that allow for this resistor to be placed and configured on the HAT if desired. In the case of our CDS Photocell using a pull-down resistor, the configuration shown in the attached image would be correct:
1. Close the “EN” jumper to enable the onboard resistor circuit
2. Solder the required resistor to this pad – these are 1206 SMD Resistor Pads – they can be soldered with a conventional iron without too much difficulty.
3. Select whether this should connect to power or ground (pull up or pull down) by soldering this jumper to the correct position.
And with that, no need for the resistor in the breadboard!
3 thoughts on “Getting Started With The Raspberry Pi 16 Channel ADC HAT V2”
David Saenz
I require 16 analog input, reading each input with a 1kHz sampling rate. Since I’m creating and deleting the sensor object, how long will it last to read all the 16 inputs?
Chris @ BCR
Hi David,
Thanks for the note! Based on some very limited testing, GPIO Zero seems to cap out at about 100Hz. This isn’t due to the object creation / deletion, but a limitation of SPI speed in GPIO Zero. We will be releasing a Python library that is a lot more intuitive (and faster) for our boards in the near future.
Mr Michael Smith
Hello,
This looks very interesting. Could this be used to pull analogue signals from vehicle engine?
They Include:
Speedometer – hall effect / VR sensor
Tacho – Taken from the -ve terminal of the ignition coil so would need to be able to detect pulses – (single bipolar transistor?, VR Sensor?)
Water and oil Temp – Thermistor / Resistance
Voltage – Would need a voltage sensor on the board?
Fuel Gauge – Potentiometer style resistance…
Would it need Opto-Isolation or another method to protect the board from voltage spikes?