How to Control the Reglo ICC Pump Using Python and Matlab ?

How to Control the Reglo ICC Pump Using Python and Matlab ?

The Reglo ICC (Independent Channel Control) peristaltic pump by Masterflex Ismatec is a high-precision instrument engineered to deliver unparalleled control and accuracy in fluid dispensing and transfer. It stands out with its ability to independently control the direction and speed of up to four channels, each with unique programs for start, stop, calibration, and more.

With a working flow rate range of 0.001 to 35 mL/min per channel and customizable pulsation levels, this pump offers the flexibility needed for a variety of applications. The intuitive digital interface and RS-232 computer connectivity allow for the creation of complex pumping sequences and the control of multiple pumps simultaneously.

In this blog post, we will explore how to control the Reglo ICC peristaltic pump using the Reglo ICC serial command protocol via two programming platforms: Python and Matlab.

TABLE OF CONTENTS

Why Choose the Reglo ICC Peristaltic Pump ?

The Reglo ICC peristaltic pump is versatile and user-friendly, and it stands out as a top choice for fluid handling needs in laboratories and industrial settings alike. Here are some key advantages:

  • Independent Channel Control of up to four channels, each with its own program, flow rates and directions simultaneously.
  • High Accuracy and Reproducibility ensuring precise and consistent fluid dispensing by minimizing tube-to-tube differences.
  • Adjustable Pulsation and Flow Range with 6, 8, or 12 rollers used to adjust pulsation and flow range (more rollers result in less pulsatility and lower flow rates).
  • Versatile Control Options via its digital interface or RS-232 connection (up to eight daisy-chain pumps).
  • Comprehensive Operating Modes including continuous dispensing at a set rate, dispensing a volume over a specified period, calibrating each channel, and more.

What do you Need to Communicate with the Reglo ICC Pump ?

To communicate with the Reglo ICC peristaltic pump you will need a few key components:

  • A Reglo ICC pump with a pump head and a tubing of your choice,
  • A mini-USB/USB cable or a DB9 connector (wired to an RS-232 control module) allowing for serial communication and enabling data transfer between the syringe pump and the computer,
  • A programming platform (Python and Matlab in the case herein) or a terminal emulator,
  • A basic understanding of the Reglo ICC command serial protocol explained below 👇 and detailed in the pump’s user guide.

How to Set Up the Communication Port ?

Before you can start sending and receiving data from the pump, you need to set up the communication port correctly. Here are the steps to follow:

  • Connect the mini-USB/USB cable or DB9 connector to the serial port on the rear of the pump and the corresponding port on the computer.
  • Turn on the pump.
  • Identify the serial port name assigned to the connection on your computer (e.g., COM4 for Windows or /dev/ttyUSB0 for Linux). You can typically find this information in the device manager or by using terminal commands.
  • Ensure that the serial port settings match the specifications of your syringe pump:
    • 1 start bit,
    • 8 data bits,
    • Parity: none,
    • 1 stop bit,
    • a baud rate of 9600 bits/s.
  • Remote mode on the screen of the pump confirms a successful connection, indicating that the pump is being remotely controlled by a computer via a USB 2.0, Mini-B or RS-232 connection.
An image of the interface of the Reglo ICC peristaltic pump while in remote control mode.
🚨 The Reglo ICC protocol uses an addressing scheme designed to control multiple pumps “daisy-chained” to the same RS-232 bus. Each pump in this case is assigned a singular address. By using an address character that defines an individual channel, the RS-232 can also control each individual channel of the pump by itself.

The Reglo ICC Command Serial Protocol

The Reglo ICC command protocol offers an array of commands for external control, categorized into distinct types for precise manipulation. These include communication management, operational modes and settings, control directives, setting configurations, calibration, and more.

There are two types of messages. Response messages sent from the pump to the PC and request messages sent from the PC to the pump. All messages are composed of a string of printable ASCII characters. Each message is terminated with a carriage return or a carriage return and a line feed.

The Reglo ICC command protocol used to control the Reglo ICC peristaltic pump is summarized below. More details can be found in the pump’s user manual.

Data Type Formats

