# Unable to interface BeagleBone Green with MCP3008 ADC using SPI

I am unable to interface MCP3008 with BeagleBone Green. I am trying to set communication in mode 0 (CPOL=0 CPHA=0), the built in frequency in dts is set to 1MHz.

Things I have tried:

1. Enable device tree BB-SPI0-MCP3008-00A0.dts on execution of ls -al /dev/spidev1.* I got crw-rw---- 1 root spi 153, 0 Oct 7 16:40 /dev/spidev1.1

2. On execution of cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pingroups group: pinmux_bb_spi0_pins pin 84 (PIN84) pin 85 (PIN85) pin 86 (PIN86) pin 87 (PIN87)

3. Executed the spidev_test to perform loopback test while connecting p9_18 and p9_21 it only returns spi mode: 0x0 bits per word: 8 max speed: 500000 Hz (500 kHz) for spidev_test I enabled the BB-SPIDEV0-00A0 device tree and disabledBB-SPI0-MCP3008-00A0.dts

4. The circuit I am following is:

My reference code for MCP3008 is as follows:

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#define ARRAY_SIZE(array) sizeof(array) / sizeof(array[0])

static const char *DEVICE = "/dev/spidev1.1";
static uint8_t MODE = SPI_MODE_0;
static uint8_t BITS = 8;
static uint32_t CLOCK = 1000000;
static uint16_t DELAY = 5;

/* * Ensure all settings are correct for the ADC */
static int prepare(int fd)
{
if (ioctl(fd, SPI_IOC_WR_MODE, &MODE) == -1)
{
perror("Can't set MODE"); return -1;
}
if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &BITS) == -1)
{
perror("Can't set number of BITS");
return -1;
}

if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &CLOCK) == -1)
{
perror("Can't set write CLOCK");
return -1;
}

if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &CLOCK) == -1)
{
perror("Can't set read CLOCK"); return -1;
}

return 0;
}
/* * (SGL/DIF = 0, D2=D1=D0=0) */
uint8_t control_bits_differential(uint8_t channel)
{
return (channel & 7) << 4;
}
/* * (SGL/DIF = 1, D2=D1=D0=0) */
uint8_t control_bits(uint8_t channel)
{
return 0x8 | control_bits_differential(channel);
}

/* * Given a prep'd descriptor, and an ADC channel, fetch the * raw ADC
value for the given channel. */
{
uint8_t tx[] = {1, control_bits(channel), 0
};
uint8_t rx[3]={0,0,0};

struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = DELAY,
.speed_hz = CLOCK,
.bits_per_word = BITS, };

if (ioctl(fd, SPI_IOC_MESSAGE(1), &tr) == 1)
{
perror("IO Error");
abort();
}
return ((rx[2] << 8) & 0x300) | (rx[2] & 0xFF);
}

int main(int argc, char **argv)
{
int fd = open(DEVICE, O_RDWR);
if (fd <= 0)
{
return -1;
}

if (prepare(fd) == -1)
{ return -1; }

for(i = 0;i < 8;i++)

close(fd);

return 0;
}


After executing this code, I am getting 1023 count for any applied voltage, where I am expecting count 0 for 0 input voltage and so on. Can anybody please help me? Can you tell me where I am going wrong? What are the other things do I have to consider while using SPI on BeagleBone? Any help will be greatly appreciated!

• try a lower baud rate then try earth gnd to 0Vdc for EMI issues. Jan 22 '19 at 5:32
• If that works then consider a DMA version to avoid the delays between bytes, Jan 22 '19 at 5:37
• by saying lowering the baud rate do you mean to change the frequency in device tree??and I didn't get "try earth gnd to 0Vdc for EMI issues" Jan 22 '19 at 5:37
• SPI rate ... floating gnd vs Earth gnd Jan 22 '19 at 5:38
• You have lots of issues with implicit type promotions in this code. Which in turn can create subtle bugs. I'd recommend to study Implicit type promotion rules. Jan 22 '19 at 12:38

I don't believe the beaglebone green is 5V tolerant, thus the 4.1V output signal of the ADC might be harming the device.

It would take some real time to see if this is correct, but I suspect it is. The Beaglebone Green is based on the ARM Cortex A8, specifically THIS FAMILY. Absolute maximum ratings on page 79 show that the max voltage at I/O pins is supply +0.3V.

That's the easy part. Now, what is the supply voltage. Unfortunately, this doesn't mean the voltage you supply to the board. It means the supply voltage sent to the microcontroller. The board uses regulators to drop down the supply you give it. We could go through the Beagleboard Green Schematic and really try to pin this down, but the A8 is fairly complex and has MANY different power supplies for many different things, as you can see by all the VDDS listings in the absolute maximum table (from the datasheet link above).

Without trying to trace the schematic, or actually reading the data sheet to find out why there are so many different absolute maximums for the "supply voltage for the dual-voltage I/O domain", you'll see that the highest number in that class is 3.8V, which suggests that your input high cannot exceed 4.1V, assuming that the Beaglebone Green provides the highest supply voltage allowable (which it may well not!). In fact, first glance at the schematic suggests that some of the VDDSXXXXX lines get 3.3V, and others get a voltage that comes out of a TPS65217C Power management chip (though that latter might be an input to that chip -- I can't chase this down through all the datasheets, as it would take too long).

It looks like you went outside the allowable limits for the pins. This doesn't necessarily mean that you broke those pins, or that the whole system is kaput. If it were me, and I had only this board available, I would try using a different port with some interface circuitry to step your inputs down. That said, starting with a fresh board is a better guarantee that things are good. It can get very frustrating debugging stuff like this when you don't know for sure that your hardware is good.

So, this was somewhat difficult to run down. Beaglebone is a great board with nice features, but the user base is much smaller than that of the Pi's, so this info wasn't readily available by searching for it.

• ok as I went through this [exploringbeaglebone.com/chapter8/] as well as on datasheet they have mentioned the MCP 3008 can be powered between 2.7 to 5 volt and the voltage on pins will be from vss to vref ,as I am giving 3.3v as vref so I am expecting it to be between 0 and 3.3volt ,am I getting it right?please correct me if I am wrong till that I will try SPIdev_test on other beagle I am hoping I have not damaged the beaglebone! Jan 23 '19 at 5:08
• In short, I don't believe you're right. I'll explain more when I'm at a real keyboard, but I'll live a link here for the moment. google.com/… Jan 23 '19 at 12:07
• @tinkerr_ Answer updated with more detail. Jan 23 '19 at 14:28
• @Scott - Hi, you said "4.1V output signal of the ADC" I can't see where you're seeing that the ADC is producing a 4.1V output. What am I missing? The schematic shows the MCP3008 is powered by 3.3V from the BBG, so the SPI interface from the MCP3008 can only produce an outout voltage of 3.3V surely?! As I said, what am I missing that leads to your point about a 4.1V output (going to the BBG)? Thanks :-) Jan 23 '19 at 20:57
• @SamGibson -- good catch. For some reason, I assumed that the MCP3008 was powered by 5V, but it's clearly working at 3.3V. I'm just wrong. I'll leave this up long enough for the asker to see before deleting the response. Jan 23 '19 at 21:11