H a r d w a r e

Overview

Our research involves generating numerous amino acid sequences predicted to be useful by AI and assaying them to demonstrate the utility of our system. Performing all these tasks manually would require considerable labor and time. Moreover, human experimental operations can present challenges in ensuring reproducibility through standardization of procedures. Therefore, we developed devices to automate relatively simple experimental operations at low cost.

We created two devices: one that automates electrophoresis and imaging, and another that automates inversion mixing. Each device was constructed primarily using 3D-printed components and readily available parts. Furthermore, we minimized the number of components to enable users to easily implement these devices in their experiments.

Automated Electrophoresis Device

Overview

We developed a device that performs electrophoresis powered by an AC adapter. Additionally, we created a device that automatically captures images of gels after electrophoresis is complete (Fig. 1).

electro_overview.webp

Fig. 1: Overview of the electrophoresis device

Usage

Assemble the device and connect the Arduino to a computer to launch the preview application.

After setting the gel in the device and applying DNA samples, place the top part and begin electrophoresis. After running for the specified time, the bottom LED illuminates and the gel is photographed.

Design

Electrophoresis Chamber

The electrophoresis chamber utilizes a plastic container, with the electrode and agarose gel mounting components fabricated using a 3D printer (Fig. 2).

electro_cell.webp

Fig. 2: Electrophoresis chamber

Power Supply

A 12V AC adapter serves as the power source, which is boosted by a DC-DC converter to secure sufficient voltage for electrophoresis. Furthermore, the distance between electrodes is shortened compared to conventional electrophoresis devices to increase migration speed.

Circuit

A relay switch controls the current flowing between the electrodes, enabling physical interruption of current at the set time (Fig. 3).

electro_test.webp

Fig. 3: DC-DC converter and relay switch

Imaging

Upon completion of electrophoresis, the LED at the bottom of the device illuminates to excite the fluorescent dye previously added to the DNA.

A standard webcam is used to capture the fluorescence. To accommodate various webcam models, cable ties are used for mounting to the device.

Preview Software

The software is built using Flet, a Python library, and allows users to view captured images along with their capture timestamps.

Validation

Electrophoresis

To verify that the electrophoresis chamber and circuit function correctly, we performed electrophoresis using a DNA ladder marker.

The figure below shows the gel after 90 minutes of electrophoresis. The results demonstrate that electrophoresis was performed correctly with no variation depending on comb position (this gel was imaged using existing imaging equipment) (Fig. 4).

Electro_image.webp

Fig. 4: Gel after electrophoresis

Issues

When operating the electrophoresis device, several problems were identified.

The first issue is the slow migration speed. With a 12V input, the voltage could not be raised sufficiently, resulting in approximately one-third the migration speed compared to conventional electrophoresis devices.

Potential solutions include increasing the input voltage from the AC adapter or using a voltage booster circuit capable of higher output voltage.

The second issue is that the stainless steel electrodes dissolved during electrophoresis. This poses problems regarding waste disposal and safety, necessitating replacement with more stable titanium or platinum electrodes.

Assembly Instructions

Circuit Diagrams

Electrophoresis Device

image.png

Circuit diagram for the electrophoresis device

Bottom LED

image.png

Circuit diagram for the bottom LED

Assembly Procedure

  1. Solder the circuit connecting the DC-DC converter, AC adapter, relay module, and fan to 20AWG (thick) copper wire and T-type connectors. Protect the base of the T-type connectors and exposed solder joints with heat-shrink tubing to prevent short circuits.

power_supply_circuit1.webp

Circuit board connecting DC jack, DC-DC converter, and fan (front side)

power_supply_circuit2.webp

Circuit board connecting DC jack, DC-DC converter, and fan (back side)

  1. Cut stainless steel electrodes to 120mm and solder 20AWG (thick) copper wire to one end. Protect the connection between electrode and copper wire with heat-shrink tubing. Bend approximately 10mm of the end with the attached copper wire.

  2. Set the stainless steel electrodes in the middle part of the electrophoresis device and bend the end without copper wire slightly to secure. Connect the electrodes using male T-type connectors.

electrode1.webp

Electrode wiring diagram

  1. Connect the DC-DC converter, DC jack, relay module, fan, and electrophoresis tank by connecting T-type connectors (refer to circuit diagram). Position the fan to cool the DC-DC converter. Wire the input terminal side of the DC-DC converter with male T-type connectors and the output terminal side with female T-type connectors. Add a voltmeter to the output terminal side and protect with heat-shrink tubing.

DC-DC_converter_circuit.webp

DC-DC converter wiring diagram

  1. Construct the bottom LED circuit. Position LEDs to illuminate the gel evenly.

  2. Wire the Arduino, tactile switch, relay module, and bottom LED using jumper wires.

  3. Stack components from bottom to top in the following order: bottom LED, electrophoresis tank bottom parts, plastic container, electrophoresis tank middle parts, electrophoresis tank top parts.

