Example data demonstrating the PCR works
{{ :bdev:timestamp_95_8_60_15.png?400 |}}
{{ :bdev:timestamp_95_15_60_30.png?600 |}}
{{ :bdev:thermocycling_comparison.png?600 |}}
Green channel was plotted to compare.
Heat conditions:
* 95C 15 seconds
* 60C 30 seconds
* 40 cycles
Samples
- beta-actin - PCR with taqman probe
- blank - water control with master mix
Note: after 30 cycles signal was visable
{{ :bdev:pcr_bactin_example.png?400 |}}
Steps for building a mini thermocycler
|{{ :bdev:image_59_.png?200 |}}|{{ :bdev:image_60_.png?200 | }}|
Custom Parts:{{ :bdev:thermoblock_holder_1inch_half.stl |}}
|1. Milling thermoblock. It costs $100 to make this. {{ :bdev:thermoblock_holder_1inch_half.stl |}}|{{ :bdev:image_52_.png?200 |}}|
|2. Lid with 2 3mm set screws {{ :bdev:drillblock_1inch_lid_half.stl |}}| {{ :bdev:image_55_.png?200 |}}|
|3. Block holder {{ :bdev:hermoblock_holder_1inch_half.stl |}}|{{ :bdev:image_56_.png?200 |}}|
|4. Extrusion connects {{ :bdev:tslot_hinge_thermalblock.stl |}} | {{ :bdev:image_57_.png?200 |}}|
|5. Brd base {{ :bdev:thermocycle_brd.stl |}}| {{ :bdev:image_58_.png?200 |}}|
|6. PCB board {{ :bdev:pcbs_thermominiblock.zip |}} Parts: {{ :bdev:gerberfiles_parts.zip |}}| {{ :bdev:above_view.png?200 |}} {{ :bdev:bottom_view.png?200 |}}|
|7. Single tip imager {{ :bdev:singletip_imager.stl |}}|{{ :bdev:singletip_imager.png?200 |}}|
Off the shelf ($43) + assembled brd is around $20 a unit + pipetters $20:
|1. Power supply| {{ :bdev:powersupply.png?200 |}}|
|2. Peltier cooling system | {{ :bdev:pelier_cooling_system.png?200 |}}|
|3. Mosfets | {{ :bdev:mosfet.png?200 |}} |
|4. Diodes | {{ :bdev:diodes.png?200 |}} {{ :bdev:diodes_1amp.png?200 |}}|
|5. Heater/Thermistors| {{ :bdev:heater_thermistors.png?200 |}}|
|6. Arduino Nano | {{ :bdev:arduino_nano.png?200 |}}|
import time,datetime,os
from datetime import datetime
import json,re
import serial
import subprocess
def timestamp(gg):
now = datetime.now() # current date and time
date_time = now.strftime("%m/%d/%Y, %H:%M:%S")
print("date and time:",date_time)
gg.write("date and time: " + date_time)
def openport(prt):
try:
ser = serial.Serial(prt, 115200, timeout=0.2)
time.sleep(2)
except:
print("its not connecting")
return ser
def whatstheports():
try:
output = subprocess.check_output("python3 -m serial.tools.list_ports -v", shell=True).decode()
b = re.split("\n", output)
if len(b)>1:
for i in b:
if re.match('^ ', i):
pass
else:
try:
dada = (re.sub(' .*', '',i))
if re.match('^.*AMA0.*$', dada):
pass
else:
#ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=0.2)
ser = serial.Serial(dada, 115200, timeout=0.2)
time.sleep(2)
ser.write(b'info\n')
time.sleep(0.2)
resp = (ser.readlines()[0].decode())
ser.close()
if re.match('^tempcontrol.*', resp):
return dada
except:
pass
else:
print("You need to plug in the device")
except:
print("please plug the device in")
def read():
port = whatstheports()
ser = openport(port)
ser.write(b'readlevel\n')
b = (ser.readlines())
temp = float(b[0].decode().rstrip())
print(temp)
def incubate(stemp):
print("Beginning to incubate at this temp "+stemp)
print("To stop, ^c to kill the program")
port = whatstheports()
ser = openport(port)
ser.write(b'settemp '+stemp.encode()+b'\n')
ser.write(b'readlevel\n')
time.sleep(0.2)
b = (ser.readlines())
temp = float(b[0].decode().rstrip())
a = 1
while a >0:
ser.write(b'readlevel\n')
time.sleep(0.2)
b = (ser.readlines())
temp = float(b[0].decode().rstrip())
print(temp)
def coolon():
print("cooling ... ")
port = whatstheports()
ser = openport(port)
ser.write(b'fanon\n')
time.sleep(0.5)
ser.write(b'coolon\n')
time.sleep(0.5)
ser.write(b'settemp 0\n')
a = 1
while a > 0:
ser.write(b'readlevel\n')
time.sleep(0.2)
b = (ser.readlines())
temp = float(b[0].decode().rstrip())
print(temp)
def flashon():
port = whatstheports()
ser = openport(port)
ser.write(b'strobmic\n')
return ser
def flashoff(ser):
ser.write(b'off\n')
ser.close()
def runcycle(dtemp,dtemptm,etemp,etemptm,cy):
print(int(cy))
ccy = int(cy)
gg = open("log.txt", "w")
timestamp(gg)
gg.write("Thermcycler denature "+dtemp+"C time "+dtemptm+" extend "+etemp+" time "+etemptm+" cycle "+cy+"\n")
print("Thermcycler denature "+dtemp+"C time "+dtemptm+" extend "+etemp+" time "+etemptm+" cycle "+cy)
print("To stop, ^c to kill the program\n")
port = whatstheports()
ser = openport(port)
time.sleep(1)
#ser.write(b'setp 300\n')
for i in range(0,ccy):
print("cycle "+str(i))
gg.write("cycle "+str(i)+"\n")
cycle(dtemp,dtemptm,etemp,etemptm,cy,ser,i,gg)
print("finished thermocycling")
timestamp(gg)
gg.write("finished thermocycling\n")
gg.close()
def cycle(dtemp,dtemptm,etemp,etemptm,cy,ser,cycle,gg):
print("Cycle "+str(cycle))
print("Setting denaturing temperature to "+str(dtemp)+"C")
gg.write("Cycle "+str(cycle)+"\n")
gg.write("Setting denaturing temperature to "+str(dtemp)+"C\n")
ser.write(b'settemp '+dtemp.encode()+b'\n')
ser.write(b'readlevel\n')
time.sleep(0.2)
b = (ser.readlines())
temp = float(b[0].decode().rstrip())
while temp < (int(dtemp)+1):
ser.write(b'readlevel\n')
time.sleep(0.2)
b = (ser.readlines())
temp = float(b[0].decode().rstrip())
print(temp)
gg.write(str(temp)+"\n")
if temp == (int(dtemp)):
break
time.sleep(int(dtemptm))
ser.write(b'settemp 0\n')
print("Setting extend temperature to "+str(etemp)+"C")
print("Cooling ... ")
gg.write("Setting extend temperature to "+str(etemp)+"C\n")
gg.write("Cooling ... \n")
ser.write(b'fanon\n')
time.sleep(0.3)
ser.write(b'coolon\n')
time.sleep(0.3)
ser.write(b'readlevel\n')
time.sleep(0.2)
b = (ser.readlines())
temp = float(b[0].decode().rstrip())
while temp > (int(etemp)+1):
ser.write(b'readlevel\n')
time.sleep(0.2)
b = (ser.readlines())
temp = float(b[0].decode().rstrip())
print(str(cycle) + ' ' + str(temp))
gg.write(str(cycle) + ' ' + str(temp)+'\n')
if temp == (int(etemp)):
break
ser.write(b'fanoff\n')
time.sleep(0.3)
ser.write(b'cooloff\n')
time.sleep(0.3)
print("extend temperature begins")
gg.write("extending \n")
time.sleep(0.3)
ser.write(b'settemp '+etemp.encode()+b'\n')
while temp > (int(etemp)+1):
ser.write(b'readlevel\n')
time.sleep(0.2)
b = (ser.readlines())
temp = float(b[0].decode().rstrip())
print(temp)
gg.write(str(temp)+"\n")
gg.write("incubating at extend temperaure\n")
print("incubating at extend temperaure\n")
time.sleep(int(etemptm))
input_var = input("Thermobock controller [help|h, about|a, incubate|i, cycle|c], read|r, cool, flashon: ")
if re.match("help|h", input_var):
print("This controller the thermocycler. Here are the available commands")
print("\thelp[h] - Provides the options")
print("\tabout[a] - About the program, the product its used for and the developer")
print("\tincubate[i] - Incubate at specific temperate. The command goes like this -incubate[i]_[your temperature]. So something like this 'i_55' or 'incubate_55' for incubating at 55C")
print("\tread[r] - Read temperature sensor, it reports in Celcius")
print("\tcycle - Cycling conditions. Argument goes like this -cycle[c] extent_time_denature_time_cycles. Like cycle_94_30_55_180_40 for 55C for 30 seconds then 55 for 180 seconds")
print("\tflashon - Turns on LED")
elif re.match("port", input_var):
whatstheports()
elif re.match("read|r", input_var):
read()
elif re.match("cool", input_var):
coolon()
elif re.match("incubate_.*|i_.*", input_var):
[arg, temp] = re.split('_', input_var)
incubate(temp)
elif re.match("cycle_.*|c_.*", input_var):
[arg, dtemp,dtemptm,etemp,etemptm,cy] = re.split('_', input_var)
runcycle(dtemp,dtemptm,etemp,etemptm,cy)
elif re.match("flashon", input_var):
ser = flashon()
floff = input("Press [enter] to turn off")
flashoff(ser)
else:
print("command not recognized")
----
#include
#include
//#include
Servo myservo; // create servo object to control a servo
#include
#include
#define THERMISTOR_PIN A7
#define TEMPCONTROL 3
#define FANPIN 5
#define THERMOELECTRIC_COOL 6
#define LED 9
//Define the aggressive and conservative Tuning Parameters
double aggKp=150, aggKi=0.5, aggKd=0;
int thermoelectricval = 255;
int ledval = 255;
int tempcontrol = 3;
String command;
float currpos;
int celsius;
int levelstreamon;
double settemp = 0;
double Setpoint, Input, Output;
int tme = 250;
//Specify the links and initial tuning parameters
//PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
PID myPID(&Input, &Output, &Setpoint, aggKp, aggKi, aggKd, DIRECT);
#define NUMTEMPS 20
short temptable[NUMTEMPS][2] = {
{1, 841},
{54, 255},
{107, 209},
{160, 184},
{213, 166},
{266, 153},
{319, 142},
{372, 132},
{425, 124},
{478, 116},
{531, 108},
{584, 101},
{637, 93},
{690, 86},
{743, 78},
{796, 70},
{849, 61},
{902, 50},
{955, 34},
{1008, 3}
};
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
analogWrite(TEMPCONTROL, 0);
analogWrite(FANPIN, 0);
Setpoint = settemp;
//turn the PID on
myPID.SetMode(AUTOMATIC);
analogWrite(THERMOELECTRIC_COOL,0);
analogWrite(LED,0);
}
void loop() {
Input = read_temp();
double gap = abs(Setpoint-Input); //distance away from setpoint
myPID.SetTunings(aggKp, aggKi, aggKd);
myPID.Compute();
analogWrite(TEMPCONTROL,Output);
int rawvalue = analogRead(THERMISTOR_PIN);
float celsius = read_temp();
int fahrenheit = (((celsius * 9) / 5) + 32);
if (levelstreamon == 1) {
Serial.println(celsius);
delay(500);
}
if(Serial.available())
{
char c = Serial.read();
if (c== '\n')
{
parseCommand(command);
command = "";
}
else
{
command +=c;
}
}
delay(1);
}
float parseCommand(String com)
{
if(com.equalsIgnoreCase("info")){
Serial.println("tempcontrol");
}
else if(com.equalsIgnoreCase("levelstreamon")){
levelstreamon = 1;
}
else if(com.equalsIgnoreCase("defaultpid")){
double aggKp=19.56, aggKi=0.71, aggKd=134.26;
}
else if (com.substring(0,4) == "setp") {
aggKp = com.substring(5).toDouble();
}
else if (com.substring(0,4) == "seti") {
aggKi = com.substring(5).toDouble();
}
else if (com.substring(0,4) == "setd") {
aggKd = com.substring(5).toDouble();
}
else if(com.equalsIgnoreCase("coolon")){
analogWrite(THERMOELECTRIC_COOL,thermoelectricval);
}
else if(com.equalsIgnoreCase("cooloff")){
analogWrite(THERMOELECTRIC_COOL,0);
}
else if (com.substring(0,10) == "setledval") {
ledval = com.substring(11).toInt();
}
else if(com.equalsIgnoreCase("levelstreamoff")){
levelstreamon = 0;
}
else if(com.equalsIgnoreCase("fanon")){
analogWrite(FANPIN, 255);
}
else if(com.equalsIgnoreCase("fanoff")){
analogWrite(FANPIN, 0);
}
else if(com.equalsIgnoreCase("readlevel")){
int rawvalue = analogRead(THERMISTOR_PIN);
float celsius = read_temp();
Serial.println(celsius);
}
else if (com.substring(0,12) == "setthermoval") {
//Serial.println("setting temperature");
thermoelectricval = com.substring(13).toInt();
//Serial.println(settemp);
}
else if (com.substring(0,7) == "settemp") {
//Serial.println("setting temperature");
settemp = com.substring(8).toInt();
//Serial.println(settemp);
Setpoint = settemp;
}
else if(com.equalsIgnoreCase("strobmic")){
strobingmic(ledval, tme);
delay(10);
}
}
float read_temp()
{
int rawtemp = analogRead(THERMISTOR_PIN);
float current_celsius = 0;
byte i;
for (i=1; i rawtemp)
{
float realtemp = temptable[i-1][1] + (rawtemp - temptable[i-1][0]) * (temptable[i][1] - temptable[i-1][1]) / (temptable[i][0] - temptable[i-1][0]);
if (realtemp > 255)
realtemp = 255;
current_celsius = realtemp;
break;
}
}
// Overflow: We just clamp to 0 degrees celsius
if (i == NUMTEMPS)
current_celsius = 0;
return current_celsius;
}
void strobingmic(int ledval, int tme){
int strobtimer = 1;
while (strobtimer > 0 && Serial.available() == 0){
analogWrite(LED, ledval);
delayMicroseconds(tme);
analogWrite(LED, 0);
delayMicroseconds(tme);
strobtimer++;
}
analogWrite(LED, 0);
}