Neuron SPI overlay and TCP modbus with docker
-
Hi, I'm Leonardo I work at Kartrak Automation and recently we bought a Neuron L203 to test our system in a UNIPI board. We would like to share with you some details of our installation.
Our system rely on the Balena OS, a Yocto-based system which simplify the development of applications in a dockerized environment. Since our goal is making a low-level communication with the board we decided to install only the SPI overlay and TCP modbus service instead of the whole Evok system.
We don't use Raspbian and we work with docker, the installation on the github does not work straightforward. The steps below show some details of the instalating that might help other users.
Inside a container, you can follow the instructions to acess the HW of a neuron board.
1 - Installing dependencies
Install the dependencies:
> apt-get install build-essential > apt-get install -y apt-transport-https > apt-get install -y wget > apt-get install -y libmodbus-dev
Download neuron spi-overlay and tcp-modbus server
> wget https://github.com/UniPiTechnology/neuron-tcp-modbus-overlay/archive/v.1.0.3.tar.gz > tar xvf v.1.0.3.tar.gz > cd neuron-tcp-modbus-overlay-v.1.0.3/
2- Making the SPI overlay
We generate the
neuron-spi.dtbo
compilingneuron-spi.dts
following the github instructions> cd spi_overlay > sh compile-dtc
The important thing to remember here is to copy the
neuron-spi.dtbo
inside the boot partition mtn/boot/overlays of the sd card. Different from the Raspbian, this folder is not accessible from inside a container so mount the RPI sd card in a computer and copy from there.For other OS the overlays folder can be handled differently. One may wrongly think that coping the .dtbo folder inside a /boot/overlays folder inside the container will make this work, but it won't. You have to use the boot partition since the OS will look for the overlays there.
When restarting the board is important to make sure the overlay is working with
ls /dev
and see the devices:spidev0.0 spidev0.1 spidev0.2 spidev0.3
If only
spidev0.0
andspidev0.1
is appearing, the spi overlay didn't work correctly.3- Using TCP modbus
The TCP modbus uses systemctl commands to manage services. The problem here is that is not possible to run systemd daemon inside a docker container. To make this work we can use the docker-systemctl-replacement which allow us to exec systemctl commands. Therefore we have to replace the systemctl with:
> wget https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl3.py -O /usr/local/bin/systemctl
Now, just follow the github instructions making the neuron tcp server:
> cd neuron-tcp-modbus-overlay-v.1.0.3/ > cd neuron_tcp_server > make > make install > cp neurontcp.service /lib/systemd/system/
Enable the neurontcp server with:
> python /usr/local/bin/systemctl daemon-reload > python /usr/local/bin/systemctl enable neurontcp
Start the server with:
> python systemctl start neurontcp
If everythig is working you should see your service active with:
> python systemctl status neurontcp
Testing with a python script
Below is a very simple python code that changes sequantially the status of all relays and digital outputs on the L203 board. Inspired by this topic:
#from pyModbusTCP.client import ModbusClient from pymodbus.client.sync import ModbusTcpClient as ModbusClient import time try: c = ModbusClient('localhost', port=502, unit_id=0, debug=False) c.connect() except ValueError: print("Error with host or port params") running=True while running: print (c.read_coils(0,12)) for ad in range(0,4): rq = c.write_coil(ad, True, unit=0) rr = c.read_coils(ad, 1, unit=0) print(str(ad), " - ", str(rr), " - ON") time.sleep(0.2) for ad in range(100,114): rq = c.write_coil(ad, True, unit=0) rr = c.read_coils(ad, 1, unit=0) print(str(ad), " - ", str(rr), " - ON") time.sleep(0.2) for ad in range(200,214): rq = c.write_coil(ad, True, unit=0) rr = c.read_coils(ad, 1, unit=0) print(str(ad), " - ", str(rr), " - ON") time.sleep(0.2) time.sleep(2) for ad in range(0,4): rq = c.write_coil(ad, False, unit=0) rr = c.read_coils(ad, 1, unit=0) print(str(ad), " - ", str(rr), " - OFF") time.sleep(0.2) for ad in range(100,114): rq = c.write_coil(ad, False, unit=0) rr = c.read_coils(ad, 1, unit=0) print(str(ad), " - ", str(rr), " - OFF") time.sleep(0.2) for ad in range(200,214): rq = c.write_coil(ad, False, unit=0) rr = c.read_coils(ad, 1, unit=0) print(str(ad), " - ", str(rr), " - OFF") time.sleep(0.2) time.sleep(2) print (c.read_coils(1000,4)) print (c.read_coils(1016,12)) print (c.read_holding_registers(0,20)) print (c.read_holding_registers(1000,32)) print (c.read_holding_registers(100,1)) time.sleep(1)
That's it!
We hope to help others that are starting with the Neuron board in a dockerized env. We are really happy with results untill now and with the UNIPI hardware. If anyone have sugestions on how to improve the setup we are really happy to talk and share.
Thanks!
(I'm not sure if this post should be on Installations, Ideas & Realisations or Tutorials but you can move there anyway)