|
@@ -0,0 +1,220 @@
|
|
|
+/*
|
|
|
+ 60W PD Powered Automatic Reflow Hoteplate
|
|
|
+ Author: tobychui
|
|
|
+
|
|
|
+ Firmware version for v6 PCB
|
|
|
+
|
|
|
+ Notes:
|
|
|
+ - Temperature sensing is done using 1k 1% resistor and a 10k Thermistor
|
|
|
+ You might need to change the code if you are using other values
|
|
|
+ - If you are using the type-C 6p version of the reflow PCB, and after
|
|
|
+ pluggin in the type C cable no led lights up, try flip the type C
|
|
|
+ cable upside down
|
|
|
+
|
|
|
+ Button Mappings (Active Low, aka not pressing = HIGH)
|
|
|
+ Start Btn: P1.4
|
|
|
+ Stop Btn: P1.7
|
|
|
+
|
|
|
+ Download Settings
|
|
|
+ CH552
|
|
|
+ 16Mhz (internal, 3.3V or 5V)
|
|
|
+*/
|
|
|
+#include <Serial.h>
|
|
|
+
|
|
|
+#define TEMP_PIN 11 //P1.1
|
|
|
+#define HEATER_PIN 34 //P3.4
|
|
|
+#define LED_PREHEAT 15 //P1.5
|
|
|
+#define LED_REFLOW 16 //P1.6
|
|
|
+#define START_BTN 14 //P1.4
|
|
|
+#define STOP_BTN 17 //P1.7
|
|
|
+
|
|
|
+//Timing settings. Each cycle is approximately 100ms
|
|
|
+#define HOLDSTART_TIME 30 //START Button hold down time in cycles
|
|
|
+#define HOLDSTOP_TIME 10 //STOP Button hold down time in cycles
|
|
|
+#define SOAKING_TIME 600 //SOAKING temperature upkeep time in cycles
|
|
|
+
|
|
|
+/*
|
|
|
+ Temperature Settings
|
|
|
+
|
|
|
+ The ADC value can be calculated using the following line equation
|
|
|
+ t=-0.7x+250
|
|
|
+
|
|
|
+ where X is ADC reading and t is target temp in degree C
|
|
|
+
|
|
|
+ Note that different setup (e.g. ref resistor value / NTC resistor value) might have different equations
|
|
|
+ You can experiment with yours and get a few data point to plot your own line
|
|
|
+*/
|
|
|
+#define COOLDOWN_TEMP_ADC 255 //Room temperature
|
|
|
+//Preheat temp & power
|
|
|
+#define PREHEAT_START_ADC 143 //150 degree C
|
|
|
+#define PREHEAT_TEMP_ADC 122 //160 degree C
|
|
|
+#define PREHEAT_PWR_PWM 155 //60% power output
|
|
|
+//Reflow temp & power
|
|
|
+#define REFLOW_TEMP_ADC 58 //220 degree C
|
|
|
+#define REFLOW_PWR_PWM 255 //100% power output
|
|
|
+//Overheat cutoff temp
|
|
|
+#define CUTOFF_TEMP_ADC 53 //250 degree C
|
|
|
+
|
|
|
+//Func def
|
|
|
+bool updateHeaterPowerState();
|
|
|
+void updateKeyStates();
|
|
|
+int readTemp();
|
|
|
+
|
|
|
+
|
|
|
+//Runtimes
|
|
|
+bool reflowing = false; //Reflow has started
|
|
|
+bool reflowComplete = false; //Indicate if the stopping is done because of reflow complete
|
|
|
+bool startPressed = false; //Start button is pressed down
|
|
|
+bool stopPressed = false; //Stop button is pressed down
|
|
|
+
|
|
|
+/*
|
|
|
+ Reflow Stages define what is the next state the hotplate should reach
|
|
|
+ 0: Standby
|
|
|
+ 1: Preheating
|
|
|
+ 2: Preheat Holding / Soaking
|
|
|
+ 3: Reflowing
|
|
|
+ 4: Cooling down
|
|
|
+*/
|
|
|
+int reflowStages = 0;
|
|
|
+int startCountdown = HOLDSTART_TIME; //Hold for HOLDSTART_TIME to start to prevent accidental touches
|
|
|
+int stopcountdown = HOLDSTOP_TIME; //Hold for HOLDSTOP_TIME to stop reflowing
|
|
|
+int cycleCounter = 0; //Record cycle time up to 10 seconds
|
|
|
+int soakingCountdown = SOAKING_TIME;
|
|
|
+
|
|
|
+//Blink state controls
|
|
|
+bool blinkState = false; //If blinking this will be switching between true and false
|
|
|
+bool blinkYellow = true; //Slow blink yellow if enabled (Standby). Do not enable both yellow and red at the same time
|
|
|
+bool blinkRed = false; //Slow blink red if enable (End of Reflow). Do not enable both yellow and red at the same time
|
|
|
+bool fastBlinkState = false;
|
|
|
+bool fastblinkRed = false;
|
|
|
+
|
|
|
+
|
|
|
+//Real-time temperature control targets
|
|
|
+int targetTempADC = 255; //Target ADC reading to reach, 255 = room temperature
|
|
|
+int targetPwrPWM = 0; //Target PWM cycle for heater, 255 = full power, 0 = off
|
|
|
+int offset = 0; //Allow +-offset for the ADC reading before reheating / cooling
|
|
|
+
|
|
|
+void setup() {
|
|
|
+ //Set button pins to input
|
|
|
+ pinMode(START_BTN, INPUT);
|
|
|
+ pinMode(STOP_BTN, INPUT);
|
|
|
+
|
|
|
+ //Set LED pins to output
|
|
|
+ pinMode(LED_PREHEAT, OUTPUT);
|
|
|
+ pinMode(LED_REFLOW, OUTPUT);
|
|
|
+ digitalWrite(LED_PREHEAT, LOW);
|
|
|
+ digitalWrite(LED_REFLOW, LOW);
|
|
|
+
|
|
|
+ //Set temp sense pin to input
|
|
|
+ pinMode(TEMP_PIN, INPUT);
|
|
|
+
|
|
|
+ //Set mosfet control pins to output and disable it
|
|
|
+ pinMode(HEATER_PIN, OUTPUT);
|
|
|
+ digitalWrite(HEATER_PIN, LOW);
|
|
|
+
|
|
|
+ USBSerial_println("Reflow Hotplate Ready!");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void loop() {
|
|
|
+ /* State Check */
|
|
|
+ updateKeyStates();
|
|
|
+
|
|
|
+ /* Main reflowing logics */
|
|
|
+ //Add delay to the end of each conditions so each loop cycle is approximate 100ms
|
|
|
+ if (reflowing) {
|
|
|
+ /* Currently is in reflow stage */
|
|
|
+ bool tempReached = updateHeaterPowerState(); //This action takes 100ms
|
|
|
+ if (tempReached) {
|
|
|
+ //This stage temperature reached. Move to next stage
|
|
|
+ if (reflowStages == 1) {
|
|
|
+ //Preheat stage completed. Enter soaking stage
|
|
|
+ USBSerial_println("Preheat temperature reached. Soaking started");
|
|
|
+ targetTempADC = PREHEAT_TEMP_ADC; //Set temperature to soaking end temp
|
|
|
+ reflowStages = 2; //Set reflow stage to soaking
|
|
|
+ soakingCountdown = SOAKING_TIME;
|
|
|
+ fastblinkRed = true;
|
|
|
+ } else if (reflowStages == 3) {
|
|
|
+ //Reflowing target temperature reached. Start cooldown and shut down heater
|
|
|
+ USBSerial_println("Reflow completed. Cooling down");
|
|
|
+ reflowStages = 4;
|
|
|
+ blinkYellow = false;
|
|
|
+ blinkRed = true;
|
|
|
+ targetTempADC = COOLDOWN_TEMP_ADC;
|
|
|
+ targetPwrPWM = 0;
|
|
|
+
|
|
|
+ //Reflow ended. Wait until stop being press to exit this state
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (reflowStages == 2) {
|
|
|
+ //Wait for the soaking to complete and enter reflow stage
|
|
|
+ soakingCountdown--;
|
|
|
+ if (soakingCountdown <= 0) {
|
|
|
+ //Soaking completed. Enter reflow stage
|
|
|
+ USBSerial_println("Soaking time ended. Reflow started");
|
|
|
+
|
|
|
+ //Set Reflow LED to high
|
|
|
+ fastblinkRed = false;
|
|
|
+ digitalWrite(LED_REFLOW, HIGH);
|
|
|
+
|
|
|
+ //Set to reflow temperature
|
|
|
+ targetTempADC = REFLOW_TEMP_ADC; //Set the target temp to reflow
|
|
|
+ targetPwrPWM = REFLOW_PWR_PWM; //Set power rating to reflow
|
|
|
+
|
|
|
+ //Update the reflow stage to 3
|
|
|
+ reflowStages = 3;
|
|
|
+ } else if (soakingCountdown % 100 == 0) {
|
|
|
+ USBSerial_print("Soaking cycles left: ");
|
|
|
+ USBSerial_println(soakingCountdown);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ delay(1);
|
|
|
+ } else {
|
|
|
+ /* Standby Mode */
|
|
|
+ digitalWrite(HEATER_PIN, LOW);
|
|
|
+ blinkYellow = true;
|
|
|
+ delay(100); //adjust this if needed to make sure reflow cycles use the same time as standby cycles
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Blink Signal Handlers */
|
|
|
+ //FastBlink handler, execute every 500ms
|
|
|
+ if (cycleCounter % 5 == 0 && fastblinkRed) {
|
|
|
+ digitalWrite(LED_PREHEAT, LOW);
|
|
|
+ if (fastBlinkState) {
|
|
|
+ digitalWrite(LED_REFLOW, HIGH);
|
|
|
+ } else {
|
|
|
+ digitalWrite(LED_REFLOW, LOW);
|
|
|
+ }
|
|
|
+ fastBlinkState = !fastBlinkState;
|
|
|
+ }
|
|
|
+
|
|
|
+ //Blink handler, execute every 2 seconds
|
|
|
+ if (cycleCounter % 20 == 0) {
|
|
|
+ if (blinkYellow) {
|
|
|
+ if (blinkState) {
|
|
|
+ digitalWrite(LED_PREHEAT, HIGH);
|
|
|
+ } else {
|
|
|
+ digitalWrite(LED_PREHEAT, LOW);
|
|
|
+ }
|
|
|
+ } else if (blinkRed) {
|
|
|
+ if (blinkState) {
|
|
|
+ digitalWrite(LED_REFLOW, HIGH);
|
|
|
+ } else {
|
|
|
+ digitalWrite(LED_REFLOW, LOW);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ blinkState = !blinkState;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ Cycle Counter
|
|
|
+ Counter are limited to 600 to prevent overflow.
|
|
|
+ */
|
|
|
+
|
|
|
+ cycleCounter++;
|
|
|
+ if (cycleCounter > 600) {
|
|
|
+ cycleCounter = 0;
|
|
|
+ }
|
|
|
+}
|