Data TypeWidthUnitRangeFormat
Direction1--J = clockwise
K = counter-clockwise
Discrete type 11 to 4-0 to 99991 to 4 characters in base 10.
Unused digits are not returned.
Discrete type 24-0 to 99994 characters in base 10.
Right-justified value.
Unused digits to the left are zeros.
Discrete type 36-0 to 9999996 characters in base 10.
Right-justified value.
Unused digits to the left are zeros.
Discrete type 410-0 to 429496729510 characters in base 10.
Right-justified value.
Unused digits to the left are zeros.
Discrete type 53-0 to 9993 characters in base 10.
Right-justified value.
Unused digits to the left are zeros.
Discrete type 65-0 to 999995 characters in base 10.
Right-justified value.
Unused digits to the left are zeros.
Fractional type 1Variable--XXXX.DD
Variable width of the integer portion (XXXX).
Decimal point and two digits to the right (.DD) always provided.
Volume type 17mL-mmmmEse ⇒ m.mmm × 10^se:

mmmm — 4 character mantissa
Decimal point inferred after first character.
E — 'E' character
s — sign for the exponent : + or -
e — single digit exponent
Time type 11 to 80.1s0 to 35964000 (0 to 999 hr)1 to 8 characters representing the time.
Unused digits are not returned.
Time type 280.1s0 to 35964000 (0 to 999 hr)8 characters representing the time.
Right-justified value.
Unused digits to the left are zeros.

Response Messages

A response message is a message sent from the pump to the PC in response to a request message sent by the PC. It can be in the form of a status or a data response.

A status response message is a single ASCII character that indicates whether the command was executed successfully or not. The different ASCII characters that indicate the execution status of the requested command are represented in the table below.

ASCII CharacterDefinitionIn HexIn Base 10
*command executed successfully0x2a42
#command not executed successfully0x2335
+positive response used for some commands0x2b43
-negative response used for some commands0x2d45

A data response is received from the pump when parameter values are requested by the PC. It is composed of one or more data parameter values delimited by spaces. Each data parameter in the response message is a data value returned by the pump in a format defined by the request message.

Data Parameter 1 [SP] Data Parameter 2 [SP] Data Parameter n [CR] [LF]

Request Messages

The request messages are messages sent from the PC to the pump. These should be answered by a response message from the pump.

A device control command (as shown below) is composed of a string of printable ASCII characters and terminated with a carriage return [CR] or a carriage return [CR] and a line feed [LF]. It is addressed to an individual pump/channel to get or set some particular parameters.

Address (1-4) Command code Data Parameter 1 [VB] Data Parameter 2 [VB] Data Parameter n [CR] [LF]

In the case of a bus of pumps that are “daisy-chained”, the address is from 1 to 8 (maximum number of pumps being controlled at once). In the case where only one pump is being controlled, the address is from 1 to 4 corresponding to the number of channels being independently controlled, as presented in the control command just above.

The command string is typically one or two characters indicating the command type. The data parameters are optional values that may be provided when setting a parameter value. And finally, the vertical bar character delimits the data parameters.

Different commands can be addressed to the pump related to communications management, pump drive, operational modes and settings, calibration, and more. Some of these direct addressed commands are listed in the table below. More commands can be found and detailed in the operating manual.

CommandFunctionSet/GetPump Response
HStart pumpSet*
- : channel setting not correct
IStop pumpSet*
xIPause pumping (STOP in RPM or flow rate mode)Set*
JSet rotation direction to clockwiseSet*
KSet rotation direction to counter-clockwiseSet*
xDGet rotation directionGetJ : clockwise
K : counter-clockwise
xMGet pump/channel current modeGetL : RPM
M : Flow Rate
O : Volume at rate
G : Volume over time
Q : Volume+Pause
N : Time
P : Time+Pause
LSet pump/channel to RPM modeSet*
MSet pump/channel to Flow Rate modeSet*
OSet pump/channel to Volume at rate modeSet*
GSet pump/channel to Volume over time modeSet*
- : channel setting not correct
SRPM mode flow rate setting (0.01 RPM).
Discrete type 3.
Set*
SGet current speed setting in RPMGetFractional type 1
fSet RPM flow rate in volume/time mode (mL/min).
Volume type 2 (Similar to type 1 without the 'E' character).
SetVolume type 1
fGet current volume/time flow rate (mL/min)GetVolume type 1
xPGet pumping pause timeGetTime type 1
xYStart calibration on a channelSet*
xZCancel calibrationSet*

