Peristaltische pompen spelen een cruciale rol in microfluïdica-onderzoek en medische diagnostiek en bieden nauwkeurige vloeistofbeheersing met een minimaal risico op contaminatie. Van de vele beschikbare opties hebben Longer-pompen, geproduceerd door Longer Precision Pump Co., Ltd., een reputatie opgebouwd vanwege hun betrouwbaarheid, precisie en veelzijdigheid.
Een van de opvallende kenmerken van de peristaltische Longer-pompen is de mogelijkheid om ze op afstand te besturen vanaf een computer, waardoor gebruikers complexe pompprogramma's met lussen, pauzes en variërende debieten met grotere flexibiliteit en gemak kunnen uitvoeren.
In dit blogartikel duiken we in het aansturen van peristaltische Longer-pompen met behulp van het Modbus RTU-protocol, een veel gebruikt seriële communicatieprotocol waarmee commando's naar de pomp kunnen worden verzonden en reacties kunnen worden ontvangen. Hoewel de details van het Modbus-protocol enigszins kunnen verschillen per pompmodel, gebruiken we in dit artikel de Longer L100-1S-2 peristaltische pomp als referentiemodel. We loodsen u tevens door Python-voorbeelden en codesnippets heen, die u direct kunt kopiëren en gebruiken in uw eigen scripts om uw pomp eenvoudig aan te sturen.
🚨 U kunt dezelfde concepten en codevoorbeelden toepassen op andere Longer-pompen, waarbij u bepaalde commando's aanpast op basis van het specifieke protocol van uw pompmodel.
Wat heeft u nodig om te communiceren met uw Longer-pomp?
Om te communiceren met een peristaltische Longer-pomp via het Modbus RTU-protocol, heeft u het volgende nodig:
- Een Longer-pomp met een pompkop en tube naar keuze
- Een RS485 besturingsmodule die in de DB15-poort aan de achterzijde van de pomp wordt geplugd
- Een seriële kabel die de RS485-besturingsmodule verbindt met uw computer of apparaat
- Een programmeerplatform (in dit geval Python)
- Een basisbegrip van het Modbus RTU-protocol (hieronder uitgelegd 👇).
Hoe configureert u de communicatiepoort?
Voordat u data kunt verzenden en ontvangen van de pomp, moet u de communicatiepoort correct instellen. Volg hiervoor de volgende stappen:
- Sluit de DB15-connector aan op de DB15-poort aan de achterzijde van de pomp
- Schakel de pomp in en gebruik het toetsenbord aan de voorzijde van de pomp om naar de instellingsinterface voor afstandsbediening te gaan en de afstandsbedieningsmodus in te stellen op "COM" 🕹️
- Zorg ervoor dat de communicatieparameters op uw programmeerplatform overeenkomen met die van de L100-1S-2 (zoals te zien is in onderstaande figuur), te weten:
- 1 startbit
- 8 databits
- Pariteit: P-n (geen pariteit), P-O (oneven pariteit) of P-E (even pariteit)
- Stopbit: S-1 (1 stopbit) of S-2 (2 stopbits)
- Baudrate: 12 (1200 bit/s), 24 (2400 bit/s), 48 (4800 bit/s), 96 (9600 bit/s), 192 (19200 bit/s) of 384 (38400 bit/s).
🚨 De communicatie is alleen geldig wanneer de pomp het werkscherm van de communicatieregelmodus "COM" weergeeft.
Het Modbus RTU-protocol begrijpen
Het Modbus RTU-protocol is een algemeen aanvaarde communicatiestandaard die wordt gebruikt in industriële systemen en automatiseringssystemen om gegevens uit te wisselen tussen apparaten. Dankzij de eenvoud en robuustheid is het ideaal voor het aansturen van apparatuur zoals Longer peristaltische pompen. In dit gedeelte gaan we dieper in op de belangrijkste elementen van Modbus RTU, waaronder het communicatieformaat, de Cyclic Redundancy Check (CRC) en de communicatie-instellingen. Ook onderzoeken we de structuur van Modbus RTU-berichten en de opdrachtset die wordt gebruikt om Longer pompen effectief aan te sturen.
Modbus RTU Standaard Communicatieformaat
Het Modbus-protocol is een veelgebruikt communicatieraamwerk dat master-slave-interacties tussen intelligente apparaten mogelijk maakt. Een Modbus-bericht dat van een master naar een slave wordt verzonden, omvat het adres van de slave, een specifiek commando (zoals het lezen van of schrijven naar een register), de bijbehorende gegevens en een checksum voor foutcontrole.
Dit berichtformaat wordt beschreven in de onderstaande tabel.
| Veld | Grootte | Beschrijving |
|---|---|---|
| Slave-adres | 1 byte | Adres van de pomp. Het bereik is 1-32; 0 wordt gebruikt voor broadcast-communicatie. |
| Functiecode | 1 byte | Instructie voor het slave-apparaat: - 03H: Holding registers lezen - 06H: Enkel register schrijven - 10H: Meerdere registers schrijven |
| Datagebied | 0 – 252 bytes | Te verzenden data (variabele lengte) |
| CRC-controle | 2 bytes | Cyclic Redundancy Check voor foutdetectie: - CRC laag (1 Byte): Lagere byte van de CRC - CRC hoog (1 Byte): Hogere byte van de CRC |
CRC-controle met CRC-16 in Python
CRC (Cyclic Redundancy Check) is een essentiële techniek voor het detecteren van fouten in datatransmissie. Hieronder demonstreren we hoe u CRC-16, zoals gebruikt in het Amerikaanse binaire synchrone systeem, kunt implementeren in Python. Bij CRC-16 maakt het foutdetectie-algoritme gebruik van een polynoom G(X) = X16 + X15 + X2 + 1 om de checksum te genereren. Dit polynoom definieert de wiskundige bewerkingen die worden uitgevoerd op de bits van het bericht tijdens het berekeningsproces van de CRC. Hieronder volgt een overzicht van het algoritme:
- Initialiseer een 16-bits register met de hexadecimale waarde FFFF (allemaal enen), aangeduid als het CRC-register.
- Voer een XOR-bewerking uit op de eerste 8 bytes van het bericht met de lage byte van het CRC-register. Sla het resultaat op in het CRC-register.
- Schuif het CRC-register één bit naar rechts, waarbij de meest significante bit (MSB) op nul wordt gezet.
- Controleer de minst significante bit (LSB) van het CRC-register:
- Als de LSB 0 is, herhaal stap 3 (schuifoperatie).
- Als de LSB 1 is, voer dan een XOR-bewerking uit op het CRC-register met de polynoomwaarde 0xA001 (1010 0000 0000 0001).
- Herhaal stap 3-4, in totaal 8 verschuivingen, om elke byte te verwerken.
- Herhaal stap 2-5 voor elke byte in het bericht totdat alle bytes zijn verwerkt.
- De uiteindelijke inhoud van het CRC-register is de CRC-waarde.
Communicatie-instellingen
Elke byte aan gegevens heeft een structuur bestaande uit 1 startbit, 8 databits, 1 pariteitsbit en 1 of 2 stopbit(s). Bits worden verzonden in volgorde van de minst significante bit (LSB) naar de meest significante bit (MSB).
Voor integers (2 bytes) worden de gegevens zo gerangschikt dat de tweede byte eerst komt, gevolgd door de eerste byte. De hexadecimale waarde 2378H wordt bijvoorbeeld verzonden als 23H 78H. Voor long integers en floats (4 bytes) worden de gegevens gerangschikt met de vierde byte als eerste, gevolgd door de derde, tweede en eerste byte.
Modbus RTU-berichtframeformaat
De Modbus RTU-berichtframerate is zoals beschreven in onderstaande tabel.
| Veld | Grootte | Beschrijving |
|---|---|---|
| Start | ≥ 3,5 tekens | Geeft het begin van de transmissie aan. |
| Adres | 8 Bits | Adres van het slave-apparaat. |
| Functiecode | 8 Bits | Instructie voor het slave-apparaat. |
| Data | N x 8 bits | Over te dragen gegevens (variabele lengte, N bytes). |
| CRC-controlecode | 16 bits | Cyclic Redundancy Check voor foutdetectie. |
| Einde | ≥ 3,5 tekens | Geeft het einde van de transmissie aan. |
🚨 Zorg ervoor dat het berichtframe continu wordt verzonden zonder inactieve tussenpozen tussen karakters die groter zijn dan 1,5 karaktertijd. Onvolledige berichtframes, aangegeven door een te lange inactieve tussenpoze, moeten door het ontvangende knooppunt worden genegeerd.
Parameterinstelling
In onderstaande tabel worden de essentiële parameterinstellingen voor het L100-1S-2-model uiteengezet. Deze parameters kunnen per Longer-pompmodel verschillen, hetzij door de specifieke beschikbare functies, hetzij door het unieke adres en de beschrijvingen die aan elke parameter zijn gekoppeld.
| Parameter | Adres | Gegevenstype | Beschrijving |
|---|---|---|---|
| Snelheid | 0x01 | uint_16 | Bereik: 1-10.000, overeenkomend met 0,01 rpm tot 100 rpm, in stappen van 0,01 rpm. De pomp toont de snelheid in rpm. Voorbeeld: 100 = 0,01 rpm, 10000 = 100 rpm. |
| Debiet | 0x02 | uint_16 | De hoge bytes van het debiet. Wordt gebruikt in combinatie met de lage byte van het debiet. De eenheid van het debiet is 1 nL/min. Voorbeeld: 02 FA F0 80H = 50,0 mL/min. |
| 0x03 | uint_16 | De lage bytes van het debiet. Wordt gebruikt in combinatie met de hoge byte van het debiet. De eenheid van het debiet is 1 nL/min. Voorbeeld: 02 FA F0 80H = 50,0 mL/min. | |
| Pomptoestand | 0x04 | uint_16 | Lage byte is geldig. BIT0: Run/Stop (0 = stop, 1 = run). BIT1: Volle snelheid (0 = normale snelheid, 1 = volle snelheid). BIT2: Weergave snelheid/debiet. BIT3: Gereserveerd. BIT4: Richting (0 = CW, 1 = CCW) |
| Pompadres | 0x05 | uint_16 | Lage byte is geldig. Geldig bereik: 1-32 |
| Baudrate | 0x06 | uint_16 | Lage byte is geldig. 01H: 1200 bps 02H: 2400 bps 03H: 4800 bps 04H: 9600 bps 05H: 19200 bps 06H: 38400 bps |
| Pariteit | 0x07 | uint_16 | Lage byte is geldig. 01H: Geen pariteit 02H: Oneven pariteit 03H: Even pariteit |
| Stopbit | 0x08 | uint_16 | Lage byte is geldig. 01H: 1 stopbit 02H: 2 stopbits |
| Toetsenbordvergrendeling | 0x09 | uint_16 | Lage byte: Schakelt de vergrendelingsfunctie van het toetsenbord in. 01H: Uitgeschakeld 02H: Ingeschakeld Hoge byte: Vertraging vóór vergrendeling. 00H: 30s 01H: 60s 02H: 180s 03H: 300s 04H: 480s 05H: 600s |
💡 Belangrijke opmerkingen:
- Het Longer Modbus RTU-protocol ondersteunt uitsluitend functiecodes 03H (registers lezen), 06H (enkel register schrijven) en 10H (meerdere registers schrijven).
- Bij gebruik van functiecode 06H werkt de pomp op basis van het laatst ontvangen commando, waarbij de snelheid wordt weergegeven via een snelheidsparameter en het debiet via een debietparameter.
- Om het debiet in te stellen, moeten zowel de hoge byte als de lage byte tegelijkertijd worden opgegeven. De eenheid voor het debiet is 1 nL/min (het commando 02 FA F0 80H komt bijvoorbeeld overeen met 50,0 mL/min).
- Indien het debiet of het toerental het toegestane bereik overschrijdt, toont de pomp de maximum- of minimumwaarde zonder een waarschuwing te geven.
Omrekeningsrelatie tussen debiet en toerental
Het verband tussen het debiet en het toerental voor de L100-1S-2 kan worden beschreven met de vergelijking: Q = V x f
Waar Q het debiet in mL/min vertegenwoordigt, V staat voor het toerental in rpm, en f is de debietcoëfficiënt gemeten in mL/r, die standaard is ingesteld op 1.
De standaardwaarde f = 1 wijst op een directe correlatie tussen het toerental en het debiet onder standaardomstandigheden. Deze eenvoud maakt het voor operators erg overzichtelijk om de pompinstellingen te optimaliseren voor hun specifieke toepassingen.
Hoe communiceer je met de L100-1S-2 via Python?
In deze sectie wordt een eenvoudige Python-bibliotheek gepresenteerd die is ontworpen om communicatie met en aansturing van Longer peristaltische pompen via het Modbus RTU-protocol mogelijk te maken. Deze bibliotheek omvat essentiële functionaliteiten, zoals het instellen van het pomptoerental, het debiet en de draairichting, evenals het moeiteloos starten en stoppen van de pomp.
Deze bibliotheek is specifiek geschreven op basis van het protocol van de Longer L100-1S-2 peristaltische pomp en dient als een voorbeeld dat naar wens kan worden aangepast. Door de commando's en parameters naar behoefte aan te passen, kunnen gebruikers de code afstemmen op het Modbus RTU-protocol van hun specifieke Longer pompmodel.
🚨🚨🚨 Belangrijke opmerking
- When viewing this code, please be aware that <, >, and & symbols might not display correctly due to formatting issues. These should appear as standard Python code syntax, so make sure to interpret < as <, > as >, and & as &.
'''
-------------------------------------------------------------
Longer Peristaltic Pump Control Library Using Modbus Protocol
-------------------------------------------------------------
'''
import serial
import time
#------------------------------------------------------#
# LIBRARY MANAGING THE COMMUNICATION WITH THE PUMP #
#------------------------------------------------------#
class Longer_Pump:
# Initialize the class with serial communication parameters
def __init__(self, port, address=1, baudrate=9600, parity=serial.PARITY_NONE, bytesize=8, stopbits=1, timeout=1):
"""
Parameters:
port (str): The COM port for serial communication.
address (int): Modbus address of the pump (default is 1).
baudrate (int): The baud rate (default is 9600).
parity (str): Parity for serial communication (default is none).
bytesize (int): Number of data bits (default is 8).
stopbits (int): Number of stop bits (default is 1).
timeout (int): Timeout for serial communication (default is 1s).
"""
self.ser = serial.Serial(port=port, baudrate=baudrate, parity=parity, bytesize=bytesize, stopbits=stopbits, timeout=timeout)
self.address = address
# Open the serial port for communication with the pump
def connect(self):
if not self.ser.is_open:
self.ser.open()
# Close the serial port to end communication with the pump
def disconnect(self):
if self.ser.is_open:
self.ser.close()
# Calculate the CRC for Modbus communication
def _calculate_crc(self, data):
"""
Parameters:
data (bytearray): The data for which to calculate the CRC.
Returns:
bytes: The calculated CRC as a 2-byte value.
"""
crc = 0xFFFF
for byte in data:
crc ^= byte
for _ in range(8):
if crc & 0x0001:
crc >>= 1
crc ^= 0xA001
else:
crc >>= 1
return crc.to_bytes(2, byteorder='little')
# Send a command to the pump using the Modbus protocol
def _send_command(self, function_code, register_address, data):
"""
Parameters:
function_code (int): e.g., 0x03 for read, 0x06 for write.
register_address (int): to read from or write to.
data (list or int): to be sent (for writing registers).
Returns:
bytes: The response from the pump.
"""
# Prepare the command payload for Modbus
payload = bytearray([self.address, function_code])
payload.extend(register_address.to_bytes(2, byteorder='big'))
if isinstance(data, list):
# For multi-register commands (function code 0x10)
number_of_registers = len(data)
payload.extend(number_of_registers.to_bytes(2, byteorder='big'))
payload.append(len(data) * 2) # Byte count for the data
for value in data:
payload.extend(value.to_bytes(2, byteorder='big'))
else:
# For single-register commands (function code 0x06)
payload.extend(data.to_bytes(2, byteorder='big'))
# Append CRC
crc = self._calculate_crc(payload)
payload.extend(crc)
# Send the command to the pump
self.ser.write(payload)
response = self.ser.read(8) # Adjust this based on expected response length
return response
# Set the pump speed in RPM (0.01 RPM increments)
def set_speed(self, speed_rpm):
"""
Parameters:
speed_rpm (float): The desired speed in RPM.
"""
speed_value = int(speed_rpm * 100) # 0.01 RPM increments
response = self._send_command(0x06, 0x01, speed_value)
print(f"Set speed response: {response.hex()}")
# Set the pump flow rate in mL/min (combined high/low bytes)
def set_flow_rate(self, flow_rate_ml_min):
"""
Parameters:
flow_rate_ml_min (float): The desired flow rate in mL/min.
"""
flow_rate_nl_min = int(flow_rate_ml_min * 1_000_000) # Convert mL/min to nL/min
high_byte = (flow_rate_nl_min >> 16) & 0xFFFF
low_byte = flow_rate_nl_min & 0xFFFF
response = self._send_command(0x10, 0x02, [high_byte, low_byte])
print(f"Set flow rate response: {response.hex()}")
# Start the pump and set the display mode to either 'speed' (RPM) or 'flow_rate' (mL/min)
def start(self, display_mode="speed"):
"""
Parameters:
display_mode (str): 'speed' or 'flow_rate'.
"""
if display_mode == "speed":
pump_state = 0b00000001 # Run + Display Speed
elif display_mode == "flow_rate":
pump_state = 0b00000101 # Run + Display Flow Rate
else:
raise ValueError("Invalid display_mode. Use 'speed' or 'flow_rate'.")
response = self._send_command(0x06, 0x04, pump_state)
print(f"Start pump response: {response.hex()}")
# Stop the pump and set the display mode to either 'speed' (RPM) or 'flow_rate' (mL/min)
def stop(self, display_mode="speed"):
"""
Parameters:
display_mode (str): 'speed' or 'flow_rate'.
"""
if display_mode == "speed":
pump_state = 0b00000000 # Stop + Display Speed
elif display_mode == "flow_rate":
pump_state = 0b00000100 # Stop + Display Flow Rate
else:
raise ValueError("Invalid display_mode. Use 'speed' or 'flow_rate'.")
response = self._send_command(0x06, 0x04, pump_state)
print(f"Stop pump response: {response.hex()}")
# Set the pump direction (CW or CCW)
def set_direction(self, direction):
"""
Parameters:
direction (str): 'CW' for clockwise, 'CCW' for counter-clockwise.
"""
direction_value = 0x0010 if direction.upper() == 'CCW' else 0x0000
response = self._send_command(0x06, 0x04, direction_value)
print(f"Set direction response: {response.hex()}")
# Custom function: Run the pump at the specified speed for a certain amount of time and then stop
def run(self, speed_rpm, run_time_s, direction='CW'):
"""
Parameters:
speed_rpm (float): The speed at which to run the pump in RPM.
run_time_s (int): The time to run the pump in seconds.
direction (str): 'CW' or 'CCW'.
"""
try:
self.set_speed(speed_rpm)
self.set_direction(direction)
self.start(display_mode="speed")
# Run the pump for the specified time
for remaining_time in range(run_time_s, 0, -1):
print(f"Running... {remaining_time} seconds remaining")
time.sleep(1)
finally:
self.stop(display_mode="speed")
#-----------------------------------------------------------------------#
# EXAMPLES ON HOW TO USE THE DEFINED CLASS TO CONTROL A LONGER PUMP #
#-----------------------------------------------------------------------#
pump = Longer_Pump(port='COM7', address=1) # Adjust port and address as needed
pump.connect()
# Run the pump at 40 rpm
pump.set_speed(40.00) # Speed in RPM
pump.start(display_mode="speed")
pump.stop(display_mode="speed")
# Set direction to counter-clockwise
pump.set_direction('CCW')
# Run the pump in flow rate mode at 35 mL/min
pump.set_flow_rate(35) # Flow rate in mL/min
pump.start(display_mode="flow_rate")
pump.stop(display_mode="flow_rate") # Stop the pump
# Run the pump counter-clockwise at 10 RPM for 25 seconds
pump.run(speed_rpm=10.0, run_time_s=25, direction='CCW')
# Disconnect the pump
pump.disconnect()
Conclusie
In deze blogpost hebben we besproken hoe je Longer peristaltische pompen kunt aansturen met het Modbus RTU-protocol, waarbij we inzicht gaven in de communicatieopmaak en een Python-bibliotheek hebben gedeeld om je op weg te helpen. Of je nu werkt met het L100-1S-2-model of de code aanpast voor een ander type pomp, we hopen dat deze handleiding van waarde is.
Blijf ons volgen voor meer tutorials en praktische toepassingen in toekomstige artikelen. Veel succes met pompen en programmeren tot dan! 💻
📧 Als u vragen of opmerkingen heeft, neem dan gerust contact met ons op via support@darwin-microfluidics.com.

