LinuxCNC with raspberry as IO-Port via ethernet
===================================================
last update: 23.02.2019
LinuxCNC-kernel is now: 4.9.115-rt93 #2 SMP PREEMPT RT Mon Feb 4 18:44:13 CET 2019 x86_64 x86_64 x86_64 GNU/Linux
raspberry-PI-kernel: 4.4.4-rt9-v7+ #7 SMP PREEMPT RT Mon Mar 7 14:53:11 UTC 2016 armv7l GNU/Linux
This driver let you use a raspberry-PI as a multi-IO-port for your linuxCNC.
(instead of a parport)
You only need a ethernet connection from the PC to your raspberry. The driver
uses raw-ethernet-packets and these packets are _not_routable_!
All tests until now are made eith an 1:1 -cable and without any other traffic
in this network-segment.
latest version of raspi.tgz linuxCNC/raspberry component driver.
on linuxCNC-PC compile it with:
(in linuxCNC-src directory)
halcompile --compile raspi.comp&&cp raspi.so ../rtlib/
compile man-page:
halcompile --document raspi.comp
exampe HAL-config-line:
loadrt raspi shkey=12388 ismac=0xb8,0x27,0xeb,0xd6,0x96,0x81 irmac=0xbc,0x5f,0xf4,0x7b,0xce,0x4d ethdev=enp3s0 debug=0
on rapsberry-PI compile rasPIioEthRaw.c with:
gcc rasPIioEthRaw.c -lbcm2835 -lpthread -o rasPIioEthRaw
start with sudo or setuid root:
./rasPIioEthRaw -i eth0 -r b8:27:eb:d6:96:81 -s bc:5f:f4:7b:ce:4d
Latency of linuxCNC->raspbery-PI from setting an OUT-pin of th PC-side
until setting the pin of the raspberry-GPIO-pin: about 120usesc
The following is overaged
This is an attemt to run linuxCNC (2.7.14) in userspace on a Linuxmint-PC
with vanilla-kernel (no RT-patches installed).
The pc is an intel-i5 (6 core, 16 GB RAM, 128GB-SSD) running linuxmint 19.1.
The raspberry is conencted directly to the pc by one ethernet-cable.
Nothing else is connected to the ethernet interfacecard - no hubs, no switches,
no other network-traffic in this segment.
The parport-driver hal_parport.c is modified in that way, that it does not
need a real port any more.
If cfg="0xFFFF" is configured in the .ini-file, the driver uses 2 bytes in
shared-memory instead od a physical port. This memory is shared with 2 tasks/threads.
On the linuxcnc side, there are 2 tasks running:
pcSendEthRaw.c - reads the output-byte of the virtual parport and sends it
as raw-ethernet packets to the mac-address of the reaspberry
pcReadEthRaw.c - reads incomming raw-ethernet-packets from raspberry and puts
the GPIO-input in into the input bytes of the virtual parport
The rasberry-side also has 2 runnging tasks:
rasPIreadEthRaw.c - reads incomming raw-ethernet-packets from the pc and puts
input of the virtual parport into the output bytes of rapsberry GPIO
rasPIsendEthRaw.c - reads the input-bytes of the local rasberry GPIO and sends it as
raw-ethernet packets to the mac-address of the pc-ethernetcard
some days later
not really amazing results....
PC-side
Linux debian 3.4-9-rtai-686-pae #1 SMP PREEMPT Debian 3.4.55-4linuxcnc i686 GNU/Linux
4 cores
model name : Intel(R) Atom(TM) CPU D525 @ 1.80GHz
bogomips : 3600.09
total used free shared buffers cached
Mem: 3350624 366124 2984500 0 63544 196052
-/+ buffers/cache: 106528 3244096
Swap: 0 0 0
Jobs:
pcIOethRaw send and receive-thread which send output of the virtual-parport
to, and receives input from the rasberry GPIO
pcTestloop sends bytes received from the raspberr GPIO-input Immediately
inverted to the raspberry GPIO-output
rasPI-side
Linux cerec 4.4.4-rt9-v7+ #7 SMP PREEMPT RT Mon Mar 7 14:53:11 UTC 2016 armv7l GNU/Linux
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 76.80
total used free shared buffers cached
Mem: 945164 325524 619640 14792 30788 158516
-/+ buffers/cache: 136220 808944
Swap: 102396 0 102396
Jobs:
rasPIioEthRaw send and receive-thread, which reads local GPIO-input ans sends it
immediately to the receiving PC. packets _from_ the PC are directed
to the raspberry GPIO-out.
The result of the configuration describes above is a 2 kHz signal on the IO-Pin.
so it took about 125 usec. thats to slow.... :-(
the PC is able to send about 100k packets/second. the raspbbery is able to send
20k packets/second.
I think, it is not the best way, to do the linuxCNC/ethernet-task by polling
shared memory. Anyway: a RT-task is needed on both sides.
one day later
=============
Are the limitations from the rasPI, from the PC of from the linux-RTs?
I made further tests:
The first image shows a RT-thread of the raspberry. It toggles one GPIO-pin permanently.
The averags cycle time is 10usec. But more than 20usec are also possible.
Output frequency is about 45 kHz.
The second image is the same c-loop. But as an endles loop inside the thread.
The output frequency is 3.7 MHz(!). But the output is not really a square wave any more...
http://erste.de/rt-thread_toggle_gpio.jpg
Next question:
How will the output of a local HAL-htread with a toggle-loop look like?
On the PC and on a rasPI.
to be continued.....
loopback-HAL-script
halcmd:
loadrt threads name1=fast period1=5000 name2=slow period2=10000000
loadrt hal_parport cfg="0x378 out"
loadrt siggen
loadrt comp
loadrt constant
addf comp.0 fast
addf parport.0.write fast
addf siggen.0.update fast
addf parport.0.read fast
net a parport.0.pin-11-in-not => parport.0.pin-02-out
start
results on PC with
loadrt threads name1=fast period1=5000 name2=slow period2=10000000
(left image)
and
loadrt threads name1=fast period1=50000 name2=slow period2=10000000
(right image)
next test with the rasIP
lopback-HAL-script
about 5.7 kHz
loadrt threads name1=fast period1=40000 name2=slow period2=10000000
loadrt hal_gpio dir=4288672767 exclude=4088
loadrt not
addf not.0.funct fast
addf hal_gpio.read fast
addf hal_gpio.write fast
net dummy17 => hal_gpio.pin-03-out
net dummy17 <= not.0.out
net inv <= hal_gpio.pin-16-in
net inv => not.0.in
start
at period1 >40000 the system hangs..... :-(
so, is a latency of a litle bit below 100usec. enough?
I don't think so.
but I will check it again...
26.01.2019
My plan is/was, to use the microstepping-generator of linuxcnc - without doing much
more on the rasPI, than the IO-pin handling.
If I need 3 motor-turns/cm in 16 micorsteps, I have to send 48 signals/cm.
With a latency of 1ms, a jog-speed of 20cm/second an with a latency of
100usec, 200cm/second should be possible.
appears as a lapse of thought.... but it seems to be right.
If so, it explains the reason why my machine is working yet ;-)
I will test it the next days.
But I still need some help in writing a configure/makefile to integrate the
driver into linuxCNC.
The rasPI-side is a standalone-thread - on the linuxCNC-side, I patched the hal_parport.c
and wrote also a standalone-thread for sharemem-exchange and raw-eth-communication.
It would be fine, to have single a hal-driver for both (simulate parport and raw-eth to rasPI)
###########################################################################################
Testing-Environment 14.1.2019
===============================
the first raw concept
---------------------
Raspberry-PI Linux-PC
V3 - Debian Intel i5 Linuxmint 19.1
RTAI-Kenel Vanilla-Kernel
GPIO-IO-Ports Virtual-Parport
I/O-Pins Parport-Pins
+--------------------------------------+
J8 | RAW-Ethernet | 25-Sub-d
| Connection |
GPIO01 +---+ +---- Pin 1
GPIO02 +---+ +---- Pin 2
GPIO03 +---+ +---- Pin 3
GPIO04 +---+ OUTPUT +---- Pin 4
GPIO05 +---+ section +---- Pin 5
GPIO06 +---+ +---- Pin 6
GPIO07 +---+ +---- Pin 7
GPIO08 +---+ +---- Pin 8
GPIO09 +---+ +---- Pin 9
| |
GPIO05 +---+ +---- Pin 10
GPIO06 +---+ INPUT +---- Pin 11
GPIO07 +---+ section +---- Pin 12
GPIO08 +---+ +---- Pin 13
GPIO08 +---+ +---- Pin 15
the real system (sniplet of GPIO.h)
-----------------------------------
OUT IN
Signal SUB-D Pin PIN/BCM-Number PIN/BCM-Number Sub-D Pin Signal
1 2
3 4
5 6
Enable 1 GPIO4 7 8
9 10
A-Step 2 GPIO17 11 12
A-Dir 3 GPIO27 13 14
Y-Step 4 GPIO22 15 16
17 18
19 20
21 22 GPIO25 10 Z-Home
23 24
25 26
27 28
Y-Dir 5 GPIO5 29 30
Z-Step 6 GPIO6 31 32 GPIO12 11 A-Home
Z-Dir 7 GPIO13 33 34 GNDD
X-Step 8 GPIO19 35 36 GPIO16 12 Y-Home
X-Dir 9 GPIO26 37 38 GPIO20 13 X-Home
39 40 GPIO21 15 Probe-IN
HAL-Config-snipplet
-------------------
setp parport.0.pin-01-out-invert 1
net xenable => parport.0.pin-01-out
net astep => parport.0.pin-02-out
setp parport.0.pin-02-out-reset 1
net adir => parport.0.pin-03-out
net ystep => parport.0.pin-04-out
setp parport.0.pin-04-out-reset 1
#setp parport.0.pin-05-out-invert 1
net ydir => parport.0.pin-05-out
net zstep => parport.0.pin-06-out
setp parport.0.pin-06-out-reset 1
setp parport.0.pin-07-out-invert 1
net zdir => parport.0.pin-07-out
net xstep => parport.0.pin-08-out
setp parport.0.pin-08-out-reset 1
setp parport.0.pin-09-out-invert 1
net xdir => parport.0.pin-09-out
net home-z <= parport.0.pin-10-in-not
net home-a <= parport.0.pin-15-in-not
net home-y <= parport.0.pin-12-in-not
net home-x <= parport.0.pin-13-in-not
net probe-in <= parport.0.pin-11-in
Further infos in german language
----------------------------------
Ich baue grade an einer Loesung, um ein Raspberry-PI als
IO-Interface zu verwenden.
Der PC erhaelt eine "virtuelle" Parallelschnittstelle" und
linuxCNC wird mit einem modifizierten Parport-Treiber
verwendet.
Die Port-Stati des PC werden dabei als raw-Ethernet-Pakete
ausgetauscht und Latenzzeiten von weniger als 50usec. sollten
machbar sein.
(ja, ich weiss: es gibt Mesa&Co - aber das war mir zu teuer und
zu exotisch. Ein rasPI ist echte Massenware)
Momentaner Projektstatus:
http://erste.de/rasPiCat.html
Das System funktioniert (echte beta-Tests stehen noch aus)
Falls es hier jemand gibt, der sich dafuer interessiert, freue
ich mich ueber Rueckmeldungen.
Schoen waere es, wenn sich ein passionierter C-Entwickler mit
RT- und raw-Ethernet-Erfahrung meldet.
Aber auch reine Anwender, die nur ein Maschinchen mit einem
Motherboard ohne Parport (und das ist ja heute leider die Regel)
steuern und diese Loesung mal ausprobieren wollen, sind
mir herzlich willkommen ;-)
Benoetigte Hardware fuer den Test:
Ein rasberry PI, ein PC mit Ethernet-Karte, eine 08/15-China
TB6xxx-Schrittmotor-Steuerkarte.
Die aktuellen TB6600-China.Klone fuer weniger als 20 EUR/Stk.
funktionieren direkt am GPIO-Port des rasPI.
Be Interesse gerne eine Mail an mich:
LinuxCNC-rasPI