Getting SPI to work using SpiDev

I am trying to use SpiDev to use the SPI on the Raspberry Pi 3 B+ to communicate with an add-on board.

I am starting by just attempting to read the chip ID of the device to make sure that the SPI is working,

I initialize the SPI with the following, and it doesn’t give an error

SPI_FREQUENCY = 976563
SPI_MODE      = 1

# Initialize the wiringpi SPI setup. 
self.spi_handle = spidev.SpiDev()
# Open SPI device "/dev/spidev0.0".
self.spi_handle.open(0,0)
self.spi_handle.max_speed_hz = conf.SPI_FREQUENCY
self.spi_handle.mode = conf.SPI_MODE

if (self.spi_handle == -1):
    raise IOError("ERROR: Could not access SPI device file")

To read the Chip ID byte I use

chipId = self.spi_handle.readbytes(1)

I keep reading the Chip ID in a loop with a 100ms delay between calls, and when I probe the SCK pin with my oscilloscope I never see the clock, only noise.

If I run

ls /dev/spidev*

I get

/dev/spidev0.0
/dev/spidev0.1

After looking through the balena forums I tried “RUN modprobe bcm2835-412” and “RUN mdprobe v412_common” to no success.

Following is my Dockerfile.template:

FROM balenalib/%%BALENA_MACHINE_NAME%%-python:3-stretch-run

# enable container init system.
ENV INITSYSTEM on

# use `install_packages` if you need to install dependencies,
# for instance if you need git, just uncomment the line below.
# RUN install_packages git
RUN install_packages build-essential
RUN pip install --upgrade pip
RUN apt-get update && apt-get install -yq --no-install-recommends build-essential rpi.gpio
RUN pip install smbus2
RUN pip install spidev
#RUN modprobe bcm2835-v4l2
#RUN modprobe v4l2_common

# Set our working directory
WORKDIR /usr/src/automated_testing_button_panel

# Copy requirements.txt first for better cache on later pushes
COPY requirements.txt requirements.txt

# pip install python deps from requirements.txt on the resin.io build server
RUN pip install -r requirements.txt

# This will copy all files in our root to the working  directory in the container
COPY . ./

# Enable udevd so that plugged dynamic hardware devices show up in our container.
ENV UDEV=1

# main.py will run when container starts up on the device
CMD ["python","-u","src/automated_testing_button_panel_main.py"]

And my DT parameters and overlays.

When I run lsmod, I see spi_bcm2835, bcm2835_v4l2, v412_common, and spidev.

However, if I run

echo "abcdefghijklmnopqrstuvwxyz" > /dev/spidev0.0

I don’t see a clock signal on the SCK using my oscilloscope.

I have tried it with the add-on board that I want to control with SPI attached and without it.

How can I get SPI to work?

Were you able to fix this?

Looks like the SPI configuration on the OS is fine. Are you sure there is no issue with the hardware connections?
In another issue where you seem to have cross posted, you say you see noise. Sounds like a floating wire to me.

This is related to the Getting WaveShare High-Precision AD/DA Expansion Board to work post.

I created a new post to narrow it down to just SPI and not include the board I am attempting to communicate with, since SPI itself seems to be my current sticking point.

Currently, I am measuring the SCK directly from the RPi with a scope probe, ground attached, and no additional boards. The noise I mentioned was very low level noise.

I also tried it with only “wifi-connect” in the docker-compose.yml file.

I still see spi_bcm2835 , bcm2835_v4l2 , v412_common , and spidev .when I run lsmod.

I also still see

/dev/spidev0.0
/dev/spidev0.1

And when I run

echo “abcdefghijklmnopqrstuvwxyz” > /dev/spidev0.0

I still don’t see any signal on the SCK pin of the RPi.

Do you have a setup that is known good to get the SPI to work? Once I have something like this I think I can solve my issues with the WaveShare A/D board.

I am at a loss right now. So any help you can give would be greatly appreciated,

Hi Matt, sorry if I am missing some context but, did you try the SPI interface in Raspbian? Once that works we can help debug any specific problem with BalenaOS.

I have successfully used the Waveshare High-Precision AD/DA board in Raspbian, by following the steps from their wiki. So now I want to use it with a balena project I have.

I had tried to get it to work with no changes to the original code. However, trying unsuccessfully to get wiringPi installed and working I found the following post. He also mentioned he could not get wiringPi to work with docker. So I tried unsuccessfully to use http://abyz.me.uk/rpi/pigpio/ as he had done, but that also turned out to be a deadend. Since I just need simple SPI communication I turned to SpiDev. I was able to get this incorporated into the code via refactor, but still can’t get the simplest of SPI tests to work. I should be able to see an SCK when I try to write to the SPI bus.

