In this tutorial, I go through the steps of setting up a Raspberry Pi ADC (Analog to digital converter). As you may already know the Pi doesn’t have any GPIO pins that are analog. This lack of analog pins makes connecting analog sensors a little more complex.
There are several solutions to the lack of Analog pins like the one I did in the Raspberry Pi LDR tutorial which involved using a capacitor to measure the resistance of the LDR (Light Dependent Resistor). A better solution to this would be to use what is known as an analog digital converter (MCP3008). This chip involves a little bit of setting up which I will go into below.
I also go into setting up the MCP3008 with MyDevices Cayenne, this is a much easier process than writing the code from scratch, but sometimes half the fun is in learning how to code.
If you want to see how to do everything visually, then be sure to check out the video I have prepared below. It goes through all the steps to getting the chip wired correctly and how you can access the devices connected to it.
You will need the following equipment for this Raspberry Pi ADC tutorial. You can use different versions of the analog to digital converter such as an MCP3004 but steps to getting it working may differ from this tutorial.
MCP3008 or similar
The Raspberry Pi ADC Circuit
The circuit for connecting the MCP3008 to the Pi looks quite involved, but it’s all about just connecting the wires up correctly.
The MCP3008 is the chip that I will be using in this Raspberry Pi ADC tutorial. There is a lot of technical information on this chip, but I will just touch on the bare basics.
For anyone who is new to microchips, you will find that one end of the chip will have a notch in it. This notch represents the end where pin 1 is. It is usually the first pin on the left-hand side with the notch facing away from you (see diagram below). Pin one also sometimes has a little dot above it.
This particular chip makes use of the SPI (Serial Peripheral interface bus) which means it will only require four pins and is relatively easy to communicate to thanks to the SPIDev library for python.
The CH0->CH7 pins (Pins 1-8) are the analog inputs for the MCP3008. On the other side, we have a whole range of different pins.
- DGND (Pin 9) is the digital ground pin for the chip.
- CS (Pin 10) is the chip select.
- DIN (Pin 11) is the data in from the Raspberry Pi itself.
- DOUT (pin 12) is the data out pin.
- CLK (Pin 13) is the clock pin.
- AGND (Pin 14) is the analog ground and obviously connects to ground.
- VREF (Pin 15) is the analog reference voltage. You can change this if you want to change the scale. You probably want to keep it the same so keep this as 3v3.
- VDD (Pin 16) is the positive power pin for the chip.
If you want more information on the chip, then you can find the full datasheet over at Adafruit.
Putting the circuit together is pretty straightforward. The circuit is likely to look a bit messy since we’re going to have to use quite a few wires. You can clean this up later if you want to make it more of a permanent project. In this example, I have included an LDR to show how you can get the value of the LDR back to the Pi by using the analog to digital converter (ADC).
First, connect a 3v3 pin to the positive rail on the breadboard and a ground pin to the ground rail on the breadboard. Also, place the MCP3008 chip into the middle of the breadboard.
- VDD (Pin 16) wire this to 3.3V
- VREF (Pin 15) wire this to 3.3V
- AGND (Pin 14) wire this to ground
- CLK (Pin 13) wire this to GPIO11 (Pin 23/SCLK)
- DOUT (Pin 12) wire this to GPIO9 (Pin 21/MISO)
- DIN (Pin 11) wire this to GPIO10 (Pin 19/MOSI)
- CS (Pin 10) wire this to GPIO8 (Pin 24/CE0)
- DGND (Pin 9) wire this to GROUND
Now once you have done that you will probably want to connect the LDR up to the MCP3008, this is pretty easy to do.
First, place the LDR onto the breadboard. Next, have the 10k resistor go to one end of the LDR and the other end to the positive rail. Have a wire go from in between the LDR and the positive wire to pin 1 (CH0) of the MCP3008. Lastly, have a wire go from the other side of the LDR to the ground rail on the breadboard.
If you need further help on making the circuit, you can find a detailed diagram below. If you’re still having trouble, double check the chip connections, and also making sure all the pins are connected correctly.
The code for this is pretty simple but is also only handling just one input, the LDR. The code may be a little more complicated the more devices you add. All the required packages for this tutorial should be installed by default on Raspbian. If you find it a little overwhelming than an easier option would be to use a tool such as Raspberry Pi cayenne that I mention below.
If you come across any issues, then check out my guide on the Raspberry GPIO pins. It goes through how to set them up and install the necessary software.
To quickly download the code straight onto your Pi just run the following line in the terminal. Alternatively, you can download it over at GitHub.
git clone https://github.com/pimylifeup/Pi-ADC-Example-Code
You will need to then move into the folder that contains our script by running the following line.
You can now launch it by running the following line.
sudo python adc-code.py
You can stop the script by press ctrl c.
I will now just briefly explain the code. At the start of the code, we define the path of where Python is installed. After this, we import two packages that we will need. Time allows us to put the script to sleep (Add a delay). Spidev allows us to communicate with SPI devices, in this case, it is the MCP3008.
#!/usr/bin/python import spidev import time
Next, we define the variables and create our SPIdev object. We create two variables first being a delay in milliseconds. Alter this if you want there to be a more considerable amount of time between updates. Next is the channel our LDR is located on, this is channel 0/pin 1.
Finally, we create the SPIdev object. This object allows us to get the values we need from the device connected the SPI enabled pins.
#Define Variables delay = 0.5 ldr_channel = 0 #Create SPI spi = spidev.SpiDev() spi.open(0, 0)
Next, we have the readadc function in which we do a couple of things. Firstly, we check the parameter value to make sure it’s between 0 & 7, if not then return -1. If it is, we then proceed to get the value from the channel specified and then return the value.
def readadc(adcnum): # read SPI data from the MCP3008, 8 channels in total if adcnum > 7 or adcnum < 0: return -1 r = spi.xfer2([1, 8 + adcnum << 4, 0]) data = ((r & 3) << 8) + r return data
Lastly we have a while loop that continues until you force quit it by pressing ctrl c. The first thing we do is call the readadc function with the ldr_channel variable as the parameter.
Once we get the value, back we simply print it. The %d refers to a decimal value; we then have our variable after the print statement. You can print multiple values per line by doing something like this.
print '%s %d' % (name, number)
After we have printed the data, we delay the script for whatever the delay time is set to. By default, it is set for half a second.
while True: ldr_value = readadc(ldr_channel) print "---------------------------------------" print("LDR Value: ".ldr_value) time.sleep(delay)
I hope this has helped you understand the code a little. As I mentioned above, you can download the full script over at the GitHub. If you do come across any problems, then feel free to mention them in the comments below.
Using the ADC with Raspberry Pi Cayenne
I will now quickly go through the steps to set up the MCP3008 with Cayenne. I will also go through how to setup the LDR. If you haven’t already set it up, then be sure to follow my guide on how to install Raspberry Pi Cayenne. The tutorial goes through the steps to getting it installed and most the basics you need to know for creating your very own smart applications.
1. To begin first go to add new and then select device from the drop-down box.
2. Then either search or select “analog converter“.
3. In this list select the MCP3008
4. Now select the Raspberry Pi and then SPI Chip-Select 0
5. This selection will now bring up a screen that shows you all the values of the channels.
Now to add the LDR, the process is pretty much the same, but I will go through it anyway.
1. Go back up to add new and then select device.
2. Find or select the photoresistor (Luminosity Sensor).
3. For this one select your Raspberry Pi, your preferred widget (I went graph), then select the MCP3008 for the analog converter and finally channel 0 for the channel.
4. This sensor should now add without any issue. It will now produce a graph from the values it gets from the analog converter.
Now you can pretty much follow this same process for any analog device. I will cover any sensor or device that is analog in the near future. It includes things such as the tmp36 temperature sensor.
I hope this tutorial has helped you with setting up a Raspberry Pi ADC. If you come across any issues, have feedback or notice a mistake, then please feel free to leave a comment on the forums.