diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..80471fb --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.csv diff=localizablestrings diff --git a/Board Versions/70mm by 50mm Ver2.4 ATmega328p/Board Files/BOM_SRP 70_50mm_Release_2022-02-03.csv b/Board Versions/70mm by 50mm Ver2.4 ATmega328p/Board Files/BOM_SRP 70_50mm_Release_2022-02-03.csv index ffa9450..a63dc5e 100644 Binary files a/Board Versions/70mm by 50mm Ver2.4 ATmega328p/Board Files/BOM_SRP 70_50mm_Release_2022-02-03.csv and b/Board Versions/70mm by 50mm Ver2.4 ATmega328p/Board Files/BOM_SRP 70_50mm_Release_2022-02-03.csv differ diff --git a/Board Versions/70mm by 50mm Ver2.4 ATmega328p/HOW-TO - Programming the Board.md b/Board Versions/70mm by 50mm Ver2.4 ATmega328p/HOW-TO - Programming the Board.md index bba2204..429c28f 100644 --- a/Board Versions/70mm by 50mm Ver2.4 ATmega328p/HOW-TO - Programming the Board.md +++ b/Board Versions/70mm by 50mm Ver2.4 ATmega328p/HOW-TO - Programming the Board.md @@ -23,4 +23,8 @@ https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json - Bootloader -> No bootloader 3) Set the programmer of your choice, e.g. 'Arduino as ISP (MiniCore)', 'USB ASP', etc, and set the correct port. 4) Burn bootloader to the Solder Reflow Board. This sets fuses and registers correctly so that the sketch needs not directly deal with them. -5) Compile and upload to the Solder Reflow Board. \ No newline at end of file +5) Compile and upload to the Solder Reflow Board. + +### PWM Frequency + +By default, the PWM control of the heating element operates at the default PWM frequency used by Arduinos of around 490Hz. This can be increased to roughly 63kHz by uncommenting the definition of the FAST_PWM macro. Note that with current hardware designs, this will likely result in overheating of the input capacitor. The circuit requires redesign to correct this fault. If FAST_PWM is enabled, this will also modify the messages on the screen to remind the user that the input capacitor may get hot. diff --git a/Board Versions/70mm by 50mm Ver2.4 ATmega328p/Software/SW1.0_HW2.4_70by50mm/SW1.0_HW2.4_70by50mm.ino b/Board Versions/70mm by 50mm Ver2.4 ATmega328p/Software/SW1.0_HW2.4_70by50mm/SW1.0_HW2.4_70by50mm.ino index a789bb9..46307ee 100644 --- a/Board Versions/70mm by 50mm Ver2.4 ATmega328p/Software/SW1.0_HW2.4_70by50mm/SW1.0_HW2.4_70by50mm.ino +++ b/Board Versions/70mm by 50mm Ver2.4 ATmega328p/Software/SW1.0_HW2.4_70by50mm/SW1.0_HW2.4_70by50mm.ino @@ -29,6 +29,27 @@ #include #include +/** + * Uncomment the following line to use Fast PWM - around 63kHz. + * Leave it commented out to use default PWM frequency - around 490Hz. + * Note that current designs induce high ripple current in the input capacitor. + * High frequency operation is desirable, but until the control circuitry is updated, + * high frequency operation may cause it to get very hot and possibly fail. Low frequency + * operation avoids this problem, but will cause audible sound from the hotplate and tax + * the power supply more than is desirable. + */ +//#define FAST_PWM + +/** + * Alter messages on screen to make it clear when FAST_PWM is enabled, which may cause + * a hot input capacitor. + */ +#ifdef FAST_PWM +#define HEATING_MSG "Hot Input Cap" +#else +#define HEATING_MSG "Begin Heating" +#endif + //Version Definitions static const PROGMEM float hw = 2.4; static const PROGMEM float sw = 1.0; @@ -145,8 +166,10 @@ void setup() { maxTempIndex = EEPROM.read(tempIndexAddr) % sizeof(maxTempArray); //Enable Fast PWM with no prescaler +#ifdef FAST_PWM TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); TCCR2B = _BV(CS20); +#endif //Start-up Diplay display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS); @@ -219,7 +242,7 @@ void main_menu() { display.print(F("HOLD BUTTONS")); display.drawLine( 3, 12, 79, 12, SSD1306_WHITE ); display.setCursor(3,18); - display.print(F("Begin Heating")); + display.print(F(HEATING_MSG)); } x = ( x + 1 ) % y; //Display change increment and modulus diff --git a/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Board Files/BOM_SRP 70_50mm_Release_2022-03-04-digikey.csv b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Board Files/BOM_SRP 70_50mm_Release_2022-03-04-digikey.csv new file mode 100644 index 0000000..56479e5 Binary files /dev/null and b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Board Files/BOM_SRP 70_50mm_Release_2022-03-04-digikey.csv differ diff --git a/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Board Files/BOM_SRP 70_50mm_Release_2022-03-04.csv b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Board Files/BOM_SRP 70_50mm_Release_2022-03-04.csv index 6a15112..60d76bc 100644 Binary files a/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Board Files/BOM_SRP 70_50mm_Release_2022-03-04.csv and b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Board Files/BOM_SRP 70_50mm_Release_2022-03-04.csv differ diff --git a/Board Versions/70mm by 50mm Ver3.0 ATmega4809/HOW-TO - Build the Stock Board.md b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/HOW-TO - Build the Stock Board.md index e6402e2..2022bec 100644 --- a/Board Versions/70mm by 50mm Ver3.0 ATmega4809/HOW-TO - Build the Stock Board.md +++ b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/HOW-TO - Build the Stock Board.md @@ -5,6 +5,10 @@ Building this solder reflow plate is a intermediate level task. While not overly complicated it still features many small surface mount components and a few polarity sensitive components. Future versions of the board are being developed to make home building easier to accomplish. +## WARNING!!! + +This design lacks safety features to limit the amount of power it may draw or the temperature it may reach and there are other issues with the electrical design. With a suitable power supply and as long as the software doesn't have any major bugs, it can be operated without issue but there is a real risk that it could start a fire in the event of a software bug or other fault. Do not leave it unsupervised while connected to power. + #### Preparations Firstly, download the Gerber files and Bill of Materials. While you are there, if you download the Pick and Place Doc you can have select board manufacturers populate the boards for you, normally at extra cost. @@ -20,7 +24,7 @@ Order as many boards as you like ensuring you order the materials too. Delivery from China nrormally takes between 2 and 6 weeks. Some other bits to consider -- You will need to buy a 0.91" OLED seperately. Ebay is normally good for this. Make sure to get the 4 pin I2C version. +- You will need to buy a 0.91" OLED seperately. Ebay or Amazon are normally good for this. Make sure to get the 4 pin I2C version. - You will need a 12V power supply. Minimum of 5A (take a lot of power to heat to 180C). An enclosed power brick with a 2.5mm inner diameter barrel jack is a good option. Or you can rig one yourself from an open supply like [these](https://www.ebay.co.uk/itm/164636015985?_trkparms=ispr%3D1&hash=item2655123d71:g:0~EAAOSwWe9f-qaI&amdata=enc%3AAQAGAAACkPYe5NmHp%252B2JMhMi7yxGiTJkPrKr5t53CooMSQt2orsSLY2M1Gjmuwt9c03vWNfiRs%252FQ%252FM%252BYAJ6j8WnNhVqBTnBTru6OB86J8pc%252FYfL%252FNaBizpiin5VQ2FRoMM2xlSMmLikPq1Kfo827DnvZ98oP5KQz5lhOmHCrLavgEdachmpNk6IFLLp0VfjgkVc%252Fs%252B%252BX8KFBqiDdz4rX9wcFb7PwH1fO8ZEtIwpVbAxrW3%252FafmJJ18bdW%252BrzPZTBljdLcVAzgt7L33U2%252BnDSJ5JRD%252BA%252FmCWPD5Ah6XsDLI%252BsRJa7Xu6sBtNsFRM2CBmXp9DI6UX8qZYagrwBZa%252FjGHZTInWGRK3dJPABW%252Beq5G3GBKLwihaUJqCC5VI3fRwt%252B4pYKBpKseUG0vriRotickOTQR46RbQNNKgE4Wmf0QthOdwjOadBEksewf0Sqfs8FhBQd5ILciZSYxv%252F9MTtMLWLLqJaqGC7vd09YHPBfKJxCdZ3O0yACOYApZvqe1qnKExBBOneiSwT9%252BcrHj2LbBg53rFOsAVowVYD3uUypZ2x8WsQAM06zeZe6LoYHAKAfjmte4DfzaamhbOEAo%252FGx2hSSPkfUC8cGohhcl%252BUBomTqERhc9gly0pHWbekyhBpsr0flCOde9DuiSv3GefdP2yGA3%252FG6q34VpSfsxQUoaMNcuMXBKjUssQpRn3PitZj1Ipbor7HEPB8q3%252B8qAmTxWw5V1EUYUShj95m58kDRc9oVv3eEyryFRcMXJjavWD0leQ%252FEekao2hEheLD1U3thR%252B61JfoOMSXatZ0bMyf7NaTVmPFyDvA8AKqjWJ2jxogJ2asMWqSMCzpT92CwMjXS4NQ%252FLzdmxXwQ%252B77K20%252F9Tx%252BA2awmW1x%7Cclp%3A2334524%7Ctkp%3ABFBMmpvD9tdf), and a 2.5mm diameter barrel jack adapter. Just be careful as you will be dealing with mains (Live and Neutral) wiring so only do so if you are competent and confident. - If you picked up a stencil make sure to get some solder paste too. - Finally, some small hardware is good. The board has holes just bigger than M3 so standard motherboard stand-offs and similar should fit. The board will function without but lifting it off the desk is best. @@ -34,7 +38,8 @@ Follow the following rough guidance to get you on your way. - Carefully remove the stencil and clean it. - Starting with the smaller components, gently place them onto the board following the circuit drawing. - If you have a working solder reflow board you can now reflow your working board (if any someone would develop one). -- If not, use a fine pointed soldering iron to dab solder the smaller components. +- If you have a decent lab power supply that can output 5A or better and a spare board, you could power one of your spare boards directly by attaching to the large pad of the MOSFET (the drain pad) and the lower pad of D2 (it's cathode pad). This is relatively easy if you solder some wires to those pads. Use current limiting to control heating. Slowly and cautiously increase the heat until you see the solder paste start to activate and melt. If you have a multimeter with a thermocouple or a thermal imager, some test runs to see the temperature at different current levels is advisable. Somewhere around 3-5A will probably be enough. +- If that sounds too crazy/dangerous, use a fine pointed soldering iron to dab solder the smaller components. - More heat will be needed to solder the larger components, especially the large tab of the MOSFET. - Check for good solder joints and that there are no shorts, especially around the microcontroller. - Move onto the through-hole components. The switches need to be checked for polarity before fitting else they will confuse the software on first start-up. Fit them with the notch pointing towards the OLED. @@ -44,4 +49,4 @@ Follow the following rough guidance to get you on your way. #### Finishing up Congratulations! You've soldered a thing that will definitely maybe work on the first try! Give the board a clean with some cleaning solvent or cleaning alcohol. -You can now move onto the programming of the board so open up that document and get cracking. \ No newline at end of file +You can now move onto the programming of the board so open up that document and get cracking. diff --git a/Board Versions/70mm by 50mm Ver3.0 ATmega4809/HOW-TO - Programming the Board.md b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/HOW-TO - Programming the Board.md index 14203f4..2b456b4 100644 --- a/Board Versions/70mm by 50mm Ver3.0 ATmega4809/HOW-TO - Programming the Board.md +++ b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/HOW-TO - Programming the Board.md @@ -3,10 +3,42 @@ ## How-To - Programming the Board This Solder Reflow Plate has been specifically designed to be Arduino based and easily programmed through the Arduino IDE or any other similar environment. For ease, here is a guide to programming the board via the Arduino IDE. -The ATmega4809 is UPDI programmed. Once the boards arrive and I have experienced this myself I will write up a full guide. In the meantime there are a few good guides out there on UPDI programming from an Arduino. +The ATmega4809 is UPDI programmed so you will need a UPDI programmer. If you are harvesting your ATMega4809 from an Arduino Nano Every or other Arduino board, you may be tempted to try to program it whilst still on the source board before transferring it. This is not recommended and will likely end up loading firmware that does not work. You shouldn't break anything. You'll just end up having to rebuild and program on the real board using UPDI. ### Preparation -TBC +1) Download and install the Arduino IDE from the [Arduino Website](https://www.arduino.cc/). The sketch was originally developed on version 1.8.19, though any recent and all future versions of the Arduino IDE should be fully supported. +2) Install the [MegaCoreX](https://github.com/MCUdude/MegaCoreX) additional boards to allow programming of bare Atmega4809 and similar microcontrollers. Follow the instructions on the [MegaCoreX repository](https://github.com/MCUdude/MegaCoreX) +3) Add the boards to the board manager by searching for and installing MegaCoreX in 'Tools->Board->Board Manager'. +4) Search for and install the Bounce2, Adafruit_GFX and Adafruit_SSD1306 libraries in 'Tools->Manage Libraries'. +5) Obtain a UPDI programmer. If you don't know what that is or you don't have one, your easiest option is probably to use an Arduino board with the [JTAG2UPDI](https://github.com/ElTangas/jtag2updi) sketch loaded onto it. + +### UPDI Programming with JTAG2UPDI +If you already have a purpose built UPDI programmer and know how to use it, you can skip this section and just use your existing UPDI programmer. For the rest of us, if you have a spare Arduino board lying around, you can program it to play the role of a UPDI programmer. I used an Arduino Nano, but many other Arduino compatible boards should also work. Note that if you are using an Arduino board you need to disable the autoreset feature when using it as a programmer (ie. not during the initial programming with the JTAG2UPDI sketch, but after that). There are two main ways to do this, both of which aim to prevent the reset pin from being pulled high. Option 1, which is the option I used, is to place a large capacitance (around 10uF or bigger) between the ground and reset pins. Option 2 is to place a resistor less than 1k between reset and ground - something like 330 ohms might work although I haven't tried this option. +1) Download the [JTAG2UPDI](https://github.com/ElTangas/jtag2updi) code from Github. +2) Rename the source directory to jtag2updi to make the Arduino IDE happy. +3) Load the jtag2updi/jtag2updi.ino sketch into your Arduino IDE. +4) Connect your Arduino board via USB. +5) Select the appropriate board type via the Tools->Board menu item. +6) Select the appropriate port for you UPDI programmer Arduino board. +7) If you're using a capacitor or resistor to disable the reset, *DO NOT* have this in place yet. You won't be able to load the JTAG2UPDI sketch with that in place. +8) Compile and upload the sketch. +9) Connect your capacitor between the reset and ground pins now. +10) Connect a 4.7k resistor to the PD6 pin so it's ready to connect when you're ready to program. +You should now have a UPDI programmer ready to go. ### Program -TBC \ No newline at end of file +1) Connect your UPDI programmer to the UPDI pins on the Solder Reflow board - the 3 pin header on the right side of the board. You need to connect the top pin to ground and the centre pin to the UPDI pin on your programmer (PD6 is using JTAG2UPDI). If using JTAG2UPDI, make sure you have 4.7k of resistance between the PD6 and UPDI pins. +2) You need to provide power to the Atmega4809 in order to program it. You have two options. You can connect 12V to the DC connector on the board and the 5V LDO will supply power to the MCU. Alternatively, you can connect the 5V pin on the 3-pin UPDI header to 5V on your UPDI programmer. This will also supply power to the MCU. Pick one. Don't do both. +3) Select the following settings under the Tools menu: +- Board->MegaCoreX->Atmega4809 +- Clock->Internal 16MHz +- BOD->BOD 2.6V +- EEPROM->EEPROM retained +- Pinout->48 pin Standard +- Reset Pin->Reset +- Bootloader->No bootloader +4) Set the programmer of your choice. eg. JTAG2UPDI, Atmel ICE, etc +5) Compile and upload. + +### PWM Frequency +By default, the PWM control of the heating element operates at the default PWM frequency used by Arduinos of around 490Hz. This can be increased to roughly 63kHz by uncommenting the definition of the FAST_PWM macro. Note that with current hardware designs, this will likely result in overheating of the input capacitor. The circuit requires redesign to correct this fault. If FAST_PWM is enabled, this will also modify the messages on the screen to remind the user that the input capacitor may get hot. diff --git a/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Software/README.md b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Software/README.md new file mode 100644 index 0000000..ab94b6a --- /dev/null +++ b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Software/README.md @@ -0,0 +1,46 @@ +# **Software Revisions** +###### 70*50mm Solder Reflow plate + +## Note +This software is barely functional. It was not written by me nor would I consider it actively maintained by anybody. The original developer appears to have abandoned the project. + +I am working on new designs to address many of the hardware and software design issues. In the meantime, this design can work with some limitations. Specifically: + + - It's a little slow. + - It's not well suited for anything other than low temperature solder alloys (ie. SnBi alloys that melt around 140 celsius). + - The temperature measurements that it gives are wildly inaccurate. + - It won't follow a solder profile. It basically just heats up until it hits something it thinks is the requested maximum temperature and then shuts off power to the hotplate. + +## User Interface + +Use the buttons to adjust maximum temperature up and down in 10 degree increments. + +Press both buttons together to start the reflow cycle. + +## Operational Explanation + +The logic used to drive the heating algorithm is fundamentally flawed if the goal is to follow some kind of reflow profile. + + - It doesn't consider time while the heating cycle is running, so how can it know what temperature is should be targeting at any given point in the reflow cycle. + - It does vary the PWM duty cycle during the heating cycle, but from the logic all it really does it: + - Quickly ramp up the PWM duty cycle to a "warm-up" value. + - Once the reported temperature reaches a warm-up value, quickly ramps up the PWM duty cycle to a maximum duty cycle value. + - Once the reported temperature reaches the maximum temperature requested, shuts off power to the heating element. + - The reported temperature continues to be monitored until the reported temperature falls below 45 celsius. + +## Potential Improvement Areas + +### Follow an actual reflow profile. + +There are designs out there that already do this, but I've not seen any firmware shared to do this. This would require a control method that understands how much time has passed from the beginning of the reflow cycle, can calculate the expected temperature at that time and produce a control signal to closely follow that expected temperature. PID control is probably the most appropriate method to do this, although there are other possible approaches. + +### PID Control with Autotuning + +PID control is relatively simple to implement, but how well it works is highly dependent on the proportional, integral and differential gains used. An auto-tuning cycle using some common auto-tuning algorithm like Ziegler-Nichols would be desirable so that users can relatively easily arrive at a reaonable working set of gains for their hotplate. + +### Reflow profile customization + +Once you have PID control and auto-tuning, you can follow a reflow profile provided that the device has sufficient power to keep up. The reflow profiles should be able to be customized. The simplest way would be to provide a relatively straightforward means of defining the reflow profile in the code and simply let users upload new firmware to set up a new profile. Whether it's possible to provide customization of reflow profiles via the two-button UI is dubious. While it could definitely be implemented, whether this can be done in a way that's usable enough to justify the effort is questionable. + +A more likely option may be to define several different hard-coded profiles in the firmware and provide a simple UI to select on of several reflow profiles instead of the current UI which allows selection of one of several maximum temperature settings. + diff --git a/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Software/Revisions.md b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Software/Revisions.md deleted file mode 100644 index 7126fa1..0000000 --- a/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Software/Revisions.md +++ /dev/null @@ -1,52 +0,0 @@ -# **Software Revisions** -###### 70*50mm Solder Reflow plate - -## Note -Software not yet complete for this board version. I have several boards on the way, due late March. Software should take a day or two to convert from the original HW Ver2.4 design. It will have all the same feature-set and should be indistinguishable from the original design. - -## S/W Rev 1.0 -###### H/W Rev 3.0 -This is the first complete software revision and has been developed and finalised for hardware version 2.4. The user interface and feature scope of this project was large for the size of board. This initial release contains the following main pages and features... - -#### Start-up (contained within setup() function) -- Duration 3 seconds -- Displays Logo -- Displays S/W and H/W versions - -#### Main Menu -- Swap display on the left explains user interface -- Temperature and Board Thickness data on the right -- Available temperatures are 140C, 150C, 160C, 170C, 180C, 190C, 200C -- Available thicknesses are 0.4mm, 0.6mm, 0.8mm, 1.0mm, 1.2mm, 1.6mm, 2.0mm -- Push individual buttons to cycle through settings -- Setting saved to EEPROM and loaded from EEPROM on start-up -- Hold both buttons for 100ms, then release, to enter heating mode - -#### Heating -- Pauses for 2 seconds before enabling MOSFET, during which time it displays the maximum temperature and board thickness the user has selected -- Displays current input voltage and plate temperature -- Voltage and temperature readings are averaged from 20 consequtive samples -- Heating animation -- Heating process follows the industry standard heating profile, climbing slowly to 75% of the maximum temperature, briefly peaking to the maximum temperature, then beginning cooldown -- PWM value will be held lower if the input voltage falls below a minimum voltage (10.5V) -- Once the plate temperature reaches the user specified maximum this temperature will be held for the board thickness in mm multiplied for 5 seconds. E.g. 2.0mm thickness will be held at peak temp for 10s to allow the peak temp to propogate throughout the board -- If process is not complete within 8 minutes the heating process is cancelled due to 'time out' -- Process can be cancelled by pressing any button - -#### Cool Down -- Heating completion triggers cool down screen -- Shows current temperature -- Screen will automatically show completed screen if temperature falls below minimum value (45C) - -#### Completed -- Shows that the heating process is complete -- Board now cool enough to handle - -#### Cancelled (User Button Pressed) -- Occurs when button pressed during heating process -- Press any button to return to main menu - -#### Cancelled (Time Out) -- Occurs when heating process takes longer than 5 minutes to complete -- Press any button to return to main menu -- Suggests using a power supply with a higher maximum current \ No newline at end of file diff --git a/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Software/SW1.0_HW3.0_70by50mm/SW1.0_HW3.0_70by50mm.ino b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Software/SW1.0_HW3.0_70by50mm/SW1.0_HW3.0_70by50mm.ino new file mode 100644 index 0000000..804bf2b --- /dev/null +++ b/Board Versions/70mm by 50mm Ver3.0 ATmega4809/Software/SW1.0_HW3.0_70by50mm/SW1.0_HW3.0_70by50mm.ino @@ -0,0 +1,519 @@ + /* Solder Reflow Plate Sketch + * H/W - Ver 3.0 + * S/W - Ver 1.0 + * by Chris Halsall */ + +/* To prepare + * 1) Install MegaCoreX via Board Manager; See https://github.com/MCUdude/MegaCoreX + * 2) Install Bounce2, Adafruit_GFX and Adafruit_SSD1306 libraries (Tools->Manage Libraries) + * 3) Have a UPDI programmer. eg. Arduino Nano with JTAG2UPDI loaded - https://github.com/ElTangas/jtag2updi + */ + +/* To program + * 1) Select the following settings under (Tools) + * Board->MegaCoreX->Atmega4809 + * Clock->Internal 16MHz + * BOD->BOD 2.6V + * EEPROM->EEPROM retained + * Pinout->48 pin Standard + * Reset Pin->Reset + * Bootloader->No bootloader + * 2) Set programmer of choice, e.g.'JTAG2UPDI', 'Atmel ICE', etc, and set correct port. + * 4) Compile and upload + */ + +#include +#include +#include +#include +#include + +/** + * Uncomment the following line to use Fast PWM - around 63kHz. + * Leave it commented out to use default PWM frequency - around 490Hz. + * Note that current designs induce high ripple current in the input capacitor. + * High frequency operation is desirable, but until the control circuitry is updated, + * high frequency operation may cause it to get very hot and possibly fail. Low frequency + * operation avoids this problem, but will cause audible sound from the hotplate and tax + * the power supply more than is desirable. + */ +//#define FAST_PWM + +/** + * Alter messages on screen to make it clear when FAST_PWM is enabled, which may cause + * a hot input capacitor. + */ +#ifdef FAST_PWM +#define HEATING_MSG "Hot Input Cap" +#else +#define HEATING_MSG "Begin Heating" +#endif + +//Version Definitions +static const PROGMEM float hw = 3.0; +static const PROGMEM float sw = 1.0; + +//Screen Definitions +#define SCREEN_WIDTH 128 +#define SCREEN_HEIGHT 32 +#define SCREEN_ADDRESS 0x3C //I2C Address +Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); //Create Display + +//Pin Definitions +#define mosfet PIN_PC3 +#define upsw PIN_PD1 +#define dnsw PIN_PD0 +#define temp PIN_PF5 +#define vcc PIN_PF3 + +Bounce2::Button upButton; +Bounce2::Button downButton; + +//Temperature Info +byte maxTempArray[] = { 140, 150, 160, 170, 180, 190, 200, 210, 220 }; +byte maxTempIndex = 0; +byte tempIndexAddr = 1; + +//Voltage Measurement Info +float vConvert = 52.00; +float vMin = 10.50; + +//Solder Reflow Plate Logo +static const uint8_t PROGMEM logo[] = { + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x31, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0xe0, 0x03, 0x01, 0x80, 0x00, 0x00, 0x30, 0x70, 0x00, 0x21, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x20, 0x03, 0x00, 0xc7, 0x80, 0x00, 0x20, 0x18, 0xf0, 0x61, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x03, 0x3e, 0xcc, 0xc0, 0xc0, 0x04, 0x19, 0x98, 0x61, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x1c, 0x01, 0xf3, 0x77, 0xd8, 0xc7, 0xe0, 0x06, 0x33, 0x18, 0x61, 0x8f, 0x88, 0x00, 0x00, 0x00, + 0x06, 0x03, 0x3b, 0x61, 0xd0, 0xc6, 0x00, 0x07, 0xe2, 0x18, 0x61, 0x98, 0xd8, 0x04, 0x00, 0x00, + 0x01, 0xc6, 0x0b, 0x60, 0xd9, 0x86, 0x00, 0x06, 0x03, 0x30, 0xff, 0xb0, 0x78, 0x66, 0x00, 0x00, + 0x40, 0xe4, 0x0f, 0x60, 0xdf, 0x06, 0x00, 0x07, 0x03, 0xe0, 0x31, 0xe0, 0x78, 0x62, 0x00, 0x00, + 0x40, 0x3c, 0x0f, 0x61, 0xd8, 0x06, 0x00, 0x07, 0x83, 0x00, 0x31, 0xe0, 0x78, 0x63, 0x00, 0x00, + 0x60, 0x36, 0x1b, 0x63, 0xc8, 0x02, 0x00, 0x02, 0xc1, 0x00, 0x18, 0xb0, 0xcc, 0xe2, 0x00, 0x00, + 0x30, 0x33, 0x3b, 0x36, 0x4e, 0x03, 0x00, 0x02, 0x61, 0xc0, 0x0c, 0x99, 0xcd, 0xfe, 0x00, 0x00, + 0x0f, 0xe1, 0xe1, 0x3c, 0x03, 0xf3, 0x00, 0x02, 0x38, 0x7e, 0x0c, 0x8f, 0x07, 0x9c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x84, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xe4, 0x00, 0x18, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x3c, 0x3c, 0x18, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x1e, 0x06, 0x7f, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x3e, 0x03, 0x18, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x36, 0x7f, 0x19, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xe6, 0xc7, 0x19, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x07, 0x83, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x07, 0x81, 0x18, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x06, 0xc3, 0x98, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x04, 0x7e, 0x08, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const uint8_t logo_width = 128; +static const uint8_t logo_height = 27; + +//Heating Animation +static const uint8_t PROGMEM heat_animate[] = { + 0b00000001, 0b00000000, + 0b00000001, 0b10000000, + 0b00000001, 0b10000000, + 0b00000001, 0b01000000, + 0b00000010, 0b01000000, + 0b00100010, 0b01000100, + 0b00100100, 0b00100100, + 0b01010101, 0b00100110, + 0b01001001, 0b10010110, + 0b10000010, 0b10001001, + 0b10100100, 0b01000001, + 0b10011000, 0b01010010, + 0b01000100, 0b01100010, + 0b00100011, 0b10000100, + 0b00011000, 0b00011000, + 0b00000111, 0b11100000 +}; +static const uint8_t heat_animate_width = 16; +static const uint8_t heat_animate_height = 16; + +//Tick +static const uint8_t PROGMEM tick[] = { + 0b00000000, 0b00000100, + 0b00000000, 0b00001010, + 0b00000000, 0b00010101, + 0b00000000, 0b00101010, + 0b00000000, 0b01010100, + 0b00000000, 0b10101000, + 0b00000001, 0b01010000, + 0b00100010, 0b10100000, + 0b01010101, 0b01000000, + 0b10101010, 0b10000000, + 0b01010101, 0b00000000, + 0b00101010, 0b00000000, + 0b00010100, 0b00000000, + 0b00001000, 0b00000000, + 0b01111111, 0b11100000 +}; +static const uint8_t tick_width = 16; +static const uint8_t tick_height = 15; + +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 +#ifdef FAST_PWM + TCA0.SPLIT.CTRLA = TCA_SPLIT_ENABLE_bm; +#endif + + //Start-up Diplay + display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS); + display.clearDisplay(); + display.setTextSize(1); + display.setTextColor(SSD1306_WHITE); + display.setCursor(0,0); + display.drawBitmap(0, 0, logo, logo_width, logo_height, SSD1306_WHITE); + display.setCursor(80,16); + display.print(F("S/W V")); + display.print(sw, 1); + display.setCursor(80,24); + display.print(F("H/W V")); + display.print(hw, 1); + display.display(); + delay(3000); + + //Go to main menu + main_menu(); +} + +void main_menu() { + + int x = 0; //Display change counter + int y = 200; //Display change max (modulused below) + while(1) { + upButton.update(); + downButton.update(); + analogWrite(mosfet,0); //Ensure MOSFET off + display.clearDisplay(); + display.setTextSize(1); + display.drawRoundRect( 0, 0, 83, 32, 2, SSD1306_WHITE); + + //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 * 0.5)) { + display.setCursor(3,4); + display.print(F("SINGLE BUTTON")); + display.drawLine( 3, 12, 79, 12, SSD1306_WHITE); + display.setCursor(3,14); + display.print(F(" Change MAX")); + display.setCursor(3,22); + display.print(F(" Temperature")); + } + else { + display.setCursor(3,4); + display.print(F("BOTH BUTTONS")); + display.drawLine( 3, 12, 79, 12, SSD1306_WHITE ); + display.setCursor(3,18); + display.print(F(HEATING_MSG)); + } + x = ( x + 1 ) % y; //Display change increment and modulus + + //Update Display (right-side) + display.setCursor(95,6); + display.print(F("TEMP")); + display.setCursor(95,18); + display.print(maxTempArray[maxTempIndex]); + display.print(F("C")); + display.display(); + } +} + +bool heat(byte maxTemp) { + //Heating Display + display.clearDisplay(); + display.setTextSize(2); + display.setCursor(22,4); + display.print(F("HEATING")); + display.setTextSize(1); + display.setCursor(52,24); + display.print(maxTemp); + display.print(F("C")); + display.display(); + 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 + + //Other control variables + int x = 0; //Heat Animate Counter + int y = 80; //Heat Animate max (modulused below) + + 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); + + //Heat Animate Control + display.clearDisplay(); + display.drawBitmap( 0, 3, heat_animate, heat_animate_width, heat_animate_height, SSD1306_WHITE); + display.drawBitmap( 112, 3, heat_animate, heat_animate_width, heat_animate_height, SSD1306_WHITE); + display.fillRect( 0, 3, heat_animate_width, heat_animate_height * (y - x) / y, SSD1306_BLACK); + display.fillRect( 112, 3, heat_animate_width, heat_animate_height * (y - x) / y, SSD1306_BLACK); + x = ( x + 1 ) % y; //Heat animate increment and modulus + + //Update display + display.setTextSize(2); + display.setCursor(22,4); + display.print(F("HEATING")); + display.setTextSize(1); + display.setCursor(20,24); + display.print(F("~")); + display.print(v,1); + display.print(F("V")); + if( t >= 100 ) { display.setCursor(78,24); } + else if ( t >= 10 ) { display.setCursor(81,24); } + else { display.setCursor(84,24); } + display.print(F("~")); + display.print(t,0); + display.print(F("C")); + display.display(); + } + + // Tell everyone we were successful! + return 1; +} + +void cancelledPB() { //Cancelled via push button + + //Update Display + display.clearDisplay(); + display.drawRoundRect( 22, 0, 84, 32, 2, SSD1306_WHITE ); + display.setCursor(25,4); + display.print(F(" CANCELLED")); + display.drawLine( 25, 12, 103, 12, SSD1306_WHITE ); + display.setCursor(25,14); + display.println(" Push button"); + display.setCursor(25,22); + display.println(" to return"); + display.setTextSize(3); + display.setCursor(5,4); + display.print(F("!")); + display.setTextSize(3); + display.setCursor(108,4); + display.print(F("!")); + display.setTextSize(1); + display.display(); + delay(50); + + //Wait to return on any button press + while(!downButton.pressed() && !upButton.pressed()) { + upButton.update(); + downButton.update(); + } +} + +void cancelledTimer() { //Cancelled via 5 minute Time Limit + + //Initiate Swap Display + int x = 0; //Display change counter + int y = 150; //Display change max (modulused below) + + //Wait to return on any button press + while(!downButton.pressed() || !downButton.pressed()) { + upButton.update(); + downButton.update(); + //Update Display + display.clearDisplay(); + display.drawRoundRect( 22, 0, 84, 32, 2, SSD1306_WHITE ); + display.setCursor(25,4); + display.print(F(" TIMED OUT")); + display.drawLine( 25, 12, 103, 12, SSD1306_WHITE ); + + //Swap Main Text + if( x < (y * 0.3)) { + display.setCursor(25,14); + display.println(" Took longer"); + display.setCursor(25,22); + display.println(" than 5 mins"); + } + else if( x < (y * 0.6)) { + display.setCursor(28,14); + display.println("Try a higher"); + display.setCursor(25,22); + display.println(" current PSU"); + } + else { + display.setCursor(25,14); + display.println(" Push button"); + display.setCursor(25,22); + display.println(" to return"); + } + x = ( x + 1 ) % y; //Display change increment and modulus + + display.setTextSize(3); + display.setCursor(5,4); + display.print(F("!")); + display.setTextSize(3); + display.setCursor(108,4); + display.print(F("!")); + display.setTextSize(1); + display.display(); + delay(50); + } + main_menu(); +} + +void coolDown() { + + float t = getTemp(); //Used to store current temperature + + //Wait to return on any button press, or temp below threshold + while(!downButton.pressed() || !downButton.pressed() && t > 45.00) { + upButton.update(); + downButton.update(); + display.clearDisplay(); + display.drawRoundRect( 22, 0, 84, 32, 2, SSD1306_WHITE ); + display.setCursor(25,4); + display.print(F(" COOL DOWN")); + display.drawLine( 25, 12, 103, 12, SSD1306_WHITE ); + display.setCursor(25,14); + display.println(" Still Hot"); + t = getTemp(); + if( t >= 100 ) { display.setCursor(49,22); } + else { display.setCursor(52,22); } + display.print(F("~")); + display.print(t,0); + display.print(F("C")); + display.setTextSize(3); + display.setCursor(5,4); + display.print(F("!")); + display.setTextSize(3); + display.setCursor(108,4); + display.print(F("!")); + display.setTextSize(1); + display.display(); + } +} + +void completed() { + //Update Display + display.clearDisplay(); + display.drawRoundRect( 22, 0, 84, 32, 2, SSD1306_WHITE ); + display.setCursor(25,4); + display.print(F(" COMPLETED ")); + display.drawLine( 25, 12, 103, 12, SSD1306_WHITE ); + display.setCursor(25,14); + display.println(" Push button"); + display.setCursor(25,22); + display.println(" to return"); + display.drawBitmap( 0, 9, tick, tick_width, tick_height, SSD1306_WHITE); + display.drawBitmap( 112, 9, tick, tick_width, tick_height, SSD1306_WHITE); + display.display(); + + //Wait to return on any button press + while(downButton.pressed() || upButton.pressed()) { + upButton.update(); + downButton.update(); + } +} + +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 +} diff --git a/Board Versions/README.md b/Board Versions/README.md new file mode 100644 index 0000000..369c311 --- /dev/null +++ b/Board Versions/README.md @@ -0,0 +1,69 @@ +# **Designing Your Own Hotplate** + +If you're the kind of person interested in building a project like this, you may also be the kind of person who might want to improve upon it or adjust it for a different operating environment. For example, you may want to operate from a higher voltage supply, design a larger sized hotplate or other similar options. What do we know from this design that could help inform such modifications? + +My experience with hotplate design is based on designing separate hotplates (ie. without integrated electronics onboard) that fall within the size limitations of the cheap Chinese PCB manufacturers (ie. 100x100mm maximum size). The heated area of my hotplates are roughly 86mm square due to allowances for mounting the hotplate. Secondly, I am designing for reflowing traditional Tin-Lead (SnPb) solder alloys, which melt at approximately 180 celsius. If you are only intersted in reflowing lower temperature solder alloys like Tin-Bismith (SnBi) alloys, the power requirements can be lowered slightly. The common commercial lead-free alloys (ie. SAC305, SAC405, etc) are probably unsuitable for reflowing on a PCB based hotplate, so this discussion will not consider them. + +## Decide on Target Heating Power ## + +Calibration data from my hotplates suggest that a hotplate of that shape and size has a thermal resistance to ambient air of about 2.4 K/W. For reflowing SnPb, you want to aim for a peak temperature of at least 205 celsius. This is lower than most commercial reflow profiles, but from my experience this is more than hot enough to get reliable and repeatable results. For SnBi, typical reflow profiles aim for around 180 celsius peak temperatures. Assuming that we have an ambient air temperature of about 20 celsius, then we're looking to support a temperature delta of about 160 kelvin for SnBi or about 185 kelvin for SnPb. For SnPb, the calculations end up being: + +$$\frac{185 K}{2.4 K/W} = ~77 W$$ + +That is how much power you need to simply maintain that temperature against ambient air at 20 celsius. To get there in a reasonable amount of time, you will need more. My rule of thumb is to add 20-50% more power. Higher power will allow you to achieve higher temperature gradients and improve your ability to closely follow a reflow profile. 20% additional power should be good enough to achieve reliable and repeatable results but may struggle with some of the steeper temperature gradients during preheat in some reflow profiles. 50% should give you more than enough power to follow most reflow profiles pretty closely. So for a hotplate my size to reflow SnPb solder we're looking at somewhere around 90-115W as a good range of power to aim for in our heating element. If you do the calculations for SnBi, you get slightly lower power range of about 80-100W. Note that you can reflow either of these alloys with less power, but you will need to trade off either hotplate size or heating speed or both in order to do this. + +One last comment on heating power requirements... If you're designing a different sized hotplate, you will need to scale these numbers somehow. While I doubt this will scale linearly, in the absence of a better theoretical model, I would suggest starting with linearly scaling the power requirement by area. My heating element area is close to 75 square centimetres, so the holding power required is roughly 1W per square centimetre. This makes the target power range to be roughly 1.2 - 1.5 W per square centimetre of heating element. Given how heat transfer works, I expect smaller hotplates will lose heat to the environment more quickly than larger hotplates, so these numbers may estimate low for smaller sizes and might estimate high for larger hotplates. That's just a guess on my part. For smaller hotplates, I'd err closer to the 1.5 W per square centimetre to be safe. For larger hotplates, if you're power constrained, you may be able to work closer to 1.2 W per square centimetre or possibly lower and still get decent results. + +## Drive Voltage ## + +Let's assume you're designing to run from something like a laptop power brick or USB-PD supply. Laptop power bricks commonly output 19V and are often rated at 90W or more. USB-PD can support voltages up to 20V at currents up to 5A, so 100W. We'll work with the laptop power brick specs, as the lower specs will be more limiting for our hotplate perforance, but I expect these results will still work reasonably well for USB-PD and give us a hotplate that can be supported by a wide range of available hardware that's already out there in the world. + +Before we get carried away, we also need to consider the impacts of PWM and the maximum practical duty cycle we can use. Because of a variety of factors, such as non-zero turn-on and turn-off times, it's not really practical to operate all the way up to 100% duty cycle. Realistically, the highest practical duty cycle value is likely around 95% or less. The effect of this is that our maximum operating voltage for the heating element is reduced to 95% of our power supply voltage. If you want to limit duty cycle to some lower value than 95%, then use that percentage as well. + +Additionally, our power conversion electronics will not be 100% efficient. For the purpose of these calculations, we're going to assume around 95% efficiency ($\eta$). This may be optimistic, so you may want to choose a lower value depending on your own experience. + +$$ V_{operating} = V_{supply} \times D_{max} \times \eta $$ + +$$ V_{operating} = 19 \times 0.95 \times 0.95 = 17.15 V $$ + +From ohm's law, we have that the power dissipated in the heating element is: + +$$ P_{heating element} = \frac{V_{operating}^2}{R_{heating element}} $$ + +Rearranging to calculate required resistance from voltage and power: + +$$ R_{heating element} = \frac{V_{operating}^2}{P_{heating element}} $$ + +$$ R_{heating element} = \frac{17.15 \times 17.15}{90} = 3.27 \Omega $$ + +## Resistance Versus Temperature ## + +We need to allow for the fact that our heating element's resistance will increase as it gets hotter. In fact, this is one good option you can use to determine the temperature of the hotplate if your control scheme has access to accurate real-time voltage and current information from the hotplate. It's impractical to try to be overly precise as there can be substantial variation between boards in a batch as well as process variation between batches and between manufacturers. Because of this, it's probably not worth more than a rough approximation here. At reflow temperatures, your heating element's resistance will be roughly 70% higher than it will be at ambient temperatures. I typically take the resistance value calculated above as the resistance of the heating element at peak temperature (ie. when "hot"), so to determine the target resistance for my heating element at ambient temperatures, I take the number from above and divide it by 1.7. + +$$ \frac{3.27 \Omega}{1.7} = 1.92 \Omega $$ + +That's the value I design for in my heating element. + +## PCB Design To Resistance ## + +Some PCB design software may provide tools for estimating the resistance of PCB traces. In the absence of that, the following approach may be close enough, although from my results, I suspect that what happens around corners or at changes in trace width may be more complex than this model allows, so if your design includes very large numbers of corners or variations in width, the real world results may be different from what you get from this calculation. + +To calculate the resistance of a linear trace of constant width, you would use the formula: + +$$ R = \frac{\rho \times length}{width \times thickness} $$ + +where $\rho$ is the resistivity of the material in $\Omega m$ and length, width and thickness are all distances measured in *metres*. For 1 oz copper, the theoretical thickness of the copper foil on a PCB would be about $35 \times 10^{-6} m$ thick (ie. 0.0000035m thick). For annealed copper, $\rho$ is about $1.72 \times 10^{-8} \Omega m$. So for a copper trace 1.5mm wide, 70mm long in 1 oz copper, we would have + +$$ R = \frac{1.72 \times 10^{-8} \times 0.07}{0.0015 \times 0.000035} = 0.02293 \Omega $$ + +or about 23 $m\Omega$. From working with JLCPCB for some of our earlier revisions, the actual resistances seemed to suggest that the copper thickness may be closer to 29 microns (ie. 0.000029m) than the 35 microns we expect. Although I now recommend PCBWay as a better option for manufacturing hotplates, I have less experience with them so far. I think 29 microns may also be a reasonable approximation of copper thickness there, but I have had some surprising results with some of my later, more complex layouts, so maybe my expectations are wrong or some process has changed at PCBWay in recent months. Your mileage may vary. Based on this, we can proceed as follows: + +1. Break your heating element up into a series of linear traces with constant width. +1. For each linear trace, measure the length of the trace along the centre of the trace. The ends of each trace should touch the ends of neighbouring traces, so at a corner the end would be in the mid-point of the corner for both traces entering or leaving that corner. +1. Sum the lengths of all the traces with the same width. +1. Calculate the total resistance for each trace width you have using the formula as shown above. +1. Sum all of the resistances calculated for each different trace width. + +That last number is the estimated resistance of the entire heating element. It can take some trial and error to dial in the resistance just where you want it, so be patient. Alternatively, use someone else's well tested design if it's close enough to your design requirements. + +Hopefully this gives enough of a background that someone interested in the challenge of designing their own hotplate can get a start without having to reinvent everything. Good Luck! diff --git a/README.md b/README.md index a505527..fa2d5df 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,27 @@ ###### By AfterEarth Ltd -## As Seen On GreatScott! +This is a largely unmodified version of the design by AfterEarthLTD that was also seen on a [GreatScott! video](https://www.youtube.com/watch?v=QarizoUnRfk). I have made some tweaks to the software to get it to work on the ATMega4809 and also added instructions on how to build it and program it. It does work, but there are some problems with the design. I am working on newer designs but the best design out there today is probably the one by [DerSpatz](https://github.com/DerSpatz/PCB-reflow-solder-heat-plate) -This project has recently featured on a DIY or BUY GreatScott! video. +## WARNING!!! -Check it out here - [The Best way to reflow solder? Hot Plate to the rescue! DIY or Buy](https://www.youtube.com/watch?v=QarizoUnRfk) +This design lacks safety features to limit the amount of power it may draw or the temperature it may reach and there are other issues with the electrical design. With a suitable power supply and as long as the software doesn't have any major bugs, it can be operated without issue but there is a real risk that it could start a fire in the event of a software bug or other fault. Do not leave it unsupervised while connected to power. If you're designing your own version, some considerations you may want to include are: + +- Safety!!! What can happen with your design in the event of a hardware or software fault? Can it draw enough power to catch fire? At a minimum, some kind of overcurrent protection like a fuse would be prudent. +- Heating element resistance. The original board layouts have very low resistance that typically ends up around 0.9 ohms or so. A higher resistance that's closer to your design maximum power at 100% duty cycle would help ensure that the device cannot draw excessive currents, overheat and catch fire in the event of a fault. Since the design goal was about 60W, something closer to 2 ohms at peak temperatures would be more prudent to help prevent large overcurrent faults. For about 2.1 ohms at 180 celsius, you'd want about 1.3 ohms at 20 celsius. +- Poor regulation in the PWM and/or input circuits. The existing design may be suitable for low power scenarios like managing the brightness of small, indicator LEDs, but it's inadequate for higher power devices like a 60+W heating element. + - Ideally, the PWM should be operating at moderately high frequencies above 30kHz. The original firmware used a frequency of roughly 63kHz, but suffered from the input capacitor getting extremely hot during hearing cycles. The quick fix for this was to lower the PWM frequency to the default frequency of 490Hz, which lowered the power dissipation in the input capacitor. + - Without sufficient inductance in the circuit to smooth out current ripple, it's impossible to get the ripple currents in the input capacitor to manageable levels. Larger input capacitors can make marginal improvements, but mostly because their larger size allows them to dissipate more heat. Ultimately, they will still end up with large ripple currents with each on-off cycle of the MOSFET. + - Simple retrofits, such as adding a series inductor inline with the power supply is also unable to address the issue. The position of the MOSFET switch means that when it is off there is nowhere for the inductor to discharge it's energy except into the input capacitor. Such an inline inductor makes the input capacitor power dissipation problem worse, not better. + - What's really required is a redesign that includes an inductor, capacitor and freewheel diode connected with the heating element and the MOSFET switch situated so as to switch power on and off into these components as a unit in a manner similar to how a buck converter works. It needs to be designed such that when the switch is off, the inductor can discharge its current into the heating element. This filter arrangement should probably be separate from the input capacitor, but should ensure that the device does not excessively load the power supply and keep current ripple to a minimum. + - The firmwares in this repo have been modified to use the FAST_PWM macro to determine whether or not to use high PWM frequency. In the current code, this define is commented out and the firmware will use the default PWM frequency of about 490Hz. Uncommenting this line will change the PWM frequency to approximately 63kHz. It also modifies the messaging on the screen to suggest that the input capacitor may get hot so that it's clear to users if they're running a FAST_PWM firmware. + - Since the input capacitors are largely ineffectual in the current design, they could probably be removed although I have not and probably won't try this. +- Thermal gradients. The standard layout has a uniform track layout across the entire board, but since you lose heat much more easily at the edge than in the centre, thermal gradients of 50 celsius between the centre of the board and the edge are not uncommon. Having thinner tracks near the edge can help reduce this effect. +- Thermal sensing. The temperature sensor off the side of the hotplate is ineffective at accurately sensing hotplate temperature and will likely be 20-30 celsius lower than the temperature at the edge of the board, even if you install it as close to the board as possible. Ideally, the sensor setup should measure temperature within the hotplate area itself or on the board being reflowed. Suggested approaches are using the heating element itself as the sensor, using a remote sensor that can be attached to the board being reflowed or possibly using some kind of thermography or IR sensor. ## UPDATE!!! -Join the [DISCORD!](https://discord.gg/YzhG6FcCRA) +The old Discord server has been nuked by trolls due to a lack of anyone with admin privileges frequenting the server any more. We now have a [new Discord server](https://discord.gg/5wSnbg9q). Checkout the new Ver 3.0 design. Very similar to Ver 2.4 but now comes with ATmega4809 as its availability is much better than the 328p at the moment. Code is still in development but the board designs are available in the Board Versions Folder. @@ -23,7 +35,7 @@ Checkout the new Ver 3.0 design. Very similar to Ver 2.4 but now comes with ATme - ATmega328p Microprocessor - 70mm x 50mm (Ver 3.0) **NEW** - - 12VDC (5A Minimum) + - 12VDC (15A Minimum) - 5.5mm x 2.5mm Barrel Jack - 0.91" OLED Display - ATmega4809 Microprocessor