My current test are without the Waveshare board, I am just trying to get the SCK working or do a basic loop-back test by jumping MISO and MOSI together with only the Raspberry Pi 3 B+ hardware in the loop.

hey @mdcraver

Can you confirm that you have a single container in your application? I’m asking since if you are using a multicontainer application you might need set the container to privileged mode. see the related docs here

Regarding using spi device with balenaOS, you can see the train sign project as an example.

Also, perhaps you can try to use the raspbian base image and see if you have better luck installing the required dependencies? you will need to change FROM balenalib/%%BALENA_MACHINE_NAME%%-python:3-stretch-run to FROM balenalib/rpi-raspbian.

hope this is helpful.
Thanks

Hey @rahul-thakoor,

I am using a multicontainer application, and the container is set to privileged mode. Below is my docker-compose.yml file.

version: '2.1'
volumes:
    uart_messages:
    uart_logs:
services:
    wifi-connect:
        build: ./wifi-connect
        network_mode: "host"
        labels:
            io.balena.features.dbus: '1'
        cap_add:
            - NET_ADMIN
        environment:
            DBUS_SYSTEM_BUS_ADDRESS: "unix:path=/host/run/dbus/system_bus_socket"
    pyro-ns:
        privileged: true
        restart: always
        build: ./pyro-ns
        command: ["--host=pyro-ns"]
    automated_testing_button_panel:
        privileged: true
        restart: always
        build: ./automated_testing_button_panel
        depends_on:
            - pyro-ns

I will try changing to the raspbian base image and also give the train sign example a look, and let you know what I find.

Thanks,

Hi Matt, your compose file looks good regarding the privileged containers. Trying the raspbian base image is a good idea. We’ll wait for the outcome of this experiment!

Hey @mbalamat and @rahul-thakoor,

So I looked at the train example and was able to get the SCK signal. Since I noticed that the train example used SpiDev as the base level for its SPI communication, I decided to try my automated_testing_button_panel as single container application.

When I ran automated_testing_button_panel as a single container I was able to see the SCK. However, I need to be able to run this as a multi-container application.

Using the above docker-compose.yml and the following is the Docker.template file that worked when used as a single container application.

FROM balenalib/%%BALENA_MACHINE_NAME%%-python:3-stretch-run

# enable container init system.
ENV INITSYSTEM on

# use `install_packages` if you need to install dependencies,
# for instance if you need git, just uncomment the line below.
#RUN install_packages git
RUN install_packages build-essential
RUN pip install --upgrade pip
RUN apt-get update && apt-get install -yq --no-install-recommends build-essential rpi.gpio 
RUN apt-get install apt-utils
RUN pip install smbus2
RUN pip install spidev

# Set our working directory
WORKDIR /usr/src/automated_testing_button_panel

# Copy requirements.txt first for better cache on later pushes
COPY requirements.txt requirements.txt

# pip install python deps from requirements.txt on the resin.io build server
RUN pip install -r requirements.txt

# This will copy all files in our root to the working  directory in the container
COPY . ./

# Enable udevd so that plugged dynamic hardware devices show up in our container.
ENV UDEV=1

# main.py will run when container starts up on the device
CMD ["python","-u","src/automated_testing_button_panel_main.py"]

What am I missing to get this to work as a multi-container project?

Thanks

Hi @mdcraver, what kind of errors do you see in the logs when you transform the working version into a multicontainer project?

This blog post could help out with troubleshooting: https://www.balena.io/blog/top-6-tips-for-troubleshooting-your-host-os-with-resin-io/

Next, why do you enable INITSYSTEM?
We no longer support the INITSYSTEM flag in our current balenalib base images. However, there is a working example of how to install systemd into a service and then run here: https://github.com/balena-io-playground/avahi-zoo-publisher

There is also more info in the docs: https://www.balena.io/docs/reference/base-images/base-images/#installing-your-own-initsystem

Although I don’t know much about SPI and your use case, I suspect that using systemd might help with troubleshooting here.

After looking back at it, I was mistaken about getting the SCK signal with the train program.

@gelbal, thanks for the monitoring information. I am going to go back to the train example, and will look into using the resources you mentioned to debug the SPI.

At this point I think I will also go get an additional RPi 3 B+ to be sure I don’t have bad hardware.

Also, does anyone know of a known good RPi 3 B+ SPI loopback project to allow for testing the SPI after connecting the MOSI and MISO?

Hi,

Great, let us know how it turns out. We don’t have a balena-specific project, but this third-party wiki has a nice example (about half way down the page). Note that we haven’t tested this and can’t vouch for it per se.

John