On Simplicity and Sensitivity – The Texas Instruments ADS1247

I’m still very much in the prototyping and design phase of this project – trying out component circuits with a hodge-podge of jumper wires and breakout boards to ultimately create a working prototype.

An analog to digital converter (A2D) takes an analog signal within a specific voltage range and estimates the numerical value that best represents that signal. Because the Resistance-Temperature-Device (RTD) used in this project changes resistance as temperature changes, we need a way to accurately and reliably measure the subtle changes in resistance that will occur. I’m aiming for an accuracy of 0.1°C or better for this project which translates to a change of only 0.0379Ω per 0.1°C. So here’s the rationale: if we pass a fixed current across the RTD, then the voltage will always be proportional to the resistance according to Ohm’s law. If we can find a suitably sensitive device to measure the small changes in voltage, we have a way to measure the PT100 resistance and thus estimate the temperature. Moreover, the RTD is only expected to have ~80Ω worth of change in the temperature range that Silvia will be operating. At the low currents that we’ll be using on the RTD, we’re looking at only 120mV of voltage change. That’s a fraction of the total 0V-5V range that normal A2Ds use as a reference (including the A2D on the Arduino Pro Mini). So, we need a way to scale up that 120mV to something that’s easier to quantify. Most people would turn to an Op Amp based circuit. This type of device effectively feeds back on itself to scale an analog signal in amplitude. However, this requires a bit of external circuitry and can be subject to electrical noise if the circuit isn’t clean.

Enter the ADS1247 – an all-in-one device that: has 24 bits of resolution (21 effective bits, or 2.1 x 106 possible values), generates a fixed current on its analog pins, and can scale input voltages using a Programmable Gate Array (PGA) (similar to an op-amp circuit). This chip can communicate with the Arduino via 3 pins dedicated to the SPI communication bus.

I will eventually publish the full schematic, however the basic design for a circuit incorporating the ADS1247 chip is simple and follows a similar design to the TI published example (see Example 7). Effectively I will use a low tolerance 140Ω (0.05% tolerance) resistor as RREF to centre the 80Ω resistance swing at the half-way point (~140Ω at 100°C) and a 750Ω (0.05% tolerance) resistor as RBIAS to create a reference voltage (±2.25V). I’ll set the analog input pins to output a fixed 1500μA current and the PGA to multiply the ±60mV voltage developed across the analog input pins by 32 to ±1.92V (and well within the ±2.25V reference range). With this setup, I expect to obtain a maximum resolution of ~8.4 x 10-9 V per bit. Fantastic!

While this design is fine in theory, I wanted to try it in practice. More importantly, I wanted to see if I could even get it working smoothly with the Arduino. So I wired up a prototype circuit based on TI Example 7 using a couple of resistors as RREF and RBIAS, as well as a trim-pot to simulate the RTD. The only other component required was a 10μF capacitor between VREFCOM and VREFOUT to stabilize the internal voltage reference.

I coded up the Arduino as follows:

#include <SPI.h>

unsigned long A2DVal=0x0;

void setup()
{
SPI.setClockDivider(SPI_CLOCK_DIV16); //1MHz Bus Speed
SPI.setDataMode(0x04); //SPI_MODE1
delay(2000); //Give you time to open up the Serial monitor as it will restart the Arduino but not ADS1247
SPI.begin(); //Turn on the SPI Bus
SPI.transfer(0x06); //Reset the ADS1247
delay(2); //Minimum 0.6ms required for Reset to finish.
SPI.transfer(0x16); //Issue SDATAC
SPI.transfer(0x40); //Set MUX0 Register (00h) Write 01h
SPI.transfer(0x00);
SPI.transfer(0x01);
SPI.transfer(0x42); //Set MUX1 Register (02h) Write 38h - Select internal reference always on, internal ref connected to REF0 pins. Use 33h if wanting an on chip temp read.
SPI.transfer(0x00);
SPI.transfer(0x33);
SPI.transfer(0x43); //Set SYS0 Register (03h) Write 52h - PGA:32, Sample at 20sps
SPI.transfer(0x00);
SPI.transfer(0x52);
SPI.transfer(0x4A); //Set IDAC0 Register (0Ah) Write 07h - Select 1.5mA reference current for RTD
SPI.transfer(0x00);
SPI.transfer(0x07);
SPI.transfer(0x4B); //Set IDAC1 Register (0Bh) Write 01h - Output reference current on ANIN0,1
SPI.transfer(0x00);
SPI.transfer(0x01);

//Enable Serial
Serial.begin(115200);
}

void loop()
{
//Reset A2D Storage Value
A2DVal = 0x0;

SPI.transfer(0x12); //Issue RDATA
A2DVal |= SPI.transfer(0xFF); //Write NOP, Read First Byte and Mask to A2DVal
A2DVal <<= 8; //Left Bit-Shift A2DVal by 8 bits
A2DVal |= SPI.transfer(0xFF); //Write NOP, Read Second Byte and Mask to A2DVal
A2DVal <<= 8;
A2DVal |= SPI.transfer(0xFF); //Write NOP, Read Third Byte and Mask to A2DVal

//SPI.transfer(0x22); //Read Register 0x2
//SPI.transfer(0x00); //N - 1 Bytes To Be Read
//A2DVal |= SPI.transfer(0xFF); //Mask to A2DVal

Serial.println(A2DVal,HEX);
delay(1000);
}

The ADS1247 also has an onboard temperature sensor that can be read instead of the analog inputs by writing to MUX1 register with 33h. When doing this, the value returned by the Arduino was 0764XXh where XX (the least significant byte) fluctuated. I could push this up to 0771XXh when I blew on it with my breath or touched the chip with my finger! I also tried out the actual analog inputs (MUX1 should be set to 38h) and was able to get the value to change according to the trim pot.

It’s now just a matter of sourcing some low tolerance resistors for the final circuit – let me know if anyone knows of any vendors!

More to come soon.

On Brains and Brawn …

I have decided to use an Arduino Pro Mini (5V @ 16MHz) as the brain inside Silvia. The Arduino community is very active, the devices are well-supported, and above all, it’s cheap. This microcontroller is $19, and has everything onboard to immediately begin controlling Miss Silvia including built-in serial, SPI, and I2C communication busses and of course digital input/output pins.

The temperature sensor I chose to replace the bi-metal thermostats inside Silvia is a PT100 RTD sensor (a platinum resistor inside of a bi-metal thermostat case) from Auber Instruments. This device should provide accurate and reliable temperature measurement to within 0.1°C. The electrical resistance across the RTD changes proportionate to the temperature (more on this in a bit). Effectively, this is a drop-in replacement for the bi-metal thermostat and does not require any tinkering short of swapping one for the other. At $23, this component is by far one of the most expensive that I plan on using.

That the RTD sensor is so accurate necessitates a comparably accurate device capable of measuring the small changes in resistance that the RTD will produce. An analog-to-digital (A2D) converter measures the voltage of a device in reference to known voltages and converts it into a number. The Arduino has a 10-bit (1023 possible values) A2D converter on board, but the voltage range is between 5V and 0V, giving an effective measurement range of 4.88mV. While this might seem like a small voltage to many, this only translates to an effective accuracy of ±10°C across the RTD. I needed a device far more sensitive and able to provide 2 orders of magnitude greater resolution. I settled on the Texas Instruments ADS1247. This is a 24-bit resolution A2D that supports SPI serial communication, has a built-in PGA (signal amplifier) and is able to take 2000 sample readings from the RTD every second. Based on the working design that I’ve come up with, this device will be able to effectively measure voltages as low as 3.35×10-8V. That’s really low, and in fact provides effective accuracy of 0.02°C. Moreover, this device contains two A2Ds allowing for a second temperature reading if a second RTD is present. Is it overkill? Maybe, but the ADS1247 is thoughtfully designed and easy to implement, making this a good choice. Quite literally, two low-tolerance resistors and the PT100 RTD sensor will be wired across this device. The remaining pins will be at ground, 5V, or wired to the Arduino for communication. While the device has a nominal $5 price, Texas Instruments has a fantastic ‘Sample’ program. I was able to obtain three of these little guys for free!

