UNILOGO

Messdatenerfassung mit MATLAB

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.

Zugriff auf die ActiveX-Komponente

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),
Settings
legt Übertragungsgeschwindigkeit, Parität, Zeichenlänge, Zahl der Stopbits fest,
PortOpen=1
öffnet die Schnittstelle - übernimmt den Besitz, 
InputLen=0
ordnet an, dass beim Einlesen der gesamte Eingabepuffer gelesen wird,
Handshaking=2
bedeutet Hardware- bzw. RTS/CTS-Handshake (0 wäre kein, 1 Software- bzw. XON/XOFF-Handshake, 3 sowohl 1 als auch 2). 

Mit CloseComm() wird die Schnittstelle wieder freigegeben:

function CloseComm(s) 

set(s, 'PortOpen', 0); 
release(s);

Steuerung des Spektrometers

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.

Einlesen von Messdaten

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.

Messablauf für ein Spektrum

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.

Mittelung mehrerer Einzelspektren

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.