Programable Reflow Oven

After making the reflow oven, I wanted to make the oven more universal. An oven can e a help tool for heating, curing and drying.

The first setup just had one program that could be adjusted within limits. The controller had a temperature profile programmed into it and the user could change the temperature and the duration time at that temperature. Each setting had limits. Once the settings are saved, the user would need to change the settings again for a different function.

The new Controller can almost be programmed to do any type of heating between the room temperature and 250 degrees Celsius. It can be easily programmed/changed using G-code on an SD card, each file is a different programmed oven function. this allows the oven to almost do any temperature profile.

Using the oven

Using the oven is very simple, ensure the SD is inserted and has the correct program file required for the temperature profile. Power the oven controller and using the up/down buttons, navigate to the correct file and press enter(middle button). the oven will now start running that programmed temperature profile.

Code for Project

GNU General Public License v3.0

#include <Plex.h>
#include "max6675.h"
#include <gcode.h>
#include <SPI.h>
#include <SD.h>

#define UpPin 14
#define DownPin 15
#define SelectPin 16

#define replayPin A3
#define buzzerPin A4

#define NumberOfMenuItems 7

#define ktcCLK 13 /// change
#define ktcCS 13 /// change
#define ktcSO 13 /// change

#define MAX_FILE_SIZE 1024
#define JSON_BUFFER_SIZE 512



void rampOven();
void stepOven();
void ToTemp();
void Finished();

commandscallback commands[6] = {{"G1",ToTemp},
                                {"G2",stepOven},
                                {"G3",rampOven},
                                {"G4",Finished}};

gcode Commands(6,commands);
Plex PLEX;
MAX6675 ktc(ktcCLK, ktcCS, ktcSO);

File dir;
File Files;

unsigned long currentPosInFile = 0;
bool Running = false;
int fileID = -1;
long inPos = 0;

int menuLocation = 0;

int  type = 0;
long temp = 0;
long time = 0;
                                

void setup() 
{
  Serial.begin(115200);
  Serial.println("Start");
  
  pinMode(UpPin, INPUT);
  pinMode(DownPin, INPUT);
  pinMode(SelectPin, INPUT);
  pinMode(replayPin,OUTPUT);
  digitalWrite(replayPin,LOW);
  pinMode(buzzerPin,OUTPUT);
  digitalWrite(buzzerPin,LOW);


  PLEX.lcd.clear();
  PLEX.lcd.print("  Oven Control  ");
  PLEX.lcd.setCursor(0, 1);
  PLEX.lcd.print("Tinkers Projects");

  delay(3000);
  

  while (!SD.begin(10))
  {
    PLEX.lcd.clear();
    PLEX.lcd.print("Card failed");
  }

  loadMenuLocation();
}

void loop() 
{
  onOven(-10000);

  if(fileID != menuLocation)
  {
    PrintFileName();
  }
  
  if(digitalRead(UpPin)==HIGH)
  {
      menuLocation--;// menu will go up but the count will go down
      delay(200);
      PrintFileName();
      while(digitalRead(UpPin)==HIGH){}
  }

  if(digitalRead(DownPin)==HIGH)
  {
      menuLocation++;// menu will go dpwn but the count will go up
      delay(200);
      PrintFileName();
      while(digitalRead(DownPin)==HIGH){}
  }

  if(digitalRead(SelectPin)==HIGH)
  {
      delay(200);
      while(digitalRead(SelectPin)==HIGH);
      saveMenuLocation();
      Run();
      PrintFileName();
  } 

}
/*
void PrintFileName(File entry,File NextFiles)
{
    PLEX.lcd.setCursor(0, 0);
    PLEX.lcd.print(">");
    PLEX.lcd.print(entry.name());
    PLEX.lcd.print("                ");
    PLEX.lcd.setCursor(0, 1);
    if(NextFiles)
    {
      PLEX.lcd.print(entry.name());
    }
    PLEX.lcd.print("                ");
}*/



