15-Amp AC Wall Outlet (Home Depot) Replaced with IEC Outlet
15-Amp AC Wall Switch (Home Depot) Removed. May be replaced in next version.
14 Gauge Romex (Home Depot)
Donor Cord from 6-Outlet Strip (to plug into wall) (Home Depot) Replaced with IEC Inlet
Crydom SSR D2425 (Mouser)
Heat Sink
Thermal Pad
To Be Added:
A couple of LEDs Added
Buttons Added
Character LCD Added, 16×2 to be replaced with 20×4 display soon.
Custom Enclosure Workd
Schematic:
Overall Hardware
Controller Board
The controller board is based on the Arduino Leonardo’s ATmega32u4. This eliminates the USB to serial chip and helps to avoid the auto-reset issue presented into the Uno design. This makes it possible to attach or detach the USB cable for logging without causing the controller to reset (potentially during a reflow cycle.)
EAGLE Project files for R1: Reflow_Control_Board_R1 (zip)
Schematic in PDF: Reflow Control Board (pdf)
Firmware
For now, I’ve separated the work on the UI and code that runs the oven.
Menu Software
A basic structure for a multi-level menu is in place. It is possible to edit multi-digit values (like 255) by increasing/decreasing individual digits. All information is saved to the ATmega32u4’s onboard EEPROM. The software is on GitHub.
Control Software
The current firmware is borrowing heavily from the Rocket Scream Arduino Reflow Shield. In fact, this code just changes support to the MAX31855, disables the buzzer, disables LCD, and provided more output to Serial.
I plan to fork this code into a different path, but for now it provides an excellent starting point and I sincerely appreciate the efforts of Rocket Scream.
/*** Modified Reflow Oven Code.
* Original Author: Rocket Scream Electronics, www.rocketscream.com
* Modified Author: James Lewis, [email protected], baldengineer.com
*
* This firmware owed very much on the works of other talented individuals as
* follows:
* ==========================================
* Brett Beauregard (www.brettbeauregard.com)
* ==========================================
* Author of Arduino PID library. On top of providing industry standard PID
* implementation, he gave a lot of help in making this reflow oven controller
* possible using his awesome library.
*
* ==========================================
* Limor Fried of Adafruit (www.adafruit.com)
* ==========================================
* Author of Arduino MAX6675 library. Adafruit has been the source of tonnes of
* tutorials, examples, and libraries for everyone to learn.
*
* Disclaimer
* ==========
* Dealing with high voltage is a very dangerous act! Please make sure you know
* what you are dealing with and have proper knowledge before hand. Your use of
* any information or materials on this reflow oven controller is entirely at
* your own risk, for which we shall not be liable.
*
* Licences
* ========
* This reflow oven controller hardware and firmware are released under the
* Creative Commons Share Alike v3.0 license
* http://creativecommons.org/licenses/by-sa/3.0/
* You are free to take this piece of code, use it and modify it.
* All we ask is attribution including the supporting libraries used in this
* firmware.
#include "Adafruit_MAX31855.h"
#include
// ***** TYPE DEFINITIONS *****
typedef enum REFLOW_STATE{
REFLOW_STATE_IDLE,
REFLOW_STATE_PREHEAT,
REFLOW_STATE_SOAK,
REFLOW_STATE_REFLOW,
REFLOW_STATE_COOL,
REFLOW_STATE_COMPLETE,
REFLOW_STATE_ERROR
} reflowState_t;
typedef enum REFLOW_STATUS{
REFLOW_STATUS_OFF,
REFLOW_STATUS_ON
} reflowStatus_t;
typedef enum DEBOUNCE_STATE{
DEBOUNCE_STATE_IDLE,
DEBOUNCE_STATE_CHECK,
DEBOUNCE_STATE_RELEASE
} debounceState_t;
// ***** CONSTANTS *****
#define TEMPERATURE_ROOM 50
#define TEMPERATURE_SOAK_MIN 150
#define TEMPERATURE_SOAK_MAX 200
#define TEMPERATURE_REFLOW_MAX 250
#define TEMPERATURE_COOL_MIN 100
#define SENSOR_SAMPLING_TIME 1000
#define SOAK_TEMPERATURE_STEP 5
#define SOAK_MICRO_PERIOD 9000
#define DEBOUNCE_PERIOD_MIN 50
#define THERMOCOUPLE_DISCONNECTED 10000
// ***** PID PARAMETERS *****
// ***** PRE-HEAT STAGE *****
#define PID_KP_PREHEAT 300
#define PID_KI_PREHEAT 0.05
#define PID_KD_PREHEAT 400
// ***** SOAKING STAGE *****
#define PID_KP_SOAK 300
#define PID_KI_SOAK 0.05
#define PID_KD_SOAK 250
// ***** REFLOW STAGE *****
#define PID_KP_REFLOW 300
#define PID_KI_REFLOW 0.05
#define PID_KD_REFLOW 350
#define PID_SAMPLE_TIME 1000
// ***** LCD MESSAGES *****
const char* lcdMessagesReflowStatus[] = {
"Ready",
"Pre-heat",
"Soak",
"Reflow",
"Cool",
"Complete",
"Error"
};
// ***** DEGREE SYMBOL FOR LCD *****
unsigned char degree[8] = {140,146,146,140,128,128,128,128};
// ***** PIN ASSIGNMENT *****
int ssr = 6;
int thermocoupleSO = 8;
int thermocoupleCS = 9;
int thermocoupleCLK = 10;
int ledRed = 3;
int ledGreen = 2;
/* int lcdRs = 2;
int lcdE = 3;
int lcdD4 = 4;
int lcdD5 = 5;
int lcdD6 = 11;
int lcdD7 = 12;
int buzzer = 5;
int button1 = 13;
int button2 = 3; */
// ***** PID CONTROL VARIABLES *****
double setpoint;
double input;
double output;
double kp = PID_KP_PREHEAT;
double ki = PID_KI_PREHEAT;
double kd = PID_KD_PREHEAT;
int windowSize;
unsigned long windowStartTime;
unsigned long nextCheck;
unsigned long nextRead;
unsigned long timerSoak;
unsigned long buzzerPeriod;
// Reflow oven controller state machine state variable
reflowState_t reflowState;
// Reflow oven controller status
reflowStatus_t reflowStatus;
// Button debounce state machine state variable
debounceState_t debounceState;
// Button debounce timer
long lastDebounceTime;
// Button press status
boolean buttonPressStatus;
// Seconds timer
int timerSeconds;
// Specify PID control interface
PID reflowOvenPID(&input, &output, &setpoint, kp, ki, kd, DIRECT);
// Specify LCD interface
//LiquidCrystal lcd(lcdRs, lcdE, lcdD4, lcdD5, lcdD6, lcdD7);
// Specify MAX6675 thermocouple interface
//MAX6675 thermocouple(thermocoupleCLK, thermocoupleCS, thermocoupleSO);
/*
int thermocoupleSO = 8;
int thermocoupleCS = 9;
int thermocoupleCLK = 10;*/
Adafruit_MAX31855 thermocouple(thermocoupleCLK, thermocoupleCS, thermocoupleSO);
void setup()
{
// SSR pin initialization to ensure reflow oven is off
Serial.println(F("Init and Turn off SSR"));
digitalWrite(ssr, LOW);
pinMode(ssr, OUTPUT);
// Buzzer pin initialization to ensure annoying buzzer is off
/* digitalWrite(buzzer, LOW);
pinMode(buzzer, OUTPUT);
*/
// LED pins initialization and turn on upon start-up (active low)
digitalWrite(ledRed, LOW);
digitalWrite(ledGreen, LOW);
pinMode(ledRed, OUTPUT);
pinMode(ledGreen, OUTPUT);
/* // Push button pins initialization
pinMode(button1, INPUT);
pinMode(button2, INPUT);
*/
// Start-up splash
/* digitalWrite(buzzer, HIGH);
lcd.begin(8, 2);
lcd.createChar(0, degree);
lcd.clear();
lcd.print("Reflow");
lcd.setCursor(0, 1);
lcd.print("Oven 1.1");
digitalWrite(buzzer, LOW);
delay(2500);
lcd.clear();
*/
Serial.println(F("Reflow Oven 1.1"));
// Serial communication at 57600 bps
Serial.begin(115200);
// Turn off LED (active low)
digitalWrite(ledRed, HIGH);
digitalWrite(ledGreen, HIGH);
// Set window size
windowSize = 2000;
// Initialize time keeping variable
nextCheck = millis();
// Initialize thermocouple reading varible
nextRead = millis();
}
void loop()
{
// Current time
unsigned long now;
// Time to read thermocouple?
if (millis() > nextRead)
{
// Read thermocouple next sampling period
nextRead += SENSOR_SAMPLING_TIME;
// Read current temperature
input = thermocouple.readCelsius();
// If thermocouple is not connected
if (input == THERMOCOUPLE_DISCONNECTED)
{
// Illegal operation without thermocouple
reflowState = REFLOW_STATE_ERROR;
reflowStatus = REFLOW_STATUS_OFF;
}
}
if (millis() > nextCheck)
{
// Check input in the next seconds
nextCheck += 1000;
// If reflow process is on going
if (reflowStatus == REFLOW_STATUS_ON)
{
// Toggle red LED as system heart beat
digitalWrite(ledRed, !(digitalRead(ledRed)));
// Increase seconds timer for reflow curve analysis
timerSeconds++;
// Send temperature and time stamp to serial
Serial.print(timerSeconds);
Serial.print(" ");
Serial.print(setpoint);
Serial.print(" ");
Serial.print(input);
Serial.print(" ");
Serial.println(output);
}
else
{
// Turn off red LED
digitalWrite(ledRed, HIGH);
}
// Clear LCD
// lcd.clear();
// Print current system state
// lcd.print(lcdMessagesReflowStatus[reflowState]);
Serial.println(lcdMessagesReflowStatus[reflowState]);
// Move the cursor to the 2 line
// lcd.setCursor(0, 1);
// If currently in error state
if (reflowState == REFLOW_STATE_ERROR)
{
// No thermocouple wire connected
Serial.println("No TC!");
}
else
{
// Print current temperature
/* lcd.print(input);
#if ARDUINO >= 100
lcd.write((uint8_t)0);
#else
// Print degree Celsius symbol
lcd.print(0, BYTE);
#endif
lcd.print("C "); */
}
}
// Reflow oven controller state machine
switch (reflowState)
{
case REFLOW_STATE_IDLE:
// If button is pressed to start reflow process
if (Serial.available()) {
if (Serial.read())
{
// Ensure current temperature is comparable to room temperature
// TO DO: To add indication that temperature is still high for
// reflow process to start
if (input = TEMPERATURE_SOAK_MIN)
{
// Chop soaking period into smaller sub-period
timerSoak = millis() + SOAK_MICRO_PERIOD;
// Set less agressive PID parameters for soaking ramp
reflowOvenPID.SetTunings(PID_KP_SOAK, PID_KI_SOAK, PID_KD_SOAK);
// Ramp up to first section of soaking temperature
setpoint = TEMPERATURE_SOAK_MIN + SOAK_TEMPERATURE_STEP;
// Proceed to soaking state
reflowState = REFLOW_STATE_SOAK;
}
break;
case REFLOW_STATE_SOAK:
// If micro soak temperature is achieved
if (millis() > timerSoak)
{
timerSoak = millis() + SOAK_MICRO_PERIOD;
// Increment micro setpoint
setpoint += SOAK_TEMPERATURE_STEP;
if (setpoint > TEMPERATURE_SOAK_MAX)
{
// Set agressive PID parameters for reflow ramp
reflowOvenPID.SetTunings(PID_KP_REFLOW, PID_KI_REFLOW, PID_KD_REFLOW);
// Ramp up to first section of soaking temperature
setpoint = TEMPERATURE_REFLOW_MAX;
// Proceed to reflowing state
reflowState = REFLOW_STATE_REFLOW;
}
}
break;
case REFLOW_STATE_REFLOW:
// We need to avoid hovering at peak temperature for too long
// Crude method that works like a charm and safe for the components
if (input >= (TEMPERATURE_REFLOW_MAX - 5))
{
// Set PID parameters for cooling ramp
reflowOvenPID.SetTunings(PID_KP_REFLOW, PID_KI_REFLOW, PID_KD_REFLOW);
// Ramp down to minimum cooling temperature
setpoint = TEMPERATURE_COOL_MIN;
// Proceed to cooling state
reflowState = REFLOW_STATE_COOL;
}
break;
case REFLOW_STATE_COOL:
// If minimum cool temperature is achieve
if (input buzzerPeriod)
{
// Turn off buzzer and green LED
// digitalWrite(buzzer, LOW);
digitalWrite(ledGreen, HIGH);
// Reflow process ended
reflowState = REFLOW_STATE_IDLE;
}
break;
case REFLOW_STATE_ERROR:
// If thermocouple is still not connected
if (input == THERMOCOUPLE_DISCONNECTED)
{
// Wait until thermocouple wire is connected
reflowState = REFLOW_STATE_ERROR;
}
else
{
// Clear to perform reflow process
reflowState = REFLOW_STATE_IDLE;
}
break;
}
// If button is pressed
if (Serial.available()) {
//if (buttonPressStatus == true)
if (Serial.read())
{
// If currently reflow process is on going
if (reflowStatus == REFLOW_STATUS_ON)
{
// Button press is for cancelling
// Turn off reflow process
reflowStatus = REFLOW_STATUS_OFF;
// Reinitialize state machine
reflowState = REFLOW_STATE_IDLE;
}
}
}
// PID computation and SSR control
if (reflowStatus == REFLOW_STATUS_ON)
{
//unsigned long now;
now = millis();
reflowOvenPID.Compute();
if((now - windowStartTime) > windowSize)
{
// Time to shift the Relay Window
windowStartTime += windowSize;
}
if(output > (now - windowStartTime)) {
//Serial.println("SSR ON");
digitalWrite(ssr, HIGH);
} else {
//Serial.println(F("SSR OFF"));
digitalWrite(ssr, LOW);
}
}
// Reflow oven process is off, ensure oven is off
else
{
digitalWrite(ssr, LOW);
}
}
Demonstration
Temporary video of the oven actually reflowing.
Reflow of a capacitor board
Menu System Working
From Stencil to Reflow
Acknowledgements
1. Limor Fried for creating the MAX31855 Breakout Board and Arduino Library
2. Rocket Scream Electronics for providing the code and inspiration from their Arduino Reflow Shield
3. By extension of #2, Brett Beauregard (www.brettbeauregard.com) for the PID library the code is based on.
4. My neighbors, for not calling the Fire Department after my first attempt… *grin*
Fan of making things beep, blink and fly. Created AddOhms. Writer for Hackster.io News. Freelance electronics content creator for hire! KN6FGY and, of course, bald.
Hello.
I found the whole project very interesting. Reading the code above I failed to understand at what point the button reads to start the reflow process. Could you help me understand?
Sorry for my elementary English.
MeoZot
Like other websites, this one uses cookies to remember things. Mostly, I use Google Analytics to know how many people come here. ¯\_(ツ)_/¯
By clicking “Accept”, you consent to the use of ALL the cookies.
This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
Cookie
Duration
Description
cookielawinfo-checkbox-advertisement
1 year
Set by the GDPR Cookie Consent plugin, this cookie is used to record the user consent for the cookies in the "Advertisement" category .
cookielawinfo-checkbox-analytics
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functional
11 months
The cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessary
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-others
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performance
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
CookieLawInfoConsent
1 year
Records the default button state of the corresponding category & the status of CCPA. It works only in coordination with the primary cookie.
viewed_cookie_policy
11 months
The cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Cookie
Duration
Description
language
session
This cookie is used to store the language preference of the user.
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
Cookie
Duration
Description
_ga
2 years
The _ga cookie, installed by Google Analytics, calculates visitor, session and campaign data and also keeps track of site usage for the site's analytics report. The cookie stores information anonymously and assigns a randomly generated number to recognize unique visitors.
_ga_LHR6J24XSY
2 years
This cookie is installed by Google Analytics.
_gat_gtag_UA_42726312_1
1 minute
Set by Google to distinguish users.
_gid
1 day
Installed by Google Analytics, _gid cookie stores information on how visitors use a website, while also creating an analytics report of the website's performance. Some of the data that are collected include the number of visitors, their source, and the pages they visit anonymously.
browser_id
5 years
This cookie is used for identifying the visitor browser on re-visit to the website.
CONSENT
2 years
YouTube sets this cookie via embedded youtube-videos and registers anonymous statistical data.
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
Cookie
Duration
Description
VISITOR_INFO1_LIVE
5 months 27 days
A cookie set by YouTube to measure bandwidth that determines whether the user gets the new or old player interface.
YSC
session
YSC cookie is set by Youtube and is used to track the views of embedded videos on Youtube pages.
yt-remote-connected-devices
never
YouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
yt-remote-device-id
never
YouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
yt.innertube::nextId
never
This cookie, set by YouTube, registers a unique ID to store data on what videos from YouTube the user has seen.
yt.innertube::requests
never
This cookie, set by YouTube, registers a unique ID to store data on what videos from YouTube the user has seen.
4 Comments
Hello.
I found the whole project very interesting. Reading the code above I failed to understand at what point the button reads to start the reflow process. Could you help me understand?
Sorry for my elementary English.
MeoZot
This code is out of date. It is much bigger now. The latest code is here: https://github.com/baldengineer/Open-Vapors/tree/master/code/open-vapors.
Pingback: baldengineer | Minor updates to the Open Source Reflow Oven Project
Pingback: CMiYC Labs, Inc. | Revision 2 of the open source reflow solder oven is done!