someboxiSoham
Created July 24, 2019

Low-cost Turbidostats for Microbial Evolution Experiments

We are engineering an array of turbidostat systems with improved control to run robust and fast long-term microbial evolution experiments

AdvancedWork in progressOver 4 days168
Low-cost Turbidostats for Microbial Evolution Experiments

Things used in this project

Hardware components

High-precision Peristaltic pumps
×2
Low-precision peristaltic pumps
×1
3-way pinch valves
×1
2-way pinch valves
×1
Silicon Tubing for peristlatic pumps
×1
Bench Power Supply, DC
Bench Power Supply, DC
×1
Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×4
Raspberry Pi Touch Display
Raspberry Pi Touch Display
×1
Raspberry Pi Keyboard
Raspberry Pi Keyboard
×1
Axial Fan, 12 VDC
Axial Fan, 12 VDC
×5
Emitters 905 nm
×5
Sensor 905 nm
×5
Glass Vials
×12
Circular magnet
×5
Magnetic Stirrer
×10
Epoxy Resin
×1

Hand tools and fabrication machines

Laser cutter
3D printer

Story

Read more

Schematics

Controller and Simulation Schematic

This shows the information flow between the controller software running on a Raspberry Pi, and a simulation script which generates data we might expect to observe in experimental setups.

OD measurement

Chamber installation

Circuit Diagram

Code

Simulation Code

Python
Script to simulate the physical readings that might be observed for the given conditions and controls set by the controller. The simulation and controller scripts are separated and communicate via MQTT in order to demonstrate the controller action.
import paho.mqtt.publish as publish
import paho.mqtt.client as mqtt
from matplotlib import pyplot as plt
import numpy as np

OD = 0.01
biofilm_formed = False
i = 0

MQTT_SERVER = "192.168.0.79"
MQTT_PATH = "pi_channel"

MQTT_DATA_SERVER = "localhost"
MQTT_DATA_PATH = "data_channel"


def on_connect(client, userdata, flags, rc):
    print("Connected with result code " + str(rc))
    client.subscribe(MQTT_DATA_PATH)
    publish.single(MQTT_PATH, OD, hostname=MQTT_SERVER)


# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    print(msg.topic + " " + str(msg.payload))

    global OD
    global biofilm_formed
    global i
    global xdata
    global ydata
    global line

    if i <= 200:
        xdata.append(i)

        if i == 100:
            biofilm_formed = True  # Form a biofilm around halfway through the simulation

        if str(msg.payload) == 'b\'continue\'':
            OD = abs(ydata[-1] * 1.07 + np.random.normal(0, 0.005, 1)[0])
        elif str(msg.payload) == 'b\'bleach\'':
            OD = 0.01
            biofilm_formed = False
        elif str(msg.payload) == 'b\'dilute\'':
            if biofilm_formed is False:
                OD = ydata[-1] * 0.5 + np.random.normal(0, 0.001, 1)[0]
            else:
                OD = abs(ydata[-1] * 1.07 + np.random.normal(0, 0.005, 1)[0])

        ydata.append(OD)
        line.set_xdata(xdata)
        line.set_ydata(ydata)
        plt.draw()
        plt.pause(1e-17)
        publish.single(MQTT_PATH, OD, hostname=MQTT_SERVER)
        i += 1
    else:
        plt.show()



client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect(MQTT_DATA_SERVER, 1883, 60)

xdata = [0]
ydata = [0.01]

plt.show()

axes = plt.gca()
axes.set_xlim(0,200)
axes.set_ylim(-0.2,0.7)
axes.set_xlabel("time (h)")
axes.set_ylabel("OD")
line, = axes.plot(xdata, ydata, 'b-')

client.loop_forever()

Controller code

Python
Code for Raspberry Pi to control the simulation and represent the steps required to achieve this control with LED lights for demonstration.
from gpiozero import LED
import time

import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish


green1 = LED(2)
yellow1 = LED(3)
red1 = LED(4)

green2 = LED(17)
yellow2 = LED(27)
red2 = LED(22)
 
MQTT_SERVER = "localhost"
MQTT_PATH = "pi_channel"

# Connect to Simulation to send commands to pumps and valves

MQTT_DATA_SERVER = "192.168.0.27"
MQTT_DATA_PATH = "data_channel"

 .
def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe(MQTT_PATH)
    publish.single(MQTT_DATA_PATH, 'continue', hostname=MQTT_DATA_SERVER)


# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    print(msg.topic+" "+str(msg.payload))
    OD = float(msg.payload)
    
    if OD >= 0.2 and OD < 0.5:
        # Pump half to waste
        red1.on()
        time.sleep(1)
        red1.off()
        
        # Insert 1 part media, 10 parts wateer
        yellow1.on()
        time.sleep(0.1)
        yellow1.off()
        green1.on()
        time.sleep(1)
        green1.off()
        
        publish.single(MQTT_DATA_PATH, 'dilute', hostname=MQTT_DATA_SERVER)
        
    elif OD >= 0.5:
        # Wash system
        red2.on() # Bleach
        time.sleep(1)
        red2.off()
        yellow2.on() # Ethanol
        time.sleep(1)
        yellow2.off()
        green2.on() # Water
        time.sleep(1)
        green2.off()

        red1.on() # Waste (Remove bleach and ethanol mixture)
        time.sleep(1)
        red1.off()
        # Insert 1 part media, 10 parts wateer
        yellow1.on()
        time.sleep(0.1)
        yellow1.off()
        green1.on()
        time.sleep(1)
        green1.off()
        
        publish.single(MQTT_DATA_PATH, 'bleach', hostname=MQTT_DATA_SERVER)
        
    else:
        publish.single(MQTT_DATA_PATH, 'continue', hostname=MQTT_DATA_SERVER)
        
 
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
 
client.connect(MQTT_SERVER, 1883, 60)
client.loop_forever()

Credits

someboxi

someboxi

1 project • 0 followers
Soham

Soham

0 projects • 0 followers

Comments