// OLD
void PrintFileName() 
{
  fileID = menuLocation;
      if(menuLocation<0)
        menuLocation = 0;
      Files = getFile(menuLocation);  
      if(Files) 
      {
        PLEX.lcd.clear();
        PLEX.lcd.setCursor(0,0);
        PLEX.lcd.print(Files.name());
        
        File NextFiles = getFile(menuLocation+1);
        if(NextFiles) 
        {
          PLEX.lcd.setCursor(0,1);
          PLEX.lcd.print(NextFiles.name());
        }
      }
      else if(menuLocation>0) 
        menuLocation = menuLocation-1;
}


File getFile(int number) 
{
  int count = 0;
  dir = SD.open("/");
  while (true) 
  {
    File entry =  dir.openNextFile();
    
    if (!entry.available())
    {
      return entry;
    }
    
    if (!entry.isDirectory()) 
    {
      
      if(number == count)return entry;
      count++;
    }
    entry.close();
  }
}


void Run()
{
  temp = 0;
  time = 0;
  
  File dataFile = getFile(fileID);
  if(dataFile) 
  {
    while (dataFile.available()) 
    {
      char SDinput = dataFile.read();
      Serial.print(SDinput);
      if(Commands.available(SDinput))
      {
        if(Commands.availableValue('F'))
          temp = (Commands.GetValue('F')− 32) × 5/9;
        if(Commands.availableValue('C'))
          temp = Commands.GetValue('C');
        if(Commands.availableValue('S'))
          time = Commands.GetValue('S');
          
      Serial.println(temp);
      Serial.println(time);
        Commands.clearBuffer();
      }
    }
  }
  dataFile.close();

  onOven(-10000);
}



void rampOven()
{
  Serial.println("rampOven");
  if(Commands.availableValue('F'))
    temp = (Commands.GetValue('F')− 32) × 5/9;
  if(Commands.availableValue('C'))
    temp = Commands.GetValue('C');
  if(Commands.availableValue('S'))
    time = Commands.GetValue('S');
  rampOven(time, temp);
}

void stepOven()
{
  Serial.println("stepOven");
  if(Commands.availableValue('F'))
    temp = (Commands.GetValue('F')− 32) × 5/9;
  if(Commands.availableValue('C'))
    temp = Commands.GetValue('C');
  if(Commands.availableValue('S'))
    time = Commands.GetValue('S');
  stepOven(time, temp);
}

void ToTemp()
{
  Serial.println("ToTemp");
  if(Commands.availableValue('F'))
    temp = (Commands.GetValue('F')− 32) × 5/9;
  if(Commands.availableValue('C'))
    temp = Commands.GetValue('C');
  ToTemp(temp);
}


void rampOven(long time, long temp)
{
  unsigned long FinishTime = millis()+time*1000;
  unsigned long startTime = millis();
  long startTemp = ktc.readCelsius();
  
  while(FinishTime>millis())
  {
    long G = (temp - startTemp)/(time*1000);
    long currentRampTemp = G*millis()+startTemp;
    unsigned long timeLeft = (FinishTime - millis())/1000;
    onOven(currentRampTemp);
    
    PLEX.lcd.setCursor(0, 1);
    PLEX.lcd.print((int)currentRampTemp);
    PLEX.lcd.print("C   ");
    
    PLEX.lcd.setCursor(5, 1);
    PLEX.lcd.print((int)ktc.readCelsius());
    PLEX.lcd.print("C   ");
    
    PLEX.lcd.setCursor(10, 1);
    PLEX.lcd.print(timeLeft);
    PLEX.lcd.print("Sec    ");
  }
}

void stepOven(long time, long temp)
{
  unsigned long FinishTime = millis()+time*1000;

  while(FinishTime>millis())
  {
    unsigned long timeLeft = (FinishTime - millis())/1000;
    onOven(temp);
    
    PLEX.lcd.setCursor(0, 1);
    PLEX.lcd.print((int)temp);
    PLEX.lcd.print("C   ");
    
    PLEX.lcd.setCursor(5, 1);
    PLEX.lcd.print((int)ktc.readCelsius());
    PLEX.lcd.print("C   ");
    
    PLEX.lcd.setCursor(10, 1);
    PLEX.lcd.print(timeLeft);
    PLEX.lcd.print("Sec    ");
  }
}

unsigned long starttotemp;

void ToTemp(long temp)
{
  starttotemp = millis()+300000;
  while(ktc.readCelsius()<temp-10 && starttotemp>millis)
  {
    onOven(temp);
    PLEX.lcd.setCursor(0, 1);
    PLEX.lcd.print((int)temp);
    PLEX.lcd.print("C   ");
    
    PLEX.lcd.setCursor(5, 1);
    PLEX.lcd.print((int)ktc.readCelsius());
    PLEX.lcd.print("C   ");
  }
}

void onOven(long temp)
{
  long currentTemp = ktc.readCelsius();
  if(currentTemp<temp-10)
  {
    digitalWrite(replayPin,HIGH);
  }
  if(currentTemp>temp)
  {
    digitalWrite(replayPin,LOW);
  }
}

void Finished()
{
  onOven(-10000);
  digitalWrite(replayPin,LOW);
  digitalWrite(buzzerPin,HIGH);
  delay(2000);
  digitalWrite(buzzerPin,LOW);
}

void Error()
{
  onOven(-10000);
  digitalWrite(replayPin,LOW);
  digitalWrite(buzzerPin,HIGH);
  delay(2000);
  digitalWrite(buzzerPin,LOW);
}





















void loadMenuLocation()
{
          Serial.println("load:");
  File ovenControllerFile = SD.open("ovenController.data",FILE_READ);
  if (ovenControllerFile) {
    
          Serial.println("ovenController");
    String currentFileName = "";
    while (ovenControllerFile.available()) {
      currentFileName += String(ovenControllerFile.read());
    }
    ovenControllerFile.close();
    
    int count = 0;
    dir = SD.open("/");
    while (true) 
    {
      File entry =  dir.openNextFile();
      if (!entry.isDirectory()) 
      {
        if(currentFileName.equals(entry.name()))
        {
          Serial.print("got:");
          Serial.print(currentFileName);
          Serial.print(",");
          Serial.print(currentFileName);
          Serial.println(entry.name());
          break;
        }
        count++;
      }
      entry.close();
    }
    menuLocation = count;
    ovenControllerFile.close();
  }
}

void saveMenuLocation()
{
  File ovenControllerFile = SD.open("ovenController.data", FILE_WRITE);
  File file = getFile(menuLocation);
  if (file && ovenControllerFile) 
  {
          Serial.println(file.name());
    ovenControllerFile.print(file.name());
    ovenControllerFile.close();
  }

}

Related Projects

Reflow Oven

Reflow Oven

For years, I have been making PCBs. Have been through etching homemade PCBs to using a manufacturer and through-hole to SMT. the next step is from hand soldering to reflowing. I have been using hot air and has been good but I wanted to try to use an oven for reflowing. At first, I just got a cheap toaster oven, set it to about 220 degrees and wait to see the results. Some times it would work …
Read more


G-Code-Arduino-Library

G-Code-Arduino-Library

This is a library that allows any machine or robot to be controlled by G-Code What is G-Code? G-Code is the instructions that 3D Printer and CNC used to create there part. G-Code is a set of instruction commands sent to the controller of the machine to be performed. Position, feed rate, and tool used are some of the items that G-Code can control. The G-Code can either be sent from the …
Read more


PLEX Controller

PLEX Controller

PLEX is a development board using the Arduino UNO bootloader to be easily programmed by the Arduino IDE. The board has many selectable analog inputs and digital output (up to 32, not including LCD interface). The board was originally designed for one project but has been used in many other projects that require a fast and simple solution. The PLEX board is the same dimensions as a 16×2 LCD …
Read more


Latest Projects

Popular Projects