Code covered by the BSD License  

Highlights from
Knauer pump RS232 communication

from Knauer pump RS232 communication by Geoffrey Akien
Functions for communicating with Knauer pumps via RS232.

knauerpumpobjcomm(serialObject, type, command)
function output = knauerpumpobjcomm(serialObject, type, command)
% KNAUERPUMPOBJCOMM Reads and writes data from Knauer pumps
% knauerpumpobjcomm(serialObject, type, command) reads from or writes
% information to Knauer pumps connected via RS232 serial ports.
% serialObject is the valid serial object, type is 'read' or 'write',  and
% command the command to be sent (string). Automatically leaves a 0.15 s
% pause after any commands where there is no response expected to prevent
% communications issues. (PAUSE HAS NOT BEEN OPTIMISED)

% checks the number of arguments
error(nargchk(3, 3, nargin))

% error checking here
if ~isa(serialObject, 'serial') || ~isvalid(serialObject) || ~strcmp(serialObject.Status, 'open')
    
    % the serial object must be valid and open to send or receive data
    error('serialObject must be a valid open serial object.')
    
elseif ~isequal(type, 'read') && ~isequal(type, 'write')
    
    % errors
    error('type must be "read" or "write".')
    
elseif ~ischar(command) || ~isvector(command) || any(command == ' ')
    
    % string must only be a single "word"
    error('command must a string with no spaces.')
end

% sees if a colon has been specified
commandColonPosition = strfind(command, ':');

% if there's a colon in there then check there's a valid number after it
if ~isempty(commandColonPosition)
    
    % if there's a colon, then you also can't put a ? at the end
    
    if command(end) == '?'
        
        % complain
        error('If '':'' is present, then cannot have a ''?'' at the end of the command.')
    end
    
    % convert it to a number
    commandNum = str2double(command(commandColonPosition + 1:end));
    
    % checks that number is OK
    if isempty(commandNum) || isnan(commandNum) || isinf(commandNum) || ~isreal(commandNum) || commandNum < 0 || commandNum ~= round(commandNum)
        
        % complain
        error('If a number is specified, it must be a valid positive integer.')
    end
    
    % if it got that far then define the commandWord for further checking
    % later
    commandWord = command(1:commandColonPosition - 1);    

elseif command(end) == '?'
    
    % if it was a read command, then return that, less the '?'
    commandWord = command(1:end - 1);
    
else
    
    % then it was neither of those, and the commandWord is the command
    % as-is
    commandWord = command;
end

% flushes everything in the buffer
fread(serialObject, serialObject.BytesAvailable);

% sends command
fprintf(serialObject, command, 'async')

% gets the response up to the terminator, discard it
response = fgetl(serialObject);

% if no response, then there was a problem
if isempty(response)
    
    % error
    error('No response to command.')
end    

% now parse the response - find the location of the colon
responseColonPosition = strfind(response, ':');

% complain if it wasn't there
if isempty(responseColonPosition)
    
    % complain
    error('Unexpected response from Knauer pump - no '':''.')
    
else
    
    % it's OK, so we can define the word that the instrument sent
    responseWord = response(1:responseColonPosition - 1);
end

% if it was an error...
if strcmp(responseWord, 'ERROR')
    
    % then say so
    error(['Error response from Knauer pump - code ', response(responseColonPosition + 1:end)])
end

% check that it matched the initial command (case-insensitive check - the
% pump appears to be case insensitive)
if ~strcmpi(commandWord, responseWord)
    
    % problem
    error('Unexpected response from Knauer pump (''%s'') - does not match initial command.', response)
end

% if reading data, check the response
if strcmp(type, 'read')
    
    % the number is nearly always just a number, but ERRORS returns the
    % last five error codes as x,x,x,x,x so we need to cover that
    % eventuality - most of the timer this is overkill but this
    % futureproofs it
    response = textscan(response(responseColonPosition + 1:end), '%f', 'Delimiter', ',');
    
    % annoying formatting (thanks MATLAB) - turns it into a horizontal
    % vector
    output = response{1}';
    
elseif strcmp(type, 'write')
    
    % need to check it was written... the response is command:OK if it was
    if ~strcmp(response(responseColonPosition + 1:end), 'OK')
        
        % error
        error('Command was not written to pump - no OK was received.')
    end
    
end

Contact us