In this project we modified a coffee roaster to make it computer controlled. It uses an Arduino Uno and some custom hardware we installed into the roaster. The Arduino is interfaced via USB to a PC. The PC runs Linux and a user interface designed with Gambas 2.
WARNING!
This project involves voltages and currents that can easily kill or injure you or others. Unless you really know what you are doing – and have experience and training in how to deal safely with high voltages and currents – do not attempt to duplicate this project. Regardless of your experience level, if you do try to build any part of this project, you assume all liability for anything that happens as a result.
Here is the original coffee roaster that we started with.
Below is the original heater circuit used in the coffee roaster. There is a similar circuit used to control the fan speed.
Note that this is a classic dimmer circuit using a phase-angle fired triac. The potentiometer adjusts the voltage at which the triac fires. This type of dimmer has been well described elsewhere – including Wikipedia – so I won’t repeat that here. There is an application note from Littlefuse here and you can find plenty of other documentation on the web.
In our case we use the Arduino to decide when to fire the triacs rather than using the original analog circuit.
The Arduino controls the fan speed and the heater current based on serial commands from the PC, or based on knob settings on the front panel, depending on the control option setting. It also reads the roaster temperature using a type K thermocoupe and reports this data to the PC.
Here is a snapshot of the user interface.
The serial protocol for communicating between the Arduino and the PC can be found here. The state machine for decoding the serial protocol in the Arduino is below.

The thermocouple is read using the MAX 6675 thermocouple interface chip. We ordered a breakout board and thermocouple from Adafruit.
Here are some pics of the Arduino with the breakout board and thermocouple attached.
Here are the I/O pins we are using:
Arduino Uno I/O Pin Usage | ||
Digital Pin | Connection | I/O |
0 | Serial Receive Data | Input |
1 | Serial Transmit Data | Output |
2 | Zero Crossing Detect (INT0) | Input |
3 | MAX 6675 Ground | Output |
4 | MAX 6675 VCC | Output |
5 | MAX 6675 DO | Input |
6 | MAX 6675 CS | Output |
7 | MAX 6675 CLK | Output |
8 | Open | |
9 | Fan triac trigger | Output |
10 | Heater triac trigger | Output |
11 | Front panel LED – Manual | Output |
12 | Front panel LED – Computer | Output |
13 | On-board LED | Output |
Analog Pin | Connection | |
A0 | Heater Front Panel Pot. | Input |
A1 | Fan Front Panel Pot. | Input |
A2 | Open | |
A3 | Open | |
A4 | I2C Display Interface | Output |
A5 | I2C Display Interface | Output |
The circuit for the power control is below.
It was difficult to find a good well-written example of Arduino code to do phase-angle firing of a triac. There are examples out there but they tend to use existing timer libraries (which are really intended for PWM) or other methods that are more approximate.
We need to drive two triacs that are triggered at different times during each cycle. Luckily the ATmega 328 processor on the Arduino Uno includes a 16-bit timer (Timer 1) with two compare registers that can each drive an output pin (pins 9 and 10 on the Arduino board). We load the two timer compare registers with the turn-on time for each triac, reset the timer when a zero-crossing is detected, and let the timer trigger each triac. The timer compare interrupt service routine then resets the triac trigger signal after an appropriate delay. The timer prescaler is set to clk/8 so the timer resolution is 0.5 microseconds, which is fine for our purposes. The zero-crossing detector is connected to the interrupt 0 pin (pin 2) and will cause an interrupt at each zero crossing. The interrupt service routine then resets the timer.
Note that for the heater what we really want is to deliver power (watts) that vary linearly between 0-100%. This is because the heat generated by the heater element is proportional to the power supplied. The application note from Littlefuse shows a graph of how RMS voltage, average voltage, and power vary with the angle (or time) at which the triac is fired. I have also generated a graph of firing angle versus power output which is shown below. As you can see, the power output is not linear with respect to the time at which the triac is fired.
We use a lookup table in the Arduino to know when to fire the triac to provide a linear power output of 0-100%.
The fan motor control is a little more complicated. We use current rather than power to linearize the output, and there is an offset below which the fan will not turn at all. The fan motor also does not like rapid changes from one output level to another, as the inductance of the motor causes problems with the triac circuit. We could have compensated for this in hardware, but we chose to use software to simply ramp the output between settings at a fixed rate. In the end this all worked quite well.
The two front panel control knobs (potentiometers) on the roaster are connected to two analog inputs on the Arduino board. When the unit is powered on it defaults to manual control and the knobs will control the heater and fan speed. The PC can send a command to switch to computer control and in that mode the front panel knobs will be ignored. LEDs on the front panel indicate the control mode (manual or computer).
The source code for the Arduino software is listed here.
The waveforms for the triac triggering look like this:
The upper waveform shows the zero crossing detect signal and the bottom waveform shows the triac trigger pulses. The output is set to 50% in this case so the triac is triggered halfway through the cycle.
Here is the power control board:
The top half of the board is the high voltage section and the bottom half is the isolated low voltage section that connects through the ribbon cable to the Arduino.
As we were going through final testing of the circuits before installing them in the roaster, we decided to add a small LCD display as well. This will allow us to read the temperature even when there is no computer attached. The display interfaces to the Arduino using I2C and the Wire library. Here is a picture of the display we picked, Jameco part number 2118651.
Here is the complete set of boards prior to installing in the roaster.
It was quite difficult to fit all this in the roaster, but we did manage to get it all in there with some careful mounting. Check the blog for more details on how that was accomplished.
Success! In the end it all worked out very well.