Problem with Arduino PCR ( amplifies of DNA )

hi everyone
i am working on Project to amplifies of DNA using PCR technique Where the process revolves around the heating and cooling the sample of DNA to a range of cycles .
It must be running on the 25 cycle to cycle 30 to success the DNA amplifies
And the supposed after the first cycle is complete the cycle again returned automatically, but it doesn’t work automatically , except in the case that I’m doing reset on the arduino Board
does anyone know where the Problem in Code ??

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int tempPin = A0;
const int heatpin = 3;
const int coolpin = 9;
int DENATURE_TEMP = 94;
int ANNEALING_TEMP = 54;
int EXTENSION_TEMP = 73;
int temp;
int cycles =0;
void setup(){ 
 Serial.begin(9600);
 pinMode(tempPin, INPUT);
 pinMode(heatpin, OUTPUT);
 pinMode(coolpin, OUTPUT);
}

void loop()
{
  if(cycles = 0) {
      // if this is the first cycles, hold denature temp for longer
      digitalWrite(heatpin, HIGH); 
      delay(120000);
    }
  temp = readTemp();
 do{
   digitalWrite(heatpin, HIGH); 
  temp = readTemp();
  }while(temp < DENATURE_TEMP); 
play_tone(13, 220, 100);
do  {
   digitalWrite(coolpin, HIGH);
   digitalWrite(heatpin, LOW); 
   temp = readTemp();
  }while(temp > ANNEALING_TEMP);
play_tone(13, 220, 100);
do {
  digitalWrite(heatpin, HIGH);
  digitalWrite(coolpin, LOW);
  temp = readTemp();
}while(temp <= EXTENSION_TEMP);
play_tone(13, 220, 200);
cycles++;
lcd.print("Cycle #");
 lcd.print(cycles);
}

  int readTemp() {  // get the temperature and convert it to celsius
  temp = analogRead(tempPin);
  return temp * 0.48828125;
}
void play_tone(int pin, int freq, int duration) {
  int i = 0;
  int sleep = 1000 / (2*freq);
  int periods = duration / (2 * sleep);
  pinMode(pin, OUTPUT);
  for (i = 0 ; i < periods; i++) {
    digitalWrite(pin, 1);
    delay(sleep);
    digitalWrite(pin, 0);
    delay(sleep);
  }
}

arduino_PCR_finale.ino (1.41 KB)

