An android reflow controller that anyone can build
The story so far
Welcome to the never ending saga of Andy and his reflow controllers. About a year ago I published a project writeup showing how I built a PID-based reflow controller. It featured a 640×360 graphical LCD from the Sony U5 Vivaz mobile phone and was all-surface mount. It worked well and continues to serve me well to this day but I always thought that there were improvements that I could make in several areas.
Firstly, there’s no reason why it should have been all surface-mount. The LCD in particular has a 0.4mm connector that many people will find very hard to solder by hand. After all, presumably you’re building a reflow controller to help solve that very problem. Chicken and egg.
Difficult 0.4mm connector
Secondly, the built-in LCD is overkill. We live in the age of the so called landfill android device where you can buy a powerful tablet computer for just £30 online. Why not harness that power and use bluetooth to transmit a control protocol back and forth to a simple on-board controller?
7″, 1024×600 IPS, bluetooth. £35 delivered.
Finally, I used an SSR to pulse the oven power supply on and off. That always irked me. A fully integrated controller would be supplied by the mains and use zero-crossing detection to drive a triac that would dim the halogen oven instead of just switching it on and off.
A few months ago I set to work solving all these issues and I’m happy to say that they’ve all been addressed. In the remainder of this article I’ll present a reflow controller that’s almost entirely through-hole so anyone can build it. It’ll be driven direct from the mains supply and will feature bluetooth control via an Android app.
The schematic
Let’s get straight into the schematic. This is a modular design so I’ll pick on each part individually and explain what’s going on. Here’s the full document.
This design is for countries with a 220-240VAC supply. I have estimated some of the values that I consider to be appropriate for countries with a 120VAC supply and they are shown in red on the schematic but I haven’t tested these and would appreciate any corrections from people in those countries.
The high-side of the board
MAINS_L and MAINS_N are the live and neutral mains terminals, respectively. SW_IN and SW_OUT are the terminals that connect to the on-off switch. The maximum current rating for this design is 8A so the switch must be rated accordingly and should contain an embedded fuse because there’s no provision for one on the board itself. There’s not much chance of a standard household fuse blowing before the triac is destroyed but it should blow before anything really bad, such as a fire, starts.
C4 is an X-class film capacitor rated at 275VAC. It’s used for emissions filtering and can be considered optional if you’re not bothered about that.
You have your fuse for overcurrent protection and now you have R3, a varistor for overvoltage protection. Under normal operating conditions the varistor has a very high resistance but when a voltage spike is encountered the varistor quite suddenly becomes very low resistance, protecting the triac from the spike. I’ve never personally witnessed a triac failure but I’m informed that they can fail explosively so it’s good to protect them if we can.
OVEN_L and OVEN_N are the live and neutral output terminals to the halogen oven. The triac controls when these terminals are switched on and off. Speaking of the triac…
The triac
Q4, R1, U3, Q1, R2 and R4 form the triac control circuit and it’s worth exploring this in a little more detail.
A triac is an electronically controlled semiconductor that, when activated, can conduct current through it in either direction. This bi-directionality makes it a good choice for using a small DC control signal to switch a large AC mains supply on and off. Another key feature is that once a triac is activated (latched) it will stay latched on until the AC sine wave crosses zero again. If we combine this feature with a zero-crossing detector then it becomes a simple matter of timing to ‘dim’ an AC wave by chopping it off at the same point in each half-cycle.
Chopped (dimmed) AC waveform
The diagram above shows an example of how AC dimming is achieved. You wait until the wave crosses zero, then you wait some more depending on how little or how much dimming you want and then you switch on the triac. The triac will then stay switched on until the next zero crossing at which point you start again.
It’s important to choose a triac that’s rated comfortably in excess of the current that you plan to conduct so that it can handle the inrush current surge that happens when the halogen oven first switches on. I rate this controller for an 8A load so I’ve chosen a BTA312-600B 12A triac from NXP to do the job. Note as of 2017 this Triac is now obsolete. Replace it with the directly equivalent ST Micro BTA12-600BWRG.
The TO-220 package can be cooled in accordance with the rating of the BTA312.
A triac of this size will typically come in a TO-220 package and it will get hot during use so an appropriately rated heatsink is absolutely required.
Fairchild MOC3020M in an on-trend white package
I use a MOC3020M triac optocoupler to control the triac’s gate and the driving circuit is taken from the MOC3020M datasheet with the RC snubber components removed. A snubber is used to prevent false triggering of the triac when the load being driven has an inductive component such as the fan on the halogen oven that I’m using. False triggering tends to happen during the 4th triac quadrant and can be eliminated by using a triac that only triggers in quadrants 1 to 3, such as the BTA312 that I’m using. Therefore I don’t need an RC snubber and have removed it from the circuit.
The MOC3020M requires between 30 and 60mA to switch on. This is too much to drive directly from the pin of an MCU so I’m using the 2N5551 transistor, Q1, to drive it. There’s nothing special about the 2N5551, I just happen to have some in stock. If you have another general purpose NPN knocking around then you can use that. Just be sure to choose a base resistor that fully switches the transistor on.
Triac thermal considerations
I mentioned before that a triac can get hot and we need to provide them with at least a heatsink and sometimes even a fan for active cooling. Heatsinks are rated in °C/W which tells you how many degrees they will rise above ambient per Watt of thermal energy that you ask them to dissipate.
NXP publish a helpful and well-written application note that walks you through the maths required to calculate the power dissipated by the triac.
P is the power dissipation in Watts, V0 is the triac’s knee voltage, given in the datasheet. IT(AVE) is the average load current and is calculated from the RMS load current using the following equation:
RS is the triac slope resistance and can be found in the datasheet. Referring to the BTA312 datasheet we find V0 = 1.164 and RS = 0.027. I’ll use IT(RMS) of 8A as the worst case for this design. Using the second equation I calculate that IT(AVE) = 7.2A. Now I can use the power equation to determine that P = 10.1W. I’ll definitely need a heatsink.
Choosing a suitable heatsink
Tj is the triac’s junction temperature and it must be kept below the maximum value specified in the datasheet: 125°C for the BTA312 and in practice we need to stay well away from that value due to the error margin between the theoretical thermal calculations and real life.
AN10384 gives us the equation that we need to calculate the junction temperature for the power dissipation that we have just calculated.
Ta is the ambient temperature (°C) and Rthj−a is the junction-to-ambient thermal resistance (°C/W). The package’s Junction-to-ambient will often be quoted in the datasheet and can be used to determine if you can operate your design without a heatsink. It is 60°C/W for the BTA312’s TO-220 package which means that I must definitely use a heatsink.
Thermal resistance, like electrical resistance, can be broken down into several smaller resistances connected in series. The TO-220 package used by the BTA312 has the following resistance model:
See figure 3 in AN10384 for a pictorial representation of where the different components of the overall thermal resistance occur in the TO-220 package.
Rth j-mb is the thermal resistance of the junction to mounting base. The value is quoted in the datasheet as 2°C/W for a half-cycle.
Rth mb-hs is the resistance between the mounting base of the TO-220 and the heatsink. This will vary depending on whether the package is screwed or clipped to the heatsink and whether or not thermal grease is used. I am screwing the TO-220 to the heatsink and I will use thermal grease. AN10384 quotes a typical value of 0.5°C/W for this method.
Rth hs-a is the resistance between the heatsink and ambient and will be quoted by the manufacturer. I’ve now got enough numbers to work out the maximum thermal resistance that I can accept from my heatsink. If I assume that I don’t want the junction temperature any higher than 100°C then the maximum heatsink thermal resistance works out to be 5°C/W.
I had a browse through the range of TO-220 heatsinks at Farnell and found that the FA-T220-38E offers a thermal resistance of 3.8°C/W in a nice compact unit.
Ohmite FA-T220-38E heatsink
Putting the rating of 3.8°C/W into the Tj equation yields a value of 88°C for an ambient temperature of 25°C. This value will rise by 1°C for every degree rise in ambient. I’m happy with that value and will definitely use this heatsink in my design.
The transformer
In the interests of safety I decided to use an isolation transformer to step down the mains voltage to a safe level for the low side of the board. Transformer-less designs for powering MCUs from the mains do exist and are cheaper to build but they are not as safe.
The Myrra 44193 steps down a 220-240VAC input to a 6VAC output with full isolation protection. The coils are encased in an insulating material and you can’t see it but there will be a piece of insulating material between the two coils to prevent accidental short circuit. Finally the whole unit is potted with some kind of resin. It’s a very heavy component and certainly feels well made.
The mains connector
The mains connector block is a 6-way 5.08mm connector designed to handle all the mains inputs and outputs. Two pins are provided for 240VAC live and neutral. Two similar pins are provided for the oven output and two more pins are provided for routing out to an external on-off switch.
I’ve chosen an appropriately rated connector block that you can get from Maplin (order code A18QN). You could use screwed down spade connectors instead if you’re unable to obtain a suitable connector in your country. Directly soldering mains wires to a PCB is generally not recommended because stress over time can result in a cracked joint.
I’ll be running a 3-core cable to the metal housing that I use to enclose the PCB. The earth wire will be screwed to the metal housing as will the metal mounting screws for the project PCB that will also connect to the ground plane on the low-side of the device.
There was no room to mount a fuse on the PCB so the IEC connector that I will mount to the chassis of the enclosure has a fuse holder built in to it.
The low-side of the board
Now we’re done with the mains stuff, let’s move on to the low-side of the board, starting with the bridge rectifier and zero-crossing detection circuits.
Bridge rectifier and zero-crossing detector
The output of the transformer is a sine wave, shown below:
Diodes D1 to D4 form a classic full wave bridge rectifier circuit used to turn the negative part of the wave into positive.
Full-wave rectified output
I used 1N4007 diodes for the rectifier which, with their 1kV rating are very much over-specified for this purpose. I used them simply because I had a lot of them in stock. You can just as easily use any of the others from the 1N400x range if that’s what you have available.
Capacitor C3 is used to smooth the rectified wave into something that we can sensibly use for input to the LDO regulators that will supply 5V and 3.3V to the rest of the board. Diode D6 shields the zero-crossing detection circuit from the effect of the smoothing capacitor.
Smoothed output
The scope’s voltage scale is 2V/div in the above screen shot so we can see that I’m getting around 6.5V which is enough to power the LD1117 5V regulator with its 1V (typical) drop-out. The capacitor C3 can’t completely smooth the output on its own which is why there’s an apparent sawtooth ripple to the output. Let’s have a look at that ripple magnified:
Magnified ripple
My scope shows that the peak-to-peak ripple voltage is about 1.2V, quite a lot really and we’ll have to see how that affects the output from the regulators, particularly the 3.3V regulator that powers the thermocouple A-D converter.
R5, R6 and Q2 form the zero crossing circuit. What we aim to do is convert the rising and falling AC wave into a digital on-off signal that we can use as an input to an MCU pin. We can then use the MCU’s ability to raise an interrupt on the rising or falling edge of a signal to tell us when the zero crossing has happened.
Scope probe of the AC wave and the ZSENSE pin level
The AC wave is applied through a base resistor to the 2N5551 general purpose NPN transistor. When the wave rises past the base-emitter ‘turn-on’ voltage of the transistor then it will conduct and the ZSENSE pin will sense zero since the transistor is now allowing current to flow through it to ground. When the wave falls below the ‘turn-on’ voltage the transistor will stop conducting and the ZSENSE pin will read high. The falling edge happens close enough to the zero crossing for me to use as a signal to start my triac activation timing calculations.
On/off switching for different percentages
This animated image shows the ACTIVE signal in relation to different dimming percentages from zero to 100 in steps of 10. For the 100% signal I just set the line high and for zero it is set low.
The JP1 jumper is my way of safely working on the low-side of this board without having to connect it to the mains. The normal case is for the jumpers to be fitted and the low-side is then powered by the mains. When I’m working on it I remove the two jumpers and connect my bench DC power supply to pins 1 and 3.
Voltage regulation
The roughly 6.3V output from the bridge-rectifier is fed to a pair of ST Micro LD1117 regulators in TO-220 packages. I would have liked to have had the whole board running at 3.3V but unfortunately the HC-06 bluetooth module has a bizarre power arrangement whereby the signal levels are specified to be at 3.3V but the adaptor board takes a 5V power input. That’s annoying but LD1117 voltage regulators are cheap and I’ve got the board space so it’s no problem to take two.
I haven’t measured the noise levels on the regulator outputs in isolation – only with the full board built and with no issues observed in the prototype I can only assume that the outputs are stable enough for this design.
The thermocouple ADC
In my previous design I elected to use the older MAX6675 K-type thermocouple ADC. That chip is now obsolete, replaced by the pin-compatible MAX31855 that adds a few new features, the most notable of which is the ability to measure below zero. Firmware written for the MAX6675 will need to be re-written for the MAX31855 but the differences are minimal and it’s still the same old poll-over-SPI protocol.
Bad Max 2
I am beginning to lose faith in Maxim’s ability to produce things that work. Readers of my previous article will remember that I managed to get hold of a bad MAX6675 that caused me to lose hours of my life trying to figure out what was wrong before figuring out that the IC itself was bad.
Well it happened again with the MAX31855. This time the symptoms were an incorrect scaling as the temperature rose. That is, it would appear to be correct at room temperature but would then lag as the temperature increased. For example, dunking a waterproofed thermocouple probe in boiling water would read around 75°C when the real temperature is obviously 100°C. Having been burned before by dodgy Maxim gear I googled around and stumbled across this article on the eevblog forum. Exactly the same symptoms as me and yes, I had a MAX31855 with one of the date codes identified as dodgy.
253AL date code
So if you’ve got a MAX31855K with this date code then don’t even bother trying to fit it. Toss it in the bin or return it to your supplier and get a replacement.
The replacement that arrived worked perfectly. No more dodgy temperature readings. After all these less than ideal experiences I’m tempted to drop the whole K-type thermocouple approach and use an RTD instead.
The two ferrite beads and the 10nF capacitor are there to clean the weak signal before it gets to the MAX31855. Maxim recommends the presence of the capacitor in their datasheet and experience reported on the internet is that you get severe noise issues if you choose not to fit it. The ferrites are my own addition and I can say that my readings are completely stable with no false reports at all.
The T-GND jumper is not fitted in my design. If fitted then it can be used to ground the negative wire of the thermocouple. The old MAX6675 required this but the MAX31855 does not. If you decide to fit a MAX6675 instead of the 31855 then you’ll need this jumper block and it will need to be fitted.
The bluetooth module
As mentioned previously I’ve decided to integrate with the very cheaply available HC-06 module that you can get from China for about £3. These boards only require power to be applied before they will automatically find and pair with any compatible nearby device. After they’re paired then you can send and receive data using an MCU’s UART at 9600 baud.
I’ve added a LED to my schematic that will light up when the device is paired and communication between the Android app and the firmware on the board is active.
The MCU
With the ‘easy build’ aim of this project in mind there was only ever going to be one range of MCUs in the frame for the controller and that would be Atmel’s 8-bit AVRs. They’re widely available, they come in DIP packages and thanks to the popularity of the Arduino platform there’s an army of hackers out there who know something about how to write firmware for them even if their choice of platform does mean that they may never get familiar with the instruction set or the IO registers.
The L is important – the regular ATmega8 will not work at 3.3V
I prototyped the firmware build with the ATmega328P MCU that you can find in the Arduino Uno and when I’d more-or-less finished the code size was 12 or 13K. After moving the entire implementation from an old-style .cpp
/.h
structure to inline
header-only methods the gcc 4.9.2 optimiser was able to really grasp the nettle and bring the image down to about 7.5Kb, and that’s with using expensive floating point operations for the PID algorithm. A round of applause from me goes to the authors of the gcc optimiser.
With only a little finishing off to do I knew I would be able to fit the whole thing into an ATmega8L. Some of the peripherals are lacking or are not as capable on the ATmega8L compared to the ATmega328P but not enough to cause me any issues.
I need to interface the MCU with some 3.3V peripherals so the actual MCU that I’ve chosen is the ATmega8L running at 3.3V and 8Mhz. As you can see from the schematic I’ve selected an external crystal with 22pF load capacitors for the system clock source even though the ATmega8L has an internal oscillator that can run at 8MHz.
The reason for this choice is that I’ve read about considerable variation in the accuracy of the internal oscillator that could potentially affect the device’s ability to do reliable UART communications – a UART is an asynchronous peripheral that relies on each end to have accurate enough clocks to communicate. We also need it to accurately track time over a reflow program so I decided to play safe and install an external crystal.
The Nokia 5110 LCD
Obviously the main GUI for this project is your handheld Android device but I still decided to add a small and cheap LCD to the design to provide feedback on the current temperature and the bluetooth link status. With the addition of a rotary encoder and a button the entire process, including configuration and reflow, can be operated from this little LCD. This could be useful if you just want to do a quick reflow and don’t have your Android tablet or phone handy.
The photograph shows the actual LCD that I bought. I chose the red one because it matches the colour of the PCB that I’m using. Do note that the one that you use must have the pins in the same order on the breakout header to mine if you want it to press down directly into the board.
Another key point to note is that the backlight pin, labelled ‘LIGHT’ on the PCB must be the output from the backlight circuit and not the input. As you can see from the schematic I’m applying a PWM waveform to a transistor to set the backlight brightness in the assumption that the ‘LIGHT’ pin is an output to ground.
General purpose 2N5551 used for backlight PWM control
If you happen to get a board where the LED pin is a VCC input then my backlight circuit won’t work and you won’t have a backlight. That’s no big deal because these STN LCDs are readable in ambient light unlike the reflective TFTs that must have a backlight to allow you to see anything at all.
The fan connector
The fan will be mounted close to the triac
The fan connector will accept any 3-pin computer fan that will run at 6.3V. Most of them will do and they’ll run nice and quiet as well. My heatsink calculations indicate that I probably won’t need a fan but those calculations assume that the heatsink is in free air. When it’s enclosed in a sealed box I will have to provide some form of ventilation and may have to fit a fan as well.
Bill of materials
Here’s a table that contains the bill of materials for this project. I got nearly all the parts from Farnell and have included their part number where available for easy reference.
These parts are for a 220-240VAC design. If your mains supply is 120VAC then you’ll need to calculate appropriate substitutes. If anyone does build a 120VAC design then I’ll be happy to publish the components that are required here.
Identifiers | Value | Quantity | Description | Footprint | Farnell code |
---|---|---|---|---|---|
ACTION, SELECT, TEMP | 3 | 2-Pin PCB terminal block | 5.04 mm | (ebay) | |
C1, C5, C14 | 10u | 3 | Polarized Capacitor (Radial) | CAPPR2-5x11 | 1902913 |
C2, C6 | 22u | 2 | Polarized Capacitor (Radial) | CAPPR2-5x11 | 1870976 |
C3 | 470u | 1 | Polarized Capacitor (Radial) | CAPPR5-8x12 | 9693602 |
C4 | 100n | 1 | Panasonic ECQU2A104KLA X2 Film Capacitor | 1673308 | |
C7, C8, C11, C12, C15, C16 | 100n | 6 | Ceramic Capacitor | 2.54mm | 2309020 |
C9, C17 | 22p | 2 | Ceramic Capacitor | 2.54mm | 1100369 |
C10 | 10n | 1 | Ceramic Capacitor | 5.08mm | 2309024 |
C13 | 1u | 1 | Ceramic Capacitor | 5.08mm | 2112910 |
D1, D2, D3, D4, D6 | 1N4007 | 5 | 1 Amp General Purpose Rectifier | 2317417 | |
D5 | 1 | Typical white GaAs LED | 5mm domed | ||
FB1, FB2 | BLM18PG221SN1D | 2 | Ferrite bead | AXIAL-0.3 | 2292304 |
JP1 | 1 | Header, 2-Pin, Dual row | 2.54mm | ||
P1 | 1 | Header, 6-Pin | 5.08mm | A18QN (maplin) | |
P3 | 1 | 3-Pin fan header | 2.54mm | 588581 | |
P4 | 2 | Header, 4-Pin | 2.54mm | ||
P6 | 1 | Header, 3-Pin, Dual row | 2.54mm | ||
P8 | 1 | Nokia 5110 breakout board on 8 way female header | 2.54mm | (ebay) | |
Q1, Q2, Q3 | 2N5551 | 3 | NPN Bipolar Transistor | TO-92 | 9846751 |
Q4 | BTA12-600BWRG | 1 | Silicon Bidirectional Triode Thyristor | TO-220AB | 1057276 |
R1 | 360 | 1 | Resistor | AXIAL-0.5 | 2329779 |
R2, R5, R12 | 1K | 3 | Resistor | AXIAL-0.3 | 2329486 |
R3 | 275VRMS | 1 | Varistor (Voltage-Sensitive Resistor) | Varistor 20D series | 1856919 |
R4 | 47 | 1 | Resistor | AXIAL-0.3 | 1128034 |
R6 | 470 | 1 | Resistor | AXIAL-0.3 | 2329531 |
R7, R9, R10, R11 | 10K | 4 | Resistor | AXIAL-0.3 | 2329474 |
R8 | 100 | 1 | Resistor | AXIAL-0.3 | 2329473 |
R13 | 33 | 1 | Resistor | AXIAL-0.3 | 2329516 |
T1 | 6VAC | 1 | Myrra 44193 | 1689073 | |
U1 | LD1117V50 | 1 | 800mA Low-Dropout Linear Regulator, 3-pin TO-220 | TO-220AB | 1087175 |
U2 | LD1117V33C | 1 | 800mA Low-Dropout Linear Regulator, 3-pin TO-220 | TO-220AB | 1703357 |
U3 | MOC3020M | 1 | Opto-Triac | DIP-6 | 1471017 |
U4 | 1 | 8-Bit AVR Microcontroller with 8K Bytes of In-System Programmable Flash Memory | DIP-28 | 9171533 | |
U5 | MAX31855KASA+ | 1 | Cold-Junction-Compensated K-Thermocoupleto- Digital Converter | SOIC127P600-8AN | |
Y1 | 8MHz | 1 | Crystal Oscillator | HC49 thru hole | 2063945 |
HS1 | Heatsink | 1 | Ohmite FA-T220-38E | 2097690 | |
Thermocouple | 1 | K-Type thermocouple | Bare wire | (ebay) | |
Hex PCB standoffs | 2 | brass standoffs for the LCD | M3 x 11mm | (ebay) | |
HC-06 | 1 | Bluetooth module | 4-pin breakout board | (ebay) | |
PCB jumpers | 2 | 2-pin PCB jumpers | 2.54mm (0.1") | (ebay) |
PCB design
I decided to go for a two layer board that fits within a 10x10cm square. This means that you can get 10 copies of the board printed at one of the Chinese online services such as Elecrow, Seeed or ITead for about US$13. I’ve been using Elecrow recently and have been very happy with their service. I uploaded my gerbers to their site, paid the fee and went and did something else for 3 weeks. Time passes…
I laid out the PCB with the high side of the board marked off at the top left. A warning legend in the silkscreen states the obvious about the high voltage present in that area. There is no absolute number for the width of a trace required to carry a given current across a PCB. Increasing the width of a trace will lower the electrical resistance and hence decrease the power loss and the heat generated to dissipate that power loss. If you approach the problem with power-loss and heat in mind then you can calculate a figure for the trace width that’ll deliver those numbers for you.
No, I’m not going to subject you to the mathematics behind it all because there are on-line calculators out there that’ll let you experiment interactively with your numbers. I settled on a trace width of 140mil which for an outer layer on 1oz copper conducting 8A would result in a 20°C worst case temperature rise for a power loss of 500mW.
The only exception to this 140mil design rule is the middle pin of the TO-220 package that houses the triac’s MT2 terminal. There’s just no way around the fact that you have to neck down the trace quite drastically to get it through the middle pin.
I’ve tried to ameliorate this by mirroring the narrow part of that trace on the bottom layer of the board and joining it to the top layer with a pair of vias on each side.
There are standards for how close high voltage traces can get to other traces (creepage distance) that take into account the environment that the product will operate in (pollution level). You might be surprised at how low those minimums are; for this board 1.5mm would be enough. I leave much more spacing than that and I also provide routed cutouts in the places where the high voltage areas come closest to low voltage.
The bottom side of the board outside the high voltage area is filled and connected to the GND net. Likewise for the top layer except the fill is connected to the 3.3V net. Having GND and VCC as fills on alternate sides takes out the two largest nets from the routing problem and makes it easy to route the rest of the board.
The four corner mounting screw holes are part of the earthing strategy and will be screwed into the metal enclosure that I use to house this project. The three screws that are in the low voltage area also connect to the GND plane on the bottom.
Building the PCB
The only surface mount device on this PCB is the MAX31855 and it has a low number of generously spaced pins. I eschewed my hot air gun, previous reflow oven and hot plate in favour of a plain old iron and the tack-soldering method because I wanted to show how easy it is to assemble this PCB and you can see me soldering the MAX31855 in the video that accompanies this article. No laughing at the back please; it’s hard to solder from behind a video camera!
Of course the remainder of the through hole components are very easy to solder, if a little time consuming due to all the bending, threading and trimming of leads. There are a few tips I can give for building this board:
- Start with the lowest profile components and work up to the tallest. That way when you flip the board over to solder a component it should rest on itself which helps prevent it falling back through the board.
- The pin-spacing in the footprint for the 2N5551 transistors in the TO-92 package is quite narrow. To avoid solder bridges I recommend starting each pin with a clean iron and taking care to not over-apply solder.
- I use sockets for my ICs. You don’t have to but you’ll remove the possibility of causing damage through excess heat if you use sockets.
Important safety note
The mains traces on the top of the board may run directly under the metal of the Triac heatsink. It will depend on the type of heatsink that you have chosen to use and it definitely happens with the large Ohmite FA-T220-38E that I have selected. The solder mask is then the only thing preventing the heatsink becoming live and of course solder mask is far from being an appropriate insulator for mains voltages.
To avoid this issue, simply ensure that there is at least a couple of millimetres of air-gap between the bottom of the heatsink and the board when you solder the Triac into place. The large lugs on the bottom of the heatsink fit into the board holes provided for them and can be soldered into place to totally prevent any movement.
Alternatively, insulate the base of the heatsink with electricians tape rated well in excess of the AC peak voltage which is about 340V in the UK and 170V in the USA.
Here it is, fully built. There’s something deeply satisfying about completing a through-hole board. All the large components make it really look like you’ve actually built ‘a thing’. I know that technically you achieve a lot more for a given surface area with surface mount but the finished article does often look a bit like a few black plastic shavings with some capacitative dust sprinkled hither and thither. Old school wins in the looks department for me.
The firmware
The firmware for this device was compiled using avr-gcc 4.9.2 and can be cloned from github. You can compile it from source or you can flash it directly to the MCU if your mains frequency is 50Hz. I include a reference build for 50Hz mains supplies in the bin
folder.
Flashing the program to the MCU
The firmware can be uploaded directly to the MCU using a USBASP 3.3v programmer connected to the P6 header using jumper wires. Avoid the older version of the programmer that only supports 5V programming. The newer versions have a jumper that allows you to select between 5V and 3.3V.
For safety please do not program the MCU while the board is connected to the mains. The jumpers must be removed from JP1 and a DC power source connected to pins 1 and 3. This power source connects directly into the 5V LD1117 regulator. If you have a bench power supply then 6.3V would be ideal. If you don’t then a wall-wart that can supply between 6.3 and 12V would work. Don’t attempt to use a 9V battery because they can’t supply enough current for long enough.
Jumpers on = transformed mains (as illustrated). Jumpers off = DC supply
Flashing is a two step process using the avrdude utility. Firstly you should program the MCU fuses to use an external crystal instead of the internal oscillator. The command for that is:
avrdude -c usbasp -p m8 -e -U lfuse:w:0xff:m -U hfuse:w:0xd9:m
You only ever need to program the fuses once. Secondly you should program the MCU, again using avrdude:
avrdude -c usbasp -p m8 -e -U flash:w:awreflow2.hex
That’s it. The board should now be up and running. You can of course re-run the programming command as many times as you need to.
Compiling from source
I use scons
to build the firmware. To compile, cd
into the atmega8l
directory and use scons to build it:
$ scons
scons: Reading SConscript files ...
Usage: scons mains=<FREQUENCY> [upload]
<FREQUENCY>: 50/60.
50 = 50Hz mains frequency
60 = 60Hz mains frequency
[upload]
specify this option to automatically upload to
using avrdude to a USBASP connected MCU.
Examples:
scons mains=50 // UK mains frequency
scons mains=60 // USA mains frequency
A timer peripheral is used to work out where in the half-wave I need to turn the triac on and off. The duration of a half-cycle is different for people on 50Hz and 60Hz supplies therefore the build command needs to know which frequency you are on so that it can pass that information to the source code through a preprocessor definition.
The timing part of the controller firmware is probably the most interesting. Let’s take a look in detail at how it works. The one-paragraph summary of the flow of control is this. The zero-crossing event triggers an external interrupt in the MCU. The desired power percentage is used to calculate a timer comparator value and the timer is started. The comparator triggers an interrupt and the triac gate is activated inside the interrupt handler. The timer is bumped forward so that its counter will overflow in a number of ticks equal to the triac’s gate minimum latching pulse width. When the overflow interrupt is triggered the triac gate control is released and the timer stopped. The triac will remain latched until the next zero crossing and the whole thing starts again.
This sequence allows us to control the triac asynchronously and under interrupt control. The following diagram should serve to illustrate the explanation in the previous paragraph.
I’m using the TIMER2
peripheral on the ATmega8 to do the work. TIMER2
is an 8-bit up-counter with a comparator register. It can raise an interrupt when the comparator is matched and when the timer overflows, that is it ticks over from 255 back to zero. The timer clock can be sourced from the CPU clock and has a number of divider options so that you can have the resolution that you need.
In the zero crossing handler I start the timer like this:
// OCR2 is the comparator register. See main source code for
// the code that calculates the _counter variable.
OCR2=_counter;
TCNT2=0;
// start timer at 8MHz / 1024 = 128uS per tick
TCCR2=(1 << CS20) | (1 << CS21) | (1 << CS22);
The choice of 128µS per tick is made so that the timer doesn't overflow during the 50Hz/2 half wave. When TCNT2
reaches the _counter
variable the comparator interrupt will trigger, and here's the handler:
/*
* The comparator ISR handler
*/
inline void OvenControl::timerComparatorHandler() const {
// activate the triac gate. we must hold it active for a minimum amount
// of time before switching it off
GpioActivateOven::set();
// the overflow interrupt will fire when the minimum pulse width is reached
TCNT2=256-TRIAC_PULSE_TICKS;
}
Now the timer is running again and will overflow after TRIAC_PULSE_TICKS
clock ticks have elapsed. TRIAC_PULSE_TICKS
is defined in the SConstruct
build file as 4 which is 512µS and is enough to latch the BTA312 triac.
Finally, when the overflow does happen here's the handler:
/*
* The overflow ISR handler
*/
inline void OvenControl::timerOverflowHandler() const {
// turn off the oven
GpioActivateOven::reset();
// turn off the timer. the zero-crossing handler will restart it
TCCR2=0;
}
A millisecond timer
I need a general purpose timer for checking timeouts and performing short delays so I use TIMER0
for that purpose. TIMER0
is the least capable of the three timers on the ATmega8L so I'm always pleased to find a use for it. Here's how I set it up:
TCCR0 |= (1 << CS01); // CLK/8
TIMSK |= (1 << TOIE0); // Timer0 overflow interrupt
CLK/8
gives me an 8MHz/8 = 1MHz 8-bit counter. It'll overflow every 256 ticks so the overflow interrupt call frequency will be (CLK/8)*256 = 256µS. If I were to increment my millisecond counter every 4 ticks then I'd get a counter that ticks every 256*4 = 1024µS. That's no good, I need 1000µS for an accurate counter which would mean an overflow interrupt every 250µS.
The solution is to add 6 to the TCNT0
register each overflow interrupt and this is possible because TCNT0
is read/write at all times. The overflow interrupt handler looks like this:
ISR(TIMER0_OVF_vect) {
using namespace awreflow;
MillisecondTimer::_subCounter++;
if((MillisecondTimer::_subCounter & 0x3)==0)
MillisecondTimer::_counter++;
TCNT0+=6;
}
Communicating with the MAX31855
The MAX31855 is a SPI slave device implemented with 3 wires: MISO, CS and SCLK. The Nokia 5110 board on this controller is also an SPI slave device and the ATmega8L has only one SPI peripheral therefore I share the SPI bus by using different CS lines for each device. Here's the SPI pin initialisation code:
// SPI limiting values:
// 1. Max Nokia 5110 LCD clock = 4MHz
// 2. Max MAX31855 clock = 5MHz
// Selected clock is osc/4, mode is 0
SPCR=(1 << MSTR) | // master
(1 << SPE) | // enabled
(0 << SPR1) | (0 << SPR0); // (for clarity) we are intentionally choosing fosc/4 here
SPSR |= (1 << SPI2X);
// clear interrupt flag by reading this register
uint8_t dummy __attribute__((unused))=SPSR;
dummy=SPDR;
Some of the firmware operates under asynchronous interrupt control and some of it works synchronously via a main loop. The SPI communication works in the main loop. I sample the temperature from the MAX31855 every 500ms like this:
inline bool TemperatureSensor::loop() {
uint8_t i;
uint32_t value;
// if ready then process the raw response
if(MillisecondTimer::hasTimedOut(_lastTemperatureTime,500)) {
// bring CS low
GpioSpiCs::reset();
// clock 4 bytes from the SPI bus
value=0;
for(i=0;i<4;i++) {
SPDR=0; // start "transmitting" (actually just clocking)
while((SPSR & (1<<SPIF))==0); // wait until transfer ends
value<<=8; // make space for the byte
value|=SPDR; // merge in the new byte
}
// restore CS high
GpioSpiCs::set(); // deselect the slave
// parse out the value/code from the packed response
processResponse(value);
_lastTemperatureTime=MillisecondTimer::millis();
return true;
}
return false;
}
The 32-bit response from the SPI bus contains the temperature and some status information about the state of the thermocouple. The MAX31855 is able to detect states such as open circuit and shorts to GND and VCC. Here's my conversion code. I take only the integer part of the temperature, discarding the fractional part.
inline void TemperatureSensor::processResponse(uint32_t value) {
// we need a sane compiler
static_assert(sizeof(Response)==3,"Internal compiler fail: sizeof(Response)!=3");
if(value & 1)
_lastTemperature.status=Status::OC_FAULT;
else if(value & 2)
_lastTemperature.status=Status::SCG_FAULT;
else if(value & 4)
_lastTemperature.status=Status::SCV_FAULT;
else {
// if negative value, drop the lower 18 bits and extend sign bits
if(value & 0x80000000)
value=0xFFFFC000 | ((value >> 18) & 0x00003FFFF);
else
value >>= 18;
// resolution is 0.25C, divide by 4 to get the integer value
_lastTemperature.celsius=value/4;
_lastTemperature.status=Status::OK;
}
}
Communicating with the HC-06 Bluetooth module
Communicating with the bluetooth module could not be simpler. The module implements a 9600 baud UART port. You don't have to worry about pairing because it'll do that automatically when it detects a compatible master device and since I'm a slave device I only need to respond to commands that I receive from the master, and receiving commands implies that I'm paired. A flashing red LED on the HC-06 board goes solid red when pairing is successful.
Setting up the USART peripheral in the ATMega8L for 9600 board communications is straightforward:
// 9600 baud: (http://wormfood.net/avrbaudcalc.php?postbitrate=9600&postclock=8&hidetables=1)
UBRRH=0;
UBRRL=51;
UCSRA=0;
UCSRB=(1 << RXEN) | (1 << TXEN); // enable RX, TX
UCSRC=(1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); // 8-N-1
I set out to prove this as a synchronous implementation with the intention of moving it to an asynchronous interrupt-driven implementation if the polling frequency of the main loop caused problems with the protocol. There were no such problems, it seems that my main loop is plenty fast enough so I left as synchronous.
Checking to see if a byte has arrived in the peripheral's data register and then reading it out is a simple task:
// is something ready?
if((UCSRA & (1 << RXC))==0)
return Command::NONE;
// move data into storage
_commandData[_commandPos]=UDR;
Likewise, when you've got some data to send it's just as simple. You just need to wait for a flag to tell you that the data register is clear then you can write to it:
for(i=0;i<5+1+dataSize;i++) {
while(!(UCSRA & (1 << UDRE)));
UDR=_commandData[i];
}
There are many other reusable classes in the firmware. For example there are minimal size implementations of a rotary encoder and a debounced button. There are also very small and efficient GPIO input/output classes implemented in assembly language. You can browse the firmware here on Github.
The Android App
When designing the Android app I had the aim of it working on resolutions down to 800x480 and it should work on tablets and phones alike. 800x480 was chosen as the most common resolution available today on very cheap tablets that you can pick up on ebay. Modern brand-name phones and tablets have much, much higher resolutions. My Google Nexus 10, for example, has a resolution of 2560x1600 - the same as a high-end 30" desktop monitor.
Android programming is straightforward stuff. The need to run on low-end devices means that the APIs are necessarily quite simple. If you've ever programmed C#/WPF then you'll feel at home with the XML/code combination used to create designs and implement code-behind and there are none of the complex features such as property paths and routed events that raise the learning curve for a C#/WPF beginner.
I just can't abide small monitors! (click for larger)
The Android Studio development environment is based on the IntelliJ platform which is pretty good and definitely fit for purpose. It's not as slick and professional as Visual Studio and the Android build/debug process feels slow and cobbled together from command-line tools running behind the scenes but it does work and I've never had to break out of the development flow to go fix some plumbing manually in a config file somewhere. Google have done well to make all that stuff hang together.
The main screen of the app lists a number of options. You can select between the two reflow profiles: leaded and unleaded. You can start the reflow session. You can see the current temperature of the oven and you can change any of the parameters that you can change using the rotary encoder input on the controller itself.
The app will automatically try to connect to the controller when it starts up and will keep trying until it succeeds. Note that communications will continue even after the user navigates away from the app. This is so that when the wife phones up to tell you to record Coronation Street while you're in the middle of a reflow session it doesn't get cancelled or suspended.
The downside of this is that you must manually close the application when you're finished to preserve your battery life. All recent android versions have a button that will show you a list of running apps. Sometimes it's a rotating list and sometimes a left-to-right list. You can use this list to close my app and save battery life.
On this android version you long-press an app icon to close it
Moving on from the main screen to the reflow screen (android calls these screens 'activities') we see a reflow profile chart waiting to start. When you're ready to go you can hit the 'Go' button and the process will start.
A cool glowing green blob will track the progress of the reflow session and you can see this in action in the video that I've linked in later in this article. You can abort it at any time by clicking the 'Stop' button at the top right. I've provided an 'Exit' button to go back to the main screen but you can just as well use Android's built-in 'Back' button.
Credit where credit's due, the icons used in my app are from the icons8 site.
Watch the video
I've uploaded a video to YouTube that shows me going through the build process and then doing a test run at the end. It came out surprisingly long at just under an hour so if you don't mind watching me waffling on for ages then click on the link below to watch it.
Build your own
If you're interested in building one of these boards then here's a summary of the steps you need to take.
- Download the gerbers from my downloads page and send off to Elecrow, ITead or Seeed to get them manufactured.
- Order the parts from the bill of materials from Farnell or your favourite local supplier. Build the board. The video might help you with this.
- Clone the firmware from Github.
- Upload
awreflow2.hex
to the ATMega8L using a USBASP 3.3V programmer connected to the board pins while powering it with 6.3V from a bench power supply. (see Flashing the program to the MCU in the main article). Enable application side-loading on your Android device then installUpdate! You can now get the app direct from Google Play by searching the Play Store for Andy's Workshop.awreflow2.apk
from thebin/
firmware directory.- Switch the controller on first, then the Android device. Pair them. The HC-06 pairing code is probably 1234. Now start the app and wait for the connection. It will take a few seconds.
Enjoy your reflow controller and remember, always treat the mains supply as potentially deadly. Never work on or even touch any part of the board while the mains supply is connected and never work on a mains project unless you're able to give it your full and undivided attention at all times.
That's all for now folks. I hope you've enjoyed reading this article and if you've got any comments then please feel free to leave them below. Questions and discussions can be posted over in the forum where I'm looking forward to hearing your thoughts.
Update 1: improving the phase angle timing
A reader contacted me to suggest that the mapping of the output from the PID algorithm (a percentage) could be improved by considering a non-linear mapping to the mains phase angle. Currently my algorithm linearly maps the desired power percentage to a time along the x-axis of the half-wave. This does not take into account the rising and falling of the waveform — particularly at the start and end of the phase.
So I started thinking. It seems logical that the actual output power at a given phase angle is going to be proportional not to the linear distance along the axis but to the area under the curve. The area under the curve is the definite integral from zero to the phase angle. I could pre-calculate a mapping table of desired output power percentage to a linear percentage phase time duration and store it in flash at a cost of just 98 bytes.
The area under the curve is an easy integration formula
I fired up Excel and got calculating. You can see the results in the spreadsheet in the doc directory on Github. Beware that this spreadsheet contains array formulae that Excel appears to be spectacularly bad at recomputing. Be ready for a few minutes of delay when you open the worksheet.
Calculating a lookup table with Excel
The output from the sheet is a mapping of the desired output power percentage to a linear integer percentage that has the least error from the ideal percentage.
The implementation in OvenControl.cpp and OvenControl.h is trivial and I moved quickly to running a test cycle.
Test run results
The improvements are noticeable in the way that the oven applies power at the low and high ends of the output but I clearly have more work to do to eliminate the oscillation that I get as the algorithm struggles to accurately follow the curve. I intend to improve the insulation, tweak the algorithm parameters and increase the temperature sampling rate in the firmware and the app. More updates to follow.
Update 2: fixing bugs, addressing heat loss
I think I've finally got it where I want it now. There were a number of issues that I addressed to get to this end state.
Firstly there was a bug in the android app. It was supposed to sample the temperature at 0.33Hz on the options screen and 1Hz during a reflow job. The bug meant it always sampled at 0.33Hz. I've changed the logic to 0.5Hz for the options screen and 4Hz for the reflow job. The source and compiled binaries on github have been updated.
Secondly I've insulated the top of my oven with foil. I can't understate the difference that this has made. Heat loss through the glass top was the single biggest issue.
Fully insulated oven (with small observation gap in lid)
Thirdly I've changed my PID parameters to 10/1/0. A large proportional component makes the oven react quickly when needed. I don't need a derivative component.
Test run
The difference is amazing — particularly the insulation. The oven never has to apply 100% power except for a second or two during the ramp-up period. The rest of the time it just gently applies small nudges to the temperature. Ignore the steep ragged falls at the end — that's me lifting the lid to cool it down because the oven has no means to actively lose heat.
You can see the effect of all these improvements in this followup video:
Update 3: Bug fixes and ATMega8L firmware improvements
Version 2 of the app is now available from the Google Play Store and fixes a few minor issues. I'd advise everyone to upgrade to this new version. Details of the bugs that were fixed are in the Play Store release notes.
There's also a new version of the ATMega8L firmware available now in github. This release fixes bugs in the manual reflow option and adds a new feature that continually shows the current oven duty cycle while the android device is connected.
Pingback: Android-based Reflow Brings Solder Profiles to Your Lab | Hackaday()
Pingback: Android-based Reflow Brings Solder Profiles to Your Lab | Hack The Planet()
Pingback: Android Based Reflow Controller - Electro-Labs.com()
Pingback: Projects i want to do. | John's Ramblings()
Pingback: Homemade Reflow Controller with Android & Bluetooth via @andyworkshop « Adafruit Industries – Makers, hackers, artists, designers and engineers!()