Different symbols are used to represent ASCII characters in the defined request messages. Some of these are presented in the table below.

SymbolDefinitionIn HexIn Base 10
[CR]carriage return0x0d13
[LF]line feed0x0a10
[SP]space0x2032
[VB]vertical bar0x7c124
@'@' character0x4064

Examples of Commands

In order to communicate with the pump, one should understand the different commands the pump takes and prepare the needed control computer command strings.

In the table below, a few examples of direct-addressed commands are presented and explained.

CommandDefinitionPump ResponseDefinition
1H[CR]Start channel 1*Command executed successfully
4I[CR]Stop channel 4*Command executed successfully
2xD[CR]Get the direction of channel 2K[CR][LF]Direction of rotation is counter-clockwise
3J[CR]Set the direction of rotation of channel 3 to clockwise*Command executed successfully
1xM[CR]Get the operational mode of channel 1L[CR][LF]Current mode is RPM
3G[CR]Set the operational mode of channel 3 to volume over time*Command executed successfully
1S[CR]Get the drive speed of channel 122.50[CR][LF]Response in the form of "fractional type 1". The drive speed is 22.5 RPM
1S004500[CR]Set the drive speed of channel 1 to 45 RPM. The speed setting has a resolution of 0.01 RPM (45 assigned as 4500) in the form of a "discrete type 3" with a width of 6 characters with unused digits to the left being zeros (=> 004500).*Command executed successfully
3f[CR]Get the pumping rate of channel 31275E+1[CR][LF]Response in the form of a "volume type 1" (mmmmEse => m.mmm x10se):

  • mmmm = 1275

  • E = 'E' character

  • s is +

  • e = 1

Therefore, the pumping rate of channel 3 is 12.75 mL/min (1.275x10+1)
3f1500-3[CR]Set the pumping rate of channel 3 to 1.5 μL/min. Pumping rate setting in the form of "volume type 2" (mmmmse => m.mmm x10se).
1.5 µL/min = 1.500x10-3 mL/min, therefore:

  • mmmm = 1500

  • s is -

  • e = 3

1500E-3[CR][LF]Response in the form of "volume type 1".

How to Control the Reglo ICC Pump Using IsmaTerm ?

IsmaTerm is a software that allows one to control the Reglo ICC pump. It is a terminal emulation software that communicates with the pump via RS-232 serial port. IsmaTerm can be used to start and stop the pump, set and get the pump parameters, and program the pump operation. It is compatible with Windows operating systems and can be downloaded via this link.

To communicate with the pump, launch the IsmaTerm software, select the COM port that corresponds to the pump and enter the settings of the port in order to change its characteristics (as can be shown in the figure below). The default baud rate is 9600 bits/s, with 8 data bits, 1 stop bit and no parity.

Screenshot of the IsmaTerm software with two opened windows for the settings and characteristics of the port.

In the IsmaTerm window, one can type commands to control the pump and view its responses. These commands are case sensitive and must be followed by a carriage return (Enter key).

The IsmaTerm window presented below shows some messages sent to and received from the pump, allowing to start/stop the pump and set/get pump parameters. In this example, only channel 3 is being controlled. Each command sent to the pump receives a response from it (intended messages in the figure below).

The commands just presented in the IsmaTerm window are briefly explained in the table below.

CommandDefinitionPump ResponseDefinition
3HStart channel 3*Command executed successfully
3xDGet the directionK{13}{10}Direction of rotation is counter-clockwise
{13} — carriage return [CR]
{10} — line feed [LF]
3JSet the channel rotation direction to clockwise*Command executed successfully
3xMGet the operational mode of channel 3L{13}{10}Current mode is RPM
3SGet the setting speed in RPM10.00{13}{10}Fractional type 1.
Rotation speed of 10 RPM.
3S002400Set the speed to 24 RPM*Command executed successfully
3IStop channel 3*Command executed successfully

