I got a bit disappointed with my little bus pirate yesterday. I'll investigate how to update it to fix the odd SPI behaviour another time, but for now, its on to trying to read the MCP3002 SPI ADC chip directly using the Raspberry Pi. However, this one I'm going to do a bit differently. My desk is filling up with breadboards and floating wires, and working out each time which wire to connect to which header pin is becoming annoying. So I have decided to wire up a simple plugin board with the MCP3002 connected to the correct SPI pins on a 26-way header. That way I can just plug it in when I want to use it, and unplug it if I want to use the rspberry Pi for something else.
I have a fairly diverse collection of prototype boards, some with strips, some with grouped pads and some with just a grid (a.k.a. "pegboard", "pad per hole", etc.) of tinned holes. For this little project I thought I'd have a go at using one of the "pad per hole" boards. They are very cheap, particularly when ordered from China, so I'm not too worried if I mess it up. One of my collection has a grid of 14 x 20 holes. This is almost exactly the right width for the 2x13 Raspberry Pi GPIO header and it looks like it will sit nicely on top of the Raspberry Pi. My plan is to add a socket for the MCP3002 (just in case I suddenly want to use it for something else) and wire the socket and the GPIO header together.
While thinking about how to lay out the board, I found that if I put the IC socket on the "header" side of the board, and arrange it in the right way, the MOSI, MISO and CLK pins line up with each other. That certainly makes wiring simpler, so that's the way I have decided to do it.
Of course, I can't resist adding a little bit of extra. The Raspberry Pi provides two SPI /CS lines (labelled CE0 and CE1). Although I only plan to use CE0 at the moment, I thought I might as well add a little pin-and-jumper switch to allow me to choose which one to use without re-soldering. Also, I guess it makes sense to add a header to connect whatever the ADC will be reading. This one will provide GND, Vcc and a signal input pin. Other than that, the circuit is very simple, mainly a matter of connecting the right Raspberry Pi headers to the right MCP3002 pins.
The next step was to try out the software. To start with I just re-used some of the software bits I had built for driving a 7219 LED matrix from a Raspberry Pi and sent the intended 0x60 0x00 to the board, while monitoring the traffic on the logic analyser. This looked like plausible SPI traffic, so I changed one of the resistors and tried again. Reassuringly different!
Now that I was fairly comfortable that the hardware was working, I just needed to tweak the software to not only send the right SPI data, but also to retrieve and interpret the response:
Note that the SPI protocol "returns" the same number of bits as sent, and in this case the 10-bit ADC data is encoded in the last two bits of the first byte and the eight bits of the second byte. I chose to retrieve the data in MSB-first order, so the result is the sum of (the bottom two bits of the first byte shifted up by eight bits) + the second byte.
#include
#include
#include
#include
#include
#include
#include
#define CHANNEL 0
uint8_t buf[2];
unsigned int sample(int channel) {
buf[0] = 0x60 + channel;
buf[1] = 0x00;
wiringPiSPIDataRW(CHANNEL, buf, 2);
return buf[1] + (buf[0] & 0x03) << 8;
}
void main(int argc, char** argv) {
if (wiringPiSPISetup(CHANNEL, 4000000) < 0) {
fprintf (stderr, "SPI Setup failed: %s\n", strerror (errno));
exit(errno);
}
printf("sample=%04x\n", sample(0));
}
That should do for now. Next time I'll take a look at what I can do to use this chip to read changing signals rather than a fixed voltage.
As usual, all code, including a makefile to build it, can be found on github.