if(cycles = 0) {

==>

if(cycles == 0) {

= is a asssignment
== is a compare

give it a try

It helps to have functions to handle reaching and holding a temperature. This allows the temperature control to be a little more complex so it maintains the temperature rather than just heating up and waiting.

#include <Wire.h>
//#include <LiquidCrystal_I2C.h>
//LiquidCrystal_I2C lcd(0x27, 16, 2);

const int tempPin = A0;
const int heatpin = 3;
const int coolpin = 9;
const int tonePin = 13;

int DENATURE_TEMP = 94;
int ANNEALING_TEMP = 54;
int EXTENSION_TEMP = 73;

int cycle = 0;
void setup() {
  Serial.begin(9600);
  pinMode(tempPin, INPUT);
  pinMode(heatpin, OUTPUT);
  pinMode(coolpin, OUTPUT);
}

void loop() {
  cycle++;
//  lcd.print("Cycle #");
//  lcd.print(cycle);

  if (cycle == 1) {
    // Pre-denaturing
    holdTemperature(DENATURE_TEMP, 120);  //Two minutes
  }

  // Denaturing
  holdTemperature(DENATURE_TEMP, 2);  //Two seconds
  play_tone(13, 220, 100);

  // Annealing
  holdTemperature(ANNEALING_TEMP, 30);  // Thirty seconds
  play_tone(13, 220, 100);

  // Extension
  holdTemperature(EXTENSION_TEMP, 60);  // Sixty seconds
  play_tone(13, 220, 200);

  if (cycle >= 40) {
    // Final extension
    holdTemperature(EXTENSION_TEMP, 420);  // Seven minutes
    while (true) {}  // STOP EXECUTION
  }

}

int readTemp() {  // get the temperature and convert it to celsius
  return analogRead(tempPin) * 0.48828125;
}

void holdTemperature(int target, unsigned int seconds) {
  unsigned long startTime;
  // Heat or cool to desired temperature
  reachTemperature(target);

  startTime = millis();
  while (millis() - startTime < (seconds * 1000UL)) {
    reachTemperature(target);
  }

  // End of temperature cycle
  digitalWrite(heatpin, LOW);
  digitalWrite(coolpin, LOW);
}

void reachTemperature(int target) {
  digitalWrite(heatpin, LOW);
  digitalWrite(coolpin, LOW);

  // Heat up to target temperature if below
  while (readTemp() < target) {
    digitalWrite(heatpin, HIGH);
  }
  digitalWrite(heatpin, LOW);

  // Cool down to target temperature if above
  while (readTemp() > target) {
    digitalWrite(coolpin, HIGH);
  }
  digitalWrite(coolpin, LOW);
}


void play_tone(int pin, int freq, int duration) {
  int i = 0;
  int sleep = 1000 / (2 * freq);
  int periods = duration / (2 * sleep);
  pinMode(pin, OUTPUT);
  for (i = 0 ; i < periods; i++) {
    digitalWrite(pin, 1);
    delay(sleep);
    digitalWrite(pin, 0);
    delay(sleep);
  }
}

Thanks All for replay and Feedback

mr.johnwasser I've downloaded a file to Arduino board

But it does not work correctly

Since the device operates bulb alone and do not turn Off

Where is the problem ?

I refactored the code, please read it carefully to see you understand the changes and then give it a try

I cannot compile it as I got an error on the I2C LCD .

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

const int tempPin = A0;
const int heatpin = 3;
const int coolpin = 9;
const int maxCycles = 30;

int DENATURE_TEMP = 94;
int ANNEALING_TEMP = 54;
int EXTENSION_TEMP = 73;

int cycles = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(tempPin, INPUT);
  pinMode(heatpin, OUTPUT);
  pinMode(coolpin, OUTPUT);
  digitalWrite(coolpin, LOW);
  digitalWrite(heatpin, LOW);

  // this is the first cycle, hold denature temp for longer
  digitalWrite(heatpin, HIGH);
  delay(120000UL);
}


void loop()
{
  // DO THE HEAT-COOL CYCLE
  digitalWrite(coolpin, LOW);
  digitalWrite(heatpin, HIGH);
  while (readTemp() < DENATURE_TEMP);  // busy wait loop

  play_tone(13, 220, 100);

  digitalWrite(coolpin, HIGH);
  digitalWrite(heatpin, LOW);
  while (readTemp() > ANNEALING_TEMP);

  play_tone(13, 220, 100);

  digitalWrite(heatpin, HIGH);
  digitalWrite(coolpin, LOW);
  while (readTemp() <= EXTENSION_TEMP);

  play_tone(13, 220, 200);
  
  // DO CYCLE ADMIN
  cycles++;
  // YOU MIGHT NEED A LCD.GOTO(0,0)  OR LCD.HOME() HERE
  lcd.print("Cycle # ");
  lcd.print(cycles);
  if (cycles >= maxCycles)
  {
    lcd.print("Done ...");
    while(1); // stop effectively????
  }

}


int readTemp()
{
  temp = analogRead(tempPin);
  return temp * 0.48828125;
}


void play_tone(int pin, int freq, int duration)
{
  int sleep = 1000 / (2 * freq);
  int periods = duration / (2 * sleep);
  pinMode(pin, OUTPUT);

  while (periods > 0)
  {
    digitalWrite(pin, HIGH);
    delay(sleep);
    digitalWrite(pin, LOW);
    delay(sleep);
    periods = periods - 1;
  }
}

thanks robtillaart for feedback
but i have still problem to how a stabilize a temperature for 1 min on Specific time
johnwasser send to me this code for stabilize a temp but it didn’t work correctly
and i didn’t understand this code :

"
startTime = millis();
while (millis() - startTime < (seconds * 1000UL)) {
reachTemperature(target);

"
could anyone help me ?

So let first get your requirement correctly,
so can you please write down in English want you expect the system to do

step 1: you want to heat it up to DENATURE_TEMP
step 2: you want to keep it at that temperature for 1 minute

step 3: you want to cool down to ANNEALING_TEMP
step 4: you want to keep it at that temperature for 1 minute

step 5: you want to heat it up to EXTENSION_TEMP
step 6: you want to keep it at that temperature for 1 minute

step 7: show the cycle number on display
step 8: repeat from step 1:

robtillaart:
So let first get your requirement correctly,
so can you please write down in English want you expect the system to do

step 1: you want to heat it up to DENATURE_TEMP
step 2: you want to keep it at that temperature for 1 minute

step 3: you want to cool down to ANNEALING_TEMP
step 4: you want to keep it at that temperature for 1 minute

step 5: you want to heat it up to EXTENSION_TEMP
step 6: you want to keep it at that temperature for 1 minute

step 7: show the cycle number on display
step 8: repeat from step 1:

Yes, just like what you said exactly

read this code before testing,

//
//    FILE: PCRArduino.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: demo PCR code
//    DATE: 10-jun-2015
//     URL: http://forum.arduino.cc/index.php?topic=326424.0
//
// Released to the public domain
//

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

const int tempPin = A0;
const int heatpin = 3;
const int coolpin = 9;
const int maxCycles = 30;

int DENATURE_TEMP = 94;
int ANNEALING_TEMP = 54;
int EXTENSION_TEMP = 73;

int cycles = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(tempPin, INPUT);
  pinMode(heatpin, OUTPUT);
  pinMode(coolpin, OUTPUT);

  digitalWrite(coolpin, LOW);
  digitalWrite(heatpin, LOW);

  // this is the first cycle, hold denature temp for longer
  digitalWrite(heatpin, HIGH);
  delay(120000UL);
}


void loop()
{
  // DO THE HEAT-COOL CYCLE

  // DENATURE STEP
  digitalWrite(coolpin, LOW);
  digitalWrite(heatpin, HIGH);
  while (readTemp() < DENATURE_TEMP);  // busy wait loop
  unsigned long start = millis();
  while (millis() - start < 60000UL) keepTemperature(DENATURE_TEMP);


  digitalWrite(coolpin, HIGH);
  digitalWrite(heatpin, LOW);
  while (readTemp() > ANNEALING_TEMP);
  start = millis();
  while (millis() - start < 60000UL) keepTemperature(ANNEALING_TEMP);


  digitalWrite(heatpin, HIGH);
  digitalWrite(coolpin, LOW);
  while (readTemp() <= EXTENSION_TEMP);
  start = millis();
  while (millis() - start < 60000UL) keepTemperature(EXTENSION_TEMP);


  // DO CYCLE ADMIN
  cycles++;
  // YOU MIGHT NEED A LCD.GOTO(0,0)  OR LCD.HOME() HERE
  lcd.print("Cycle # ");
  lcd.print(cycles);
  if (cycles >= maxCycles)
  {
    digitalWrite(coolpin, LOW);
    digitalWrite(heatpin, LOW);
    lcd.print("Done ...");
    while (1); // stop effectively
  }

}


void keepTemperature(float value)
{
  float t = readTemp();
  digitalWrite(coolpin, t > value);  // workse because TRUE == HIGH  FALSE == LOW
  digitalWrite(heatpin, t < value);
}


int readTemp()
{
  return analogRead(tempPin) * 0.48828125;
}

WARNING: although this code will probably work it is not as robust as it should be for professional use.
If there are errors either in the temp sensor or the heating/cooling element, this code can block and cause damage. To make it fool proof additional code is needed.

  • Above code a bit refactored
  • Time out to prevent blocking. The SAFETY_TIME needs to be adjusted. now 10 minutes.
  • Feedback on the LCD about which phase
//
//    FILE: PCRArduino.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.02
// PURPOSE: demo PCR code
//    DATE: 10-jun-2015
//     URL: http://forum.arduino.cc/index.php?topic=326424.0
//
// Released to the public domain
//

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

const int tempPin = A0;
const int heatpin = 3;
const int coolpin = 9;
const int maxCycles = 30;

int DENATURE_TEMP = 94;
int DENATURE_TIME = 60;
int ANNEALING_TEMP = 54;
int ANNEALING_TIME = 60;
int EXTENSION_TEMP = 73;
int EXTENSION_TIME = 60;

const unsigned long SAFETY_TIME = 600000UL; // 10 minutes in millis()

int cycles = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(tempPin, INPUT);
  pinMode(heatpin, OUTPUT);
  pinMode(coolpin, OUTPUT);

  digitalWrite(coolpin, LOW);
  digitalWrite(heatpin, LOW);

  // this is the first cycle, hold denature temp for longer
  lcd.clear();
  lcd.print("PCR init");
  gotoAndHoldTemperature(DENATURE_TEMP, DENATURE_TIME *2);
}