A control command communicated to the pump is sometimes obtained after some calculations and conversions. It is therefore important to prepare all the needed commands before starting the external control of the pump.

Moreover, it is easier to have these control commands written and communicated to the pump via a set of codes (already prepared), using programming platforms such as Python and Matlab, than to write and send a command every now and then to the pump via a terminal program. These platforms allow not only an easier communication with the pump, but also, an easier external communication with a bus of pumps and allow writing a pumping program with loops, pauses, etc.

Quick start serial communication code snippets using Python and Matlab, that serve as a small introduction on how to communicate with the Reglo ICC pump via these two programming platforms, are provided and explained in the following.

How to Control the Reglo ICC Pump Using Python ?

The Reglo ICC pump can be controlled remotely using Python, offering greater flexibility and convenience for running complex pumping programs with loops, pauses, and varying speeds/flow rates. This approach is particularly useful when integrating multiple devices, as it allows for the automation of sequences involving all connected equipment.

In this section, we will show first how to open the serial port and send simple commands to the pump using Python. Then, a dedicated custom Python library that utilizes the Reglo ICC command protocol will be introduced, allowing one to open the serial port and send control command strings to the Reglo ICC pump. We’ll cover examples that show how to start and stop the pump, set speed, set rate, etc., providing a practical guide to using Python for controlling the Reglo ICC pump.

				
					'''
------------------------------------------------
Writing/Reading Simple Commands to/from the Pump
------------------------------------------------
'''

import serial # Python module for serial communication

# Open the serial port with the data format corresponding to the Reglo ICC pump
ser = serial.Serial('COM5', 9600, parity=serial.PARITY_NONE, bytesize=8, stopbits=1, timeout=None, xonxoff=0, rtscts=0) # modify your COM#

### Start channel 3 of the pump 
# Method 1
cmd = str(3) + 'H' + chr(13) # concatenate strings :
                             # 3 represents channel 3
                             # 'H' to start the channel
                             # 13 for the carriage return [CR]
ser.write(cmd.encode()) # write the concatenated string to ser

# Method 2
ser.write(f'{3}H{chr(13)}'.encode()) # write string literals to ser

read_data = ser.read(ser.in_waiting).decode() 
# read all the available bytes from the serial port connection as a char vector
# The pump returns '*' after a successful execution of the command

### Read the rotation direction of channel 3
ser.write(f'{3}xD{chr(13)}'.encode()) # 'xD' to get the rotation direction 
read_data = ser.read(ser.in_waiting).decode() 
# The pump returns : K[CR][LF] --> counter-clockwise

### Change the rotation direction of channel 3 to clockwise
ser.write((str(3) + 'J' + chr(13)).encode()) # 'J' to set the direction to clockwise
read_data = ser.read(ser.in_waiting).decode() 
# The pump returns '*' after a successful execution of the command

### Change the setting speed to 24 RPM
ser.write((str(3) + 'S002400' + chr(13)).encode()) 
# Setting speed has a resolution of 0.01 RPM so 24 RPM is assigned as 2400
# Discrete type 3 data has a width of 6 characters with unused digits to the left being zeros --> 002400
read_data = ser.read(ser.in_waiting).decode() 
# The pump returns '*' after a successful execution of the command

### Stop channel 3 of the pump
ser.write((str(3) + 'I' + chr(13)).encode()) # 'I' to stop the channel
read_data = ser.read(ser.in_waiting).decode() 
# The pump returns '*' after a successful execution of the command











				
			

Below, the custom Python library that utilizes the Reglo ICC command protocol is presented. This library enables the creation of complex pumping programs, including features such as pauses, loops, conditional logic, and more and enabling an easier control of a bus of pumps. 

				
					'''
------------------------------------------
Reglo ICC Peristaltic Pump Control Library
------------------------------------------
'''

import serial
import time

#---------------------------------------------------------------------------------#
# LIBRARY MANAGING THE COMMUNICATION WITH A REGLO ICC WITH 3 INDEPENDENT CHANNELS #
#---------------------------------------------------------------------------------#

class RegloICC:
    # Initialize the pump
    def __init__(self, COM):
        self.COM = COM
        # Open the serial port with the data format corresponding to the RegloICC pump
        self.sp = serial.Serial(self.COM, 9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS)
        self.direction = [0, 0, 0]  # 0 = clockwise, 1 = counter-clockwise
        self.mode = [0, 0, 0]  # 0 = RPM, 1 = Flow Rate, 2 = Volume (over time), one can add here all other modes
        self.speed = [0, 0, 0]  # rotation speed for each channel in RPM mode
        # Change the size of 'direction', 'mode' and 'speed' according to the total number of channels to control. 
        # In the case herein, 3 channels are being independently controlled

    # Delete the pump
    def __del__(self):
        self.sp.close()
        
    # Start the corresponding channel
    def start_channel(self, channel):
        command = f'{channel}H\r'.encode() # 'H' to start the channel
        # \r for the carriage return [CR] required to tell the pump that the command is finished
        self.sp.write(command) # write the command to the pump
        time.sleep(0.1) # give the pump time to process the command after sending it before reading the response
        return self.sp.read(self.sp.in_waiting).decode() # read the pump response 
  
    # Stop the corresponding channel
    def stop_channel(self, channel):
        command = f'{channel}I\r'.encode() # 'I' to stop the channel
        self.sp.write(command)
        time.sleep(0.1)
        return self.sp.read(self.sp.in_waiting).decode()

    # Set the rotation direction for a single channel
    def set_direction(self, channel, direction):
        if direction == 1:
            command = f'{channel}K\r'.encode() # counter-clockwise
        else:
            command = f'{channel}J\r'.encode() # clockwise
        self.sp.write(command)
        self.direction[channel - 1] = direction # pyhton count starts from 0
        time.sleep(0.1)
        return self.sp.read(self.sp.in_waiting).decode()

    # Get the rotation direction of a single channel
    def get_direction(self, channel): 
        command = f'{channel}xD\r'.encode() # 'xD' to get the rotation direction
        self.sp.write(command)
        time.sleep(0.1)
        # read the rotation direction from the corresponding channel
        return self.sp.read(self.sp.in_waiting).decode()

    # Set the speed for a single channel in RPM when in RPM mode
    def set_speed(self, channel, speed): # in RPM, with speed <= 100
        speed = max(min(speed, 100), 0) # speed between 0 and 100 RPM
        speed_string = f'{int(speed):03d}{int((speed - int(speed)) * 100)}' # format speed explained below
        command = f'{channel}S0{speed_string}\r'.encode()
        self.sp.write(command) # set the speed for the corresponding channel
        self.speed[channel - 1] = speed
        time.sleep(0.1)
        return self.sp.read(self.sp.in_waiting).decode()

#--------------------------------------------------------------------------------#    
# SPEED_STRING EXAMPLE                                                           #
## Speed value :                                                                 #
# speed = 123.456                                                                #
#                                                                                #
## Convert the integer part to a string with at least three digits :             #
# integer_part = f'{int(speed):03d}'; ## --> Result: '123'                       #
#                                                                                #
## Convert the decimal part to a string with two digits :                        #
# decimal_part = f'{int((speed - int(speed)) * 100)}'; ## --> Result: '45'       #
#                                                                                #      
## Concatenate the two parts :                                                   #
# speed_string = f'{int(speed):03d}{int((speed - int(speed)) * 100)}';           #
## --> Result: '12345' representing 123.45 in fixed-point notation               #
#                                                                                #      
## When the two strings are concatenated, the result is a string that represents #
## the original speed value in a fixed-point notation with three digits before   #
## the decimal point and two digits after, without the decimal separator.        #
#--------------------------------------------------------------------------------# 

    # Read out speed of a single channel in RPM when in RPM mode
    def get_speed(self, channel):
        command = f'{channel}S\r'.encode() # 'S' to get the setting speed in RPM
        self.sp.write(command)
        time.sleep(0.1)
        return self.sp.read(self.sp.in_waiting).decode()

    # Set the operational mode for a single channel (you can add all other modes)
    def set_mode(self, channel, mode):
        if mode == 0:
            command = f'{channel}L\r'.encode()  # RPM mode
        elif mode == 1:
            command = f'{channel}M\r'.encode()  # Flow rate mode
        else:
            command = f'{channel}G\r'.encode()  # Volume (over time) mode
        self.sp.write(command)
        self.mode[channel - 1] = mode
        time.sleep(0.1)
        return self.sp.read(self.sp.in_waiting).decode()

    # Get the operational mode of a single channel
    def get_mode(self, channel):
        command = f'{channel}xM\r'.encode() # 'xM' to get the operational mode
        self.sp.write(command)
        time.sleep(0.1)
        return self.sp.read(self.sp.in_waiting).decode()

