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

NEW:german installation and testing howto



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