Arduino/Raspberry als Interface für LinuxCNC

14.04.2019 - LinuCNC Grossdisplay mit 7-Segment und LED-Matrix

Arduino/Raspberry als Interface für LinuxCNC

04.04.2019 - LinuCNC Rotary-Encoder einlesen mit Arduino

China-Encoder (1600 edges/r):
Ich kann mt dem Arduino momentan 13kHz abtasten, die Werte umgerechnen und
mit 115kBaud ausgegeben. Theoretisch fuer 8 Encoder.
Vermutlich geht mit ASM noch mehr  - und ein Raspberry sollte das ganz locker
mit mehr als 20 kHz schaffen.
Da ist dann auch bei den Encodern das Ende erreicht.

Oben der Output eines Encoderkanals, unten das Abtastsignal des Arduino.
Ab 10kHz wird es etwas grenzwertig.
(den Frequenzanzeigen des Oscs. darf man nur bedingt trauen - mehr als 
ein grober Richtwert sind die nicht)

Ich bastel gerade die linCNC-Reader Componente und bin mir grad noch nicht 
sicher, ob ich direkt lesen oder via Shmem die Daten annehmen soll.
Im Moment tendiere ich zu Shmem. 

29.03.2019 - LinuCNC Treiberpaket - Neue Version


Endlich ist wieder eine neue Version zum Testen fertig geworden.
linCNC_eth.20190329_09.tgz
Ich werde in den naechsten Tage nochmal eine komplette Neuinstallation auf Basis
dieser Veroeffentlichung vornehmen und gefundene Fehler korrigieren.

30.3.2019 - step_by_step.txt
Wahrscheinlich kommt dann auch noch ein Encoder-Modul fuer China-Drehwinkelgeber dazu.

Was das Paket enthaelt
######################

ethraw.comp-Treiber
Sendet linuxCNC-OUT-Pins zum Rapsberry und empfaengt GPIO-IN-Pins von dort.
Sendet zudem linuxCNC-Float-Values per UDP an beliebige IP-Adresse.


Laeuft z.zt. nur mit PREEMPT bzw. im Userspace.
Fuer RT-Systeme muss der ethsh.comp-Treiber verwendet werden.


ethsh.comp-Treiber
Sendet linuxCNC-OUT-Pins zum Rapsberry und empfaengt GPIO-IN-Pins von dort.
Sendet zudem linuxCNC-Float-Values per UDP an beliebige IP-Adresse.
ethsh.comp macht das aber nicht eigenstaendig sondern benoetigt ein
externes Programm im Userspace (pcIOethRwa) das das Kommunikation
via shares-Memory handlet.


raspIOethRaw
Das Raspberry-seitige Gegenstueck zu obigem Treiber. Details weiter unten.

linCNC_max
Raspi-Seitiger UDP-Client zur Anzeige von linCNC-Float Values (positionen)
auf einer fast beliebig grossen LED-matrix


etheraw.ino
Zur Zeit etwas spiefmuetterlich behandelter Arduino-Client fuer den
ethraw.comp-Treiber


und dann gibts noch

pcIOethRaw
Driver und Test-Tool fuer den ethraw.comp-Treiber.
Dient zum Testen der PC/Rapsberry-Kommunikation _UND_ als PC-seitiger Treiber,
wenn die "ethsh.comp"-Komponente verwendet wird.
"ethsh" ist eine RT-Kompomente, die ausschliesslich ueber shared-Memory
kommuniziert.



26.03.2019 - 4-Fach 8-stellige Matrix-Positionsanzeige. Datenzufuhr von linCNC via UDP/WLAN

Dieses Paket linCNC_max.tgz enthaelt den UDP-Treiber
fuer linuxCNC und das Raspberry-Gegenstueck um Float-Values
(z.B. die aktuelle Position) auf einer 64x32-Punkte groessen LED-Matrix
zur Anzeige zu bringen.
Diese Version hat eine fettere Schrift.

Die Maschinensteuerung erfolgt ebenfalls ueber ein Raspberry, das
mittels raw-Ethernet mit den Motorsteuerimpulsen versorgt wird.
Die aktualisierten Sourcen dafuer folgen denmaechst.

20.03.2019 - 4-Fach 8-stellige Matrix-Positionsanzeige. Datenzufuhr von linCNC via UDP/WLAN

Noch immer nicht fertig, fliegender Aufbau - aber einigermassen zufrieden. ;-)
Aussenmasse: 250x140mm - Ziffernhoehe: 33mm

Etwas aufgehuybscht.....

19.03.2019 - Eine 8-stellige Matrix-Positionsanzeige - skalierbar. RAW-ETH und UDP

die ersten display sind angekommen.

8-stelliges matrixdisplay mit raspberry-zero per wlan-UDP tut jetzt
(per kabel natuerlich auch)
http://erste.de/ethraw/max_raspi_8-stellig.avi

(ein 1-EUR-Stueck zum groessenvergleich im vordergrund)

vor und nachkommstellen koennen beliebig gewaehlt werden.

ich glaube, wenn man "condensed" schrift waehlt, bekommt man auch
10 oder 12 stellen auf die anzeige ohne qualitaetsverlust. 



16.03.2019 - Eine Matrix-Positionsanzeige - skalierbar. RAW-ETH und UDP

Der Treiber ist jetzt auch auf UDP erweitert. 
D.h.: Man kann nun auch mehrere Anzeigen davon an uterschiedenlichen Standorten
auch ueber Router hinweg betreiben.
Die Matrix-Display koennen in Reihe geschaltet und bleibig verlaengert 
werden. Hier ist testweise eine fuenfte Stelle an das 4-stellige Modul 
angefrickelt.
Die Schriften koennen natuerlich auch noch aufgehuebscht werden.
Im Video ist zu sehen, dass die Matrix-Anzeige deutlich schneller reagiert
als der Bildschirm:
5-stellige Anzeige - Video
Dies ist aber noch nicht in den veroeffentlichen Sourcen implementiert.
Ich denke, das kommt naechste Woche - dann sollen auch die nachbestellten Matrix-Displays 
ankommen.

14.03.2019 - Ein Matrix-Positionsanzeige mit Rasberry via ETH

Ein Nebenprodukt des raw-eth-Treibers:
Wird einfach mit

net X ethraw.0.par-00-pos <= stepgen.0.position-fb

eingebunden.
Das hier wird von einem Raspberry-Zero gesteuert (mit usb-eth dran).
Ich glaube, ich baue fuer die gemaechlichen Sachen noch einen
"normalen" IP-Stack mit ein.

irgendwie kommen immer neue baustellen dazu... ;)

10.03.2019 - Weitere Messergebnisse mit Rasberry

Man muss wohl den Tatsachen ins Auge sehen:
Die Zeitbasis des Raspberry ist einfach zu schlecht.

Verlustfreier Datenempfang ist moeglich - aber die 
Timings sind unter aller Sau.

Naechste Idee: die gpio-Clock als Zeitbasis.
Ist auch nix. Sobald man die Pulsseite auf mehr als 1 usec erhoeht, 
sind immer wieder low-Peaks oder Aussetzer drin.
Dann das pwm-Signal der gpio?
gruselig!


zwischen 3 usec und 60 usec ist alles moeglich.....

dann kann man nur noch ueber eine externe hw-clock nachdenken....

oder man muss einsehen, dass mehr als 5kHz nicht geht.. 

07.03.2019 - Messergebnisse mit Rasberry


Wie man sieht: oberhalb von 8 kHz wird es instabil.

04.03.2019 - Work in progress

Aktueller Stand: Rapsberry/Arduino Treiberpaket fuer LinuxCNC via Raw-Ethernet

DOWNLOAD: http://erste.de/ethraw/linuxCNC.ethraw.tgz
Um mit LinuxCNC Steuerungen zu entwickeln sind Interfaceboards notwendig.
Die einfachste Loesung verwendet dabei den Parallelport des Motherboards
und stellt damit 10 Ausgabe- und mehrere Eingabe-Pins zur Verfuegung.
Das funktioniert auch alles wunderbar, bis hin zu Signalerzeugung fuer
jeden einzelnen Schritt eines Schrittmotors.
Leider bringt es aber auch einige Nachteile mit sich:

        Begrenzte Laenge der Steuerleitungen
        Begerenzte Anzahl IO-Pins
        Motherboards mit LPT-Port sind kaum noch zu bekommen
        Ein Schaltungsfehler bei Aufbau himmelt u.U. das gesamte Board

USB-to-Paralell-Wandler sind fuer LinuxCNC nicht geeignet (fehlende
Echtzeitfaehigkeit von USB).
Es gibt IO-Karten (Mesa), die mit LinuxCNC arbeiten. Aber die hat nicht
jeder in seiner Bastelkiste. Und zum "nur mal ausprobieren" sind sie
zu teuer.
Was aber jeder hat (naja, jeder irre Elektrolurch ;-)) sind Raspberries
oder Arduinos. Daher entstand der Plan, daraus ein Interface fuer
LinuxCNC zu bauen.

Und daraus enstand dann dieses kleine Treiberpaket, welches fuer viele
Einsatzzwecke geeignet ist. Der folgende Text beschreibt dessen Aufbau
und den Einsatz.

In dem oben verlinken Paket bedindet sich ein "README", das die Vorgehensweise
erlaeutert.
Praktisch habe ich echte Taktfrequenzen von deutlich ueber 20kHz, ja sogar ueber
30kHz mit einem Raspberry erreichen koennen.
Alles was ueber 10kHz hinaus geht, setzt aber auf der Raspberry-Seite einige
(softwareseitigen) Aenderungen voraus, die ich demnaechst noch naeher berscheiben
werde.

Momentan waere mir erst mal wichtig:

Ist das Paket so wie es ist benutzbar? 
Ist die "Bedienungsanleitung" halbwegs verstaendlich?
Sind Dinge unklar oder falsch beschrieben?

feedback bitte an wicki[AT]erste.de


------------ die folgenden Zeilen sind nur aus historischen Gruenden noch vorhanden ------------------


04.03.2019 - Work in progress

Aktueller Stand: Rapsberry mit LinuxCNC via Raw-Ethernet: 33kHz am Stepper-Pin

Ich gebe zu, das ist etwas tricky - aber das teil laeuft jetzt mit 33kHz,
zittert kaum noch und scheint auch stabil zu sein:
Mit den Funktionen des Raspberry-RT-Kerns geht das aber nicht.
(das haben aber ja auch schon genug andere vor mir festgestellt)
hier
z.b.

Ich werde das in den kommenden Tagen mal Dokumentieren.

-----------------------------------
ich bin ja selbst sketptisch... aber ich sehe, dass ich um die 30k pakete/sekunde sende.
und ich sehe, dass ich keine pakete verliere.
triggern tut es eigentlich auf den peak in der mitte. es kann aber nicht sein, dass da 2 peaks
in 2 usec abstand auftauchen. also sind das wohl irgendwelche doppenbilder
wenn das signal ideal waere, dann muessten es wirklich um die 6 grids sein.

aber den peak erzeuge ich momentan ueber einen loop - damit das osc. ihn ueberhaupt erfasst.
- und der ist dann mal einige ns breiter oder schmaler - daher traue ich dem osc.zaehler auch
nicht wirklich. meine anderen messgeraete kriegen das auch nicht richtig gebacken.

ich werde mit den zeitschleifen mal rumprobieren um ein besser darstellbares signal zu bekommen.
und auch nochmal mit einem anderen osc. messen.
aber wie gesagt: wenn die packets rausgehen und reinkommen und nix verloren geht, dann
kommt das mit den 33kHz hin. 
------------------------------------



25.2.2019 - Work in progress

Aktueller Stand: Rapsberry mit LinuxCNC via Raw-Ethernet: 12kHz am Stepper-Pin

Um mit LinuxCNC Steuerungen zu entwickeln sind Interfaceboards notwendig.
Die einfachste Lösung verwendet dabei den Parallelport des Motherboards
und stellt damit 10 Ausgabe- und mehrere Eingabe-Pins zur Verfügung.
Das funktioniert auch alles wunderbar, bis hin zu Signalerzeugung für
jeden einzelenen Schritt eines Schrittmotors.
Leider bringt es aber auch einige Nachteile mit sich:

	Begrenzte Länge der Steuerleitungen
	Begerenzte Anzahl IO-Pins
	Motherboards mit LPT-Port sind kaum noch zu bekommen
	Ein Schaltungsfehler bei Aufbau himmelt u.U. das gesamte Board
	
USB-to-Paralell-Wandler sind für LinuxCNC nicht geeignet (fehlende
Echtzeitfähigkeit von USB).
Es gibt IO-Karten (Mesa), die mit LinuxCNC arbeiten. Aber die hat nicht
jeder in seiner Bastelkiste. Und zum "nur mal ausprobieren" sind sie
zu teuer.
Was aber jeder hat (naja, jeder irre Elektrolurch ;-)) sind Raspberries
oder Arduinos. Daher entstand der Plan, daraus ein Interface für
LinuxCNC zu bauen.

Und daraus enstand dann dieses kleine Treiberpaket, welches für viele 
Einsatzzwecke geeignet ist. Der folgende Text beschreibt dessen Aufbau 
und den Einsatz.


Files in diesem Paket:


  267 Feb 22 07:13 halcmd.hal		example HAL-file (use "halrun")

 7,2K Feb 22 13:07 etheraw.ino          sourcecode for arduino-Uno

  15K Feb 22 16:12 ethraw.comp          linuxCNC component-driver

  16K Feb 22 18:19 pcIOethRaw.c         standalone PC-arduino I/O-test


 6,6K Feb 21 17:23 func.c		include-file
 2,8K Feb 21 17:23 commandline.c	include-file
 2,8K Feb 21 18:08 defs.h		include-file


Die Huerden beim Einsatz eines Arduino sind etwas geringer als beim Einsatz
eines Raspberry. Denn auf der Raspberry-Seite sollte ein Realtime-Kernel
installiert sein. Der Arduino ist ein klein wenig langsamer. Dafuer aber billiger
und unkomplizierter. Allerdings benoetigt man einen "Ethernet-Shield" - also
eine Universal-Erweiterungskarte, die i.d.R. keine 10 EUR kostet und neben
dem Ethernet-Anschluss auch noch einen Steckplatz fuer eine Speicherkarte
enthaelt.
Fangen wir also damit an:

In dieser Beta-Version stehen 10 Output-Pins und 8 Input-Pins zur Verfuegung.

Zunaecht wird "etheraw.ino" auf den Arduino-Uno hochgeladen.
Vorher werden die Wunsch-MAC-Adressen (ja, die kann man sich frei aussuchen)
im Quellcode angepasst:


Die lokale Adresse des Arduino - ich nehme immer AFFEAFFEAFFE

// the MAC-address of myself
static byte myadr[6]={0xAF,0xFE,0xAF,0xFE,0xAF,0XFE};


Und die MAC-Adresse der PC-netzwerkkarte (mit "ifconfig" nachsehen)

// the MAC-address of my the linuxCNC-Master
static byte radr [6]={0x70,0x85,0xc2,0x89,0x68,0xb7};



TESTEN
=======

PC und Arduino mit eimem 1:1-Kabel verbinden 
(kein Router, kein Switch dazwischen!)

Starten von "tcpdump" am angeschlossenen PC:
sudo tcpdump -i eno1 -s 2000 ether host af:fe:af:fe:af:fe or ether host 70:85:c2:89:68:b7

Wenn man nun die Eingangs-Pins zwischen "0" und "1" umschaltet 
(also z.B. "A0" auf GND zieht), dann sollte der tcpdump am PC
so etwas zeigen:

11:22:06.902447 af:fe:af:fe:af:fe (oui Unknown) > 70:85:c2:89:68:b7 .... Unknown) Null Information, length 50
        0x0000:  0000 003f 0000 0000 001b 1b21 0000 0000  ...?.......!....
        0x0010:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0020:  0000 0000 0000 0000 0000 0000 1b00 2100  ..............!.
        0x0030:  0000                                     ..

Das sind die Datenpakete, die der Arduino bei jedem Pegelwechsel verschickt.

Nun compiliert man "pcIOethRaw.c" - Ein Testprogramm fuer die Ausgabe:

 gcc pcIOethRaw.c -lpthread -o pcIOethRaw

heraus kommt das Binary: pcIOethRaw


Auf der PC-Seite startet man  
sudo ./pcIOethRaw -i eno1 -s af:fe:af:fe:af:fe  -r 70:85:c2:89:68:b7 

Heraus kommt etwas in diser Art:
------------------------
Opening interface [eno1].
send to  Mac-address [AF:FE:AF:FE:AF:FE].
recieve for Mac-address [70:85:C2:89:68:B7].
destination MAC: af:fe:af:fe:af:fe
rec. for MAC: 70:85:c2:89:68:b7
interface:eno1
init_rec_socket eno1
sending to MAC: af:fe:af:fe:af:fe
s_sockfd is: 6
------------------------

Dieses Test-Tool schaltet nun Pins der Ein- oder Ausgagabeports.
Mit den Tasten 1-8 werden die Bits 0-7 eines Ports getogglet.

Mit "o" wechselt man in den Ausgabemodus (nur der ist fuer diesen
Test relevant - es wird kein Tastenecho angezeigt)

