Last active
December 16, 2015 16:40
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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