Software/MATLAB

From ZaberWiki
Jump to navigation Jump to search

Here are two short examples of controlling a Zaber device with either Zaber ASCII or Binary protocol. A newer and complete official Zaber MATLAB Toolbox is also available.

ASCII

In this example, two helper functions are provided. The helper functions should be saved as separate files, sendCommand.m and pollUntilIdle.m, at the same directory of the main script, or within project search path.

% Specifying serial port examples
% Windows: 'COM5'
% Linux: '/dev/ttyUSB0'
% Mac: '/dev/tty.usbserial-DA00FT01'
portName = 'COM5';

deviceAddress = 1;
axisNumber = 1;

% Set up serial object
s = serial(portName);
set(s, 'BaudRate',115200, 'DataBits',8, 'FlowControl','none',...
    'Parity','none', 'StopBits',1, 'Terminator','CR/LF');

% Open serial port. Fails if port is already opened or non-existent.
fopen(s);

try
    % Send a home command, ignoring the reply
    sendCommand(s, deviceAddress, axisNumber, 'home');
    
    % Wait until axis finishes homing
    pollUntilIdle(s, deviceAddress, axisNumber);
    
    % Get current position
    reply = sendCommand(s, deviceAddress, axisNumber, 'get pos');
    pos = str2num(reply.data);
    disp(['Current position is ' num2str(pos) '.']);
    
catch e
    % close port first if an exception occurs
    fclose(s);
    rethrow(e)
end

% Close port and clean up serial object
fclose(s);
delete(s);
clear s

In sendCommand.m

function reply = sendCommand(ser, deviceAddress, axisNumber, command)
% SENDCOMMAND  Send an ASCII command to a Zaber device and receive a reply.
%   REPLY = SENDCOMMAND(SER, DEVICEADDRESS, AXISNUMBER, COMMAND)
%
% This function sends an ASCII command formatted as
% '/DEVICEADDRESS AXISNUMBER COMMAND\n' to the serial object SER.
% The reply is formatted as a struct.
%
% EXAMPLE
% sendCommand(s,1,2,'move abs 256') will result in
%   '/1 2 move abs 256\n'
% being sent to the device at serial object s, and a struct
%            type : '@'
%   deviceAddress : 1
%      axisNumber : 2
%            flag : 'OK'
%          status : 'BUSY'
%         warning : '--'
%            data : '0'
% to be returned by the function.
%
% NOTE
% The 'Terminator' property of the serial object should be set to 'CR/LF'
% so that ASCII message footer is properly handled when sending commands
% and receiving replies.
%
% Complete protocol manual can be found at
% https://www.zaber.com/wiki/Manuals/ASCII_Protocol_Manual

if isempty(command)
    fprintf(ser, '/%d %d\n', [deviceAddress, axisNumber]);
else
    fprintf(ser, '/%d %d %s\n', [deviceAddress, axisNumber, command]);
end

% Get device reply. FGETL blocks a line is received.
replyStr = fgetl(ser);

% Parse reply into struct.
[type, deviceAddress, axisNumber, flag, status, warning, data] = ...
    strread(replyStr, '%c%d %d %s %s %s %s');
reply = struct('type', type, 'deviceAddress', deviceAddress,...
    'axisNumber', axisNumber, 'flag', flag, 'status', status,...
    'warning', warning, 'data', data);

In pollUntilIdle.m

function pollUntilIdle(ser, deviceAddress, axisNumber, pauseDuration)
% POLLUNTILIDLE  Poll an axis until it becomes idle.
%   POLLUNTILIDLE(SER, DEVICEADDRESS, AXISNUMBER)
%   POLLUNTILIDLE(SER, DEVICEADDRESS, AXISNUMBER, PAUSEDURATION)
%
% This function sends an empty ASCII command and checks whether an axis has
% become idle. If axis is busy, pauses for a specific duration and retry.
% This function returns when the axis is idle.
%
% PAUSEDURATION is specified in seconds. If not provided, 0.05 is used.
%
% EXAMPLE
% This example sends a 'home' command and waits until axis has finished
% homing.
%   sendCommand(ser, 1, 2, 'home');
%   pollUntilIdle(ser, 1, 2);
%   disp('Finished homing!');
%
% NOTE
% The 'Terminator' property of the serial object should be set to 'CR/LF'
% so that ASCII message footer is properly handled when sending commands
% and receiving replies.
%
% Complete protocol manual can be found at
% https://www.zaber.com/wiki/Manuals/ASCII_Protocol_Manual

if nargin < 4
    pauseDuration = 0.05;
end

while true
    reply = sendCommand(ser, deviceAddress, axisNumber, '');
    if strcmp(reply.status, 'IDLE') == 1
        % axis is now idle
        break
    end
    
    % axis still busy, sleep a while before checking again
    pause(pauseDuration)
end

Binary

s = serial('COM5','BaudRate',9600);

% Open serial port. Fails if port is already opened.
fopen(s);

% Send a home command
command_home = [1 1 0 0 0 0];
fwrite(s,command_home);       % send command to device

% Device replies once command is completed when using Binary protocol
% This is different from ASCII, which replies immediately after receiving a command
while s.BytesAvailable < 6    % wait for response
    pause(0.01);
end

% Read response
response = fread(s,6)

fclose(s);
delete(s);
clear s;

Working with serial ports

Available serial ports and port status can be queried with INSTRHWINFO and INSTRFIND.

>> info = instrhwinfo('serial')
info = 
     AvailableSerialPorts: {3x1 cell}
           JarFileVersion: 'Version 2.8.0'
    ObjectConstructorName: {3x1 cell}
              SerialPorts: {3x1 cell}

>> info.AvailableSerialPorts
ans = 
    'COM1'
    'COM3'
    'COM4'

If a port has been previously opened and is preventing a script from opening it again, try the following to close the port.

>> s = serial('COM3');

>> fopen(s)
??? Error using ==> serial.fopen at 72
Port: COM3 is not available. Available ports: COM1, COM4.
Use INSTRFIND to determine if other instrument objects are connected to the requested device.

>> serialObj = instrfind

   Instrument Object Array

   Index:    Type:     Status:   Name:  
   1         serial    closed    Serial-COM3
   2         serial    open      Serial-COM3
   3         serial    closed    Serial-COM3

>> fclose(serialObj(2))

Unofficial Drivers and Examples

We have removed previously customer-supplied drivers and examples, which do not support newer products. If you require one of these drivers or examples, please contact us.