image.png

Assembly diagram for 3D-printed parts and container

  1. Install an orange filter to cover the webcam lens.

  2. Mount the webcam on top of the electrophoresis tank top parts using cable ties.

  3. Upload the source code to the Arduino.

  4. Launch the software following the Preview Software Usage instructions.

Parts List

Part NameModel NumberQuantityNotes
Electrophoresis tank top parts13D-printed using PLA
Electrophoresis tank middle parts13D-printed using PLA
Electrophoresis tank bottom parts13D-printed using PLA
Plastic container1Dimensions: 170mm × 120mm × 55mm height
WebcamUCAM-C980FBBK1Standard webcams can be used
Orange filter1
Electrodes21.2mm stainless steel wire
DC jackAE-DC-POWER-JACK-DIP1DIP-type
Relay module1Product equipped with JQC-3FF-S-Z
DC-DC converter1DROK 8-32V to 8-46V converter
12V 3A AC adapter1
6cm PC fan112V operation
Copper wire for electrophoresis chamber120AWG for high voltage/current
DC voltage display DC 0-100V1Required to monitor DC-DC converter output voltage
Blue LEDs12Use LEDs matching the excitation wavelength of the dye
10kΩ resistors12
Jumper wiresFor wiring except electrophoresis chamber
Arduino Uno R31ELEGOO compatible board used
T-type connector (male)2
T-type connector (female)2
Heat-shrink tubingApprox. 30cmDiameter sufficient to cover T-connector base
Universal circuit board1 (optional)Size: 5×7cm, thickness: 1.2mm, hole pitch: 2.54mm (0.1 inch). Convenient for connecting DC-DC converter, relay module, and fan

Preview Software Usage

Install Python (Version 3.3 or later) on your computer.

  1. Execute the following command in the directory where you want to run the Python code to create a virtual environment:
python -m venv .venv 
  1. Activate the virtual environment by executing the following command in the command prompt:

For Windows (command prompt):

.venv\Scripts\activate.bat

For Mac/Linux:

source .venv/bin/activate
  1. When the virtual environment is successfully activated, the environment name appears before the path:
(.venv) C:\Users\...
  1. Install required packages by executing the following command within the virtual environment:
pip install opencv-python pyserial flet

The program execution environment setup is now complete.

  1. To run Python using VS Code extensions, open the command palette with Ctrl+Shift+P, select “Python: Select Interpreter,” choose the virtual environment you just created, and then execute.

Source Code

Arduino

const int outputPin = 2;
const int inputPin = 4;
const int LEDPin = 5;
// 3600000ms = 1hour
unsigned long ELECTROPHORESIS_TIME = 1000 * 60 * 60;

void setup()
{
  Serial.begin(9600);
  pinMode(outputPin, OUTPUT);
  pinMode(LEDPin, OUTPUT);
  pinMode(inputPin, INPUT_PULLUP); 
}

void loop()
{
  if (digitalRead(inputPin) == LOW)
  {
    digitalWrite(outputPin, HIGH);
    unsigned long start_time = millis();
    unsigned long current_time = millis();
    while (current_time - start_time < ELECTROPHORESIS_TIME)
    {
      current_time = millis();
    }
    digitalWrite(LEDPin, HIGH);
    Serial.println("capture"); // Send instruction to PC
    delay(3000);             
    while (true)
    {
      digitalWrite(outputPin, LOW);
      if (digitalRead(inputPin) == LOW)
      {
        break;
      }
    }
  }
}

Preview Software

import cv2
import serial
import flet as ft

from datetime import datetime

# Select Arduino Serial port
ser = serial.Serial('COM4', 9600)  

# Web camera initialization
cap = cv2.VideoCapture(1)

def main(page: ft.Page):
    t = ft.Text(value="Figure", color="black")
    page.add(t)       
    page.update()

    if not cap.isOpened():
        print("Cannot connect Web camera")
        exit()

    print("Waiting...")

    while True: 
         monitor_Serialport(page)

def monitor_Serialport(page):
    if ser.in_waiting > 0:
            line = ser.readline().decode('utf-8').strip()
            print(f"Recieve: {line}")

            if line == "capture":
                ret, frame = cap.read()
                if ret:
                    now = datetime.now()
                    filename = f"photo_{now.strftime("%Y%m%d%H%M%S")}.jpg"
                    cv2.imwrite(filename, frame)
        
                    print(f"saved: {filename}")
            
                    ft_image = ft.Image(src=filename, width=600, height=400)
                    page.add(ft_image)
                    ft_time = ft.Text(value=now, color="black")
                    page.add(ft_time)
                    page.update()
                
                else:
                    print("failed to get iamge")

