Gone are the days when you could do most of your own maintenance on your car’s engine. Today they’re sophisticated electronic systems. But there are some things you can do with the right tools. In this article, Jeff talks about how using the timing light on his car engine introduced him to non-contact sensor technology. He discusses the types of probes available and how to use them to read the magnitude of alternating current (AC).
No doubt you’ve looked under the hood of your automobile to find every conceivable piece of real estate crammed with mechanical and electrical components. Believe it or not, there was a time when you could see clear to the ground around the engine. People use to change their own oil, spark plugs, and thermostat, doing all the periodic maintenance themselves. Today we pass this all off to the local mechanic. Annually I would change the points, plugs, condenser and adjust the distributor using a timing light. The timing light was a strobe that was triggered by clamping a probe onto one spark plug. Whenever the plug fired, its high voltage pulse was picked up by the probe, which triggered the timing light flash. You point the flash at a timing mark on the engine and watch the groove in the engine shaft’s pulley. With the distributor loosened, you rotate the distributor to adjust the point in the piston cycle where the spark plug would fire to ignite the gas mixture (Figure 1).
Those of you who want to tune-up your own engine can stop reading this now. I don’t claim to be a grease monkey. Mind you I use the term grease monkey as I would nerd—it’s my professional description of someone who loves to work on automobiles. For me, the timing light is one of the tools of that trade that introduced me to non-contact sensor technology. The probe that clamped around the spark plug wire could be capacitive or inductive. This discussion will center around using inductive technology as a current probe.
The probe is an electrical device that surrounds an electrical conductor. This allows measurement of the current through the conductor without the need to make physical contact with it. This type of current probe comes in two varieties. First there’s the closed probe—which requires the conductor to be disconnected, passed through the toroid, and reconnected. Next is the clamp probe—which can be placed around the conductor without disconnection. Obviously, it is easier to use a clamp probe, but the closed probe is smaller and often less expensive. In this project, we will be using these probes to read the magnitude of alternating current (AC).
CURRENT PROBE TEARDOWN
The current probe is essentially a transformer that uses the conductor as a one-turn primary coil, as shown in Figure 2, unless you wrap the conductor so it goes through the core multiple times. The core is usually a ferrite toroid (one-piece, Figure 3a) as used in a closed probe, or a split-ferrite toroid, as used in a clamp probe (Figure 3b). Current moving through any conductor creates a magnetic field around the conductor. The magnetic field is happy to flow through the ferrite. Since the transformer secondary is also wound on the ferrite, the magnetic field induces a current in the secondary. This current passes through a load resistor, which develops a voltage across it in proportion to the secondary current and the magnetic field in the transformer core.
When dealing with voltage, the ratio of the primary to secondary windings of the perfect transformer directly determines the ratio of input to output voltage, with more secondary turns producing higher output voltages. While the output voltage increases, output current is reduced by the turns ratio.
The load resistor placed on the output of the current probe is called the “burden resistor.” If we design for a 1 V maximum output voltage on the burden resistor of 100 Ω, we will have a current through this resistor of 1V/100Ω = 10 mA. If we want this maximum of 10 mA in the secondary to equal 1 A of current through the primary, then we will need a turns ratio of 1A/0.01A = 100 or 1 primary turn to 100 secondary turns, 1:100. Both transformer core losses and saturation issues must be taken into consideration. Probe manufacturers have done all the design work for you and offer datasheets and application notes to make this all “a piece of cake.”
You can purchase low-cost probes that already contain the necessary transformers and burden resistors to ease your design. Many are designed for ±1 V output for rated current. The SCT-013 is available without a burden resistor. Add the appropriate burden resistor, and you can measure any current range up to 100 A. Use a burden resistor of 10 Ω, and at 50 mA you will measure ±1 V for a full scale of 100 A. Use a 100 Ω resistor, and you get a range of 0-10 A. A 1,000 Ω resistor will give you 0-1 A. This line also has separate products available with burden resistors for a full scale ±1 V output of 5, 10, 15, 20, 30, 50, 60 and 100 A.
When measuring AC current, the voltage presented will alternate in polarity. For most analog-to-digital converters (ADCs) that are an internal peripheral in a microcontroller (MCU) this is an issue, because they tend to be referenced to ground. To use these probes, you need to apply the probe’s voltage to a bias voltage, which will raise it sufficiently to prevent negative voltages. This design will allow the probes to be used with a 5 V or 3 V supply. I’ve selected a Texas Instruments (TI) LM4040 Precision Micropower Shunt Voltage Reference to provide this bias. It’s available in a variety of different reference voltages from 2.048 V to 10 V. Either the 2.048 V or 2.5 V reference could be used here—depending on the maximum current you expect and the references available to the ADC in your MCU.
The device is a precision Zener for which a series resistor sets the maximum current that can be handled by the Zener. In this case, 15 mA is suggested. To operate correctly, it must have a minimum of approximately 200 µA of current. Since whatever you connect as a load across the Zener will share the current through the series resistor, you must make sure your load does not require more that the design current—15 mA minus the minimum regulation current—or else the reference cannot regulate properly.
The basic load across the Zener is a voltage divider that will provide a reference of one-half the Zener value. The lower leg of the divider has a capacitor across it to further prevent this reference from wavering under changing load conditions. Figure 4 shows the schematic of this probe’s preconditioning circuitry. The probe is connected across the upper leg of the voltage divider. It is therefore referenced to the bias voltage. With no signal from the probe, the voltage presented to the ADC is one-half the Zener reference. This is the bias that lets the probe’s output rise above and fall below it by 1 V without going negative. Using a 2.048 V LM4040, a full-scale probe output will vary from 0.024 V, during the negative output of the probe (1.024 V to 1 V), to 2.024 V, during the positive output of the probe (1.024 V + 1 V).
Because this probe is being used on 60 Hz AC, we know that any output is going to be continually changing at this rate. A single sample could get a measurement from anywhere in the cycle. We could look for zero-crossings by physical or measurement means, and then resample after a 4.1 ms (peak), or just sample during a 16.6 ms period (1 full cycle), looking for maximum and minimum values (peaks). I will use the second option here.
This project (Figure 5) uses a Microchip Technology PIC16F18313 MCU, whose ADC can be referenced to VCC, an external input or one of the internally generated reference voltages. I want to use the same reference as the Zener in the pre-processing circuitry, 2.048 V. I am using two inputs of this 8-pin MCU’s six I/O pins for analog voltages. This means I will be alternating inputs to the ADC. It is recommended that whenever a channel is selected (changed), you wait some acquisition time for the input’s internal capacitor to charge properly. The acquisition time depends on the input impedance presented to the ADC, in our case approximately 2 µs. We will want to take at least 100 samples in 16.6 ms, which is 160 µs between samples. An acquisition time of 160 µs is adequate. We need to see if we can handle processing the measurements in that period.
Using RA2 as a temporary output, a toggle pin routine is placed in the ADC interrupt routine—at the entry and exit points—so we can see the execution of that routine. Figure 6 shows the routine takes about 10 µs. This happens every 250 µs for a total of 25 ms for each channel. If we compress this, we get Figure 7, which shows the channel conversions happening at 1 second intervals. I chose 1 second for the ADC/display refresh rate.
While we are looking at execution timing, take note of Figure 8. I moved the toggle pin routine to measure all the time spent in the calculations done on the two channel measurements. This is about 900 µs for both channels. With measurements taking 50 ms and the calculations for each measurement requiring 1 ms, we could increase the sampling rate more than 10 times and still have plenty of horsepower. I’m happy with 1 per second for this project, because in either of the uses for this project there is no need for faster sampling. The first application for this project is that of a monitor/logger. The second application will be as a slave sensor module. I’ll discuss each of these later in the article.
The calculations for each measurement are handled by the main loop, which essentially waits for the 250 µs timer to overflow 4,000 times. The ADC interrupt is responsible for collecting the maximum and minimum voltage measurements for each channel over the 25 ms sampling period for each channel. Once per second, we have to calculate what these measurements mean. With each measurement on the load of our probe biased at 1.024 V, current through the probe’s conductor will be reflected as an addition to or subtraction from this bias voltage.
Our maximum and minimum measure-ments are the most positive voltage above the bias and most negative voltage below the bias, respectively. Assuming we’ve chosen the probe correctly, this should never go above 2.024 V or below 0.024 V, and is the peak-to-peak voltage on the load resistor. We can find this by subtracting the minimum from the maximum measurements. Peak voltage will be one-half of this calculated value. The calculated peak value and the scale value are used to arrive at the actual probe current.
We know that each probe is designed to have a full-scale output of 1 V. However, each probe is designed for a different current range. The range is normally part of the probe’s part number. In this case SCT-013-010 designates 10 A full scale. A scale value of 10 is used to transform the 0-1,000 mV calculated value to its proper probe value. We are using the UART in this MCU to send out formatted data to a PC or LCD for display in the format:
I2C Twin Analog Probes
I2C Address = 0x10
Scale = 0x0A
000.00 Amps 000.00 Amps
000.00 Amps 000.00 Amps
000.00 Amps 000.00 Amps
000.00 Amps 000.00 Amps
Note that after a sign-on message and a display of an
I2C Address and
Scale values, the currents for each channel are displayed at a rate of once per second. Not only can this be used to monitor the active currents, but also by connecting an OpenLog module, the data are automatically logged into a file on the attached SD card.
While this four-wire UART port (+V, Gnd, TX and RX) has the potential of bidirectional communication, this project does not make use of user input through the port. It could be used to set various function of the project such as Scale of the connected probe. I’ll leave this up to the user, because the second application already has this.
SLAVE SENSOR MODULE
So far, we’ve used four of the six I/Os available in this 8-pin MCU. The remaining I/Os will be used for the slave I2C sensor module. In this application, the probe’s data are made available to an I2C master. The I2C bus was initially designed for interfacing to other circuitry on the same PCB. This eliminated the need for the main processor to use separate I/Os to communicate with a potentially large number of devices. Devices such as LCDs, GPS and accelerometers still offer this interface. Many times, I’ve needed to measure currents in a project, and this offers a quick way to get measurements without having to deal with AD conversions.
I treated this project like a registered I2C device. In other words, it uses a pointer requesting a reply from a number of possible registers. The pointer is set by the first value, in a write to the device. Subsequent values are placed into the register pointed to—the pointer automatically is advanced for each new value. It is important to note that you should set the pointer with a write before reading the device, as the pointer is used for both reading from and writing to specific registers. If you try reading more registers than there are, the device will normally wrap the pointer back to the beginning. On a Write this could be disastrous, so additional writes are discarded.
In this device, there are six registers of interest, and these are located using a pointer value of 0-5, as follows:
|Register Description |
Channel 1 MSB
Channel 1 LSB
Channel 2 MSB
Channel 2 LSB
I2C Address will default to Scale=1 and an
I2C Address=0x10, if you hold down the push button (RX input) while powering up the board. Otherwise, any values written to those locations will be used by the application and saved to EEPROM memory for subsequent power-ups.
Each channel will always be a value of 0-1,000, representing millivolts. The scale factor allows one to put the channel measurements into perspective. I use Arduino for many projects. It has support for I2C and is easy to program. Listing 1 is a sketch to allow an Arduino to read and write to an I2C slave device.
Shown here is an Arduino sketch to allow an Arduino to read and write to an I2C slave device.
const String SignOn = “I2C Dual Current”;
int Index = 0;
unsigned char Data;
int I2C1 = 0x10;
int Current1 = 0;
int Current2 = 0;
int Scale = 0;
int I2CAddress = 0;
// I2C Start
Wire.begin(); // join i2c bus
// I2C End
Serial.begin(9600); // start serial for output
Serial.println(SignOn); // print message
// Get the Currents
// Display the Currents
Serial.print(“Amps: “); // print the character
Serial.print(Current1Scale/1000.0); // print the character Serial.print(“ “); // print the character Serial.print(Current2Scale/1000.0); // print the character
Serial.print(“ Scale: “); // print the character
Serial.println(Scale); // print the character
Current1=Data256; Current1=Current1+Data; Current2=Data256;
int ReadCurrent(int Address)
Wire.beginTransmission(Address); // transmit to device
Wire.write(0x00); // sends pointer value byte
Wire.endTransmission(); // stop transmitting
Wire.requestFrom(Address, 6); // request 6 bytes
from slave device
int result = 0;
Data[result] = Wire.read(); // receive a byte as character
The output from this sketch is as follows:
I2C Dual Current
Amps: 0.00 0.00 Scale: 10
Amps: 0.00 0.00 Scale: 10
Amps: 0.00 0.00 Scale: 10
Amps: 0.00 0.00 Scale: 10
Amps: 0.00 0.00 Scale: 10
While the scale has already been applied to the Amps value, it is displayed just for confirmation that you are using the correct probes. Also note that with no probe attached (no burden resistor), the inputs will float, giving a non-true value.
With a low pin count MCU, there are a number of barriers you need to understand before assigning all the I/O pins to application tasks. First off, to use the debug interface requires two predefined I/O pins, which means while debugging an application these are not available to you. In the case of the PIC16F18313, they are pins 6 and 7. By default, two analog inputs, RX (UART receive) and SCL (I2C clock) share these pins. However, this device has the PPS (Programmable Pin Select) feature, which allows many of the peripherals to be assigned to alternate locations. Without this feature you couldn’t possibly use this device to the extent I have in this project. I used this feature to temporarily reassign specific peripheral I/O to unused pins RA2, RA4 and RA5. This allowed me to write and debug code for each peripheral, one at a time. First the UART code, so I would have a way of displaying information. Second, the analog conversion code, so I would have something to display. Finally, the I2C code could be written and debugged.
If you look at the source code, you’ll see multiple routines that were only written to help debug the I2C code—by displaying received bytes in real time—and also toggle an output bit routine to allow a scope to grab execution timing. Once all routines were finished, the I/O was reassigned and the debugging feature was disabled to make use of its default I/O. The final assignment is shown in Table 1.
Like many of my projects, using the internal oscillator has the advantage of gaining two I/O pins. Using an external crystal requires an input and an output pin. These internal oscillators are being improved continuously, and while their accuracy for software real-time clocks (RTCs) may be barely acceptable, for most applications they are entirely adequate ±2% (with the extremes, over VSS and temperature, falling off to ±5%).
I had a stumbling block early on in getting RA5 to output any value. Most of the PIC MCUs I’ve used in the past require a single configuration of the oscillator being used. This device requires two—one to enable the internal oscillator, and one to disable the external oscillator. In failing to disable the external oscillator, it remained defined as an external crystal input and would not allow a redefinition of its TRIS value (direction control of the pin).
At a cost of less than $10, split-core current probes are a great way to measure AC currents of various capacities. The same circuitry can be used independent of the current range necessary, since each probe is designed to present the same output. Simple scaling is done on the out value to achieve the correct current range.
The versatility of low-pin-count devices continues to grow. When first introduced on the market, the laughter from most people was inescapable. Even though these were smaller than most logic chips at the time, most lost sight of the power inside. Granted, in the beginning few peripherals were available, but as engineers showed their skillfulness manufacturers responded with more peripheral power.
Even though the hoops required to use multiple peripherals in this tiny device made me feel more like a circus contortionist than a programmer, the end result is very satisfying.
Additional materials from the author are available at:
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • MARCH 2019 #344 – Get a PDF of the issue