Skip to content

gunakkoc/HiPeristaltic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DOI License

HiPeristaltic

Graphical Abstract Image credit: Michael Buchhorn - https://doi.org/10.1039/D5DD00157A

HiPeristaltic is a fully open-source (hardware and software) peristaltic pump with multiple independent channels, developed in Germany at Helmholtz Institute Erlangen-Nürnberg for Renewable Energy/Forschungszentrum Jülich.

This repo is a part of our publication An open-source peristaltic pump with multiple independent channels for laboratory automation from team High-Throughput Electrocatalysis (HTE).

HiPeristaltic is built using 3D printed and off-the-shelf parts, with software based on Python for the user interface and pure C for the microcontroller firmware. The total cost for the entire system is approximately 280USD. It is accurate up to 0.2% volume and comes optimized, thread-safe and error-resistant software.

HiPeristaltic includes a SiLa2 software module for easy integration to digital laboratories and for Self Driving Laboratories (SDLs). SiLa2 also allows controlling the pump with a GUI over web browser for non-coder users. Additionally, Python API is available under /interface/ for non-SiLa integration.

The software stack is designed to be compatible with a wide range of MCUs (STM32, Arduino, Pico), stepper motor drivers (A4988, DRV8825, TMC2209, ...) and connectivity options (UART, USB, Ethernet/Wifi).

  • Users who just want to get started can refer to Getting Started Quickly. This is the best option to replicate HiPeristaltic as published and with the recommended hardware.
  • For experienced users, a step by step guide is given in Advanced Installation to enable customizations.
  • For those familiar with MCU platforms and motor drivers, all other supported hardware combinations are listed under Hardware Options.
  • For developers looking to integrate concurrent stepper motor control, a spin-off library MultiStepperLite is also published.

Getting Started Quickly

In this section, only the most straightforwad software setup to enable pump through SiLa2 is provided. The hardware connections are assumed to be completed as given in the publication. The hardware setup manual can be found in HiPeristaltic Hardware Zenodo. Furthermore, this tutorial assumes the user has the following:

  • Raspberry Pi 4 Model B
  • A microSD card with minimum 16GB capacity.
  • BIGTREETECH SKR Mini E3 v3.0 board
  • Another microSD card with minimum 1MB capacity.
  • Raspberry Pi 4 Model B and the client (e.g., user or laboratory PC) computers being on the same network (i.e., both are connected to the same router or same Ethernet switch)

The following steps are the summarized points from the setup guide that includes more details and pictures/screenshots. The guide can be found in the HiPeristaltic Software Zenodo or directly here Software_Setup_Guide.pdf.

  1. Download and flash the Raspberry Pi image to the microSD card (one with 16GB+ capacity). The image is located in HiPeristaltic Zenodo page with filename raspi_image.img.
  2. Insert this microSD card to Raspberry Pi but don't turn it on yet.
  3. Download and place the firmware to the other SD Card (one with 1MB+ capacity). The firmware is located in HiPeristaltic Zenodo page with filename FIRMWARE.bin.
  4. Insert this microSD card to BIGTREETECH SKR Mini E3 v3.0 board, then power on and wait for 15 seconds.
  5. Power down and then re-start all devices.
  6. On your PC, Download SiLa2 Universal Client for Windows or for other OS.
  7. Make sure Java 8 is installed,
  8. On Windows, run the executable /artifacts/back/target/usc.exe. For other OS, use java -jar back-0.10.0-SNAPSHOT-app.jar in folder /artifacts/back/target/
  9. Browse to http://localhost:8080/ and Discover Devices. HiPeristaltic should be discovered now.

Continue with example calibration scenario:

  1. Fill in the tubings (e.g., with pure water) by running a pump channel, for instance by using StartPumpCalibration with PumpIndex : 0, RPM : 40, TargetRevolutions : 50 and with the correct direction set by cw for clockwise and ccw for counter-clockwise.
  2. Once this task is finished, place a container which is already weighted when empty, and run StartPumpCalibration with desired parameters, note the TargetRevolutions value.
  3. Weight the container again and calculate the pumped liquid weight. Convert the weight to volume in microliters using the density of the liquid.
  4. Divide the volume with TargetRevolutions to obtain calibration factor with units "microliters per revolution". Use SetPumpCalibration function with this calibration factor.

