/* Solder Reflow Plate Sketch
* H/W - Ver 3.0
* S/W - Ver 1.0 */
#include <SPI.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <Bounce2.h>
//Version Definitions
static const PROGMEM float hw = 3.0;
static const PROGMEM float sw = 1.0;
//Screen Definitions
#define LCD_RS 10
#define LCD_E 9
#define LCD_D4 6
#define LCD_D5 7
#define LCD_D6 3
#define LCD_D7 2
LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
//Pin Definitions
#define mosfet 8
#define upsw 4
#define dnsw 5
#define temp A1
#define vcc A0
Bounce2::Button upButton;
Bounce2::Button downButton;
//Temperature Info
byte maxTempArray[] = { 140, 150, 160, 170, 180 };
byte maxTempIndex = 0;
byte tempIndexAddr = 1;
//Voltage Measurement Info
float vConvert = 52.00;
float vMin = 10.50;
void setup() {
//Pin Direction control
pinMode(mosfet,OUTPUT);
digitalWrite(mosfet,LOW);
pinMode(temp,INPUT);
pinMode(vcc,INPUT);
upButton.attach(upsw);
upButton.setPressedState(LOW);
upButton.interval(10);
downButton.attach(dnsw);
downButton.setPressedState(LOW);
downButton.interval(10);
//Pull saved values from EEPROM
maxTempIndex = EEPROM.read(tempIndexAddr) % sizeof(maxTempArray);
//Enable Fast PWM with no prescaler
//TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
//TCCR2B = _BV(CS20);
//Start-up Diplay
lcd.clear();
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print("S/W V");
lcd.print(sw);
lcd.setCursor(0, 1);
lcd.print("H/W V");
lcd.print(hw);
delay(3000);
//Go to main menu
lcd.clear();
main_menu();
}
void main_menu() {
int x = 0; //Display change counter
int y = 100; //Display change max (modulused below)
while(1) {
upButton.update();
downButton.update();
analogWrite(mosfet,0); //Ensure MOSFET off
//Button Logic
if(downButton.pressed() || upButton.pressed()) { //If either button pressed
delay(100);
//upButton.update();
//downButton.update();
if(downButton.pressed() && upButton.pressed()) { //If both buttons pressed
if(!heat(maxTempArray[maxTempIndex])) {
//cancelledPB();
main_menu();
}
else {
//coolDown();
//completed();
main_menu();
}
}
if(upButton.pressed() && maxTempIndex < sizeof(maxTempArray) - 1) { //If upper button pressed
maxTempIndex++;
EEPROM.update(tempIndexAddr, maxTempIndex);
}
if(downButton.pressed() && maxTempIndex > 0) { //If lower button pressed
maxTempIndex--;
EEPROM.update(tempIndexAddr, maxTempIndex);
}
}
//Change Display (left-side)
if( x == y) {
lcd.setCursor(0, 0);
lcd.print("U or D for MAX T");
}
else if(x == 0) {
lcd.setCursor(0, 0);
lcd.print("U+D for Heating ");
}
x = ( x + 1 ) % ( 2 * y ); //Display change increment and modulus
//Update Display (right-side)
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.print(maxTempArray[maxTempIndex]);
lcd.print(" C | @");
}
}
bool heat(byte maxTemp) {
//Heating Display
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Heat to ");
lcd.print(maxTempArray[maxTempIndex]);
lcd.print(" C");
lcd.setCursor(0, 1);
lcd.print("@");
lcd.print(" ");
lcd.print(" C | @");
delay(3000);
//Heater Control Variables
/* Heater follows industry reflow graph. Slow build-up to 'warmUp' temp. Rapid ascent
* to 'maxTemp'. Then descent to room temperature.
*/
//byte maxTemp; //Declared in function call
byte maxPWM = 0.70 * maxTemp; //Temperatures (in PWM / 255) influenced by paste temperature
byte warmUpTemp = 0.75 * maxTemp;
byte warmUpPWM = 0.72 * warmUpTemp;
float t; //Used to store current temperature
float v; //Used to store current voltage
byte pwmVal = 0; //PWM Value applied to MOSFET
unsigned long eTime = (millis() / 1000) + (8*60); //Used to store the end time of the heating process, limited to 8 mins
while(1) {
upButton.update();
downButton.update();
//Button Control
if(downButton.pressed() || upButton.pressed()) {
analogWrite(mosfet, 0);
return 0;
}
//Check Heating not taken more than 8 minutes
if(millis() / 1000 > eTime) {
analogWrite(mosfet, 0);
//cancelledTimer();
}
//Measure Values
t = getTemp();
v = getVolts();
//Reflow Profile
if (t < warmUpTemp) { //Warm Up Section
if (pwmVal != warmUpPWM) { pwmVal++; } //Slowly ramp to desired PWM Value
if (v < vMin && pwmVal > 1) { pwmVal = pwmVal - 2; } //Reduce PWM Value if V drops too low but not unless it is still above 1 (avoid overflow/underflow)
}
else if (t < maxTemp) { //Push to maximum temp
if (pwmVal != maxPWM) { pwmVal++; } //Slowly ramp to desired PWM Value
if (v < vMin && pwmVal > 1) { pwmVal = pwmVal - 2; } //Reduce PWM Value if V drops too low but not unless it is still above 1 (avoid overflow/underflow)
}
else { //Heating Complete, return
analogWrite(mosfet, 0);
break;
}
if (pwmVal > maxPWM ) { pwmVal = maxPWM; } //Catch incase of runaway
//MOSFET Control
analogWrite(mosfet, pwmVal);
//Update display
lcd.setCursor(0, 1);
lcd.print("@");
lcd.print(t);
lcd.print(" C | @");
lcd.print(v);
lcd.print("V");
}
}
float getTemp(){
float t = 0;
for (byte i = 0; i < 100; i++){ //Poll temp reading 100 times
t = t + analogRead(temp);
}
return ((t / 100) * -1.46) + 434; //Average, convert to C, and return
}
float getVolts(){
float v = 0;
for (byte i = 0; i < 20; i++){ //Poll Voltage reading 20 times
v = v + analogRead(vcc);
}
return v / 20 / vConvert; //Average, convert to V, and return
}
void loop() {
// Not used
}