File: /~heha/mb-iwp/Antriebe/Schrittmotorsteuerung/Firmware.zip/Programmierung.txt

Programmierung der Schrittmotorsteuerung „SM1“ und „SM2“
(PT_PIESA, Teilprojekt A2)

┌───────────────────┐
│ Achsen-Festlegung │
└───────────────────┘

Die 6-Achs-Motorsteuerung kennt zwei Arten von Achs-Festlegungen:
- Bediener-Achsen (so wie in Bedienung.txt festgelegt)
- Motor-Achsen (so wie die Motoren hardwaremäßig angeschlossen sind)

Wenn nicht anders bezeichnet, geht es in diesem Dokument um Motor-Achsen.
Diese sind standardmäßig wie folgt angeschlossen:
0 = A - Drehachse mit 1 Referenzkontakt
1 = B - Drehachse mit 1 Referenzkontakt
2 = S - Spindel als Demonstrator ohne Kontakt
3 = X - Schiebetisch mit 2 Endschaltern
4 = Y - Schiebetisch mit 2 Endschaltern
5 = Z - Hubtisch mit 2 Endschaltern
Macht in Summe 8 Endschalter = maximal anschließbar

┌───────────┐
│ Steuerung │
└───────────┘
Serielle Schnittstelle: 38400-8-n-1, globales TimeOut bei 200 ms, kein oder Hardware-Handshake


│Schnittstellen-Kommandos:
└─────────────────────────
Die Fernbedienung erfolgt mit den folgenden Steuerzeichen.
Die Zeichen <80h haben faktisch die gleiche Funktion wie die Lokalbedienung.
Alle Mehr-Byte-Binärzahlen sind Little-Endian (LSB zuerst) und vzb. Integerzahlen.
Die Motorsteuerung sendet niemals von sich aus Daten.
Viele Binärkommandos, erspart printf()/scanf() in Firmware

Werden mehrere Kommandos hingeschickt, kommen auch mehrere Antworten.
Eine Ausnahme ist '&', es wird durch Folgekommandos abgebrochen.
Abfragen (bspw. Motorposition) werden sofort beantwortet und in den
256-Byte-Ausgabepuffer eingeschrieben.

=== EINZELBYTE-KOMMANDOS ===

PC OUT	PC IN	Funktion
──────────────────────────────────────────────────────────────────────────
0	-	wird ignoriert, kann zur Synchronisation
		nach Kommunikationsverlust gesendet werden
20-25	-	Stopp für Einzelmotor
'#'	'#'	Echo-Prüfung (kurzer Anwesenheitstest der Motorsteuerung)
'$'	4 Byte	Datensatz-Nummer (0-basiert), bei dem der Abbruch
		der letzten koordinierten Bewegung erfolgte
'%'	4 Byte	Mikrocontroller-Auslastung abfragen und Min/Max rücksetzen
		1 Byte Minimum-Load (hier ca. 20 = 0%, aber 0 = 0% kann man getrost annehmen)
		1 Byte Maximum-Load (0xFF = 100%)
		2 Byte gleitender Load-Mittelwert (0xFF00 = 100%)
'&'	'&'	liefert Antwort sobald alle Motoren ohne Zielfahrt sind
		ODER EEPROM-Schreiben beendet wurde.
		Ggf. TimeOut-Wert der Schnittstelle erhöhen.
		Andere Kommandos beenden diesen Wartemodus
'?'	"SM1"	(sm1) zur Unterscheidung und Anwesenheitstest …
	"SM2"	(sm2) … für die Anwendungssoftware
'0'-'8'	-	Achse für Folgekommandos auswählen (sm1)
		Zuweisung (Verkabelung) zurzeit:
		0 = OWIS-Schiebetisch: Greiferverschiebung
		1 = OWIS-Drehtisch: Revolver
		2 = Eigenbau-Schiebetisch (zz. nicht benutzt)
		3 = Greiferplattform Z-Achse (Hubbewegung)
		4 = Greiferplattform links/rechts neigen
		5 = Greiferplattform vorn/hinten nicken
		6 = Parallelkinematik Einzelmotor vorn links
		7 = Parallelkinematik Einzelmotor vorn rechts
		8 = Parallelkinematik Einzelmotor hinten