void loop()
{
  // PRINT CYCLE NUMBER
  lcd.clear();
  lcd.print("# ");
  lcd.print(cycles);
  lcd.print(" ");

  // DO THE HEAT-COOL CYCLE
  lcd.print("D.");
  gotoAndHoldTemperature(DENATURE_TEMP, DENATURE_TIME);
  lcd.print("A.");
  gotoAndHoldTemperature(ANNEALING_TEMP, ANNEALING_TIME);
  lcd.print("E.");
  gotoAndHoldTemperature(EXTENSION_TEMP, EXTENSION_TIME);

  // DO CYCLE ADMIN
  cycles++;
  if (cycles >= maxCycles) stop("done ... ");
}


void gotoAndHoldTemperature(int temperature, uint16_t holdSeconds)
{
  unsigned long start = millis();
  unsigned long hold = 0;
  while ((hold != 0) && (millis() - hold < (holdSeconds * 1000UL)))
  {
    int t = readTemp();
    digitalWrite(coolpin, t > temperature);  // workse because TRUE == HIGH  FALSE == LOW
    digitalWrite(heatpin, t < temperature);
    if ((t == temperature) && (hold == 0)) hold = millis();  // start the holding time once

    if (millis() - start > SAFETY_TIME) stop("Safety alert");
  }
}