Wenn man nun die Tasten 1-8 drueckt, wird der jweilige Pin des
Arduino umgeschaltet (LED anschliessen zum Pruefen).

Sie sieht die Ausgabe aus:
(eine einmalige "PACKET LOST!" Meldung kann ignoniert werden - 
die Counter sind beim Start noch ansynchron)
 

(1<<f):= 1
 toggle OUT bit 1 of byte[1]
 0:-> 1
PACKET LOST!!!lastEthInNr:   0 pktInNr:  15
(1<<f):= 1
 toggle OUT bit 1 of byte[1]
 1:-> 0
(1<<f):= 1
 toggle OUT bit 1 of byte[1]
 0:-> 1

Wenn man mit "+" in die Ebene "byte[1]" umgeschaltet hat,
dann bedienen nur noch die Tasten "1" und "2" die Ausgabepins
"8" und "9".
Die anderen 6 Bits des Ausgabeports werden vom Arduino selbst 
benoetigt.


Was fehlt (und bald kommt):

Wie schliesse ich einen Schrittmotor an und teste diesen?

Ganz einfach. 
So:

An einen billig-China-TA6600 werden A0, A1 und A2 angeschlossen.
A2 an ENA, A1 an DIR und A0 an STEP.
Und schon kann man mit pcIOethRaw den Motor Schrittweise bewegen.
(Umschalten auf output mittels "o" nicht vergessen!)




Wie konfiguriere ich LinuxCNC so, dass es mit diesem Treiber und
dem Schrittmotor zusammen arbeitet ?

Im wesentlichen so:
(ich habe hier A8 fuers "Enable" genommen - was in diesem Fall
noch invertiert werden muss)

net dummy17 => ethraw.0.pin-08-out
net dummy17 <= not.0.out
net xenable         => not.0.in
net astep           => ethraw.0.pin-00-out
net adir            => ethraw.0.pin-01-out

Und schon kann man die A-Achse ueber die Handsteuerung bewegen.
Eine "Minimalconfig" nur zum testen kommt bald nach....

Hier ist sie:
http://gnipsel.com/linuxcnc/examples/winder.zip

Meine Aenderungen in start.hal:



#use ethraw instaed od parport
#loadrt hal_parport cfg="0x378 out"    <-- comment out

# load realtime components
loadrt threads name1=fast period1=25000 fp1=0 name2=slow period2=1000000
#                         ^^^^^^^^^^^^^ 
#                 vanilla-kernel in userspace



loadrt ethraw shkey=12390 ismac=0xaf,0xfe,0xaf,0xfe,0xaf,0xfe irmac=0x70,0x85,0xc2,0x89,0x68,0xb7 ethdev=eno1 debug=0
## ^^^^^^^^^^^ my MAC-addresses
#### 




addf ethraw.0.hread fast
addf ethraw.0.hwrite fast

# ^^^^^^^^^^^ hread, hwrite instaed of read and write


net winder-step ethraw.0.pin-00-out <= stepgen.0.step
net winder-dir  ethraw.0.pin-01-out <= stepgen.0.dir

#             ^^^^^^^^^^^^^^^^^^^^^^^ OUT-pins are A0 and A1 of arduino

#############################
start mit: 

halrun -f start.hal 

Frustrierenderweise ist aber beim Arduino tatsaechlich bei rund 1ms Zykuszeit 
Schluss.
Bei schnellerer Paketfolge verschluckt er sich.
Man wird sicherlich am Treiber noch was optimieren koennen.
Aber wenn nicht die w5100-lib des Arduino einen fetten Bug hat,
dann wird man damit auch nur ein paar % mehr heraus holen koennen.


Gleicher Aufbau mit Raspberry

Bis knapp ueber 5 kHz ist das Signal stabil.
Er verbraucht dafuer eine Sendebandbreite, die nur 1/3 von dem betraegt,
was man in einem Thread pro Sekunde uebertragen kann.
Nimmt man also einen schnelleren Empfaenger, kann man sicher 10kHz erreichen,
schaetze ich.
Und weder auf Sende- noch auf Empfangsseite ist irgendwas optimiert. Da geht
sicher auch noch was....

Meine Motoren geben im uebrigen bereits bei deutlich unter 5kHz den Loeffel ab ;-)

Rapsberry mit linuxCNC via Raw-Ethernet: 12kHz am Stepper-Pin