'0'-'7'	-	Achse für Folgekommandos auswählen (sm2)
		0 = Schrittmotor-Achse A
		1 = Schrittmotor-Achse B
		2 = Schrittmotor-Achse S
		3 = Schrittmotor-Achse X
		4 = Schrittmotor-Achse Y
		5 = Schrittmotor-Achse Z
		6 = DC-Fokusmotor 0 *
		7 = DC-Fokusmotor 1 *
'A'-'F'	8 Byte	Motorstruktur der Schrittmotoren 6,7,8,0,1,2 (sm1) oder 0..5 (sm2) abfragen
		1 Byte Zustand
		 HUNT   Bit 0: Zielfahrt-Modus
		 REFF   Bit 1: Referenzfahrt-Modus
		 BRAKE	Bit 2: Bremsung aktiv
		 SLOW	Bit 3: Langsame Referenzschaltersuche (3. Pass)
		 FULL	Bit 4: Motor bestromt
		 PHA	Bit 7-5: Phasenlage
		1 Byte vzb. Beschleunigung (max. ±64), in Mikroschritt/125²µs² * 2^ea (zz. ea=-9)
		2 Byte vzb. Geschwindigkeit (max. ±512) in Mikroschritt/125µs
		4 Byte vzb. Mikroschritt-Position
		256 Mikroschritte sind 1 Halbschritt
'G'-'J'	-	Greifer 0..3 auswählen (sm1), Zuweisung zurzeit:
		G = Hochspannungs-Greifer 300 V
		H = Vakuum-Greifer
		I = nicht belegt
		J = frei für Hochspannungs-Greifer 2 kV
'K'-'Z'	-	Greifer 4..19 auswählen (nur „sm1“ mit kaskadierter „do1“)
		allesamt Magnetventile für Ansaugvorrichtungen
'g'	-	Greifer ein/ausschalten (nur sm1)
'h'	-	Greifer ausschalten (nur sm1)
'+'	-	1 Schritt mit ausgewählter Achse in positive Richtung
'-'	-	1 Schritt mit ausgewählter Achse in negative Richtung
'a'	-	1 Geschwindigkeits-Schritt mit ausgewählter Achse in positive Richtung
'b'	-	1 Geschwindigkeits-Schritt mit ausgewählter Achse in negative Richtung
'c'	-	Stopp für alle Achsen (für alle Motoren)
'd'	-	Demo-/Schmiermodus Serienkinematik (Anbauten abbauen!)
'e'	-	Demo-/Schmiermodus Parallelkinematik (Anbauten abbauen!)
'f'	-	Nullpunkte (für Parallelkinematik und Eigenbau-Schiebetisch) setzen
		Setzt alle (mit "A".."F" abfragbaren) Positionen zu Null.
		Setzt Referenzierung (REF-Bit).
		Bei vorhandener Referenzierung werden auch die Software-Endschalter verschoben.
't'	-	Referenzierung aller Motoren aufheben (löscht die REF-Bits)
'u'-'z'	-	Referenzierung eines Motors aufheben (löscht REF-Bit)
'@'	abcd	von Lokalbedienung einstellbare Zustände abfragen (binäre Bytes)
		a = Achsnummer (0..8 bzw. 0..7)
		b = Greifer-Nummer {nur sm1}
		c = Greifer-Zustand (0 oder !0) {nur sm1}
		d = DemoMode
'~'	a	bringt die Motorsteuerung für 100 ms in den Remote-Zustand
		(d.h. Lokalbedienung wirkungslos) und fragt den Tastenzustand ab
		Bit 0 - rechte Taste (rot)
		Bit 1 - Shift-Taste oder Druckknopf des Inkrementalgebers (schwarz)
		Bit 2 - nächste Taste (grün)
		Bit 3 - linke Taste (blau)
		Bit 7:4 - Position des Inkrementalgebers
		Differenzen und Tastenstatusänderungen muss die Auswertesoftware bilden.
		Gelbe LED im Flackerlicht (zeigt Remote-Zustand an, wechselt bei jeder Anfrage)

