Im Versuch "Spektrometer" des Fortgeschrittenen-Praktikums Physik wird die Steuerung und Datenerfassung mit MATLAB realisiert. Dazu wird die in der aktuellen Windows-Version von MATLAB bereitgestellte Möglichkeit genutzt, ActiveX-Komponenten einzubinden. Die Kopplung des Rechners ans Experiment erfolgt über die serielle Schnittstelle des Rechners. Die für diese Schnittstelle zuständige ActiveX-Komponente (ActiveX Control) ist MsComm32.ocx; sie gehört nicht direkt zum Betriebssystem sondern muss auf dem Rechner zusätzlich installiert und registriert werden, in der Regel als mitinstallierte Komponente der Visual-Studio-, Visual-C++- oder Visual-Basic-Installation.
Die Einbindung in die MATLAB-Arbeitsumgebung erledigt die Funktion actxcontrol(),
die eine Handle-Variable zurückliefert. Zur Bedienung werden Eigenschaften (Properties)
der ActiveX-Komponente mit set() gesetzt bzw. mit get() gelesen,
der Zugriff erfolgt über die Handle-Variable. Falls vorhanden, können auch
Funktionen (Methods) der Komponente mit invoke() aufgerufen werden.
Die Funktion OpenComm(), die eine serielle Schnittstelle bereitstellt und
initialisiert, könnte so aussehen:
function s = OpenComm(comx)
if nargin==0, comx = 2; end;
s = actxcontrol('MsCommLib.MsComm.1');
set(s, 'CommPort', comx);
set(s, 'Settings', '9600,n,8,1');
set(s, 'PortOpen', 1);
set(s, 'InputLen', 0);
set(s, 'Handshaking', 2);
MsCommLib.MsComm.1 ist der Name, unter dem die Komponente
registriert ist,
CommPort enthält die Schnittstellennummer (1..4), legt Übertragungsgeschwindigkeit, Parität, Zeichenlänge, Zahl der
Stopbits fest,
Settings öffnet die Schnittstelle - übernimmt den Besitz,
PortOpen=1 ordnet an, dass beim Einlesen der gesamte Eingabepuffer gelesen wird,
InputLen=0 bedeutet Hardware- bzw. RTS/CTS-Handshake (0 wäre kein, 1
Software- bzw. XON/XOFF-Handshake, 3 sowohl 1 als auch 2).
Handshaking=2
Mit CloseComm() wird die Schnittstelle wieder freigegeben:
function CloseComm(s) set(s, 'PortOpen', 0); release(s);
Zur Steuerung des Spektrometers wird die Funktion Steps() bereitgestellt,
der die Zahl der Schrittmotorschritte übergeben wird. Der Rückgabewert success zeigt
an, ob die Aktion erfolgreich (1) oder ein Misserfolg war (0), beispielsweise einer der
Endschalter erreicht wurde.
function success = Steps(s, nofsteps)
nofsteps = round(nofsteps);
if nofsteps == 0, return; end;
if nofsteps > 0
cmd = sprintf('XR%05X\r', nofsteps);
else
cmd = sprintf('XL%05X\r', -nofsteps);
end;
get(s, 'Input');
set(s, 'Output', cmd);
while get(s, 'InBufferCount') <8, end;
get(s, 'Input');
while get(s, 'InBufferCount') <3, end;
inputstring = get(s, 'Input');
succstring = sscanf(inputstring, '%s');
if succstring=='SR'
success = 1;
else
success = 0;
end;
Zum Lesen und Ausgeben der Daten werden die Eigenschaften Input und
Output der ActiveX-Komponente verwendet. Es wird zunächst der Eingangspuffer der
Schnittstelle geleert, dann die mit sprintf() formatierte Anweisung an die
Steuerung ausgegeben, auf das zugehörige Echo (8 Zeichen) gewartet, schließlich das
Ergebnis (3 Zeichen) gelesen und interpretiert.
Das Einlesen des aktuellen Messwerts besorgt die Funktion ADvalue():
function adc = ADvalue(s)
get(s, 'Input');
cmd = sprintf('A\r');
set(s, 'Output', cmd);
while get(s, 'InBufferCount') <2, end;
get(s, 'Input');
while get(s, 'InBufferCount') <4, end;
adcstring = get(s, 'Input');
adc = sscanf(adcstring, '%X');
Nach dem Leeren des Eingangspuffers wird das Kommando zur A/D-Wandlung ausgegeben, dann
Echo und Rückgabestring abgewartet (while ...). Der Rückgabestring wird
schließlich mit sscanf() analysiert.
Die Ablaufsteuerung zur Messung eines kompletten Spektrums könnte dann die Funktion
OneSpec() bewerkstelligen:
function [wavelength, intensity] = OneSpec(startWL, endWL, stepWL, actualWL)
if nargin<2, return; end;
if nargin<3, stepWL = 1; end;
if nargin<4, actualWL = endWL; end;
UNIT = 50;
PLOTINTERVAL = 5;
YMIN = 0; YMAX = 4095;
startWL = (round(startWL*UNIT))/UNIT;
endWL = (round(endWL*UNIT))/UNIT;
actualWL = (round(actualWL*UNIT))/UNIT;
stepsteps = abs(round(stepWL*UNIT));
if stepsteps==0, return; end;
if endWL<startWL, stepsteps = -stepsteps; end;
stepWL = stepsteps/UNIT;
backsteps = round((startWL-actualWL)*UNIT);
datasize = round((endWL-startWL)/stepWL);
if datasize==0, return; end;
endWL = startWL + datasize*stepWL;
datasize = datasize+1;
wavelength = linspace(startWL, endWL, datasize);
intensity = zeros(size(wavelength));
s = OpenComm(2);
Steps(s, backsteps);
for i = 1:datasize,
intensity(i) = ADvalue(s);
plot(wavelength(1:i), intensity(1:i));
axis([startWL endWL YMIN YMAX]);
if mod(i, PLOTINTERVAL)==0, drawnow; end;
if i<datasize,
if Steps(s, stepsteps) == 0, break; end;
end;
end;
CloseComm(s);
Die erste Hälfte dient dazu, die Funktion einigermaßen robust zu machen, so dass
kleinere Bedienungsfehler keine Folgen haben. So werden beispielsweise die
Wellenlängenwerte in Einheiten von Schrittmotorschritten (0.02 nm) diskretisiert.
Die Konstante UNIT gibt die Zahl der Schrittmotorschritte pro
Wellenlängeneinheit an (bei diesem Spektrometer 50 Schritte pro Nanometer). Sie sollte
nie geändert werden. PLOTINTERVAL legt fest, nach wie vielen Messungen
jeweils die Grafik regeneriert wird. Diese Konstante kann - ebenso wie XMIN und
XMAX - an die jeweilige Messung angepasst werden. Nachdem die Ergebnisvektoren
wavelength und intensity vorbereitet sind, wird das Spektrum in einer
for-Schleife punktweise gemessen. Dabei wird auf die beschriebenen vorbereiteten
Funktionen OpenComm(), Steps(), ADvalue() und
CloseComm() zurückgegriffen.
Die obige Funktion OneSpec() ist so implementiert, dass sie auch benutzt
werden kann, um Spektren mehrfach zu messen und über die Einzelmessungen zu mitteln
(sinnvoll bei schwachen und/oder verrauschten Messsignalen). Ein kurzes Skript dafür
könnte so aussehen:
[wl,int]=onespec(570, 580, 0.1, 600); for i=2:10 [wl,int1]=onespec(570, 580, 0.1); int = int+int1; end;
Zehn Einzelmessungen des Bereichs 570 - 580 nm werden aufaddiert, der Abstand der Messpunkte beträgt 0.1 nm. Die aktuelle Wellenlänge vor der Messung (im Beispiel 600 nm) braucht nur beim ersten Aufruf angegeben werden, da sie später immer gleich der Endwellenlänge des Spektrums ist.