Reading spidev

  • Bit of a follow-up of a thread I started earlier on home assistant.

    TL;DR: what is the spec of the SPI transmitted values for the neuron models?

    Since my posts there, I've been reading a bit about the way home assistant does its magic and it has a lot of built-in support for asynchronously polling IO -- which is pretty much what I'd like to do. The next step I thought of was to have a direct way to read those values -- which appear to already be available through the spidev overlay; part of the solution provided by you in the neuron modbus TCP server

    I already tried reading the spidev directly through a python library called spidev, which is quite simple really (example from neuron L303)

    >>> import spidev
    >>> spi = spidev.SpiDev()
    >>>, 1)
    >>> spi.readbytes(10)
    [250, 0, 85, 14, 182, 10, 250, 255, 255, 0]

    My question now: is there any spec of how the spi device puts those values on the spi line? How should I interpret these values? I can probably start looking into how the modbus TCP server interprets these values, but it's probably easier to ask here first :)

  • administrators

    The specification is ModBus RTU, with a custom header. For details see:

    In practice all the Neuron TCP server does is to repack the messages from ModBus TCP to a customised ModBus RTU. The overhead associated is therefore minuscule, albeit it does exist.

    It should also be noted that if you do wish to use the device directly regardless, you may have an easier time using our OSS image from, which uses a custom driver to get around certain problems associated with spidev. That way you will have a SYSFS interface along with a documented messages structure. spidev is only used in EVOK for leagcy reasons and ease of installation, both Mervis and CODESYS use the kernel driver instead.

    The IO is not asynchronous in any case. The primary reason is that there is only a single communication channel back towards the primary RPi board, and so there is no convenient way to inform it of changes as they happen. The number of interrupt lines which would be required is considerably more than the number of GPIOs provided by the RPi itself. At any rate, the maximum supported polling speed of 12MHz is more than sufficient for a fast response time.

  • administrators

    Another note - the response you read is simply a response to a request sent by the Neuron TCP server, there are no messages originating from the device, only replies. Indeed the HW devices involved are not designed for the subsidiary SOCs to act as SPI masters, only slaves. Therefore they are not capable of transmitting any information by themselves.

    The way SPI works is that the same number of bytes is transmitted both ways, it's not possible to send one-way messages using standard SPI (but see below).

    alt text

    Note that the MOSI/MISO lines are used simultaneously. It is technically possible to use one of several non-duplex SPI schemes, but they are not commonly supported by all hardware (including some of the hardware components we use) and in practice would only limit the bandwidth available on the device.

  • administrators

    For further information you may benefit from reading the source code for the driver section responsible for SPI parsing, unipi_spi.c and unipi_spi.h

  • Thanks for the quick and very extensive reply!

    Follow-up question: with the modbus TCP server / evok, I know it's possible to change the behavior of how I/O should be interpreted, e.g. the toggle or direct switch functionality. How is this initiated? Is this an interpretation that happens on the "server side" (pi-side) or is this some behavior that actually gets set on the SPI slave device? Does the server side also keep the SPI slave register state locally in its memory?

    As a more generic question, what kind of software is running on the SPI slaves? Probably something like a single program that handles the modbus RTU interfacing?

    Besides the SPI interfacing, are the standard GPIO also still used in the 24V pins? Are they also made available via the neuron TCP server?

    About the asynchronous behavior: SPI does seem indeed inherently synchronous. It might be possible to have the slave devices initiatie interrupts, but most docs I've read about it seem to indicate it's indeed not that common + I probably wouldn't know how to do it in practice :). In that respect, I am beginning to doubt whether there's much to gain by bypassing the modbus TCP server ...

  • After giving it some more thought and playing around with the setup, my main motivation really is that my (home asssistant-based) integration still feels rather slow, so I was looking on how to improve on that.

    From what I gather here however, there's probably more to gain by improving the way the front-end queries (polls) the modbus TCP server -- so I should probably focus more on that instead.