Other design choices include a 2 row x 16 character display from Newhaven Display (NHD-0216K3Z-NSW-BBW) at a $22 price tag. This display has a wide operating temperature range (-20°C to +70°C), supports I2C, SPI and RS232 serial communication, has custom programmable character sets as well as built-in backlight and contrast control. What this translates to from a design perspective is fewer pins that are required for dedicated communication with the Arduino (only two pins are required as it will be wired up to the I2C bus onboard the Arduino).

To report on the main switches, I chose to go with the MID400 AC Line Monitor from Fairchild Semiconductor. This part has a nominal $3 price tag. One chip is required per switch (Brew, Hot Water, Steam). These chips can be wired directly to the Arduino and require only a single 22k resistor to function.

Finally, to actually control and operate the boiler and pump within Silvia requires a relay capable of switching on and off 120VAC at high currents from the 5V logic that the Arduino will produce. Solid-state relays (SSRs) are an effective technology for this, reasonably priced and compact enough to fit comfortably within Silvia’s abdomen. From seeing diagrams of Silvia’s components, as well as opening up my own machine, all electrical connections within Silvia are made using QuickConnect tabs / fins (readily available from the automotive section at your favourite hardware store). This is great because it allows easy installation of a relay within Silvia. I decided to go with the Crydom UDP2415DF series as this relay has two SPST optical zero-crossover SSRs built in to one package with QuickConnect tabs allowing for effective control of both boiler and pump. Each relay within the package is rated up to 15A @ 280 VAC (more than enough for Silvia) and can be activated by 3-32 VDC. Although the price tag on this is somewhat more expensive ($58), two independent SSRs will run you about the same from Crydom. The back of the relay is metal casing and designed for connection to a heat-sink. Rather than use a heat sink, I’ll mount the relay to the metal interior using double-sided thermal heat-sink tape and therefore use Silvia’s body as the heatsink. Regardless, the relay has an operating temperature up to 80°C.

Finally, to power the Arduino, A2D converter, display, and SSR, I decided to go with the VSK-S3-5U onboard switching power supply from CUI inc. This is basically an all-in-one package designed to output 5V of regulated power and up to 600mA of current – more than enough to power Silvia’s brains. This comes in at $15. I suppose I could have hacked apart an old wall-wart power adapter, but due to the precision and stable voltages required to make an accurate reading from the A2D, I needed a stable and well-filtered 5V source.

That’s it for big-ticket items. The remaining components are standard resistors and capacitors. The rough total based on these component decisions is ~$150. Other expenses I anticipate are the final PCB and two low-tolerance (high accuracy) resistors required for the A2D.

More to come! I’ll also post a final parts-list / BOM once I get the schematics finalized.

The Idea …

So I’ve had my Miss Silvia now for five months. And in that time, I’ve managed to finess some fantastic shots from her. But there’s a routine that I must go through. Many who own a Silvia are fondly familiar with the idea of “temperature surfing” – that you catch Silvia at her warmest (and in this case, ideal temperature) by pulling water through the group head or steam arm until the boiler turns on, and then pulling your shot just after the boiler turns off. The reason for this is obligatory – in the quest for a reliable (admirably so) design, Silvia uses bi-metal thermostats to control how hot and bothered she gets. For non-technical folk, it means that the boiler temperature can fluctuate by up to 15°C (~30°F) and that translates to an inconsistent shot with a myriad of unwelcome flavours. That I pay reasonable money for my espresso beans, means that I want to enjoy the best possible flavour from my beans.

The Silvia is commonly modified (as I’ve seen online), and there are several kits that are sold to provide Silvia with optimal temperature control. The device is called a PID controller – a Proportional-Integral-Derivative controller (see the Wiki page if you want to know more).  The gist of it is that a PID installed on Silvia ought to provide reliable and accurate control of her innards. There are several kits available on the market that allow refined control of Silvia with a reasonably appealing aesthetic but with some caveats.

I’m a tinkerer, and when I’m presented with a problem, I like to reinvent the wheel. This for me means that rather than buy a PID kit, I’m going to design my own. The features that I want to include far exceed anything that’s available on the market, so it seems fitting to try my hands at this and learn a bit along the way.

My posts in this blog will be about design choices, the build process, successes, and downfalls. Ultimately, I hope to create something wonderful.