* Zurzeit (100819) nicht richtig implementiert

=== MEHRBYTE-KOMMANDOS (RAM) ===

Mehrbyte-Kommandos haben im Kommandobyte Bit 7 gesetzt.
Danach folgt die Nutzdaten-Länge in Bytes, danach die Nutzdaten.

PC OUT		PC IN	Funktion
──────────────────────────────────────────────────────────────────────────
0x80..0x85	-	Sollposition setzen und Zielfahrt/Referenzfahrt ausführen
länge			<länge> = 1..16 (typisch 1 oder 8)
Daten			1 Byte Kommando-Kode
			 Mögliche (sinnvoll erscheinende) Kombinationen
			 1 = Zielfahrt absolut
			 5 = Zielfahrt relativ (bei ROTA-Flag wird die Ist-Position vorher in den Bereich Min..Max normalisiert)
			 2 = Referenzfahrt in Normalrichtung (wie im EEPROM festgelegt)
			 6 = Referenzfahrt in Gegenrichtung
			 HUNT	Bit 0: Zielfahrt starten
			 REFF	Bit 1: Referenzfahrt starten
			 RIGHT	Bit 2: Schaltersuche umschalten / REL relative Positionsangabe für Zielfahrt
			 SLOW	Bit 3: Schleichfahrt (sonst automatisch erst schnell, dann langsam)
			1 Byte vzl. Maximalbeschleunigung, 0 = Maximum aus EEPROM, CNAN = vorhergehender Wert
			2 Byte vzl. Maximalgeschwindigkeit, in Mikroschritt/125µs, 0 = Maximum aus EEPROM, INAN = vorhergehender Wert
			4 Byte Zielposition, in Mikroschritt◊, oder explizite Referenzfahrtrichtung (negativ ist normal!), LNAN = vorhergehender Wert
				+∞ fährt bis zum positiven Limit, bei ROTA-Flag wird die Ist-Position permanent im Bereich Min..Max gehalten
				-∞ fährt bis zum negativen Limit
			4 Byte Lage des linksseitigen Software-Endschalters, in Mikroschritt◊, LNAN = vorhergehender Wert
			4 Byte Lage des rechtsseitigen Software-Endschalters, in Mikroschritt◊, LNAN = vorhergehender Wert

0x88..0x8D	-	nur Limits oder Flags setzen
länge			<länge> = 1..24
Daten			Erstes Byte (wird automatisch im EEPROM gespeichert):
			 LEFT	Bit 0: Motor dreht andersherum (bspw. sinnvoll wenn eine Phase vertauscht wurde)
			 REF	Bit 1: Motor referenziert, Software-Endschalter wirksam
			 RIGHT	Bit 2: Schaltersuche nach rechts (zum Ende hin)
			 MANU	Bit 3: Niemals Referenzfahrt; Kommando setzt Referenzposition an aktueller Stelle
			 HOLD	Bit 4: Motoren dauerhaft bestromt (mit verringertem Haltestrom)
			 ROTA	Bit 5: umlaufender Antrieb ohne Software-Endschalter, Software-Endschalter geben Periode vor (von Anfang bis Ende-1)
			 DEMO	Bit 6: Demo-Modus (ungenutzt!)
			 AZ	Bit 7: Nach Referenzfahrt zur Null eilen
				Wenn nicht gesetzt, steht nach der Referenzfahrt in <Soll> die Abweichung von der letzten Referenzfahrt.
			weiter wie oben, Folgebytes werden nicht im EEPROM gespeichert