Advanced Installation

There are a total of 4 software layers:

  1. Firmware for the MCU
  2. Python interface, directly interacting with the firmware
  3. SiLa2 server, wrapping the Python driver, running on a dedicated computer
  4. SiLa2 client, in any SiLa2 supported language (Python, Java, C#) or using web application GUI (Universal SiLa client)

After deciding on the MCU, the motor drivers' GPIO pins must be set in the corresponding firmware. Once the firmware is compiled and flashed, the pump can be connected via USB and can be controlled directly with Python interface. A more elegant alternative is controlling the pump through SiLa2 that ideally runs on a dedicated Single Board Computer (SBC).

This next sections outline all steps used to setting up of such dedicated SiLa2 server on an Rasberry Pi SBC. The included Rasberry Pi image is also created using these steps.

Step 1: Raspberry Pi Initial Setup

  1. Insert the SD card into your PC.
  2. Download Raspberry Pi Imager from here and run the software.
  3. Select the Raspberry Pi device (Raspberry Pi 4 Model B was used for the publication).
  4. For Operating System, select Raspberry Pi OS (other).
  5. Select the latest Raspberry Pi OS Lite (64-bit).
  6. Select the inserted SD card.
  7. Press Next.
  8. In Edit Settings
    • Under the GENERAL tab:
      • Check Set hostname and set to hiernpi.local.
      • Check Set username and password (example, please change) and set Username: hte, Password: hte2025.
    • Under the SERVICES tab:
      • Enable SSH.
      • Select "Use password authentication".
    • Under the OPTIONS tab:
      • Check Eject media when finished.
      • Uncheck Enable telemetry.
  9. Press Save.
  10. Press Yes to apply OS customization settings.
  11. Press Yes to continue.
  12. Once finished, remove the SD card and insert it into the Raspberry Pi.

Step 2: Install SHH (required only for Windows PCs)

Install/enable OpenSSH on Windows using the following Administrative PowerShell command: 1. Press Windows + X and open Windows PowerShell (Admin). 2. Run the following command: ```bash Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

Step 3: Setting Up Server Side

For a Linux server to which the MCU is connected, the process starts by SSH'ing into the server. For Windows based servers, we don't have a guide yet.

Following steps are tested with Raspberry Pi. For other Linux systems, you might need to enable UART manually or connect via USB and point to serial port of connection by changing the following part in HiPeristaltic.toml:

Example:

"serial_port" =  "tty/USB0"

Method 1: Use the installation script

Again for Rasberry Pi, setup_hiperistaltic.sh should take of everything, but you might need to change the username dependent paths. E.g., hte to someusername.

  1. Download:

    cd ~
    curl -L -O "https://github.com/gunakkoc/HiPeristaltic/raw/refs/heads/main/setup_hiperistaltic.sh"

    The script is designed for Raspberry Pi OS. Remove the following lines for other Debian based distros.

    # Enable UART
    echo "Enabling UART..."
    sudo raspi-config nonint do_serial_hw 0
    sudo raspi-config nonint do_serial_cons 1
  2. Give execution permission:

    sudo chmod +x ~/setup_hiperistaltic.sh
  3. Run the installation script:

    sudo ./setup_hiperistaltic.sh

Method 2: Manual/custom installation

The typical installation steps are outlined in detail here for Raspberry Pi. For your own application, a change to username-dependent paths might be required. E.g., /home/hte/ to /home/someusername.

The raspi-config commands are also Rasberry Pi specific.

Setup Communication

  • Enable UART (recommended)

    sudo raspi-config nonint do_serial_hw 0
    sudo raspi-config nonint do_serial_cons 1
  • Alternatively, connect the MCU board (i.e., BIGTREETECH SKR MINI E3 V3.0) to the Raspberry Pi via USB. A new device should show up with the command ls /dev/tty* such as /dev/ttyACM0. Note this device name.

Install Mini-Forge and Dependencies:

  1. Download mini-forge:

    curl -L -O "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh"
  2. Install mini-forge:

    bash Miniforge3-$(uname)-$(uname -m).sh -b
  3. Finalize mini-forge installation:

    ~/miniforge3/bin/conda init
    source ~/.bashrc

    The terminal should now show (base) as the prefix.

  4. Create a new environment with Python 3.9:

    conda create -n hiperis python=3.9

    Type y and press Enter to proceed.

  5. Activate the environment:

    conda activate hiperis
  6. Ensure pip is installed:

    conda install pip
  7. Install necessary libraries:

    pip install numpy pyserial toml sila2 sila2[codegen] sila2[cryptography]
  8. Install Git:

    sudo apt install git

Download HiPeristaltic:

  1. Download HiPeristaltic SiLa2/Python Interface:

    curl -L -O "https://github.com/gunakkoc/HiPeristaltic/raw/refs/heads/main/silav2/HiPeristaltic.zip"
  2. Unzip to the home directory:

    unzip HiPeristaltic.zip -d ~

Set up the startup script:

This script can be used to (manually) start the HiPeristaltic SiLa2 server.

  1. Create a new .sh file to be executed on startup:

    nano ~/run_hiperistaltic.sh
  2. Type the following inside the file:

    #!/bin/bash
    # Get the first IPv4 address (excluding loopback)
    CA_PATH=~/HiPeristaltic/HiPeristaltic_CA.pem
    IP_ADDR=$(hostname -I | awk '{print $1}')
    source ~/miniforge3/etc/profile.d/conda.sh
    conda activate hiperis
    cd ~/HiPeristaltic
    python -m HiPeristaltic --ip-address "$IP_ADDR" --port 50052 --ca-export-file "$CA_PATH"
  3. Make the script executable:

    sudo chmod +x ~/run_hiperistaltic.sh

Add systemd Service:

Enable starting the HiPeristaltic SiLav2 server automatically when the system boots.

  1. Create a systemd service file:

    sudo nano /etc/systemd/system/hiperistaltic.service
  2. Type the following inside the file:

    [Unit]
    Description=Run HiPeristaltic SiLa2 Server
    After=network.target
    
    [Service]
    WorkingDirectory=/home/hte/
    ExecStart=/bin/bash /home/hte/run_hiperistaltic.sh
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
  3. Enable the service to start on boot:

    sudo systemctl enable hiperistaltic
  4. Reboot:

    sudo reboot

Hardware Options

Microcontroller platforms

To cover the most common microcontroller platforms, 3 firmwares are provided:

  1. For STM32 platform: tested with STM32G0B1RET6.
    • Utilizes an included driver for TMC2209 to maximize performance.
    • Requires STM32Cube and STM32 debugger.
    • Both UART and USB are supported. Defaults to UART, switches to USB connection automatically if USB connection is detected and until reboot.
  2. For Arduino platform: tested with Arduino Uno Rev3 (ATmega328P) and Arduino Mega 2560 (ATmega2560)
    • Can be compiled with other Arduino compatible platforms such as stm32duino
    • Can not be directly connected to Raspberry Pi models over UART. Hence, USB only.
  3. Raspberry Pi Pico, tested with Raspberry Pi Pico (RP2040) and Raspberry Pi Pico 2 (RP2350)
    • Can be connected Raspberry Pi models over UART.

The GPIO pins for motor drivers needs to be changed accordingly in the firmware unless BIGTREETECH SKR Mini E3 v3.0 is used.

When connecting via USB, the serial port needs to be set in the configuration file HiPeristaltic.toml, for instance: "serial_port" = "tty/USB0"

Stepper Motor Drivers

Basically all 2-phase stepper drivers that can operate with an step pin can be used, including:

  1. A4988
  2. DRV8825
  3. TMC2208
  4. TMC2209
  5. TB6600
  6. DM556

The recommended board that is BIGTREETECH SKR Mini E3 v3.0 comes with 4 TMC2209 stepper motor drivers embedded. If budget is the ultimate concern, perhaps the cheapest alternative is using an Arduino+CNC Shield combo with A4988 drivers attached.

With the provided STM32 firmware, TMC2209 drivers on the BIGTREETECH SKR Mini E3 v3.0 are controlled via UART communication which allows further optimizations as well as adjustable microstepping on-the-fly. All other firmwares treat TMC2209 as a standard stepper driver.

Moreover, for standard stepper drivers or for other firmwares, the active microstepping value (e.g., 1, 2, 4, 8 and so on) needs to be specified in the HiPeristaltic.toml file, per driver. Alternatively, one can implement their own microstepping changing functionality (i.e., by switching microstepping/resolution pins) and enable it within the firmware.

Connectivity

The following connectivity options are available, depending on the selected MCU, firmware and interface combination.

  1. SiLa2 over Ethernet or WiFi.
  2. Serial over USB for direct PC to MCU communication, without SiLa2 layer.
  3. Serial over UART, typically supported only by SBCs such as Raspberry Pi.

About Pump Configuration and Usage

The default configuration file is HiPeristaltic.toml, and by default within the same folder as HiPeristalticInterface.py. Usually, no modifications to this file are necessary. However, if the stepper motor driver is using a fixed microstepping, this needs to be defined in HiPeristaltic.toml (e.g., motor_usteps = 16). Additionally, if the connected computer is not using the standart UART serial port of Rasberry Pi computer (such as a generic Windows computer), then serial_port setting also needs to set up correctly.

The calibration factor can be accessed under calibration_uL_per_Rev for each pump from the HiPeristaltic.toml file. Note that the provided SiLa2 client can be used to remotely change this parameter which is then immediately saved to this file.

The Python interface can be used to control the pump over USB serial and without SiLa2. It is built with minimum dependencies, with only additional libraries being numpy and pySerial.

Here are some examples of essential functionalities using the Python interface:

test = HiPeristalticInterface()

#load config and connect
test.load_config() #loads HiPeristaltic.toml within the same folder by default
test.connect()

#print some informations about the first channel (0 indexed)
print("Max RPM of Pump 1:",test.pumps[0].get_max_rpm())
print("Max volume(L) of Pump 1:",(test.pumps[0].get_max_volume_uL() / 1e6))
print("Min volume(uL) of Pump 1:",test.pumps[0].get_min_volume_uL())
print("Max flow rate(uL/s) of Pump 1:",test.pumps[0].get_max_flow_rate_uLpersec())
print("Min flow rate(uL/s) of Pump 1:",test.pumps[0].get_min_flow_rate_uLpersec())

#run the pumps; cw: clockwise, ccw: counter-clockwise, blocking=True blocks until the pumping task is over, blocking=False continues to next line without waiting
test.pumps[3].pump_volume(target_volume_uL=60,flow_rate_uLpersec=12,direction="cw",blocking=True)
test.pumps[1].pump_continuous(flow_rate_uLpersec=10,direction="cw")
test.pumps[2].pump_continuous(flow_rate_uLpersec=10,direction="ccw")
test.pumps[0].pump_volume(target_volume_uL=120,flow_rate_uLpersec=12,direction="ccw",blocking=False)

#query status
print("Flow rate (uL/s): ", test.pumps[0].get_flow_rate_uLpersec())
while test.pumps[0].get_running():
	print("Remaining time (s):" , test.pumps[0].get_remaining_time().total_seconds())
	print("Remaining volume (uL):" , test.pumps[0].get_remaining_volume_uL())
	sleep(1)
	
	
#stop, start, resume a pump
test.pumps[2].pump_stop()
test.pumps[2].pump_volume(target_volume_uL=60,flow_rate_uLpersec=12,direction="cw",blocking=False)
sleep(1)
test.pumps[2].pump_stop()
sleep(1)
test.pumps[2].pump_resume()
while test.pumps[2].get_running():
	print("Remaining time (s):" , test.pumps[2].get_remaining_time().total_seconds())
	print("Remaining volume (uL):" , test.pumps[2].get_remaining_volume_uL())
	sleep(0.5)

#change some config and save
test.pumps[i].uL_per_rev = 60 #change calibration factor
pump.save_config()