#----------------------------------------------------------------------------#
#   EXAMPLES ON HOW TO USE THE DEFINED CLASS TO CONTROL THE Reglo ICC PUMP   #
#----------------------------------------------------------------------------#

### Initialize the pump with the specified COM port
pump = RegloICC('COM5') # Replace 'COM5' with your actual COM port

### Start channel 3
pump.start_channel(3)

### Get the rotation direction of channel 3
print(pump.get_direction(3)) 

### Set the rotation direction of channel 3 to clockwise
pump.set_direction(3, 0)

### Get the current operational mode of channel 3 
print(pump.get_mode(3))  

### Set the operational mode of channel 3 to RPM
pump.set_mode(3, 0)

### Get the current speed setting of channel 3 
print(pump.get_speed(3))  

### Set the setting speed of channel 3 to 24 RPM
pump.set_speed(3, 24)

### Stop channel 3
pump.stop_channel(3)

### Delete the pump object
del pump







				
			

How to Control the Reglo ICC Pump Using Matlab ?

In this section, Matlab code snippets will be presented, showing how to open the serial port, write and send control command strings to the pump. Next, a quick start adapter class is defined specifically for handling Reglo ICC commands.

We’ll walk through codelines that demonstrate how to perform common tasks such as starting/stopping the pump, setting speed, getting direction of rotation, etc.

				
					%-------------------------------------------------
% Writing/Reading Simple Commands to/from the Pump
%-------------------------------------------------

%% Open the serial port with the data format corresponding to the Reglo ICC pump
sp = serialport('COM5',9600,'Parity','None','DataBits',8,'StopBits',1); % open the serial port

%% Start channel 3 of the pump (method 1)
cmd = strcat(num2str(3),'H',13); % concatenate strings : 
                                 % 3 represents channel 3, 
                                 % 'H' to start the channel
                                 % 13 for the carriage return [CR]
write(sp,cmd,"uint8"); % write the concatenated string to sp

%% Start channel 3 of the pump (method 2)
fprintf(sp,'%s',strcat(num2str(3),'H',13)); % formats the concatenated string according to '%s' (character vector or string array) and writes it to sp
read_data = read(sp,sp.NumBytesAvailable,"char"); 
% read all the available bytes from the serial port connection as a char vector

%% Read the rotation direction of channel 3
cmd = strcat(num2str(3),'xD',13); % 'xD' to get the rotation direction
write(sp,cmd,"uint8");
read_data = read(sp,sp.NumBytesAvailable,"char"); 

%% The pump returns : K[CR][LF]. Change the rotation direction of channel 3 to clockwise
write(sp,strcat(num2str(3),'J',13),"uint8"); % 'J' to set the direction to clockwise
read_data = read(sp,sp.NumBytesAvailable,"char");

%% Change the setting speed to 24 RPM
write(sp,strcat(num2str(3),'S002400',13),"uint8"); 
% Setting speed has a resolution of 0.01 RPM so 24 RPM is assigned as 2400
% Discrete type 3 data has a width of 6 characters with unused digits to the left being zeros --> 002400
read_data = read(sp,sp.NumBytesAvailable,"char");

%% Stop channel 3 of the pump
write(sp,strcat(num2str(3),'I',13),"uint8"); % 'I' to stop the channel
read_data = read(sp,sp.NumBytesAvailable,"char");


				
			
				
					%-----------------------------------------
% Reglo ICC Peristaltic Pump Adapter Class
%-----------------------------------------

%--------------------------------------------------------------------------------------%
% CUSTOM CLASS MANAGING THE COMMUNICATION WITH A REGLO ICC WITH 3 INDEPENDENT CHANNELS %
%--------------------------------------------------------------------------------------%

classdef RegloICC 
  
    %%% Define the class properties
    properties
        % Change the size of 'direction', 'mode' and 'speed' according to the total number of
        % channels to control. In the case herein, 3 channels are being independently controlled
        sp        = []; % serial port
        COM       = ''; % input parameter: COM port to use for the pump
        direction = [0 0 0]; % direction of rotation of each channel: 0 = clockwise, 1 = counter-clockwise
        mode      = [0 0 0]; % operational mode of each channel: 0 = RPM, 1 = Flow Rate, 2 = Volume (over time), one can add here all other modes (check Table 3)
        speed     = zeros(3,1); % rotation speed for each channel in case of RPM mode
    end
    
     %%% Define the class methods
    methods 
        % Initialize the pump
        function obj = RegloICC(COM)
            obj.COM = COM;
            obj.sp = serialport(obj.COM,9600,'Parity','None','DataBits',8,'StopBits',1); % open the serial port with the data format corresponding to the RegloICC pump
        end

        % Delete the pump
        function obj = delete(obj)
            delete(obj.sp);
            obj.sp = [];
        end

        % Start the corresponding channel
        function start_channel(obj,channel)
            write(obj.sp,strcat(num2str(channel),'H',13),"uint8"); % 'H' to start the channel
            % 13 for the carriage return [CR] required to tell the pump that the command is finished
            pause(0.1); % give the pump time to process the command before reading the response
            while obj.sp.NumBytesAvailable > 0 % clear the buffer
               read(obj.sp, obj.sp.NumBytesAvailable, "char");
            end
        end

        % Stop the corresponding channel
        function stop_channel(obj,channel)
            write(obj.sp,strcat(num2str(channel),'I',13),"uint8"); % 'I' to stop the channel 
            pause(0.1);
            while obj.sp.NumBytesAvailable > 0
                read(obj.sp, obj.sp.NumBytesAvailable, "char");
            end
        end

        % Set the rotation direction for a single channel
        function obj = set_direction(obj,channel,direction)
            if direction == 1
                write(obj.sp,strcat(num2str(channel),'K',13),"uint8"); % counter-clockwise rotation
                pause(0.1);
                while obj.sp.NumBytesAvailable > 0
                    read(obj.sp, obj.sp.NumBytesAvailable, "char");
                end
            else
                write(obj.sp,strcat(num2str(channel),'J',13),"uint8"); % clockwise rotation
                pause(0.1);
                while obj.sp.NumBytesAvailable > 0
                    read(obj.sp, obj.sp.NumBytesAvailable, "char");
                end
            end
            obj.direction(channel) = direction;
        end

        % Get the rotation direction of a single channel
        function getDirection = get_direction(obj,channel)
            write(obj.sp,strcat(num2str(channel),'xD',13),"uint8"); % 'xD' to get the rotation direction
            pause(0.1);
            getDirection = read(obj.sp,obj.sp.NumBytesAvailable,"char"); % read the rotation direction from the corresponding channel
        end

        % Set the speed for a single channel in RPM when in RPM mode
        function obj = set_speed(obj,channel,speed) % in RPM, with speed <= 100
            if speed > 100 
                disp('Speed higher than maximum (100 RPM), reduced to maximum.'); 
            end
            speed = max(min(speed,100),0); % speed between 0 and 100 rpm
            speedstring = strcat(sprintf('%03d',floor(speed)), num2str(floor((speed-floor(speed))*100))); % format speed explained below
            obj.speed(channel) = speed; % set the speed for the corresponding channel
            write(obj.sp,strcat(num2str(channel),'S0',speedstring,13),"uint8"); % write the speed to the corresponding channel
            pause(0.1);
            while obj.sp.NumBytesAvailable > 0
                read(obj.sp, obj.sp.NumBytesAvailable, "char");
            end
        end

