From 213b2a1bacbbe46ee92eb9441913004ba587b9ef Mon Sep 17 00:00:00 2001 From: Stefan Schueller Date: Sun, 25 Oct 2020 00:17:05 +0200 Subject: [PATCH 1/2] Multiple Profiles and Temp Holding --- .gitignore | 5 + .pretty/0802A-1-SMT.kicad_mod | 0 .pretty/C_0603.kicad_mod | 0 .pretty/C_0805.kicad_mod | 0 .pretty/FIDUCIAL-1MM.kicad_mod | 0 .pretty/HDR_1x6_Pitch2.54mm.kicad_mod | 0 .pretty/HDR_2x3_Pitch2.54mm.kicad_mod | 0 .pretty/HOLE_NPTH_2.2MM.kicad_mod | 0 .pretty/HYG9605B.kicad_mod | 0 .pretty/IT-1102W.kicad_mod | 0 .pretty/I_0603.kicad_mod | 0 .pretty/LED_0603.kicad_mod | 0 .pretty/LOGO-KICAD.kicad_mod | 0 .pretty/LOGO-KICAD_XSmall.kicad_mod | 0 .pretty/LOGO-OSHW_Small.kicad_mod | 0 ...OGO-ROCKET-SCREAM_Vertical_Small.kicad_mod | 0 ...KET-SCREAM_Without_Text_XXXSmall.kicad_mod | 0 .pretty/MF-FSMF.kicad_mod | 0 .pretty/MICRO-USB.kicad_mod | 0 .pretty/MSOP-10.kicad_mod | 0 .pretty/NX3225GD.kicad_mod | 0 .pretty/OLED-SSD1306-128X64-I2C.kicad_mod | 0 .pretty/QFN-20_4x4mm.kicad_mod | 0 .pretty/QFN-32_5x5mm_Pitch0.5mm.kicad_mod | 0 .pretty/R_0603.kicad_mod | 0 .pretty/SOD-123.kicad_mod | 0 .pretty/SOD-323.kicad_mod | 0 .pretty/SOT-1016.kicad_mod | 0 .pretty/SOT-23.kicad_mod | 0 .pretty/SOT-89.kicad_mod | 0 .pretty/TB-1776275-2.kicad_mod | 0 .pretty/TC33X-x.kicad_mod | 0 .pretty/TS-018.kicad_mod | 0 .pretty/TSSOP-14.kicad_mod | 0 .vscode/extensions.json | 7 + Gerber/TINY-REFLOW-CONTROLLER.drl | 0 Gerber/TINY-REFLOW-CONTROLLER.gbl | 0 Gerber/TINY-REFLOW-CONTROLLER.gbo | 0 Gerber/TINY-REFLOW-CONTROLLER.gbs | 0 Gerber/TINY-REFLOW-CONTROLLER.gm1 | 0 Gerber/TINY-REFLOW-CONTROLLER.gtl | 0 Gerber/TINY-REFLOW-CONTROLLER.gto | 0 Gerber/TINY-REFLOW-CONTROLLER.gtp | 0 Gerber/TINY-REFLOW-CONTROLLER.gts | 0 README.md | 114 +++- TINY-REFLOW-CONTROLLER-cache.lib | 0 TINY-REFLOW-CONTROLLER.kicad_pcb | 0 TINY-REFLOW-CONTROLLER.pdf | Bin TINY-REFLOW-CONTROLLER.pro | 0 TINY-REFLOW-CONTROLLER.sch | 0 include/README | 39 ++ lib/README | 46 ++ platformio.ini | 40 ++ TinyReflowController.ino => src/main.cpp | 590 ++++++++++-------- src/profiles.h | 24 + test/README | 11 + 56 files changed, 598 insertions(+), 278 deletions(-) create mode 100644 .gitignore mode change 100755 => 100644 .pretty/0802A-1-SMT.kicad_mod mode change 100755 => 100644 .pretty/C_0603.kicad_mod mode change 100755 => 100644 .pretty/C_0805.kicad_mod mode change 100755 => 100644 .pretty/FIDUCIAL-1MM.kicad_mod mode change 100755 => 100644 .pretty/HDR_1x6_Pitch2.54mm.kicad_mod mode change 100755 => 100644 .pretty/HDR_2x3_Pitch2.54mm.kicad_mod mode change 100755 => 100644 .pretty/HOLE_NPTH_2.2MM.kicad_mod mode change 100755 => 100644 .pretty/HYG9605B.kicad_mod mode change 100755 => 100644 .pretty/IT-1102W.kicad_mod mode change 100755 => 100644 .pretty/I_0603.kicad_mod mode change 100755 => 100644 .pretty/LED_0603.kicad_mod mode change 100755 => 100644 .pretty/LOGO-KICAD.kicad_mod mode change 100755 => 100644 .pretty/LOGO-KICAD_XSmall.kicad_mod mode change 100755 => 100644 .pretty/LOGO-OSHW_Small.kicad_mod mode change 100755 => 100644 .pretty/LOGO-ROCKET-SCREAM_Vertical_Small.kicad_mod mode change 100755 => 100644 .pretty/LOGO-ROCKET-SCREAM_Without_Text_XXXSmall.kicad_mod mode change 100755 => 100644 .pretty/MF-FSMF.kicad_mod mode change 100755 => 100644 .pretty/MICRO-USB.kicad_mod mode change 100755 => 100644 .pretty/MSOP-10.kicad_mod mode change 100755 => 100644 .pretty/NX3225GD.kicad_mod mode change 100755 => 100644 .pretty/OLED-SSD1306-128X64-I2C.kicad_mod mode change 100755 => 100644 .pretty/QFN-20_4x4mm.kicad_mod mode change 100755 => 100644 .pretty/QFN-32_5x5mm_Pitch0.5mm.kicad_mod mode change 100755 => 100644 .pretty/R_0603.kicad_mod mode change 100755 => 100644 .pretty/SOD-123.kicad_mod mode change 100755 => 100644 .pretty/SOD-323.kicad_mod mode change 100755 => 100644 .pretty/SOT-1016.kicad_mod mode change 100755 => 100644 .pretty/SOT-23.kicad_mod mode change 100755 => 100644 .pretty/SOT-89.kicad_mod mode change 100755 => 100644 .pretty/TB-1776275-2.kicad_mod mode change 100755 => 100644 .pretty/TC33X-x.kicad_mod mode change 100755 => 100644 .pretty/TS-018.kicad_mod mode change 100755 => 100644 .pretty/TSSOP-14.kicad_mod create mode 100644 .vscode/extensions.json mode change 100755 => 100644 Gerber/TINY-REFLOW-CONTROLLER.drl mode change 100755 => 100644 Gerber/TINY-REFLOW-CONTROLLER.gbl mode change 100755 => 100644 Gerber/TINY-REFLOW-CONTROLLER.gbo mode change 100755 => 100644 Gerber/TINY-REFLOW-CONTROLLER.gbs mode change 100755 => 100644 Gerber/TINY-REFLOW-CONTROLLER.gm1 mode change 100755 => 100644 Gerber/TINY-REFLOW-CONTROLLER.gtl mode change 100755 => 100644 Gerber/TINY-REFLOW-CONTROLLER.gto mode change 100755 => 100644 Gerber/TINY-REFLOW-CONTROLLER.gtp mode change 100755 => 100644 Gerber/TINY-REFLOW-CONTROLLER.gts mode change 100755 => 100644 TINY-REFLOW-CONTROLLER-cache.lib mode change 100755 => 100644 TINY-REFLOW-CONTROLLER.kicad_pcb mode change 100755 => 100644 TINY-REFLOW-CONTROLLER.pdf mode change 100755 => 100644 TINY-REFLOW-CONTROLLER.pro mode change 100755 => 100644 TINY-REFLOW-CONTROLLER.sch create mode 100644 include/README create mode 100644 lib/README create mode 100644 platformio.ini rename TinyReflowController.ino => src/main.cpp (61%) create mode 100644 src/profiles.h create mode 100644 test/README diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.pretty/0802A-1-SMT.kicad_mod b/.pretty/0802A-1-SMT.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/C_0603.kicad_mod b/.pretty/C_0603.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/C_0805.kicad_mod b/.pretty/C_0805.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/FIDUCIAL-1MM.kicad_mod b/.pretty/FIDUCIAL-1MM.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/HDR_1x6_Pitch2.54mm.kicad_mod b/.pretty/HDR_1x6_Pitch2.54mm.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/HDR_2x3_Pitch2.54mm.kicad_mod b/.pretty/HDR_2x3_Pitch2.54mm.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/HOLE_NPTH_2.2MM.kicad_mod b/.pretty/HOLE_NPTH_2.2MM.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/HYG9605B.kicad_mod b/.pretty/HYG9605B.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/IT-1102W.kicad_mod b/.pretty/IT-1102W.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/I_0603.kicad_mod b/.pretty/I_0603.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/LED_0603.kicad_mod b/.pretty/LED_0603.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/LOGO-KICAD.kicad_mod b/.pretty/LOGO-KICAD.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/LOGO-KICAD_XSmall.kicad_mod b/.pretty/LOGO-KICAD_XSmall.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/LOGO-OSHW_Small.kicad_mod b/.pretty/LOGO-OSHW_Small.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/LOGO-ROCKET-SCREAM_Vertical_Small.kicad_mod b/.pretty/LOGO-ROCKET-SCREAM_Vertical_Small.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/LOGO-ROCKET-SCREAM_Without_Text_XXXSmall.kicad_mod b/.pretty/LOGO-ROCKET-SCREAM_Without_Text_XXXSmall.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/MF-FSMF.kicad_mod b/.pretty/MF-FSMF.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/MICRO-USB.kicad_mod b/.pretty/MICRO-USB.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/MSOP-10.kicad_mod b/.pretty/MSOP-10.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/NX3225GD.kicad_mod b/.pretty/NX3225GD.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/OLED-SSD1306-128X64-I2C.kicad_mod b/.pretty/OLED-SSD1306-128X64-I2C.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/QFN-20_4x4mm.kicad_mod b/.pretty/QFN-20_4x4mm.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/QFN-32_5x5mm_Pitch0.5mm.kicad_mod b/.pretty/QFN-32_5x5mm_Pitch0.5mm.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/R_0603.kicad_mod b/.pretty/R_0603.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/SOD-123.kicad_mod b/.pretty/SOD-123.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/SOD-323.kicad_mod b/.pretty/SOD-323.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/SOT-1016.kicad_mod b/.pretty/SOT-1016.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/SOT-23.kicad_mod b/.pretty/SOT-23.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/SOT-89.kicad_mod b/.pretty/SOT-89.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/TB-1776275-2.kicad_mod b/.pretty/TB-1776275-2.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/TC33X-x.kicad_mod b/.pretty/TC33X-x.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/TS-018.kicad_mod b/.pretty/TS-018.kicad_mod old mode 100755 new mode 100644 diff --git a/.pretty/TSSOP-14.kicad_mod b/.pretty/TSSOP-14.kicad_mod old mode 100755 new mode 100644 diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..e80666b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} diff --git a/Gerber/TINY-REFLOW-CONTROLLER.drl b/Gerber/TINY-REFLOW-CONTROLLER.drl old mode 100755 new mode 100644 diff --git a/Gerber/TINY-REFLOW-CONTROLLER.gbl b/Gerber/TINY-REFLOW-CONTROLLER.gbl old mode 100755 new mode 100644 diff --git a/Gerber/TINY-REFLOW-CONTROLLER.gbo b/Gerber/TINY-REFLOW-CONTROLLER.gbo old mode 100755 new mode 100644 diff --git a/Gerber/TINY-REFLOW-CONTROLLER.gbs b/Gerber/TINY-REFLOW-CONTROLLER.gbs old mode 100755 new mode 100644 diff --git a/Gerber/TINY-REFLOW-CONTROLLER.gm1 b/Gerber/TINY-REFLOW-CONTROLLER.gm1 old mode 100755 new mode 100644 diff --git a/Gerber/TINY-REFLOW-CONTROLLER.gtl b/Gerber/TINY-REFLOW-CONTROLLER.gtl old mode 100755 new mode 100644 diff --git a/Gerber/TINY-REFLOW-CONTROLLER.gto b/Gerber/TINY-REFLOW-CONTROLLER.gto old mode 100755 new mode 100644 diff --git a/Gerber/TINY-REFLOW-CONTROLLER.gtp b/Gerber/TINY-REFLOW-CONTROLLER.gtp old mode 100755 new mode 100644 diff --git a/Gerber/TINY-REFLOW-CONTROLLER.gts b/Gerber/TINY-REFLOW-CONTROLLER.gts old mode 100755 new mode 100644 diff --git a/README.md b/README.md index 2971adf..a23fa17 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,114 @@ # Tiny Reflow Controller -An all-in-one Arduino compatible reflow controller powered by ATmega328P (V2) or ATtiny1634R (V1). A reincarnation of the Reflow Oven Controller Shield that requires an external Arduino board like Arduino Uno based on user feedbacks over the years. Powered by the ATmega328P/ATtiny1634R coupled with the latest thermocouple sensor interface IC MAX31856 from Maxim, we managed to remove the need of an Arduino board and reduce the overall cost. We also use as much SMD parts in this revision to keep the cost low (manual soldering and left over residue cleaning is time consuming) and leaving only the terminal block and the LCD connector on through hole version. We also managed to streamline all components to run on 3.3V to further simplify the design. All you need is an external Solid State Relay (SSR) (rated accordingly to your oven), K type thermocouple (we recommend those with fiber glass or steel jacket), and an oven of course! You can now select to run a lead-free profile or leaded profile from the selection switch. V2 comes with 0.96" 128*64 OLED LCD to plot the real-time reflow curve and has a built-in serial-USB interface. V2 also has an optional transistor output drive fan if needed. + +An all-in-one Arduino compatible reflow controller powered by ATmega328P (V2) or ATtiny1634R (V1). A reincarnation of the Reflow Oven Controller Shield that requires an external Arduino board like Arduino Uno based on user feedbacks over the years. Powered by the ATmega328P/ATtiny1634R coupled with the latest thermocouple sensor interface IC MAX31856 from Maxim, we managed to remove the need of an Arduino board and reduce the overall cost. We also use as much SMD parts in this revision to keep the cost low (manual soldering and left over residue cleaning is time consuming) and leaving only the terminal block and the LCD connector on through hole version. We also managed to streamline all components to run on 3.3V to further simplify the design. + +All you need is an external Solid State Relay (SSR) (rated accordingly to your oven), K type thermocouple (we recommend those with fiber glass or steel jacket), and an oven of course! + +You can now select to run a lead-free profile or leaded profile from the selection switch. + +V2 comes with 0.96" 128*64 OLED LCD to plot the real-time reflow curve and has a built-in serial-USB interface. V2 also has an optional transistor output drive fan if needed. + +## Building + +Use VS Code with platform IO. Set the version you want to build in platform.ini + +## Profile Configration + + - Each Profile has 4 stages: pre-heat, soak, reflow and cooldown + - Each Stage has: + - Max Temp: The Max Temperature for this stage in degree C. Goal Temp. + - Micro Time: Milliseconds until the next temperature setpoint increase. (set to 0 for max heating speed) + - Heat Step: Degree C step size for new setpoint (set to "Max Temp" - "previous stage max" (TEMPERATURE_ROOM for first stage) for max heating speed) + - Hold Micro Time: Milliseconds to hold at max temp once it is reached (set to 0 to skip) + - PID KP: + - PID KI: + - PID KD: + + +## Profiles + +Profiles can be configured in src/main.cpp starting on line 108. + +### Leaded Reflow Curve (Kester EP256) +``` + Temperature (Degree Celcius) Magic Happens Here! + 219-| x x + | x x + | x x + 180-| x x + | x | | x + | x | | x + 150-| x | | x + | x | | | + | x | | | + | x | | | + | x | | | + | x | | | + | x | | | + 30 -| x | | | + |< 60 - 90 s >|< 60 - 90 s >|< 60 - 90 s >| + | Preheat Stage | Soaking Stage| Reflow Stage | Cool + 0 |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ |_ _ _ _ _ _ _ _ _ _ |_ _ _ _ _ _ _ _ _ _ _ + Time (Seconds) +``` + +### Lead-Free Reflow Curve +``` + Temperature (Degree Celcius) Magic Happens Here! + 245-| x x + | x x + | x x + | x x + 200-| x x + | x | | x + | x | | x + | x | | + 150-| x | | + | x | | | + | x | | | + | x | | | + | x | | | + | x | | | + | x | | | + 30 -| x | | | + |< 60 - 90 s >|< 90 - 120 s >|< 90 - 120 s >| + | Preheat Stage | Soaking Stage | Reflow Stage | Cool + 0 |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ |_ _ _ _ _ + Time (Seconds) +``` + +### PLA Annealing +``` + Temperature (Degree Celcius) + | + 63 -| x x x x x x + | x | | x + | x | | x + | x | | x + | x | | x + | x | | x + | x | | x + 30 -| x | | | + |< 4 hours >|< 30 min >|< 3 hours >| + | Preheat Stage | Soaking Stage | Cool | + 0 |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ |_ _ _ _ _ + Time (Seconds) +``` + +### PETG Annealing +``` + Temperature (Degree Celcius) + | + 177-| x x x x x x + | x | | x + | x | | x + | x | | x + | x | | x + | x | | x + | x | | x + 30 -| x | | | + |< 4 hours >|< 30 min >|< 3 hours >| + | Preheat Stage | Soaking Stage | Cool | + 0 |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ |_ _ _ _ _ + Time (Seconds) +``` diff --git a/TINY-REFLOW-CONTROLLER-cache.lib b/TINY-REFLOW-CONTROLLER-cache.lib old mode 100755 new mode 100644 diff --git a/TINY-REFLOW-CONTROLLER.kicad_pcb b/TINY-REFLOW-CONTROLLER.kicad_pcb old mode 100755 new mode 100644 diff --git a/TINY-REFLOW-CONTROLLER.pdf b/TINY-REFLOW-CONTROLLER.pdf old mode 100755 new mode 100644 diff --git a/TINY-REFLOW-CONTROLLER.pro b/TINY-REFLOW-CONTROLLER.pro old mode 100755 new mode 100644 diff --git a/TINY-REFLOW-CONTROLLER.sch b/TINY-REFLOW-CONTROLLER.sch old mode 100755 new mode 100644 diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..b342bc1 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,40 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +default_envs = 328p8m ; Set this to the env you want to build. Remove to build both. + +; Version 2 - OLED +[env:328p8m] +platform = atmelavr +board = 328p8m +framework = arduino +monitor_speed = 115200 +build_flags = '-DVERSION=2' +lib_deps = + adafruit/Adafruit GFX Library @^1 + adafruit/Adafruit SSD1306 @^1 + adafruit/Adafruit MAX31856 Library @^1 + bitbucket-fmalpartida/LiquidCrystal @ ^1.5.0 + PID + SPI + +; Version 1 - LCD +[env:attiny1634] +platform = atmelavr +board = attiny1634 +framework = arduino +monitor_speed = 115200 +build_flags = '-DVERSION=1' +lib_deps = + adafruit/Adafruit MAX31856 Library @^1 + bitbucket-fmalpartida/LiquidCrystal @ ^1.5.0 + PID + SPI diff --git a/TinyReflowController.ino b/src/main.cpp similarity index 61% rename from TinyReflowController.ino rename to src/main.cpp index 00e8111..305df17 100644 --- a/TinyReflowController.ino +++ b/src/main.cpp @@ -1,7 +1,7 @@ /******************************************************************************* Title: Tiny Reflow Controller - Version: 2.00 - Date: 03-03-2019 + Version: 2.50 + Date: 18-10-2020 Company: Rocket Scream Electronics Author: Lim Phang Moh Website: www.rocketscream.com @@ -15,54 +15,6 @@ during system idle. The unit will remember the last selected reflow profile. You'll need to use the MAX31856 library for Arduino. - Lead-Free Reflow Curve - ====================== - - Temperature (Degree Celcius) Magic Happens Here! - 245-| x x - | x x - | x x - | x x - 200-| x x - | x | | x - | x | | x - | x | | - 150-| x | | - | x | | | - | x | | | - | x | | | - | x | | | - | x | | | - | x | | | - 30 -| x | | | - |< 60 - 90 s >|< 90 - 120 s >|< 90 - 120 s >| - | Preheat Stage | Soaking Stage | Reflow Stage | Cool - 0 |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ |_ _ _ _ _ - Time (Seconds) - - Leaded Reflow Curve (Kester EP256) - ================================== - - Temperature (Degree Celcius) Magic Happens Here! - 219-| x x - | x x - | x x - 180-| x x - | x | | x - | x | | x - 150-| x | | x - | x | | | - | x | | | - | x | | | - | x | | | - | x | | | - | x | | | - 30 -| x | | | - |< 60 - 90 s >|< 60 - 90 s >|< 60 - 90 s >| - | Preheat Stage | Soaking Stage| Reflow Stage | Cool - 0 |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ |_ _ _ _ _ _ _ _ _ _ |_ _ _ _ _ _ _ _ _ _ _ - Time (Seconds) - This firmware owed very much on the works of other talented individuals as follows: ========================================== @@ -113,6 +65,7 @@ Revision Description ======== =========== + 2.50 Support for more than 2 profiles 2.00 Support V2 of the Tiny Reflow Controller: - Based on ATMega328P 3.3V @ 8MHz - Uses SSD1306 128x64 OLED @@ -125,14 +78,80 @@ // ***** INCLUDES ***** #include #include -#include -#include -#include // Comment for VERSION 1 -#include // Comment for VERSION 1 #include #include +#if VERSION == 1 + #include +#endif + +#if VERSION == 2 + #include + #include +#endif + +// ***** CONSTANTS ***** + +// ***** GENERAL PROFILE CONSTANTS ***** +#define TEMPERATURE_ROOM 30 +#define SENSOR_SAMPLING_TIME 1000 + +// ***** SWITCH SPECIFIC CONSTANTS ***** +#define DEBOUNCE_PERIOD_MIN 100 + +// ***** DISPLAY SPECIFIC CONSTANTS ***** +#define UPDATE_RATE 100 + +// ***** PID PARAMETERS ***** +#define PID_SAMPLE_TIME 1000 + +// Profiles +const char profilename_0[] PROGMEM = "Ke. EP256"; +const char profilename_1[] PROGMEM = "Lead-free"; +const char profilename_2[] PROGMEM = "PLA Annea"; +const char profilename_3[] PROGMEM = "PETG Anne"; + +const char *const profileNames[] PROGMEM = {profilename_0, profilename_1, profilename_2, profilename_3}; + +// pre-heat +const float profilePreHeatTemps[] PROGMEM = {150, 150, 63, 177}; +const uint32_t profilePreHeatMTime[] PROGMEM = {0, 0, 120000, 120000}; +const int profilePreHeatTStep[] PROGMEM = {120, 120, 1, 1}; +const uint32_t profilePreHeatHoldTime[] PROGMEM = {0, 0, 0, 0}; +const float profilePreHeatKP[] PROGMEM = {100, 100, 100, 100}; +const float profilePreHeatKI[] PROGMEM = {0.025, 0.025, 0.025, 0.025}; +const float profilePreHeatKD[] PROGMEM = {20, 20, 20, 20}; + +// Soak +const float profileSoakTemps[] PROGMEM = {180, 200, 63, 177}; +const uint32_t profileSoakMTime[] PROGMEM = {6000, 6000, 0, 0}; +const int profileSoakTStep[] PROGMEM = {5, 5, 5, 0}; +const uint32_t profileSoakHoldTime[] PROGMEM = {0, 0, 3600000, 3600000}; +const float profileSoakKP[] PROGMEM = {300, 300, 300, 300}; +const float profileSoakKI[] PROGMEM = {0.05, 0.05, 0.05, 0.05}; +const float profileSoakKD[] PROGMEM = {250, 250, 250, 250}; + +// Reflow +const float profileReflowTemps[] PROGMEM = {180, 180, 63, 177}; +const uint32_t profileReflowMTime[] PROGMEM = {6000, 6000, 0, 0}; +const int profileReflowTStep[] PROGMEM = {5, 5, 0, 0}; +const uint32_t profileReflowHoldTime[] PROGMEM = {6000, 6000, 0, 0}; +const float profileReflowKP[] PROGMEM = {300, 300, 300, 300}; +const float profileReflowKI[] PROGMEM = {0.05, 0.05, 0.05, 0.05}; +const float profileReflowKD[] PROGMEM = {350, 350, 350, 350}; + +// Cool-down +const float profileCoolDownTemps[] PROGMEM = {TEMPERATURE_ROOM, TEMPERATURE_ROOM, TEMPERATURE_ROOM, TEMPERATURE_ROOM}; +const uint32_t profileCoolDownMTime[] PROGMEM = {6000, 6000, 420000, 420000}; +const int profileCoolDownTStep[] PROGMEM = {-5, -5, -1, -1}; +const uint32_t profileCoolDownHoldTime[] PROGMEM = {0, 0, 0, 0}; +const float profileCoolDownKP[] PROGMEM = {300, 300, 300, 300}; +const float profileCoolDownKI[] PROGMEM = {0.05, 0.05, 0.05, 0.05}; +const float profileCoolDownKD[] PROGMEM = {350, 350, 350, 350}; + // ***** TYPE DEFINITIONS ***** +char dispbuffer[10]; // profile name and reflow state read buffer max size + typedef enum REFLOW_STATE { REFLOW_STATE_IDLE, @@ -140,6 +159,7 @@ typedef enum REFLOW_STATE REFLOW_STATE_SOAK, REFLOW_STATE_REFLOW, REFLOW_STATE_COOL, + REFLOW_STATE_COOL_COMPLETE, REFLOW_STATE_COMPLETE, REFLOW_STATE_TOO_HOT, REFLOW_STATE_ERROR @@ -165,72 +185,27 @@ typedef enum DEBOUNCE_STATE DEBOUNCE_STATE_RELEASE } debounceState_t; -typedef enum REFLOW_PROFILE -{ - REFLOW_PROFILE_LEADFREE, - REFLOW_PROFILE_LEADED -} reflowProfile_t; - -// ***** CONSTANTS ***** -// ***** GENERAL ***** -#define VERSION 2 // Replace with 1 or 2 - -// ***** GENERAL PROFILE CONSTANTS ***** -#define PROFILE_TYPE_ADDRESS 0 -#define TEMPERATURE_ROOM 50 -#define TEMPERATURE_SOAK_MIN 150 -#define TEMPERATURE_COOL_MIN 100 -#define SENSOR_SAMPLING_TIME 1000 -#define SOAK_TEMPERATURE_STEP 5 -// ***** LEAD FREE PROFILE CONSTANTS ***** -#define TEMPERATURE_SOAK_MAX_LF 200 -#define TEMPERATURE_REFLOW_MAX_LF 250 -#define SOAK_MICRO_PERIOD_LF 9000 - -// ***** LEADED PROFILE CONSTANTS ***** -#define TEMPERATURE_SOAK_MAX_PB 180 -#define TEMPERATURE_REFLOW_MAX_PB 224 -#define SOAK_MICRO_PERIOD_PB 10000 - -// ***** SWITCH SPECIFIC CONSTANTS ***** -#define DEBOUNCE_PERIOD_MIN 100 - -// ***** DISPLAY SPECIFIC CONSTANTS ***** -#define UPDATE_RATE 100 - -// ***** PID PARAMETERS ***** -// ***** PRE-HEAT STAGE ***** -#define PID_KP_PREHEAT 100 -#define PID_KI_PREHEAT 0.025 -#define PID_KD_PREHEAT 20 -// ***** 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 #if VERSION == 2 -#define SCREEN_WIDTH 128 // OLED display width, in pixels -#define SCREEN_HEIGHT 64 // OLED display height, in pixels -#define X_AXIS_START 18 // X-axis starting position + #define SCREEN_WIDTH 128 // OLED display width, in pixels + #define SCREEN_HEIGHT 64 // OLED display height, in pixels + #define X_AXIS_START 18 // X-axis starting position #endif // ***** LCD MESSAGES ***** -const char* lcdMessagesReflowStatus[] = { - "Ready", - "Pre", - "Soak", - "Reflow", - "Cool", - "Done!", - "Hot!", - "Error" -}; +const char ReflowStatus_0[] PROGMEM = "Ready "; +const char ReflowStatus_1[] PROGMEM = "Pre "; +const char ReflowStatus_2[] PROGMEM = "Soak "; +const char ReflowStatus_3[] PROGMEM = "Reflow"; +const char ReflowStatus_4[] PROGMEM = "Cool "; +const char ReflowStatus_5[] PROGMEM = "Cool 2"; +const char ReflowStatus_6[] PROGMEM = "Done! "; +const char ReflowStatus_7[] PROGMEM = "Hot! "; +const char ReflowStatus_8[] PROGMEM = "Error "; + +// store in program mem to convserve SRAM +const char *const lcdMessagesReflowStatus[] PROGMEM = {ReflowStatus_0, ReflowStatus_1, ReflowStatus_2, ReflowStatus_3, ReflowStatus_4, ReflowStatus_5, ReflowStatus_6, ReflowStatus_7, ReflowStatus_8}; // ***** DEGREE SYMBOL FOR LCD ***** unsigned char degree[8] = { @@ -239,50 +214,47 @@ unsigned char degree[8] = { // ***** PIN ASSIGNMENT ***** #if VERSION == 1 -unsigned char ssrPin = 3; -unsigned char thermocoupleCSPin = 2; -unsigned char lcdRsPin = 10; -unsigned char lcdEPin = 9; -unsigned char lcdD4Pin = 8; -unsigned char lcdD5Pin = 7; -unsigned char lcdD6Pin = 6; -unsigned char lcdD7Pin = 5; -unsigned char buzzerPin = 14; -unsigned char switchPin = A1; -unsigned char ledPin = LED_BUILTIN; + unsigned char ssrPin = 3; + unsigned char thermocoupleCSPin = 2; + unsigned char lcdRsPin = 10; + unsigned char lcdEPin = 9; + unsigned char lcdD4Pin = 8; + unsigned char lcdD5Pin = 7; + unsigned char lcdD6Pin = 6; + unsigned char lcdD7Pin = 5; + unsigned char buzzerPin = 14; + unsigned char switchPin = A1; + unsigned char ledPin = LED_BUILTIN; #elif VERSION == 2 -unsigned char ssrPin = A0; -unsigned char fanPin = A1; -unsigned char thermocoupleCSPin = 10; -unsigned char ledPin = 4; -unsigned char buzzerPin = 5; -unsigned char switchStartStopPin = 3; -unsigned char switchLfPbPin = 2; + unsigned char ssrPin = A0; + unsigned char fanPin = A1; + unsigned char thermocoupleCSPin = 10; + unsigned char ledPin = 4; + unsigned char buzzerPin = 5; + unsigned char switchStartStopPin = 3; + unsigned char switchLfPbPin = 2; #endif // ***** 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 int windowSize; unsigned long windowStartTime; unsigned long nextCheck; unsigned long nextRead; unsigned long updateLcd; -unsigned long timerSoak; +unsigned int nextStepTime; +unsigned int heldPeriod; unsigned long buzzerPeriod; unsigned char soakTemperatureMax; unsigned char reflowTemperatureMax; -unsigned long soakMicroPeriod; // Reflow oven controller state machine state variable reflowState_t reflowState; // Reflow oven controller status reflowStatus_t reflowStatus; // Reflow profile type -reflowProfile_t reflowProfile; +unsigned int reflowProfile; // Switch debounce state machine state variable debounceState_t debounceState; // Switch debounce timer @@ -295,38 +267,54 @@ switch_t switchMask; unsigned int timerSeconds; // Thermocouple fault status unsigned char fault; -#ifdef VERSION == 2 -unsigned int timerUpdate; -unsigned char temperature[SCREEN_WIDTH - X_AXIS_START]; -unsigned char x; +#if VERSION == 2 + unsigned int timerUpdate; + unsigned char temperature[SCREEN_WIDTH - X_AXIS_START]; + unsigned char x; #endif // PID control interface -PID reflowOvenPID(&input, &output, &setpoint, kp, ki, kd, DIRECT); +PID reflowOvenPID(&input, &output, &setpoint, 100, 0.025, 20, DIRECT); #if VERSION == 1 -// LCD interface -LiquidCrystal lcd(lcdRsPin, lcdEPin, lcdD4Pin, lcdD5Pin, lcdD6Pin, lcdD7Pin); + // LCD interface + LiquidCrystal lcd(lcdRsPin, lcdEPin, lcdD4Pin, lcdD5Pin, lcdD6Pin, lcdD7Pin); #elif VERSION == 2 -Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire); + Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire); #endif // MAX31856 thermocouple interface Adafruit_MAX31856 thermocouple = Adafruit_MAX31856(thermocoupleCSPin); + +switch_t readSwitch(void) +{ +#if VERSION == 1 + unsigned int switchAdcValue = 0; + // Analog multiplexing switch + switchAdcValue = analogRead(switchPin); + + // Add some allowance (+10 ADC step) as ADC reading might be off a little + // due to 3V3 deviation and also resistor value tolerance + if (switchAdcValue >= 1000) return SWITCH_NONE; + if (switchAdcValue <= 10) return SWITCH_1; + if (switchAdcValue <= 522) return SWITCH_2; + +#elif VERSION == 2 + // Switch connected directly to individual separate pins + if (digitalRead(switchStartStopPin) == LOW) return SWITCH_1; + if (digitalRead(switchLfPbPin) == LOW) return SWITCH_2; + +#endif + + return SWITCH_NONE; +} + + void setup() { // Check current selected reflow profile - unsigned char value = EEPROM.read(PROFILE_TYPE_ADDRESS); - if ((value == 0) || (value == 1)) - { - // Valid reflow profile value - reflowProfile = value; - } - else - { - // Default to lead-free profile - EEPROM.write(PROFILE_TYPE_ADDRESS, 0); - reflowProfile = REFLOW_PROFILE_LEADFREE; - } + reflowProfile = 0; + heldPeriod = 0; + nextStepTime = 0; // SSR pin initialization to ensure reflow oven is off digitalWrite(ssrPin, LOW); @@ -355,15 +343,16 @@ void setup() lcd.print(F(" Reflow ")); #elif VERSION == 2 oled.begin(SSD1306_SWITCHCAPVCC, 0x3C); + oled.clearDisplay(); // don't show adafruit splash oled.display(); #endif digitalWrite(buzzerPin, LOW); delay(2000); #if VERSION == 1 lcd.clear(); - lcd.print(F(" v1.00 ")); + lcd.print(F(" v2.50 ")); lcd.setCursor(0, 1); - lcd.print(F("26-07-17")); + lcd.print(F("18-10-20")); delay(2000); lcd.clear(); #elif VERSION == 2 @@ -374,11 +363,11 @@ void setup() oled.println(F(" Tiny Reflow")); oled.println(F(" Controller")); oled.println(); - oled.println(F(" v2.00")); + oled.println(F(" v2.50")); oled.println(); - oled.println(F(" 04-03-19")); + oled.println(F(" 18-10-2020")); oled.display(); - delay(3000); + delay(2000); oled.clearDisplay(); #endif @@ -397,6 +386,80 @@ void setup() updateLcd = millis(); } +// check stage state and process to next +void processStage( + boolean heat, + float tempSetpoint, // set temp for this reflow state + uint32_t stepPeriod, // microtime until next temp change + uint32_t holdPeriod, // total microtime to set max temp + int stepSize, // temp step size per micrtime period + float tempNextSetpoint, // temp setpoint of next reflow stage + reflowState_t nextReflowState, // next reflow state + float nextPidKp, // next reflow state PID KP + float nextPidKi, // next reflow state PID KI + float nextPidKd // next reflow state PID KD + ) +{ + + // Serial.print(F("heat: ")); + // Serial.println(heat); + // Serial.print(F("tempSetpoint: ")); + // Serial.println(tempSetpoint); + // Serial.print(F("Current Temp: ")); + // Serial.println(input); + // Serial.print(F("Actial Set Temp: ")); + // Serial.println(setpoint); + // Serial.print(F("stepPeriod: ")); + // Serial.println(stepPeriod); + // Serial.print(F("holdPeriod: ")); + // Serial.println(holdPeriod); + // Serial.print(F("heldPeriod: ")); + // Serial.println(heldPeriod); + // Serial.print(F("stepSize: ")); + // Serial.println(stepSize); + // Serial.print(F("tempNextSetpoint: ")); + // Serial.println(tempNextSetpoint); + // Serial.print(F("nextReflowState: ")); + // Serial.println(nextReflowState); + // Serial.println(F("--------------------------------")); + + + // have we reached the setpoint temp? + if ((input >= setpoint && heat == true) || (input <= setpoint && heat == false)) { + + // have we reached the next time point to adjust the temperatue? + if (millis() > nextStepTime) + { + // set the next time to adjust the temperature + nextStepTime = millis() + stepPeriod; + // check if temp has reached its final set point + if ((input >= tempSetpoint && heat == true) || (input <= tempSetpoint && heat == false)) + { + // increment held period + heldPeriod += stepPeriod; + + // if we reached the hold time move to next reflowstate + if (heldPeriod >= holdPeriod) { + // have we reached total hold period + heldPeriod = 0; + + nextStepTime = millis() + stepPeriod; + // Set less agressive PID parameters for next ramp + reflowOvenPID.SetTunings(nextPidKp, nextPidKi, nextPidKd); + // Ramp up to next temperature + setpoint = tempNextSetpoint; + // Proceed to next state + reflowState = nextReflowState; + } + } else { + // Increment micro setpoint + setpoint += stepSize; + } + } + } +} + + void loop() { // Current time @@ -447,7 +510,11 @@ void loop() Serial.print(F(",")); Serial.print(input); Serial.print(F(",")); - Serial.println(output); + Serial.print(output); + Serial.print(F(",")); + Serial.print(heldPeriod); + Serial.print(F(",")); + Serial.println(nextStepTime); } else { @@ -466,14 +533,9 @@ void loop() // Print current system state lcd.print(lcdMessagesReflowStatus[reflowState]); lcd.setCursor(6, 0); - if (reflowProfile == REFLOW_PROFILE_LEADFREE) - { - lcd.print(F("LF")); - } - else - { - lcd.print(F("PB")); - } + + strcpy_P(dispbuffer, (char *)pgm_read_word(&(lcdMessagesReflowStatus[reflowState]))); + lcd.print(dispbuffer); lcd.setCursor(0, 1); // If currently in error state @@ -499,18 +561,15 @@ void loop() oled.clearDisplay(); oled.setTextSize(2); oled.setCursor(0, 0); - oled.print(lcdMessagesReflowStatus[reflowState]); + + strcpy_P(dispbuffer, (char *)pgm_read_word(&(lcdMessagesReflowStatus[reflowState]))); + oled.print(dispbuffer); + oled.setTextSize(1); - oled.setCursor(115, 0); + oled.setCursor(72, 0); - if (reflowProfile == REFLOW_PROFILE_LEADFREE) - { - oled.print(F("LF")); - } - else - { - oled.print(F("PB")); - } + strcpy_P(dispbuffer, (char *)pgm_read_word(&(profileNames[reflowProfile]))); + oled.print(dispbuffer); // Temperature markers oled.setCursor(0, 18); @@ -586,7 +645,7 @@ void loop() if (switchStatus == SWITCH_1) { // Send header for CSV file - Serial.println(F("Time,Setpoint,Input,Output")); + Serial.println(F("Time,Setpoint,Input,Output,HeldP,NextStep")); // Intialize seconds timer for serial debug information timerSeconds = 0; @@ -604,21 +663,11 @@ void loop() // Initialize PID control window starting time windowStartTime = millis(); - // Ramp up to minimum soaking temperature - setpoint = TEMPERATURE_SOAK_MIN; - // Load profile specific constant - if (reflowProfile == REFLOW_PROFILE_LEADFREE) - { - soakTemperatureMax = TEMPERATURE_SOAK_MAX_LF; - reflowTemperatureMax = TEMPERATURE_REFLOW_MAX_LF; - soakMicroPeriod = SOAK_MICRO_PERIOD_LF; - } - else - { - soakTemperatureMax = TEMPERATURE_SOAK_MAX_PB; - reflowTemperatureMax = TEMPERATURE_REFLOW_MAX_PB; - soakMicroPeriod = SOAK_MICRO_PERIOD_PB; - } + + setpoint = TEMPERATURE_ROOM; + + reflowOvenPID.SetTunings(pgm_read_byte_near(profilePreHeatKP + reflowProfile), pgm_read_byte_near(profilePreHeatKI + reflowProfile), pgm_read_byte_near(profilePreHeatKD + reflowProfile)); + // Tell the PID to range between 0 and the full window size reflowOvenPID.SetOutputLimits(0, windowSize); reflowOvenPID.SetSampleTime(PID_SAMPLE_TIME); @@ -631,58 +680,78 @@ void loop() break; case REFLOW_STATE_PREHEAT: + reflowStatus = REFLOW_STATUS_ON; - // If minimum soak temperature is achieve - if (input >= TEMPERATURE_SOAK_MIN) - { - // Chop soaking period into smaller sub-period - timerSoak = millis() + soakMicroPeriod; - // 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; - } + + processStage( + true, + pgm_read_float_near(profilePreHeatTemps + reflowProfile), + pgm_read_dword_near(profilePreHeatMTime + reflowProfile), + pgm_read_dword_near(profilePreHeatHoldTime + reflowProfile), + pgm_read_byte_near(profilePreHeatTStep + reflowProfile), + pgm_read_float_near(profileSoakTemps + reflowProfile), + REFLOW_STATE_SOAK, + pgm_read_float_near(profileSoakKP + reflowProfile), + pgm_read_float_near(profileSoakKI + reflowProfile), + pgm_read_float_near(profileSoakKD + reflowProfile) + ); + break; case REFLOW_STATE_SOAK: - // If micro soak temperature is achieved - if (millis() > timerSoak) - { - timerSoak = millis() + soakMicroPeriod; - // Increment micro setpoint - setpoint += SOAK_TEMPERATURE_STEP; - if (setpoint > soakTemperatureMax) - { - // 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 = reflowTemperatureMax; - // Proceed to reflowing state - reflowState = REFLOW_STATE_REFLOW; - } - } + + processStage( + true, + pgm_read_float_near(profileSoakTemps + reflowProfile), + pgm_read_dword_near(profileSoakMTime + reflowProfile), + pgm_read_dword_near(profileSoakHoldTime + reflowProfile), + pgm_read_byte_near(profileSoakTStep + reflowProfile), + pgm_read_float_near(profileReflowTemps + reflowProfile), + REFLOW_STATE_REFLOW, + pgm_read_float_near(profileReflowKP + reflowProfile), + pgm_read_float_near(profileReflowKI + reflowProfile), + pgm_read_float_near(profileReflowKD + reflowProfile) + ); + 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 >= (reflowTemperatureMax - 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; - } + + processStage( + true, + pgm_read_float_near(profileReflowTemps + reflowProfile), + pgm_read_dword_near(profileReflowMTime + reflowProfile), + pgm_read_dword_near(profileReflowHoldTime + reflowProfile), + pgm_read_byte_near(profileReflowTStep + reflowProfile), + pgm_read_float_near(profileCoolDownTemps + reflowProfile), + REFLOW_STATE_COOL, + pgm_read_float_near(profileReflowKP + reflowProfile), + pgm_read_float_near(profileReflowKI + reflowProfile), + pgm_read_float_near(profileReflowKD + reflowProfile) + ); + break; case REFLOW_STATE_COOL: - // If minimum cool temperature is achieve - if (input <= TEMPERATURE_COOL_MIN) - { + + processStage( + false, + pgm_read_float_near(profileCoolDownTemps + reflowProfile), + pgm_read_dword_near(profileCoolDownMTime + reflowProfile), + pgm_read_dword_near(profileCoolDownHoldTime + reflowProfile), + pgm_read_byte_near(profileCoolDownTStep + reflowProfile), + (double) TEMPERATURE_ROOM, + REFLOW_STATE_COOL_COMPLETE, + pgm_read_float_near(profileReflowKP + reflowProfile), + pgm_read_float_near(profileReflowKI + reflowProfile), + pgm_read_float_near(profileReflowKD + reflowProfile) + ); + + break; + + case REFLOW_STATE_COOL_COMPLETE: // Retrieve current time for buzzer usage buzzerPeriod = millis() + 1000; // Turn on buzzer to indicate completion @@ -691,7 +760,6 @@ void loop() reflowStatus = REFLOW_STATUS_OFF; // Proceed to reflow Completion state reflowState = REFLOW_STATE_COMPLETE; - } break; case REFLOW_STATE_COMPLETE: @@ -757,20 +825,11 @@ void loop() // Only can switch reflow profile during idle if (reflowState == REFLOW_STATE_IDLE) { - // Currently using lead-free reflow profile - if (reflowProfile == REFLOW_PROFILE_LEADFREE) - { - // Switch to leaded reflow profile - reflowProfile = REFLOW_PROFILE_LEADED; - EEPROM.write(PROFILE_TYPE_ADDRESS, 1); - } - // Currently using leaded reflow profile - else - { - // Switch to lead-free profile - reflowProfile = REFLOW_PROFILE_LEADFREE; - EEPROM.write(PROFILE_TYPE_ADDRESS, 0); - } + if (reflowProfile >= (sizeof(profileNames) / sizeof(profileNames[0])) - 1) { + reflowProfile = 0; + } else { + reflowProfile++; + } } } // Switch status has been read @@ -849,26 +908,3 @@ void loop() digitalWrite(ssrPin, LOW); } } - -switch_t readSwitch(void) -{ - int switchAdcValue = 0; -#if VERSION == 1 - // Analog multiplexing switch - switchAdcValue = analogRead(switchPin); - - // Add some allowance (+10 ADC step) as ADC reading might be off a little - // due to 3V3 deviation and also resistor value tolerance - if (switchAdcValue >= 1000) return SWITCH_NONE; - if (switchAdcValue <= 10) return SWITCH_1; - if (switchAdcValue <= 522) return SWITCH_2; - -#elif VERSION == 2 - // Switch connected directly to individual separate pins - if (digitalRead(switchStartStopPin) == LOW) return SWITCH_1; - if (digitalRead(switchLfPbPin) == LOW) return SWITCH_2; - -#endif - - return SWITCH_NONE; -} diff --git a/src/profiles.h b/src/profiles.h new file mode 100644 index 0000000..290d0d9 --- /dev/null +++ b/src/profiles.h @@ -0,0 +1,24 @@ +#ifndef PROFILES_H +#define PROFILES_H + + + +// ***** GENERAL PROFILE CONSTANTS ***** +#define PROFILE_TYPE_ADDRESS 0 +#define TEMPERATURE_ROOM 50 +#define TEMPERATURE_SOAK_MIN 150 +#define TEMPERATURE_COOL_MIN 100 +#define SENSOR_SAMPLING_TIME 1000 +#define SOAK_TEMPERATURE_STEP 5 + +// ***** LEAD FREE PROFILE CONSTANTS ***** +#define TEMPERATURE_SOAK_MAX_LF 200 +#define TEMPERATURE_REFLOW_MAX_LF 250 +#define SOAK_MICRO_PERIOD_LF 9000 + +// ***** LEADED PROFILE CONSTANTS ***** +#define TEMPERATURE_SOAK_MAX_PB 180 +#define TEMPERATURE_REFLOW_MAX_PB 224 +#define SOAK_MICRO_PERIOD_PB 10000 + +#endif \ No newline at end of file diff --git a/test/README b/test/README new file mode 100644 index 0000000..b94d089 --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html From 45df2eb8545338086ab4a070d924fbdc664a5699 Mon Sep 17 00:00:00 2001 From: Stefan Schueller Date: Sun, 25 Oct 2020 00:35:56 +0200 Subject: [PATCH 2/2] Cleanup --- src/profiles.h | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 src/profiles.h diff --git a/src/profiles.h b/src/profiles.h deleted file mode 100644 index 290d0d9..0000000 --- a/src/profiles.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef PROFILES_H -#define PROFILES_H - - - -// ***** GENERAL PROFILE CONSTANTS ***** -#define PROFILE_TYPE_ADDRESS 0 -#define TEMPERATURE_ROOM 50 -#define TEMPERATURE_SOAK_MIN 150 -#define TEMPERATURE_COOL_MIN 100 -#define SENSOR_SAMPLING_TIME 1000 -#define SOAK_TEMPERATURE_STEP 5 - -// ***** LEAD FREE PROFILE CONSTANTS ***** -#define TEMPERATURE_SOAK_MAX_LF 200 -#define TEMPERATURE_REFLOW_MAX_LF 250 -#define SOAK_MICRO_PERIOD_LF 9000 - -// ***** LEADED PROFILE CONSTANTS ***** -#define TEMPERATURE_SOAK_MAX_PB 180 -#define TEMPERATURE_REFLOW_MAX_PB 224 -#define SOAK_MICRO_PERIOD_PB 10000 - -#endif \ No newline at end of file