ft.app(target=main)

cap.release()
ser.close()

Inversion Mixer

Overview

To automate inversion mixing operations, we developed a servo motor-driven inversion mixer and a controller that continuously adjusts mixing speed and displays remaining mixing time (Fig. 5).

Mixer_overview.jpg

Fig. 5: Overview of the inversion mixer

Usage

After powering on the device, pressing the black switch on the controller adds 10 minutes to the mixing time. The inversion mixing speed can be adjusted by rotating the knob on the controller. The device stops when the remaining mixing time reaches zero.

Design

Drive Mechanism

The SG90 servo motor provides the motive power for mixing.

This is an inexpensive, compact servo motor that is readily available and possesses sufficient torque for inversion mixing of microcentrifuge tubes.

The base and arm of the drive mechanism were fabricated using a 3D printer (Fig. 6).

Mixer_arm_base.webp

Fig. 6: Drive mechanism of the inversion mixer

Controller

An Arduino UNO controls the entire device. It is readily available and equipped with sufficient digital pins to operate the seven-segment LED display. Additionally, it can control the servo motor via PWM control.

A potentiometer serves as the knob for continuously adjusting mixing speed. As a type of variable resistor, it can continuously vary voltage. The continuously varying voltage is read by a sensor, enabling continuous control of the servo motor’s movement speed.

The remaining time until completion of inversion mixing is displayed on a seven-segment LED (Fig. 7).

Mixer_controller.webp

Fig. 7: Controller

Power Supply

The inversion mixer operates by connecting the Arduino to a computer or mobile battery for power supply.

Device Control

The remaining time display on the seven-segment LED is achieved through timer-based interrupt control, while the extension of mixing time is implemented through interrupt control triggered by signals from the tactile switch.

This enables constant acceptance of operations to the inversion mixer without significantly interfering with servo motor operation.

Validation

To confirm the performance of the inversion mixer and its ability to withstand prolonged operation, we conducted 80 minutes of inversion mixing with microcentrifuge tubes containing two types of paint and water.

The figure below confirms that the two types of paint were mixed, although some undissolved material remained (Fig. 8, Fig. 9).

mixer_test1.webp

Fig. 8: Sample before mixing

mixer_test2.webp

Fig. 9: Sample after mixing

Issues

When wet lab members of iGEM TSUKUBA used this device, the following feedback was received:

  1. Reproducibility cannot be ensured without displaying mixing speed in RPM or similar units.

  2. The servo motor is loud during operation.

  3. The mixing time display is unnecessary as smartphone timers can be used instead.

To address these issues, we determined that the motor driving the arm needs to be changed. Therefore, we decided to replace the servo motor with a stepper motor and are currently developing an improved version of the device.

Assembly Instructions

Circuit Diagram

image.png

Circuit diagram for the inversion mixer

Assembly Procedure

  1. Secure the servo motor to the mixer base using M2 screws.

image.png

  1. Attach the servo horn using screws included with the servo motor.

image.png

  1. Secure the mixer arm to the servo horn using included screws. Insert an M3 screw through the hole in the arm and secure with a nut to create a rotation axis. Insert this rotation axis into the bearing of the base.

image.png

  1. Wire according to the circuit diagram.

mixer_circuit1.webp

Controller wiring example (front side)

mixer_circuit2.webp

Controller wiring example (back side)

  1. Upload the source code to the Arduino.

Parts List

Part NameModel NumberQuantityNotes
Servo motorSG-901
Mixer base13D-printed using PLA
Mixer arm13D-printed using PLA
M2 12mm screws & nuts2For securing servo motor to mixer base
M3 30mm screw1For mixer arm rotation axis
Seven-segment 4-digit LED5641AS1Common cathode type
220Ω resistors4
PotentiometerRK09D117000B1
Tactile switchDTS-63-N-V-BLK(TS-0606-F-N-BLK)1
10kΩ resistor1
Breadboard jumper wires10-20Required when constructing circuit on breadboard
Jumper wires (male-female)17
Universal circuit board2Size: 5×7cm, thickness: 1.2mm, hole pitch: 2.54mm (0.1 inch)
Pin headerPH-1x40SG20
Arduino Uno R31ELEGOO compatible board used

Source Code

To run this code, download the VarSpeedServo.h library zip file from the internet and install it in Arduino IDE via SketchInclude LibraryADD .Zip Library… by selecting the downloaded folder.

#include <VarSpeedServo.h>

VarSpeedServo myservo;

int servoPin = 3;
int buttonPin = 2;
int potentiometerPin = 2;
int potentionVal = 0;
long pitchVal = 0;

// pin for Seven-segment display (a~g, dp)
int pinA = A0;
int pinB = A1;
int pinC = 4;
int pinD = 5;
int pinE = 11;
int pinF = 12;
int pinG = 13;
int pinDP = 6;