void stop(char* reason)
{
  digitalWrite(coolpin, LOW);
  digitalWrite(heatpin, LOW);
  lcd.print(reason);
  while (1); // stop effectively
}

int readTemp()
{
  return round(analogRead(tempPin) * 0.48828125);
}

// END OF FILE

give it a try

Thanks for all the replies and helping
Finally, the project works great

Please post your working code for future reference.

Thanks

This is the final code for the project, which works great

Code

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

const int tempPin = A0;
const int heatpin = 3;
const int coolpin = 9;
const int maxCycles = 30;
int temp;
int DENATURE_TEMP = 94;
int ANNEALING_TEMP = 54;
int EXTENSION_TEMP = 73;


int max_Temp = 100; // Maximum Temp suppose dont go above  100C for Saftey

int cycles = 0;

void setup()
{
  lcd.begin();
  Serial.begin(9600);
  pinMode(tempPin, INPUT);
  pinMode(heatpin, OUTPUT);
  pinMode(coolpin, OUTPUT);
  digitalWrite(coolpin, LOW);
  digitalWrite(heatpin, LOW);

  // this is the first cycle, hold denature temp for longer
  digitalWrite(heatpin, HIGH);
  delay(120000);
}


void loop()
{
  temp = readTemp();
  digitalWrite(coolpin, LOW);
  digitalWrite(heatpin, HIGH);
  while (readTemp() < DENATURE_TEMP) {
    lcd.print(readTemp()); delay(100); lcd.clear();
  }
  // busy wait loop
  reachTemperature(50000, 94);

  play_tone(13, 220, 100);

  Saftey_temp();



  digitalWrite(coolpin, HIGH);
  digitalWrite(heatpin, LOW);
  while (readTemp() > ANNEALING_TEMP)
  {
    lcd.print(readTemp()); delay(100); lcd.clear();
  }
  reachTemperature(50000, 54);

  play_tone(13, 220, 100);


  Saftey_temp();


  digitalWrite(heatpin, HIGH);
  digitalWrite(coolpin, LOW);
  while (readTemp() <= EXTENSION_TEMP) {
    lcd.print(readTemp()); delay(100); lcd.clear();
  }
  reachTemperature(50000, 73);
  play_tone(13, 220, 200);

  Saftey_temp();


  // DO CYCLE ADMIN
  cycles++;

  lcd.print("Cycle # ");
  lcd.print(cycles);
  if (cycles >= maxCycles)
  {
    lcd.print("Done ...");
    while (1); // stop effectively????
  }
}


int readTemp()
{
  temp = analogRead(tempPin);
  return temp * 0.48828125;
}



int Saftey_temp()
{
  if (readTemp() >= max_Temp)
  {
    digitalWrite(coolpin, LOW);
    digitalWrite(heatpin, LOW);
    delay(300000);
    lcd.print("OVERHEATING");
    lcd.clear();
  }
}



void reachTemperature(long duration, int idealTemp) {
  unsigned long startTime = millis();
  long timeElapsed = millis() - startTime;
  //lcd.print(timeElapsed);
  while (timeElapsed < duration) {
    temp = readTemp();
    lcd.print(readTemp());
    if (temp < ( idealTemp - 1 )) {
      // turn up the heat for 90ms if the temperature is cooler
      digitalWrite(heatpin, HIGH);
      delay(90);
      digitalWrite(heatpin, LOW);
    } else if (temp > (idealTemp + 1 )) {
      digitalWrite(coolpin, HIGH);
      delay(90);
      digitalWrite(coolpin, LOW);
    }
    delay(210);
    timeElapsed = millis() - startTime;
  }
  delay(90);
  lcd.clear();
}


void play_tone(int pin, int freq, int duration)
{
  int sleep = 1000 / (2 * freq);
  int periods = duration / (2 * sleep);
  pinMode(pin, OUTPUT);

  while (periods > 0)
  {
    digitalWrite(pin, HIGH);
    delay(sleep);
    digitalWrite(pin, LOW);
    delay(sleep);
    periods = periods - 1;
  }
}

moderator mode: I did change quote tags 2 code tags and did a reindent (CTRL-T in the IDE)

2 points
bug:
Time/millis() related variables should be unsigned long not just long

Check spelling of safetyTemp() :wink: