Matlab-steuerung externer Komponenten (zB. Schrittmotoren) mit RS232
Inhaltsverzeichnis
Einleitung; Motivation:
Für eine Atomstrahlanlage wurde ein Softwarepaket entwickelt mithilfe dessen sämtliche Schrittmotoren gesteuert, und die Messergebnisse erfasst werden können. Als Enwicklungsumgebung wurden Matlab und Ocatve gewählt. Der Vorteil dieser Programmiersprachen liegt darin, dass Matlab und Octave mit kleinen Ausnahmen kompatibel, und in der Technik weit verbreitet sind. Weiters wird als Messrechner ein Linux-PC verwendet. Linux erlaubt problemlosen Zugriff auf Schnittstellen, wodurch sich der Datenaustausch mit der Anlage sehr einfach gestaltet. Ausserdem kann der Messrechner mit jedem Linux oder Mac-Rechner über eine SSH (secureshell) Verbindung gesteuert werden. Dadurch kann der Anlagenzustand mittels Webcam und Druck- oder Positionsdaten überwacht, und Messungen weltweit gestartet werden.
Frankensteincontrol
Zentrales Element der Anlagensteuerung ist die modular aufgebaute Steuereinheit 'Frankensteincontrol'. Sie verbindet die Hardware der Anlage mit der Software. Dieses Elektronikmodul wurde in mehrmonatiger Entwicklungszeit am Institut für Experimentalphysik von Reinhard Dämon entwickelt.
Ein Mastermodul gibt über ein internes Bussystem empfangene Befehle an die einzelnen Module weiter. Je nach Anfangsziffern wird der Befehl vom jeweiligen Prozessorboard akzeptiert und interpretiert. Ein Befehl kann zB. 04rv00 lauten. Dieses 'Befehlswort' wird über die RS232 Schnittstelle gesendet. 04 steht für Modul 4, das Spannungsmessmodul. rv steht für 'read voltage'. 00 heisst, dass Spannungskanal 00 gelesen werden soll. Das Modul antwortet mit der entsprechenden Spannung. Über die Linux Konsole kann die Spannung also wie folgt ausgelesen werden:
cat /dev/ttyS0 >> /home/user/antwortfile.txt &
echo "04rv00" > /dev/ttyS0
killall cat
Zeile 1:
cat steht für concatenate. Dieses Programm hängt Textfiles zusammen. >> heisst, dass cat den Text an den bestehenden Text in der Zieldatei anhängen soll. Will man nur die aktuelle Spannung in der Datei stehen haben schreibt man stattdessen >. Im Beispiel hängt es den Text, der im File /dev/ttyS0 liegt an das File /home/user/antwortfile.txt an. Unter Linux werden Schnittstellen wie Dateien behandelt. Deshalb spielt es keine Rolle, dass /dev/ttyS0 keine Datei, sondern die RS232 Schnittstelle ist. Das & am Ende der Zeile bedeutet, dass das Programm im Hintergrund weiterlaufen soll.
Zeile 2: Der Befehl echo schreibt beliebigen Text in eine Datei oder auf eine Schnittstelle. "04rv00" ist das Befehlswort, das an das Modul übertragen werden soll. /dev/ttyS0 ist wieder die RS232-Schnittstelle an die das Befehlswort übertragen werden soll.
Zeile 3: killall cat beendet den Befehl cat, der bis zu diesem Zeitpunkt im Hintergrund weitergelaufen ist.
Unter Matlab kann dieselbe Prozedur mit der selbst geschriebenen Funktion serwrite ausgeführt werden. Matlab beinhaltet eine Funktion mit der auf die Schnittstelle zugegriffen werden kann. Da die Geschwindigkeit der Befehlsketten allerdings variable sein muss (andernfalls hängen sich die Module auf!) wurde der Umweg über die Linux-Konsole gewählt.
!cat /dev/ttyS0$ >> /home/user/antwortfile.txt &
serwrite('04rv00')
!killall cat
Die Rufzeichen am Anfang der Zeilen 1 und 3 bedeuten, dass die Befehle in der Konsole ausgeführt werden sollen. Die Syntax von serwrite ist eigentlich serwrite(string,port). Vollständig lautet der Befehl also serwrite('04rv00','/dev/ttyS0'), der Standardwert für Port ist allerdings /dev/ttyS0, die Eingabe ist also unnötig.
Die empfangenen Daten werden automatisch auf der Festplatte zwischengespeichert. Matlab liest die Datei aus und übergibt die Daten den Unterfunktionen. Diese plotten anschliessend linear und logarythmisch und speichern jeweils ein jpg-Bild in das aktuelle Verzeichnis. Dieses Verzeichnis wird automatisch nach folgendem Muster erstellt:
file=['/home/user/messdat/',date,'/tof',phi,'degr',dur,'duration',date,'_',number]; % generates the filename.
also: home/user/messdat/DATUM/tof (für Time-of-flight-messung)-Winkel des Detektorarms-dauer der Messung-datum mit uhrzeit.txt
serwrite.m
% serwrite.m % is a function which creates the right syntax to write data out of the serial port. % Works only under Linux. the serial port (for example /dev/ttyS0) has to % be writeable. (Ether one has superuser rights, or the rights have been changed ) % written by Nikolaus Balak, spring 2008
% Syntax: []=serwrite(string,port) % => serwrite([],['/dev/ttyS0']) % global variables are in the INIT-File
function[]= serwrite(string,port); if nargin <2 port=['/dev/ttyS0']; % Standardport.. end message=[string]; % gibt aus: "string" out=['echo ', message ,' >> ', port ]; unix(out); % sollte ergeben: echo "string" >> /dev/ttyS0
Schrittmotorinitialisierung (Beispielhaft)
Die Befehlswörter des Schrittmotors bestehen aus HEX-sequenzen. Im Manual ist eine Liste mit allen Befehlen, wobei nur einige wenige wirklich benötigt werden. Als Beispiel werden hier einige Befehlswörter zusammengesetzt und übertragen.
Der Motor mit der Schrittmotorkarte ist um etwa 130 Euro erh"altlich. (Google: RN-Control). Es besteht ausserdem die Möglichkeit einen zweiten Motor an diese Karte zu hängen.
function [ status ] = tiltinit(motor, port)
% Input: port Port, ueber den Schrittmotor gest. wird % motor 1...Motor 1, 2...Motor 2, 3...beide Motoren % % Output: status Ueberpruefung ob Init. erfolgreich % 0...erfolgreich, -1...Fehler
% Motorstrom einstellen: current_hb = '02'; % Strom in mA - high byte - HEX ! 00 current_lb = '58'; % Strom in mA - low byte - HEX ! 64 ... 100 mA serwrite(command_interface, port); serwrite('06wd10',port); serwrite(['06wd' motor ],port); serwrite(['06wh' current_lb ],port); serwrite(['06wh' current_hb ],port); serwrite('06wh0',port); % Gueltigkeit nur bis zum naechsten Reset serwrite('06wh0',port); % nicht benoetigt serwrite('06wh0',port); % CRC % Vollschritt- oder Halbschrittmodus: serwrite(command_interface, port); serwrite('06wd13',port); serwrite('06wd3',port); % gilt immer fuer beide Motoren - Byte egal serwrite('06wd0',port); % 0...Vollschritt, 1...Halbschritt serwrite('06wh0',port); % Gueltigkeit nur bis zum naechsten Reset serwrite('06wh0',port); % nicht benoetigt serwrite('06wh0',port); % nicht benoetigt serwrite('06wh0',port); % CRC
Motorsteuerung
% ------------------------------------------------------------- % Initialisierung: command_interface = '06wa!#' %<CR>'; % steht für 06 (modul) wa (write ascii) !# (Befehlswortbegin des Motorboards) %command_interface = ; % I2C % ------------------------------------------------------------- % Befehlszusammenstellung und -ausgabe:
dir=num2str(dir); % Drehrichtung festlegen: serwrite(command_interface, port); serwrite('06wd52',port); % heisst für den Motor, dass es um die Drehrichtung geht serwrite(['06wd', motor ],port); % welchen Motor es betrifft serwrite(['06wh',dir],port); % Richtung 0...links herum, 1...rechts herum serwrite('06wh0',port); % nicht benoetigt serwrite('06wh0',port); % nicht benoetigt serwrite('06wh0',port); % nicht benoetigt serwrite('06wh0',port); % CRC
% Best. Schrittzahl drehen: steps_lb = num2str(dec2hex(steps)); if steps<=hex2dec('FF') steps_hb = '0'; elseif (steps <= hex2dec('FFF')) steps_hb = steps_lb(end-2); steps_lb = steps_lb(end-1:end); else steps_hb = steps_lb(end-3:end-2); steps_lb = steps_lb(end-1:end); end serwrite(command_interface, port); serwrite('06wd55',port); serwrite(['06wd', motor ],port); serwrite(['06wh', steps_lb ],port); % Schritte - low byte - HEX ! serwrite(['06wh', steps_hb ],port); % Schritte - high byte - HEX ! serwrite('06wh0',port); % nicht benoetigt serwrite('06wh0',port); % nicht benoetigt serwrite('06wh0',port); % CRC