%----------------------------------------------------------------------------------%
% SPEEDSTRING EXAMPLE                                                              %
%% Speed value :                                                                   %
% speed = 123.456                                                                  %
%                                                                                  %
%% Convert the integer part to a string with at least three digits :               %
% integer_part = sprintf('%03d', floor(speed)); %% --> Result: '123'               %
%                                                                                  %
%% Convert the decimal part to a string with two digits :                          %
% decimal_part = num2str(floor((speed - floor(speed)) * 100)); %% --> Result: '45' %
%                                                                                  %
%% Concatenate the two parts :                                                     %
% speedstring = strcat(integer_part, decimal_part);                                %
%% --> Result: '12345' representing 123.45 in fixed-point notation                 %
%                                                                                  %
%% When the two strings are concatenated, the result is a string that represents   %
%% the original speed value in a fixed-point notation with three digits before     %
%% the decimal point and two digits after, without the decimal separator.          %
%----------------------------------------------------------------------------------%

        % Read out speed of a single channel in RPM when in RPM mode
        function getRPM = get_speed(obj,channel)
            write(obj.sp,strcat(num2str(channel),'S',13),"uint8"); % 'S' to get the setting speed in RPM
            pause(0.1);
            getRPM = read(obj.sp,obj.sp.NumBytesAvailable,"char");
        end

        % Set the operational mode for a single channel (you can add all other modes)
        function obj = set_mode(obj,channel,mode)
            if mode == 0
                write(obj.sp,strcat(num2str(channel),'L',13),"uint8"); % RPM mode
                pause(0.1);
                while obj.sp.NumBytesAvailable > 0
                    read(obj.sp, obj.sp.NumBytesAvailable, "char");
                end
            elseif mode == 1
                write(obj.sp,strcat(num2str(channel),'M',13),"uint8"); % Flow rate mode
                pause(0.1);
                while obj.sp.NumBytesAvailable > 0
                    read(obj.sp, obj.sp.NumBytesAvailable, "char");
                end
            else
                write(obj.sp,strcat(num2str(channel),'G',13),"uint8"); % Volume (over time) mode    
                pause(0.1);
                while obj.sp.NumBytesAvailable > 0
                    read(obj.sp, obj.sp.NumBytesAvailable, "char");
                end
            end
            
            obj.mode(channel) = mode;
        end

        % Get the operational mode of a single channel
        function getMd = get_mode(obj,channel)
            write(obj.sp,strcat(num2str(channel),'xM',13),"uint8"); % 'xM' to get the operational mode
            pause(0.1);
            getMd = read(obj.sp,obj.sp.NumBytesAvailable,"char"); 
        end

    end
    
end

%-------------------------------------------------------------------%
% Examples on how to use the defined class to control the Reglo ICC %
%-------------------------------------------------------------------%

%%% To start the communication and open the serial port %%%
% pump = RegloICC('COM5') % Replace 'COM5' with your actual COM port

%%% Start channel 3 %%%
% pump.start_channel(3) 

%%% Get the rotation direction of channel 3 %%%
% pump.get_direction(3)

%%% Set the rotation direction of channel 3 to clockwise %%%
% pump.set_direction(3,0) 

%%% Get the current operational mode of channel 3 %%%
% pump.get_mode(3) 

%%% Set the operational mode of channel 3 to RPM %%%
% pump.set_mode(3,0) 

%%% Get the current speed setting of channel 3 %%%
% pump.get_speed(3) 

%%% Set the setting speed of channel 3 to 24 RPM %%%
% pump.set_speed(3,24) 

%%% Stop channel 3 %%%
% pump.stop_channel(3) 

%%% Delete pump %%%
% pump = delete(pump)
    
				
			

Conclusion

In this blog post, we’ve introduced the Reglo ICC (Independent Channel Control) peristaltic pump and explored the basics of its external control via two programming platforms, Python and Matlab, using the Reglo ICC communication command set.  We hope this post serves as a valuable guide for researchers and engineers seeking to employ the Reglo ICC peristaltic pump in their microfluidics research and experiments.

Stay tuned for more insights, tutorials, and practical applications in our future posts. Until then, happy pumping and coding 💻!

📧 If you have any questions or feedback, please feel free to contact us at support@darwin-microfluidics.com.