0x8E..0x8F	-	Koordinierte Bewegung einleiten
1..6			Anzahl der beteiligten Motoren (wenn =0 oder >6 ist das Kommando wirkungslos)
Kanalliste		Motoren-Liste
			Dieses Kommando schaltet die Firmware in den Modus „Koordinierte Bewegung“.
			Ab sofort wird die Schnittstelle auf 115200 Baud umgeschaltet,
			und es sollte ein Datenstrom an Geschwindigkeits- (0x8E)
			oder Beschleunigungs- (0x8F) -Vektoren mit 1 kSa/s fließen.
			Der Ausgabe-Datenfluss muss mit XON/XOFF-Protokoll gesichert werden.
			Ungültige Bytes (0x80 == NaN) führen zum (kontrollierten!) Abbruch.
			Veränderungen an der Lokalbedienung werden im Rückkanal gemeldet;
			es funktioniert nur noch S802 (Stopp).
			Fehler sind Zeitüberschreitung (bei v=0) und Datenstromabriss (bei v≠0)
			Weiterer Datenstrom siehe unten!

0x90..0x95	<länge>	Motor-Struktur (insgesamt 32 Bytes) abfragen
2	
offset		<offset> = 0..31
länge		<offset>+<länge> ≤ 32
			Damit können alle variablen Infos abgefragt werden.
			Die Daten liegen hintereinander:
			- wie bei Kommando 'A'..'F' (8 Bytes)
			- wie bei Kommando 0x88..0x8D (16 Bytes)
			- danach 8 Bytes, die weniger interessant und zumeist funktionslos sind
			  - 2 Byte Pilgerschritt
			  - 1 Byte Ruck
			  - 1 Byte Endschalter-Zuordnung
			  - 1 Byte Endschalter-Zuordnung
			    Bit 0 = Endschalter motornah vorhanden
			    Bit 1 = Endschalter motorfern vorhanden
			    Bit 2 = Referenzschalter vorhanden
			    Bit 3 = Endschalter motornah/motorfern vertauscht
			    Bit 4 = Endschalter mit invertiertem Signal
			  - 2 Byte weitere Flags
			  - 1 Byte PowerDownCounter
			  - 1 Byte Einzelbeschleunigungskommando
			Mittels <offset> und <länge> kann ein beliebiger Ausschnitt der 32-Byte-Motordaten gelesen werden,
			um den Datenverkehr auf der RS232-Schnittstelle zu minimieren.

0x98..0x9D	-	Motor-Struktur setzen (beliebiger Offset)
			Vorläufig undokumentiert!

◊ Die irrelevanten Bits werden von der Firmware auf Null gesetzt.

Die angegebenen Konstanten sind wie folgt festgelegt:
CNAN = 0x80
INAN = 0x8000
LNAN = 0x8000000
+∞   = 0x7FFFFFF
-∞   = 0x8000001

=== MEHRBYTE-KOMMANDOS (Flash/RAM/EEPROM) ===

Diese Mehrbyte-Kommandos dienen zum Zugriff insbesondere auf den EEPROM,
der die persistenten Einstellungsdaten speichert.
Damit kann PC-Steuersoftware in gewissen Grenzen plug-and-play-fähig
gemacht werden, da diese steuerungsspezifische Daten wie Spindelsteigung
aus dem EEPROM entnehmen kann.

PC OUT		PC IN	Funktion
──────────────────────────────────────────────────────────────────────────
0xA0		<länge>	Flash/RAM/EEPROM lesen
4
adrL			Adresse Low-Teil
adrH			Adresse High-Teil
target			0 = Flash, 0x80 = RAM, 0x81 = EEPROM ♠
länge			Anzahl Bytes, 1..255

0xA1		-	Flash/RAM/EEPROM schreiben
länge			<länge> = 4..255
adrL
adrH
target			0 = Flash, 0x80 = RAM, 0x81 = EEPROM ♠
<daten>			<länge>-3 Bytes Nutzdaten

♠ Dies entspricht der Linkerskript-Vorgabe des AVR-GCC,
  wobei 0x00 .. 0x7F einen bis zu 8 MByte großen Flash adressiert

EEPROM schreiben darf nicht durch ein anderes Mehrbyte-Kommando
unterbrochen werden, d.h. nach dem Absetzen dieses Kommandos
muss eine Sendepause von 10 ms pro Byte eingelegt werden.
Einzelbyte-Kommandos werden weiterhin verarbeitet,
ein Mehrbyte-Kommando bricht das EEPROM-Schreiben ab.
Einige Motorsteuer-Funktionen bestehen auf lesefähigen EEPROM,
diese funktionieren nicht während des EEPROM-Schreibens.
Auf das Ende des Schreibens kann mit dem Kommando '&' gewartet werden.

