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 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 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 then writing the code from scratch but sometimes half the fun is in learning how to code.
If you want to see everything done 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 ADB tutorial. You can use different versions of the analog to digital convert such as an MCP3004 but steps to getting it working may differ from this tutorial.
- Raspberry Pi
- Micro SD Card or 8 GB SD Card if you’re using an old Rasberry Pi (V1 etc.)
- Ethernet Cord or Wifi dongle (Raspberry Pi 3 has inbuilt WiFi)
- MCP3008 or similar
- Breadboard Wire
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 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 4 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 straight forward. It is likely to look a bit messy because we’re going to have so many wires but you can clean this up later if you want make it more of a permanent project. In this example I have included an LDR to show how you can get the value on the Pi 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 out connections whilst 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 complex 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 simply 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 greater 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 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 getting 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 at. 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 setting up the MCP3008 with Cayenne. I will also go through how to setup the LDR. If you haven’t already then be sure to follow my guide on how to install Raspberry Pi cayenne if you're interested in using this software. The tutorial goes through the steps to getting it installed and most the basics you need to know for creating your own smart applications. If you just want to jump straight in you can find it for download here.
- To begin first go to add new and then select device from the dropdown box.
- Then either search or select "analog converter".
- In this list select the MCP3008
- Now select the Raspberry Pi and then SPI Chip-Select 0
- This 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.
- Go back up to add new and then select device.
- Find or select the photoresistor (Luminosity Sensor).
- 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.
- This 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. This 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 below.