Through the first three parts of this series (links to part 1, part 2 and part 3) I’ve experimented with and refined to a degree the use of ACS712 current sensors for block occupancy detection. The system works well in DC mode, lighting up whenever a running DC train enters or is powered up in a block; program logic “remembers” block states when power is off for control reasons. My DC locos typically start drawing 30 – 50 mA when the lamps come on.
In DCC mode, ultra low current detection becomes an issue and the off-the-shelf ACS712 sensors don’t meet every need. My BLI DCC/Sound Locomotive draws enough power to be detected with the current system in idle mode, all sound and lights off. However, some standard DCC decoders draw so little current in idle mode that they are not consistently detectable. Further, constant track power in DCC invites us to find a way to sense any object drawing some minimal increment of current — such as 1.1 mA for a 10KΩ resistor wheelset on an 11 volt (in N scale) feed. There are a number of obstacles to achieving 1 mA sensitivity with ACS712 sensors.
First, there is a question of how low a current the ACS712 can resolve. Theoretically, because the chip responds in a ratiometric way to current input, any amount of current will provoke a proportional output response. In reality, the output of the chip is a little noisy, and the noise masks the low current response.
Allegro MicroSystems says that the best resolution with the optimum filter capacitor is 20 mA. There is some general agreement among internet cognoscenti that with some amplification of the signal from the ACS712, greater sensitivity should be possible.
Second, the 10 bit ADC built into most Arduino boards has a maximum resolution of 4.88 mV (5 volts / 1024 steps), limiting the minimum detectable current to 26 mA (4.88 mV resolution / 185 mV/A sensitivity). Even the 12 bit ADC found in the Due and Zero boards is not quite close enough, with a maximum resolution of 1.22 mV (5 volts / 4096 steps), resulting in minimum detectable current of 6.6 mA.
A Better Analog-to-Digital Converter
Of the two problems, this is by far the easier problem to solve by using an external ADC with a 14 or 16 bit resolution. A 14 bit ADC has a maximum resolution of .305 mV, which is a good resolution for consistently detecting current at the 1.6 mA level or higher; a 16 bit ADC would provide 76 µV resolution and current detection in the mid to high µA range. For those wanting to detect a single resistor wheelset, 16-bit is the way to go.
For my purposes and goals, I’m going to see how it goes with 14 bits so I’m not pushing resolution past the point of usefulness at this stage. My thinking is that 1.6 mA should be sufficient to detect a pair of resistor wheels. Two 10kΩ resistors in parallel have a resulting resistance of 5kΩ, which at 11 volts will draw 2.2 mA (@16 volts, 3.2 mA). Assuming I can overcome the noise problem to the point where 14 bits of resolution provides accurate current detection, the final step would be to go to 16 bits.
I looked at several ADC products and settled on the Mayhew Labs Extended ADC Shield, which is also available at Amazon. I chose this for several reasons: it supports 8 inputs, comes in a shield format and (perhaps most importantly) offers enough bandwidth to be able to sample multiple sensors at a reasonable rate.
Mayhew provides a code library for reading a variety of sensor types through the shield. It is fairly straight forward to use, and the shield is a very good quality piece of gear. I have found other ADC boards, but none with the unique capabilities of this one.
Sparkfun Low Current Sensor
Sparkfun sells a breakout board as a low current sensor using the ACS712 sensor chip plus an operational amplifier to amplify the signal. This is the only commercial solution of its type I’m aware of, so I bought one to check out and test. The schematic for the board can be seen here.
Although the circuit is promising, this board is really an experimental item and not suitable for production use on a model railroad. Part of the problem is that it does not provide — and is not drilled for — standard screw terminals for attaching the input current source, adding additional challenges to deployment. On the input side (I+ / I-) it is drilled for a pair of header pins and two larger holes with contact pads. The control side (VCC, OUT, GND) is drilled for standard headers.
Secondly, because this is an experimental board, it has two trim-pots for configuring the Op-amp. Sounds great, but in practice this setup doesn’t work well. Add sketchy instructions for setting and using the board and I think most will find this board impractical for large scale use, though an interesting experimental tool.
Learning By Failing
So when the board arrived, I soldered on some header pins and hooked up the sensor to an UNO with the Mayhew ADC Shield, then attempted to configure and use the board. Here are the setup instructions in their entirety:
“To calibrate, first set the output offset to the desired level (with zero current on the sense lines, read output with a DVM). Then with a known current input (a 100mA limited supply works well for this), set the output deflection with the gain pot. Sensitivity is then calculated as (Vref – Vdeflect)/(current input).”
The “output offset” is (presumably, though not literally stated) adjusted with the vref trim-pot. But what “level” is “desirable” for this application? The second instruction is even weirder, since you are not going to short out a power supply by directly attaching it to the sensor without a load, and its the load that determines the current flow. I’m sure they meant to say something like “supply a load with a known current draw.”
I tinkered fruitlessly with the trim-pots for hours, testing various theories about how it should work and getting nothing intelligible out of the sensor. The gain pot is straightforward enough, resulting obvious changes to readings as the trim-pot is adjusted. Its the vref adjustment that mystified me and seemed to have no logic. I did notice that when setting it there was a point where the output would suddenly, but only briefly, drop to O. That zero point is so finely specific that it is essentially impossible to set the trim-pot at that level; it always ends up off one way or another. That was a clue, but I did not yet understand.
Back to School
I found a nice tutorial about Op-amp circuits and, after a while started to understand the circuit and comprehend the problem. If you don’t understand Op-amps (who does among those of us not trained in electrical engineering?), check out the tutorial before reading further here.
The Op-amp circuit Sparkfun uses is a “voltage subtractor,” the intent of which is to subtract the input voltage from the reference voltage and amplify the difference. This is the right choice—I think—but the implementation is wrong, at least for my purposes.
Unique ACS712 Properties
Many sensors that one might use with an Arduino are straight forward linear output devices where the output voltage ranges from 0 to 5volts in proportion to an input (light, temperature, etc.).
What makes the ACS712 different is that it senses both polarity and current of the measured input. The “quiescent voltage” we measure when calibrating a sensor is the sensor’s “zero” point: ideally VCC/2 — midway between 0 and VCC (nominally 5 volts). When the polarity is one way the measured current is represented by a value above VCC/2; when the polarity is the opposite, the sensor produces a value under VCC/2.
That means that we are only interested in the offset between the sensor output and its quiescent value. The software calibration routine I’ve been using seeks to get the most accurate average mid-point value possible to enhance the accuracy of the offset measurement. Amplifying that offset should be the route to gaining sensitivity.
Shouldn’t vRef be VCC / 2?
It may well be that the vref adjustment has value when measuring DC current with a fixed polarity. However, I’ve seen no math or theory in support of that proposition. For measuring DCC current, which is an 8kHz alternating polarity wave form, there is only one correct reference voltage for comparison to the ACS712 output: VCC/2. So, Sparkfun had the right idea using a trim-pot as a voltage divider circuit to generate the reference voltage, but the trim-pot inhibits setting vref to VCC/2 because it is too imprecise to set the two resistor legs to exactly the same value.
The Sparkfun sensor experiment was a bust in that it did not produce a usable result. But it did help me research and think about what it is I need an operational amplifier to do in order to successfully amplify the ACS712 signal. Sometimes we learn more from failure than we do from success.
The next step is the set up an Op-amp with a fixed reference voltage of VCC/2, then continue experimenting from there. I have the parts. In a few weeks, if time permits (between work and our ailing Beagle, time is tight right now), I should have some sort of result.
5 thoughts on “Block Occupancy Detection for DC and DCC, Part 4”
I’m wondering if the effects with DCC would be the same on HO decoders or if the ACS712 will not detect them well either. I’m waiting for the last of my components (Uno) to come in so that I can start trying your methods.
So, using the 10-bit ADC in your Uno, a DCC loco needs to draw 26 mA to be detectable. So long as the engine moving or has a light on it should draw at least that much. The tougher issue is idle draw, and the newer decoders — even HO scale — may not draw enough when on power but otherwise inactive. DCC-Sound decoders are a different matter altogether and easily draw enough current when idle. I’ve yet to find any formal specifications for the idle draw of a decoder.
If you get inconsistent detection with the built-in ADC, try one of the Mayhew Labs boards. The additional sensitivity should help. There are a couple of other good options for external ADC’s out there as well. Watch out for bandwidth specs – that’s a limitation on the frequency you can take readings accurately.
What about using an analog comparator with an appropiate Vref+/Vref-:.
With 2 10K Resistors and just ONE trimpot of about 1K we could adjust to the desired level (my first calculation gives me about 333 Ohms should do the tric)
We do not need to amplify the (Vin-Vcc/2) just to know when it’s around Vcc/2.
The output is negated, that is: when the window comparator is HIGH, the block is NOT occupied. When it is LOW, the block IS occupied.
Interesting suggestion. I’ll add that to the circuits I’m experimenting with. Thanks!