Adding Analog Input to Raspberry Pi

One of the things that the Raspberry Pi lacks that the Arduino has in abundance is analog I/O. While teaching my Introduction to Raspberry Pi class this week, one of the topics we covered was how to use an MCP3002 2-channel 10-bit analog to digital converter with the SPI interface on the GPIO connector.

The MCP3002 is straightforward to wire up. In the picture you can see the SPI interface on the purple wires, connected to MOSI, MISO and CLK on the T-cobbler. The Chip Enable (CE) pin on the chip goes to CE0 on the T-Cobbler over the grey wire, and the 10K trimpot is wired as a voltage divider between +3.3V and GND to supply a variable voltage to ADC channel 0 (the 1K ohm resistor is there to limit the current when the trimpot is turned to zero).

Here’s some example code in Python that can return the position of the trimpot:

from __future__ import division
import spidev

def bitstring(n):
    s = bin(n)[2:]
    return '0'*(8-len(s)) + s

def read(adc_channel=0, spi_channel=0):
    conn = spidev.SpiDev(0, spi_channel)
    conn.max_speed_hz = 1200000 # 1.2 MHz
    cmd = 128
    if adc_channel:
        cmd += 32
    reply_bytes = conn.xfer2([cmd, 0])
    reply_bitstring = ''.join(bitstring(n) for n in reply_bytes)
    reply = reply_bitstring[5:15]
    return int(reply, 2) / 2**10

if __name__ == '__main__':
    print read()

The next time you are wishing for analog input to your Raspberry Pi, think of adding an MCP3002 or one of the other members of the family with more channels (MCP3004, MCP3008) or more resolution (MCP3202, MCP3302) or both (MCP3204, MCP3208, MCP3304, MCP3308).

15 responses to “Adding Analog Input to Raspberry Pi

  1. I am using a MCP 3202 to make a dual-channel digitial storage scope and spectrum analyzer, using the Pi to acquire data and send it over ethernet to my laptop for display and analysis. The oscilloscope and spectrum analyzer are written in Python and tested with data sent over ethernet from the Pi.

    My MCP3202 arrives in the mail today, and I found your site to help me communicate with the chip.

    1) Laptop requests data.
    2) Pi acquires at requested sample rate and sample count.

    3) Pi sends data to laptop.

    4) Laptop displays trace and FFT.

    5) Repeat 1-4.

    If you are interested, I plan to release the “etherscope” code as open source after final testing with the MCP3202 in the next few weeks.

    James Phillips

  2. The code appears unsuitable for high-speed array read operations for two reason:

    1) Object instantiation of the spidev object is within the read(), so time for the object instantiation and object deletion to occur happens on each read. A single external connection object fixes this by removing this functionality from the read().

    2) spidev in its current form has a memory leak, which you can see by timing how long it takes to read 10,000 values in a timed loop. On my py this generates an error due to Python being unable to destroy the currently-memory-leaked object due a maximum number of “file descriptors” being generated. This can be mitigated by having the single connection object, and the spidev software team is aware of the problem.


  3. Update: If you don’t mind being limited to audio frequencies, I use an inexpensive MCP3202 12-bit dual channel A/D converter to acquire on the pi with spidev, and pydatascope to display data passed over Ethernet via TCP socket. Pydatascope also acts as a spectrum analyzer!

    Linked screen shot is a 555 timer LED flasher, the signals are the capacitor control voltage and LED voltage. I made relatively trivial changes to the pydatascope open source code to have dual channels, mostly because it was easy and not that I really needed it.

    Post follow-ups or mail me directly if you have any questions, I’ll be glad to help out.

    James Phillips

  4. Update II: You’ve read the book, now see the movie!

    Seriously, I have some news to report from my testing. For signals with large voltage swings relative to the power supply voltages, such as a 555 timer circuit – my setup worked fine.

    However, when I tried analog signals – a 741 op amp with a condenser microphone – there was a very large noise component. From what I could find googling around, the power supplies are unsuitable for audio work as the pi was not designed for this.


  5. Update III

    I’m getting a lot of noise pickup from my unshielded, no-back-plane solderless breadboard circuits. Hmm, hmm, hmm, the main contributor may not be due to power supply noise after all. Aargh, I need a real scope and a workbench for this type of work…


  6. While this is typically used in RF designs, RFI is exactly part of my problem – nice suggestion. I tried the addition of a back-plane, which is a part of that technique, and it did not help in my specific case.

    The problem seems to be that I’m using a 741 op amp in a high-gain (X100) single stage configuration on an unshielded solderless breadboard as a preamp for the condenser microphone.

    Physically removing the microphone has no effect on the noise at all, so my cheap-n-cheesy preamp definitely needs to be changed.


  7. Update IV

    While removing the condenser microphone itself had no effect on output noise, removing the now-unused 2-inch-long coupling capacitor had a huge effect – very little noise present now. So the op-amp circuit itself was not the major noise source; rather the presence of the coupling capacitor was the determinant factor in picking up ambient electromagnetic noise for the relatively quiet op-amp circuit to amplify.

    This might be a good audio-frequency oscilloscope + spectrum analyzer after all.


  8. Replacing the unclipped-2-inch-lead electrolytic coupling capacitor with a short-trimmed-lead mylar capacitor massively improves signal-to-noise ratio. I’m back on track now.


  9. Physical breadoard photograph:

    Left-most IC chip:
    741 op-amp circuit (x100 gain)

    Mylar coupling cap and condenser microphone

    Right-most IC chip:
    MCP3202 12-bit A/D converter


  10. I’m starting on the oscilloscope how-to now. I will be referring to this page for the MCP3002/MCP3202 cip-to-Pi connection – especially since the high-resolution photo you have is outstanding.


  11. 60 Hz noise pickup in my living room:

    FFT of the same signal:

    Note the strong harmonics at 120 and 180 Hertz. The FFT display from pydatascope reads out the three strongest peak frequencies as you can see in the image, which is totally awesome!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s