Skip to content

Instantly share code, notes, and snippets.

@holachek
Last active December 16, 2015 16:40
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