Skip to content

Instantly share code, notes, and snippets.

@holachek
Last active December 16, 2015 16:40
Show Gist options
  • Save holachek/5464778 to your computer and use it in GitHub Desktop.
Save holachek/5464778 to your computer and use it in GitHub Desktop.
Code for the Toastie Reflow Oven. Uses an Adafruit MAX31855 and Thermocouple, Serial LCD, piezo, relay, and fancy programming on an Arduino Mega. And, not to be forgotten: a shiny silver button.
// Reflow Oven
// Master Controller Sketch
// By Michael Holachek
// Version 1.0
#include "Adafruit_MAX31855.h"
#include <SoftwareSerial.h>
#include "ParallaxLiquidCrystal.h"
#include <math.h>
// Pin configurations
#define PIEZO 11
#define RELAY 10
#define THERMOCOUPLE_CLK A0
#define THERMOCOUPLE_CS A1
#define THERMOCOUPLE_DO A2
#define THERMOCOUPLE_GND A3
#define THERMOCOUPLE_VCC A5
#define BUTTON_LED 3 // must be PWM pin
#define BUTTON 4
#define LCD_PIN 5
// Time constants
#define STARTTIME 0
#define HOLDTIME 100
#define MELTTIME 200
#define PEAKTIME 260
// Init variables
int toneFreq = 0;
boolean started = false;
int holdCount = 0;
int timeRemain = 100;
int stage = 0;
double temp = 25;
int timeElapsed = 0;
double desiredTemp = 0;
int relayState = 0;
String relayString = "";
boolean isStarted = false;
// Init objects
Adafruit_MAX31855 thermocouple(THERMOCOUPLE_CLK, THERMOCOUPLE_CS, THERMOCOUPLE_DO);
ParallaxLiquidCrystal LCD(LCD_PIN);
// Setup
void setup() {
// Init communications
Serial.begin(9600);
LCD.begin(9600);
// Init pin directions
pinMode(THERMOCOUPLE_GND, OUTPUT);
pinMode(THERMOCOUPLE_VCC, OUTPUT);
pinMode(RELAY, OUTPUT);
pinMode(BUTTON_LED, OUTPUT);
pinMode(BUTTON, INPUT);
// Init pin states
digitalWrite(THERMOCOUPLE_GND, LOW);
digitalWrite(THERMOCOUPLE_VCC, HIGH);
digitalWrite(RELAY, LOW);
digitalWrite(BUTTON, HIGH);
// Bootup screen + tone lets thermocouple stabalize
LCD.clear();
LCD.print("Toastie");
LCD.setCursor(0, 1);
LCD.print("Reflow Control");
tone(PIEZO, 1200);
digitalWrite(BUTTON_LED, HIGH);
delay(900);
digitalWrite(BUTTON_LED, LOW);
tone(PIEZO, 940);
delay(100);
noTone(PIEZO);
delay(1000);
LCD.clear();
}
// Program loop
void loop() {
while(isStarted == false){
// display settings before start
LCD.setCursor(0, 0);
LCD.print("ready to start");
LCD.setCursor(0, 1);
LCD.print(HOLDTIME);
LCD.print("/");
LCD.print(MELTTIME);
LCD.print("/");
LCD.print(PEAKTIME);
LCD.print(" ");
float breathVal = (exp(sin(millis()/2000.0*PI)) - 0.36787944)*108.0;
analogWrite(BUTTON_LED, breathVal);
// if button is PRESSED and HELD for 2 seconds
while(digitalRead(BUTTON) == 0){
LCD.print("STARTING");
digitalWrite(BUTTON_LED, LOW);
for(int i=2000; i>0; i-= 500){
tone(PIEZO, 440);
LCD.clear();
LCD.setCursor(0, 1);
LCD.print("hold for ");
LCD.print(i);
delay(50);
noTone(PIEZO);
delay(450);
if(digitalRead(BUTTON) == 1)break;
if(i==500){isStarted = true; break;}
}
break;
}
}
while(isStarted){
digitalWrite(BUTTON_LED, LOW);
desiredTemp = solderProfile(timeElapsed);
temp = thermocouple.readCelsius();
// temp sensor safety check
if(isnan(temp) || temp == 0){
digitalWrite(RELAY, 0);
LCD.clear();
tone(PIEZO, 2000);
LCD.print("TEMP DISCONNECT");
LCD.setCursor(0, 1);
LCD.print("safety shutoff");
while(true){
temp = thermocouple.readCelsius();
if(!isnan(temp)){ noTone(PIEZO); break; }
}
}
if( desiredTemp <= temp ) {
relayState = 0;
relayString = "OFF";
} else {
relayState = 1;
relayString = "ON";
}
digitalWrite(RELAY, relayState);
LCD.clear();
LCD.print("Stage ");
LCD.print(stage);
LCD.print(" <> ");
LCD.print(relayString);
LCD.setCursor(0, 1);
LCD.print("C: ");
LCD.print(temp);
LCD.print(" T:");
LCD.print(timeElapsed);
timeElapsed++;
delay(985);
// for beeps on transitioning stages
if( timeElapsed == 1 || timeElapsed == HOLDTIME || timeElapsed == MELTTIME || timeElapsed == PEAKTIME){
tone(PIEZO, 2000);
delay(1000);
timeElapsed++;
noTone(PIEZO);
}
// temp overheat check
if( temp > 200 ) {
tone(PIEZO, 1200);
digitalWrite(RELAY, 0);
LCD.clear();
LCD.print("OVERHEAT");
LCD.setCursor(0, 1);
LCD.print("safety shutoff");
exit(0);
}
// manual button override
while( digitalRead(BUTTON) == 0 ){
tone(PIEZO, 440);
LCD.clear();
digitalWrite(BUTTON_LED, HIGH);
LCD.print("EXITING");
LCD.setCursor(0, 1);
LCD.print("stop program");
for(int i=0; i<20; i++){
digitalWrite(BUTTON_LED, HIGH);
delay(100);
digitalWrite(BUTTON_LED, LOW);
delay(100);
if(i>10)tone(PIEZO, 880);
}
digitalWrite(RELAY, 0);
noTone(PIEZO);
exit(0);
}
}
}
// input int time
// return double temp
double solderProfile(int time){
if(time > STARTTIME && time <= HOLDTIME){
stage = 1;
return (.75 * time) + 25;
}
if(time > HOLDTIME && time <= MELTTIME){
stage = 2;
return 100;
}
if(time > MELTTIME && time <= PEAKTIME){
stage = 3;
return ((60 / (PEAKTIME-MELTTIME) * time) + 100);
}
if(time > PEAKTIME){
stage = 4;
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment