8051 Furnace Controller: Relay Chatter, ADC Jitter and Resets
An 8051 system at 11.0592 MHz monitors a furnace with an LM35 sensor (10 mV/°C) through an ADC0804 and switches a 5 V relay through a BC547, with a 1N4007 across the coil. The relay contact drives a 1 kW heater through a contactor. Timer 0 in mode 1 is loaded with TH0 = 0x4C and TL0 = 0x00 for a 50 ms tick, and the program polls the ADC every tick and energises the relay when the reading exceeds a setpoint byte. On the bench the relay buzzes when the temperature is near the setpoint, the displayed temperature flickers by about ±1 °C, and every time the relay switches the 8051 occasionally resets or the ADC returns 0x00. The board uses a single 7805 with a 100 µF input capacitor and a 10 µF output capacitor, and the relay coil is powered from the same 5 V rail. The serial port is also to be used at 9600 baud with Timer 1.
1. Verify the 50 ms Timer 0 reload and the 9600 baud Timer 1 reload, showing the arithmetic.
Read the worked answer
Machine cycle. One machine cycle is 12 oscillator periods: 12/11,059,200 = 1.085 µs.
Timer 0, mode 1 (16-bit). 50 ms needs 0.050/1.085 × 10⁻⁶ = 46,083 counts. Using 46,080, the reload is 65,536 − 46,080 = 19,456 = 0x4C00, so TH0 = 0x4C and TL0 = 0x00 is correct, giving 46,080 × 1.085 µs = 49.99 ms - an error of 0.02%, which is irrelevant here. Note that mode 1 does not reload automatically; the interrupt service routine must rewrite TH0 and TL0, and the reload instructions themselves add a few microseconds of jitter.
Timer 1, mode 2, SMOD = 0. Baud = fosc/(12 × 32 × (256 − TH1)) = 11,059,200/384/(256 − TH1) = 28,800/(256 − TH1). For 9600, 256 − TH1 = 3, so TH1 = 0xFD, giving exactly 9600 baud. This exact division is why 11.0592 MHz is chosen for 8051 serial work; a 12 MHz crystal would give 8,928 baud, a 7.4% error, which is outside the tolerance of a UART link.
If both timers are needed simultaneously, keep Timer 1 in mode 2 for baud generation and Timer 0 in mode 1 for the tick.
2. Explain the relay buzzing and the ±1 °C flicker, and design a software fix with numbers.
Read the worked answer
Quantisation. ADC0804 with Vref/2 = 2.5 V has an LSB of 5 V/256 = 19.5 mV. The LM35 gives 10 mV/°C, so one LSB is 1.95 °C and a ±1 LSB conversion uncertainty is about ±2 °C. The displayed flicker is therefore quantisation plus noise, not a sensor fault. It is also large enough to cross a single setpoint on successive samples.
Buzzing cause. The program compares one sample against one setpoint byte. When the reading oscillates around that value, the relay is commanded on and off every tick, producing audible chatter and rapid contactor cycling that will destroy the contacts.
Fix.
- Average 8 or 16 samples, or use a moving average, to reduce random noise by √N.
- Add hysteresis of at least 2 LSB (about 4 °C): switch on at setpoint + 1 LSB and off at setpoint − 1 LSB. A ±1 LSB flicker can then never toggle the output.
- Enforce a minimum on-time and off-time, for example 5 s (100 ticks), regardless of the reading.
- Filter the LM35 supply and the ADC reference, keep the analog ground separate from the relay ground, and clock the ADC within its specified range (about 100–1,460 kHz) from a timer or ALE rather than from a slow software strobe.
With these changes the same 8-bit hardware can hold the furnace within a couple of degrees even though its raw resolution is only 2 °C.
3. Diagnose the occasional resets and the ADC reading 0x00 when the relay switches, and list the hardware fixes in order of priority.
Read the worked answer
Diagnosis. The events coincide with relay switching, which points to the inductive load, not to the program. When the BC547 turns off, the coil's stored energy is clamped by the 1N4007, but the resulting current loop and the fast di/dt on the shared 5 V rail produce ground bounce and a supply dip. The 7805 with only 10 µF of output capacitance cannot hold the rail, so the 8051 sees a brown-out and resets, while the ADC0804's conversion is corrupted and returns 0x00. The contactor coil on the AC side adds further coupling through the air and the mains wiring.
Fixes, in priority order.
- Give the relay coil its own supply and ground return, or at least a separate trace to the 7805 input side, joined at one star point; never route coil current through the microcontroller's ground.
- Add a 100 nF ceramic directly across the 8051 VCC/VSS pins, plus 100 µF bulk near the regulator, and a 100 nF across the ADC supply.
- Insert an optocoupler (for example PC817) between the port pin and the transistor so the MCU drives only an LED current.
- Add an RC snubber (100 Ω + 0.1 µF) across the relay contacts and a MOV across the contactor coil to suppress mains-borne transients.
- Replace the 1N4007 with a faster diode such as a UF4007 or 1N4148, mounted at the coil terminals rather than on the board.
- Enable the 8051 watchdog, re-initialise the ADC and the port directions after reset, and re-read the ADC only after a short delay following any relay transition.
Selecting the transistor for the coil current and keeping the relay wiring away from the analog input completes the fix.