before you read this : many hobbyist simply dont use closed loop controled owen to process their reflow. They just carefully check how their owen heat with a multimeter and a thermocouple. And they control by hand the process.
It looks that with some practice they have very nice results.
you can look here :
If you want a more controled system you can read this text now.
I use an arduino board + my arduino thermocouple shield to control a
mini owen for reflow soldering of SMD.
(see Arduino shield for
two thermocouples)
The power is controled by a triac, via an opto triac for galvanic
isolation.
Software regulate owen temperature with closed loop control to follow a
correct reflow curve according JEDEC standard.
Typical reflow temperature curves from an altera document :
According reflow curves the state machine has 5 steps (+ 0 = STOP state) : reflow is divided in REFLOW_HEATING and REFLOW_STABLE.
Transtion beetwen two states is possible if desired temperature or nominal time is reached.
#define TEMP 1
#define CAN 0
#define STOP 0
#define PREHEAT 1
#define ACTIVATION 2
#define REFLOW_HEATING 3
#define REFLOW_STABLE 4
#define COOLING 5
#define PREHEAT_SLOPE 0.15 // 1.5 °C /sec (un pas toutes les 0,1 sec)
#define ACTIVATION_TEMP 150 // Flux activation temperature
#define ACTIVATION_SLOPE 0.0275 // for 33 °C in 120 sec
#define MELTING_TEMP 183 // Melting temp of solder (lead solder)
#define REFLOW_SLOPE 0.1 // 1 °C / sec --> 27 sec from 183 °C to 210 °C
#define REFLOW_TEMP 210 // 10 °C under max package temperature
#define Reflow_Time 6000 // Adjust this to stay enough time in the reflow zone
#define COOLING_SLOPE -0.4 // cooling : 4°C / sec
#define DELTA 100 // Time step of mesurements and regulation.
#define MIN(A,B) ((A) > (B) ? (B) : (A) )
#define MAX(A,B) ((A) > (B) ? (A) : (B) )
#define N_CTN 4 // number of points in TNC calibration table
#define N_TC 12 // number of points in thermocouple calibration table
// Table calibration for THERMISTOR
float calib_CTN [N_CTN][2] = { // put here calibration points : first the value read on arduino ADC, second the value read on your reference thermoemter.
{340,15},{395,19},{405,20},{470,30}
};
// Table calibration for THERMO COUPLE
float calib_TC [N_TC][2] = {
{0,0}, // first point : at 0°C the TC give no voltage
{25,10},{135,40},{305,86},{444, 125},{580,160},{616,170},{655,180},{709,195},{734,201},{841,231},{888,261}
};
int STATE = 0 , POWER = 0;
unsigned long S_millis , Reflow_start;
float Temp = 20 , Temp_theo= 20;
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
pinMode(2,OUTPUT); // Owen command
pinMode(4,OUTPUT) ; // Buzzer
pinMode(3,INPUT) ; digitalWrite(3, HIGH) ; // start button
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0 and 1 :
float Diff_correction ;
static int BUZZ = HIGH ;
static float Tfilt ;
int Can_comp = analogRead(A0);
int Can_TC = analogRead(A1);
float T_ctn = converti(Can_comp , calib_CTN, N_CTN);
float T_Thcp = converti(Can_TC, calib_TC, N_TC) ;
float Temp = T_ctn + T_Thcp ;
Tfilt = (1000*Tfilt + Temp)/1001 ; // Crude moving average filter
int BUTTON = digitalRead(3);
if (millis() >= S_millis + DELTA){
S_millis = millis();
Diff_correction = 0 ;
// STATE machine
if (STATE == STOP && BUTTON == LOW) {
STATE = PREHEAT ;
}
if (STATE == PREHEAT && Temp >= ACTIVATION_TEMP) {
STATE = ACTIVATION ;
}
if (STATE == ACTIVATION && Temp >= MELTING_TEMP) {
STATE = REFLOW_HEATING ;
}
if (STATE == REFLOW_HEATING && Temp >= REFLOW_TEMP) {
STATE = REFLOW_STABLE ; Reflow_start = millis() ;
}
if (STATE == REFLOW_STABLE && millis() >= Reflow_start + Reflow_Time) {
STATE = COOLING ;
}
if (STATE == COOLING && Temp <= ACTIVATION_TEMP){
STATE = STOP ;
}
// Theorical temp calculation
if (STATE == PREHEAT){
Temp_theo += PREHEAT_SLOPE ; Temp_theo = MIN(Temp_theo , ACTIVATION_TEMP );
}
if (STATE == ACTIVATION){
Temp_theo += ACTIVATION_SLOPE ; Temp_theo = MIN(Temp_theo , MELTING_TEMP );
Diff_correction = 20 ; // Adjust this coeff by try and miss to avoid overheating
}
if (STATE == REFLOW_HEATING){
Temp_theo += REFLOW_SLOPE ; Temp_theo = MIN(Temp_theo , REFLOW_TEMP );
Diff_correction = 50 ; // Adjust this coeff by try and miss to avoid overheating
}
if (STATE == REFLOW_STABLE){
Temp_theo = Temp_theo ;
Diff_correction = 50 ; // Adjust this coeff by try and miss to avoid overheating
}
if (STATE == COOLING){
Temp_theo += COOLING_SLOPE ;
Temp_theo = MAX(Temp_theo, 10) ;
if (BUZZ == HIGH ) {tone (4,1000);} else { noTone(4); }
if (BUTTON == LOW) BUZZ = LOW ;
}
// Regulate owen temp
POWER = Regulate (Temp_theo , Tfilt, Diff_correction) ;
// print out the value you read:
Serial.print(S_millis/1000);
/* Serial.print("\tSTATE =\t"); */ Serial.print("\t"); Serial.print(STATE);
/* Serial.print("\tTemp =\t"); */ Serial.print("\t"); Serial.print(Temp);
/* Serial.print("\tT theo =\t"); */ Serial.print("\t"); Serial.print(Temp_theo);
/* Serial.print("\tT PWR =\t"); */ Serial.print("\t"); Serial.println(POWER);
}
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
float Regulate(float Temp_theo , float Temp, int Diff_correction){
static float Old_Residu ; float DT , Residu ;
Residu = Temp - Temp_theo ;
DT = (Residu - Old_Residu) * Diff_correction ; // Crude differential correction to avoid overshoot
Old_Residu = Residu ;
if (Residu > - DT) {
digitalWrite(2, LOW); return LOW ;
} else {
digitalWrite(2, HIGH); return HIGH ;
}
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
float Int_lin(float x, float X1, float Y1 , float X2, float Y2){
float a , b ;
a = (Y1 - Y2) / (X1 - X2) ;
b = Y1 - a*X1 ;
return a*x + b ;
}
// =======================================================================================================//
float converti(float X , // value read on ADC to convert in °C
float calib[][2], // Calibration table to use --> not the same for TCN en thermo couple
int N
){
int i ;
if (X < calib [0][CAN]){ // Entry outside calibration table (lower) --> extrapolation
// with the two first points of table
return Int_lin(X,
calib [0][CAN], calib [0][TEMP] ,
calib [1][CAN], calib [1][TEMP]) ;
}
if (X > calib [N-1][CAN]){ // Entry outside calibration table (higher) --> extrapolation
// with the two last points of table
return Int_lin(X,
calib [N-1][CAN], calib [N-1][TEMP] ,
calib [N][CAN], calib [N][TEMP]) ;
}
for (i=0 ; i < N ; i++){
if (X < calib [i][CAN]){
return Int_lin(X,
calib [i-1][CAN], calib [i-1][TEMP] ,
calib [i][CAN], calib [i][TEMP]) ;
}
}
}
Man machine interface is more then basic : you need to edit the program if you want to change the parameters.
You need to plug your Arduino board to a computer to read output on the serial port.
You can monitor temperature by using the arduino serial monitor or any software listening the convenient serial port. I use "Datalogger" to record temperature curves and Gnuplot to trace them.
Turn on the serial monitor to reset the arduino : you force the system to STOP state.
With most of owen the natural cooling slope of the owen is too slow and you have to open the door to cool quickly. .
With my owen I have the best cooling slope by half opening the door.
You will need several test to find the best tuning of your process :