// digit of Seven-segment display
int D1 = 7;
int D2 = 8;
int D3 = 9;
int D4 = 10;

int segs[8] = {pinA, pinB, pinC, pinD, pinE, pinF, pinG, pinDP};
int digits[4] = {D1, D2, D3, D4};

// signal pattern of Seven-segment display
const int numbers[10][7] = {
    {1, 1, 1, 1, 1, 1, 0}, // 0
    {0, 1, 1, 0, 0, 0, 0}, // 1
    {1, 1, 0, 1, 1, 0, 1}, // 2
    {1, 1, 1, 1, 0, 0, 1}, // 3
    {0, 1, 1, 0, 0, 1, 1}, // 4
    {1, 0, 1, 1, 0, 1, 1}, // 5
    {1, 0, 1, 1, 1, 1, 1}, // 6
    {1, 1, 1, 0, 0, 0, 0}, // 7
    {1, 1, 1, 1, 1, 1, 1}, // 8
    {1, 1, 1, 1, 0, 1, 1}  // 9
};

// variable for timer
volatile int minutes = 0;
volatile int seconds = 0;

unsigned long lastUpdate = 0;

// For display
volatile int currentDigit = 0;

volatile unsigned long lastButtonPress = 0;

// define interrupt function for timer
ISR(TIMER2_COMPA_vect)
{
    unsigned long now = millis();

    // count down
    if (now - lastUpdate >= 1000)
    {
        lastUpdate = now;

        if (minutes > 0 || seconds > 0)
        {
            if (seconds > 0)
            {
                seconds--;
            }
            else if (minutes > 0)
            {
                minutes--;
                seconds = 59;
            }
        }
    }

    int d[4];
    d[0] = (minutes / 10) % 10;
    d[1] = minutes % 10;
    d[2] = (seconds / 10) % 10;
    d[3] = seconds % 10;

    for (int i = 0; i < 4; i++)
        digitalWrite(digits[i], HIGH);

    // select signal pattern
    for (int i = 0; i < 7; i++)
    {
        digitalWrite(segs[i], numbers[d[currentDigit]][i] ? HIGH : LOW);
    }

    digitalWrite(pinDP, (currentDigit == 1) ? HIGH : LOW);

    // select digit
    digitalWrite(digits[currentDigit], LOW);

    currentDigit = (currentDigit + 1) % 4;
}

void setup()
{
    for (int i = 0; i < 8; i++)
        pinMode(segs[i], OUTPUT);

    for (int i = 0; i < 4; i++)
    {
        pinMode(digits[i], OUTPUT);
        digitalWrite(digits[i], HIGH);
    }

    myservo.attach(servoPin);
    myservo.write(0, 30, true);
    pinMode(buttonPin, INPUT);
    Serial.begin(9600);

    // initialize interrupt function for adding mixing time
    attachInterrupt(digitalPinToInterrupt(buttonPin), addTime, FALLING);

    // initialize timer
    cli();
    TCCR2A = 0;
    TCCR2B = 0;
    TCNT2 = 0;
    OCR2A = 249;
    TCCR2A |= (1 << WGM21);
    TCCR2B |= (1 << CS22) | (1 << CS21);

    TIMSK2 |= (1 << OCIE2A);
    sei();
}

// function for adding mixing time
void addTime()
{
    unsigned long now = millis();
    if (now - lastButtonPress > 200)
    {
        minutes = minutes + 10;
        Serial.println("added");
        lastButtonPress = now;
    }
}

void upArm(long speedVal)
{
    myservo.write(180, speedVal, true);
}

void downArm(long speedVal)
{
    myservo.write(0, speedVal, true);
}

void loop()
{
    while (minutes == 0 && seconds == 0)
    {
        Serial.println("Waiting");
    }

    pitchVal = map(analogRead(potentiometerPin), 0, 1023, 20, 200);
    upArm(pitchVal);

    pitchVal = map(analogRead(potentiometerPin), 0, 1023, 20, 200);
    downArm(pitchVal);
}

Results

We developed devices to achieve a high-throughput experimental environment through laboratory automation. The electrophoresis device was designed to automate electrophoresis and imaging, successfully realizing high-voltage electrophoresis at relatively low cost.

The inversion mixer can be assembled inexpensively and easily by utilizing a servo motor, and its functionality was validated in actual wet lab experiments. Furthermore, validation revealed insights from the wet lab environment, such as issues with operational noise and reproducibility, enabling improvements to the device design.

Slide 1Slide 2Slide 3Slide 4Slide 5

© 2025 - Content on this site is licensed under a Creative Commons Attribution 4.0 International license

The repository used to create this website is available at gitlab.igem.org/2025/tsukuba.