Flash schreiben ist zz. nicht implementiert.

Das Lesen von RAM kann Seiteneffekte und Abstürze auslösen,
wenn vom E/A-Ports gelesen wird.
Das Schreiben von RAM löst ziemlich sicher Abstürze aus,
wenn Register, E/A-Ports oder der Stack überschrieben wird.

=== EEPROM-Inhalt ===

Der EEPROM enthält Konfigurationsinformation in der folgenden Form:
8 Byte Header ab EEPROM-Adresse 0:
 Adresse Name Länge Inhalt Beschreibung
──────────────────────────────────────────────────────────────────────────
 0       fv   2     8000   Berechnungsschritte pro Sekunde für <v> (8 kHz)
 2       ea   1     -9     Exponent zur Basis 2 für <a> (64 kHz² als Basis)
 3       xs   1     8      Irrelevante Bits für Positionsangabe (hier: Halbschritt)
 4       le   1     ≈20    Ausgabewert für Load = 0 % (siehe Kommando '%')
 5       lf   1     255    Ausgabewert für Load = 100 % (siehe Kommando '%')
 6       bd   1     0x19   Baudrate gemäß Baudrate.htm
 7       nm   1     0x46   6 Motor-Achsen (Low-Nibble) à 48 Byte,
                           4 = Shift-Wert von fv auf Sampletakt für Bahnsteuerung
			   
Die Angaben <fv> und <ea> sind zur Einheitenumrechnung bei Geschwindigkeit
und Beschleunigung erforderlich, siehe LabVIEW-Beispiel!
Die Angabe <xs> dient zum Ausblenden von Bits beim Auslesen und Anzeigen des Istwertes.
Die Angabe <nm> ist zur Berechnung von EEPROM-Offsets heranzuziehen!

Es folgen:
6 x 48 Byte Motordaten ab EEPROM-Adresse 8 (Quelltext: struct EeMotor):
 Adresse Name    Länge Inhalt Beschreibung
──────────────────────────────────────────────────────────────────────────
 0       Ist      4    0      Position zurzeit (wird häufiger geschrieben)
 4       flags    1    0      Nichtflüchtige Bits
				0 = LEFT  Phasenumkehr der Motorbestromung
				1 = REF   Position referenziert
				2 = RIGHT Default-Referenzschaltersuche zur Motorferne
				3 = MANU  Niemals Referenzfahrt, sondern Null-Setzung
				4 = HOLD  Dauer-Bestromung des Motors
				5 = ROTA  Umlaufender Antrieb ohne Endlagen
				6 = PILG  ¿Pilgern, sonst Spielausgleich
				7 = AZ    Zielfahrt nach Null nach Referenzfahrt
 5       MaxAccel 1    64     Maximale Beschleunigung
 6       MaxSpeed 2    ≈128   Maximal erlaubte Verfahrgeschwindigkeit
 8       RefPos   4    0      Position des Referenzschalters ‡
 12      Anfang   4    -∞     Software-Endschalter links †
 16      Ende     4    +∞     Software-Endschalter rechts †
 20      Pilger   2    0      Pilgerschritte oder Spiel, vzb., max. ±127 Halbschritte
 22      Jolt     1    0      (Maximaler) Ruck, 0 = ohne Ruckbegrenzung
 23      endsw    1    3      Endschalter-Zuweisung, Bits:
				0 = Endschalter motornah vorhanden
				1 = Endschalter motorfern vorhanden
				2 = Referenzschalter vorhanden (gleiche Leitung wie „motornah“)
				3 = Endschalter-Leitungen motornah/motorfern vertauscht
				4 = Endschalter mit invertiertem Signal (Schließer)
 24      fl2      1    0      weitere Flags (vorgesehene Verbote)
				4 = DEMO  ¿ungenutzt
				5 = F2AR  ¿Automatisch Referenzfahrt beim Einschalten
				6 = F2RR  ¿Keine Bewegung ohne Referennz
				7 = F2RV  ¿Referenzverlust beim Einschalten
 25      fl3      1    0      unbestimmt
 26      Current  1    ≈50    Strom durch Motorwicklung, in 20 mA (einstellbar ab SM3, sonst nur Anzeigegröße)
 27      Curve    1    0      Kurvenform der Sinusinterpolation (mikroschrittfähiges SM3+)
 28      PerUnit  4    ≠0     Mikroschritt pro Einheit — nur für PC-Software (C: float, PASCAL: single)
 32      Unit     8    "mm"   Einheitenbezeichner in UTF-8 — nur für PC-Software
				(nullterminiert oder nicht terminiert)
 40    FreeForApp 8    0      Handle o.ä. für Anwendungsprogramm
 
† darf ∞ sein, wenn Hardware-Endschalter vorhanden, sonst nicht.
  NaN ist nicht erlaubt.
‡ darf sich auch außerhalb von Anfang und Ende befinden.
  NaN oder ∞ ist nicht erlaubt.

Es folgen:
6 x ?? Bytes Motor-Achsbezeichnung (nullterminierte UTF-8-Strings)



In LabVIEW exisitert für die Binär-Interpretation des seriellen Datenstroms
eine passende Komponente: Daten serialisieren / deserialisieren.

=== Koordinierte Bewegung ===

Nach dem Umschalten auf Koordinierte Bewegung erwartet die Steuerung
die stetige Übergabe von char-Geschwindigkeits- bzw. Beschleunigungsvektoren
für jede der Achsen, mit XON/XOFF-Flusskontrolle.
(char-Geschwindigkeitsvektoren beschränken auf vmax=±127!)

Der Eingangspuffer hat eine Größe von 256 Byte
und die XON/XOFF-Schwelle (High/Low-Watermark) liegt bei 128 Byte.

Die Abnahme der Vektoren durch die Steuerung erfolgt mit 500 Hz,
d.h. auch bei 6 Motoren ist die Datenrate (3840 Byte/s)
immer noch ausreichend (6 x 500 Byte/s = 3000 Byte/s Verbrauch).

Nach dem Umschalten besteht ein TimeOut von 64 ms bis zum Senden
des ersten Vektors.

Das Datenbyte 0x80 (CNAN) beendet den Datenstrom regulär und schaltet auf
die normale Steuerung zurück. Zurückgesendet wird:
	80 = End Of Stream erkannt, speed=0 (OK)
	Bx = End Of Stream erkannt, speed≠0 (nicht OK!)
Irreguläre Abbrüche sind:
	Fx = Beschleunigung zu groß
	Ex = Geschwindigkeit zu groß
	Dx = Position außerhalb erlaubter Bereich oder auf Endschalter
	Cx = Datenstrom-Abriss (Unterlauf) mit speed≠0
	A3 = CNAN (0x80) an nicht-erster Position
	A2 = Puffer-Überlauf
	A1 = Abbruch durch BREAK im Eingangsdatenstrom
	A0 = Taste HALT (S802) betätigt
	81 = Datenstrom-TimeOut (Unterlauf, speed=0) (auch OK)

Die Ausgabe von BREAK bei Fehlern ist vorgesehen, aber nicht implementiert.

Nach irregulären Abbrüchen verarbeitet die Steuerung eingehende Datenbytes als Kommandos.
Um ein Verhaspeln zu vermeiden, sollte die Steuerung 256 Null-Bytes senden.
(TODO: Dies ist unsauber gelöst.)

Weiterhin meldet die Steuerung Tasteneingaben wie beim Kommando '~',
mit Offset 0x40 (um nicht als XON/XOFF detektiert zu werden), wenn sich da etwas ändert.
Für die Inkrementalgeber-Differenzen werden nur 2 Bit benutzt, und es wird nur 0, +1 oder -1 geliefert.
Damit lässt sich die Lokalbedienung zum Eingriff in die Bahnsteuerung verwenden.
Außer der HALT-Taste; diese terminiert die Bahnsteuerung irregulär.


heha, 110518 ~ 140127
Detected encoding: ASCII (7 bit)8