A Means of Measuring
Jeff says he likes being able to measure things—for example, measuring load current so he can predict how long a battery will last. With that in mind, he recently found a high-side current sensing device, Microchip’s EMC1701. Here, Jeff takes you through the details of the device and how to make use of it in a battery-based system.
We’ve had an abundance of rain this year. As I write this article, Washington DC has already reached its average rainfall for the year. My shady front lawn—if patches of crabgrass can be considered a lawn—looks like I’m raising mushrooms for profit. They just keep popping up overnight! An elderly couple walking past while I was collecting the fungi asked if they were edible. I shrugged my shoulders and asked if they wanted to take a few for their evening salad. They either didn’t hear me or felt the same way I do about mushrooms, because they just waved and continued down the road.
I like being able to measure things. You can learn a lot by taking an occasional measurement. You may have grown up marking one specific door frame in your house with a line signifying your height and labeling it with your name and date. Many have a bathroom scale they step on each morning just to track their weight. My dad always calculated MPG every time he filled up the Ford. My Prius does that automatically now.
When my projects use batteries, I like to be able to measure the load current so I can predict how long a battery will last. I recently found a high-side current sensing device that I think you might find useful. High-side means that it measures via the supply line, as opposed to the circuit ground. This adds some complexity but leaves the ground connection unaltered. The device uses a series resistance in the supply line, which must be fairly small or the drop across it will reduce the supplies voltage too much. The device will operate with a source voltage of up to 24 V. The SMB (Systems Management Bus) interface has a separate supply input that can be tied to the source voltage, and because the interface is open-collector, it plays nicely with 3-5 V logic levels. Let’s take a closer look at SMSC’s (Standard Micro Systems Corporation’s) EMC1701.
Any Trekkie will recognize this device number as that of the Enterprise, the starship from the original Star Trek television series. Coincidence? Or some engineer’s way of paying homage to a classic? SMSC was acquired by Microchip in 2012. When I found the datasheet on the Microchip website, it had the SMSC logo on it. From the datasheet, we see that the EMC1701 includes a high-side current sensing device with a precision temperature sensor. While it measures the voltage developed across an external sense resistor to represent the high-side current of a battery or voltage regulator, it also measures the source voltage, and uses these values to present a proportional power calculation. The bi-directional peak detection circuitry flags instantaneous current spikes with programmable time duration and magnitude threshold. Both current sensing and temperature monitoring include external outputs that can assert a current ALERT pin and/or a thermal THERM pin.
The block diagram of the EMC1701 is shown in Figure 1. The device comes as either a 12- pin DFN (-1) or a 10-pin MSOP (-2). I chose to use the MSOP package, as it has leads I can (barely) solder to, given the 0.05 inch pitch. Note: This package (-2) does not have two input pins for externally selecting peak threshold and duration. These can be configured through the SMB channel. The SMB is a single-ended, simple, two-wire bus for the purpose of lightweight communication. It is based on the I²C serial bus protocol created by Philips Semiconductors, now NXP Semiconductors. While SMB has some enhancements to the original I²C serial bus protocol, it’s basically the same. You can check out some of the info on Circuit Cellar’s article materials webpage to learn more about SMB and I2C.
Those of you who are familiar with SMB/I2C protocol will note that physical address selection is handled a bit differently on this device. Commonly a device has a preset 7-bit address, with one or more pins on the device defining externally chosen alternate address bits. One pin, two alternate addresses, two pins, four alternate addresses and so on. But this uses up precious pins. The EMC1701 uses a single pin to set one of 16 alternate addresses by reading the pin as an analog input. A resistor from this pin to ground determines which of the 16 addresses will be used (Table 1).
|RESISTOR (5%)||SMBUS ADDRESS||RESISTOR (5%)||SMBUS ADDRESS|
TABLE 1 – The EMC1701 uses a unique way of selecting alternate SMBus addresses. A resistor on an input pin is read with an A-D converter and its resistance determines which of 16 alternate addresses will be used.
The EMC1701 has 36 registers. Of these, 16 are read-only (status), one is write-only (take sample), and 19 are read/write (configuration). The easiest way to communicate uses only three formats: write one data byte (selects a register by loading the register pointer), write two data bytes (selects a register by loading the register pointer and writes to the register pointed to), and read a data byte (reads from the register pointed to). Like many devices, the register pointer (first data byte in the write format) is automatically incremented each time there is a read or write of data. To read a specific register you must write the register pointer first and then read the data. Consecutive reads will read incremented registers. To reread one register, you must always write then read.
Each command begins by sending the address of the device you want to communicate with, the appropriate 7-bit address, plus a “0” or “1” added on as the LSB (least significant bit). A “0” signifies the command is a write to the device with a matching 7-bit address, and a “1” signifies the command is a read from the device with a matching 7-bit address. Following this address, the command includes one of the three formats just mentioned, for a total of 2 or 3 bytes for each command. Note: I am only using the single data byte read command, no consecutive register reads. To learn more on the actual bus activity and handshaking that goes on for each command, you can check out some of the references listed. See Table 2 and Table 3 for listings of all the registers available in the EMC1701. We’ll get into them shortly.
|00h||R||Internal Diode Data High Byte||Stores the integer data for the Internal Diode(mirrored at address 38h)||00h|
|02h||R||Status||Stores the status bits for the Internal Diode(mirrored at address 34h)||00h|
|03h||R/W||Configuration||Controls the general operation of the device(mirrored at address 09h)||00h|
|04h||R/W||Conversion Rate||Controls the conversion rate for updating measurement data (mirrored at address 0Ah)||06h (4/sec)|
|05h||R/W||Internal Diode High Limit||Stores the 8-bit high limit for the Internal Diode(mirrored at address 0Bh)||55h (85°C)|
|06h||R/W||Internal Diode Low Limit||Stores the 8-bit low limit for the Internal Diode(mirrored at address 0Ch)||80h(-128°C)|
|09h||R/W||Configuration||Controls the general operation of the device(mirrored at address 03h)||00h|
|0Ah||R/W||Conversion Rate||Controls the conversion rate for updating measurement data (mirrored at address 04h)||06h (4/sec)|
|0Bh||R/W||Internal Diode High Limit||Stores the 8-bit high limit for the Internal Diode(mirrored at address 05h)||55h (85°C)|
|0Ch||R/W||Internal Diode Low Limit||Stores the 8-bit low limit for the Internal Diode(mirrored at address 06h)||80h(-128°C)|
|0Fh||W||One-Shot||A write to this register initiates a one-shot update.||00h|
|1Fh||R/W||Channel Mask Register||Controls the masking of individual channels||00h|
|20h||R/W||Internal Diode Tcrit Limit||Stores the 8-bit critical temperature limit for the Internal Diode||64h (100°C)|
|21h||R/W||Tcrit Hysteresis||Stores the 8-bit hysteresis value that applies to all THERM limits||0Ah (10°C)|
|22h||R/W||Consecutive Alert||Controls the number of out-of-limit conditions that must occur before an interrupt is asserted||70h|
|29h||R||Internal Diode Data Low Byte||Stores the fractional data for the Internal Diode(mirrored at register 39h)||00h|
|34h||R-C||Status||Stores the status bits for the measured temperature channels, Current Sense circuitry, and Peak Detector circuitry||00h|
|35h||R-C||High Limit Status||Status bits for the High Limits||00h|
|36h||R-C||Low Limit Status||Status bits for the Low Limits||00h|
|37h||R-C||Crit Limit Status||Status bits for the Tcrit and Vcrit Limits||00h|
|38h||R||Internal Diode High Byte||Stores the integer data for the Internal Diode||00h|
|39h||R||Internal Diode Low Byte||Stores the fractional data for the Internal Diode||00h|
TABLE 2 – Listed here are the registers available in the EMC1701 (more in Table 3).
|Current Sense Control and Measurement|
|50h||R/W||Voltage Sampling Configuration||Controls voltage sampling||80h|
|51h||R/W||Current Sense Sampling Configuration||Controls the current sensing sampling and update times||03h|
|52h||R/W||Peak Detection Config||Controls the peak detection configuration||00h|
|54h||R||Sense Voltage High Byte||Stores the voltage measured across RSENSE||00h|
|55h||R||Sense Voltage Low Byte||00h|
|58h||R||Source Voltage High Byte||Stores voltage measured on the source side of RSENSE||00h|
|59h||R||Source Voltage Low Byte||00h|
|5Bh||R||Power Ratio High Byte||Stores the power ratio value||00h|
|5Ch||R||Power Ratio Low Byte||00h|
|Current Sense and Source Voltage Limits|
|60h||R/W||Sense Voltage High Limit||Stores the high limit for VSENSE||7Fh|
|61h||R/W||Sense Voltage Low Limit||Stores the low or negative limit for the VSENSE voltage||80h|
|64h||R/W||Source Voltage High Limit||Stores the high limit for the voltage on the source side of RSENSE||FFh|
|65h||R/W||Source Voltage Low Limit||Stores the low limit for the voltage on the source side of RSENSE||00h|
|66h||R/W||Sense Voltage Vcrit Limit||Stores the critical limit for VSENSE||7Fh|
|68h||R/W||Source Voltage Vcrit Limit||Stores the critical limit for the voltage on the source side of RSENSE||FFh|
|69h||R/W||Sense Vcrit Hysteresis||Stores the hysteresis for the VSENSE Vcrit limit||0Ah|
|6Ah||R/W||Source Voltage Vcrit Hysteresis||Stores the hysteresis for the source voltage Vcrit limits||0Ah|
|FCh||R||Product Features||Stores information about which pin controlled product features are set||00h|
|FDh||R||Product ID||Stores a fixed value that identifies each product||38h|
|FEh||R||SMSC ID||Stores a fixed value that represents SMSC||5Dh|
|FFh||R||Revision||Stores a fixed value that represents the revision number||82h|
TABLE 3 – More EMC1701 registers, including the Current Sense Control and Measurement registers and the registers for Current Sense and Source Voltage Limits.
The EMC1701 includes circuitry for both source current sensing and source voltage measurement. From these measurements, a ratiometric value corresponding to the power delivered at the SENSE+ pin is calculated. Refer back to the block diagram (Figure 1) for this functional description. The high-side current sensing circuit measures the differential voltage, VSENSE, induced across a fixed external current sense resistor, RSENSE (SENSE+ to SENSE-). This voltage is stored as a signed 11-bit number in the Sense Voltage Registers. Note that the sign means it is capable of measuring the current flowing in both directions. This may seem silly, but it means it could be used in-line with a battery to determine charging or discharging conditions, sinking or sourcing current.
You can choose from four Full Scale Sense Ranges (FSSR) of ±10 mV, ±20 mV, ±40 mV or ±80 mV, (the default is ±80 mV). This will be used with the value of your external RSENSE resistor to determine the maximum current the circuit can measure. Let’s say you were using a 0.1 Ω RSENSE, with a maximum of 80 mV across the resistor. The current through it would be, 0.08 V / 0.1 Ω = 0.8 A. If you knew your maximum current was only going to be 100 mA, you could set the FFSR register for 10 mV and get a full scale of 0.01 V / 0.1 Ω = 0.1 A. Lowering RSENSE to 0.01 Ω would allow the FS 80 mV to measure up to 8 A!
VSENSE measurements are averaged over a user programmable time via the Current Sense Sampling Configuration Register. This is compared against programmable high and low limits through the Sense Voltage High and Low Limit Registers. If VSENSE exceeds (or drops below) the respective limits, the ALERT bit/pin goes high. A user programmable, current peak detection circuitry will raise the THERM bit/pin, if a current spike is detected larger than the programmed threshold and of longer duration than the programmed time in the Peak Detection Configuration Register.
We’ve previously calculated the FS current using a specific external resistor. Using this FS value and the value from the Sense Voltage Registers, we can determine the actual current through RSENSE.
The source voltage is measured on the supply side of the RSENSE resistor (SENSE+ to ground) and stored as an unsigned 11-bit number in the Source Voltage Registers as VSOURCE. Each measurement is averaged over a user programmable time via the Conversion Rate Register. This measurement is delayed by the programmed conversion rate. VSOURCE is compared against programmable High, Low, and Critical Limit Status Registers. If the value meets or exceeds the high limits or drops below the low limits, the ALERT bit/pin goes high. If the value meets or exceeds the critical limit, the THERM bit/pin will be asserted. The EMC1701 has a maximum VSOURCE(max) of 23.9884 V. Using VSOURCE(max) and the value from the Source Voltage Registers, we can determine the actual voltage on SENSE+.
The maximum power the device will measure is based on the product of the FS current and VSOURCE(max), or 0.8 A × 23.9884 V = 19.2 W. Note: This will increase as RSENSE is reduced. To find the average power provided at SENSE+, we use the value, PRATIO, contained in the Power Ratio Registers. This value represents the percent of maximum power, and is updated whenever either VSENSE or VSOURCE is updated.
The wide device-operating voltage range allows the EMC1701 to be powered from either the source voltage or an external supply, by detecting the voltage on the VDD pin and enabling an internal regulator if necessary. There are four modes of operation: fully active, current sense only, temperature sense only and standby. The default mode is fully active, with measurements continuously updated. Standby is the low-power mode. In this mode, the device accepts communications, but no measurements are taken unless you write to the write-only register—which takes one sample and then returns to standby mode.
We’ve already seen how to convert the data in the current voltage and power registers to meaningful information. Let’s look at a few other conversions. The Temperature Data Registers are set up a bit differently from what we’ve seen already. The high register is the temperature as a signed-whole number in degrees Celsius, and the low register is a 3-bit fractional component. You only have to read the high byte, if you are interested in the temperature to the nearest degree. If you concatenate the low value, then the total conversion is in eighths of a degree.
You’ll notice a few of the top read-only registers have identification information. These enable you to ID the device to assure you know with whom you are talking. You have access to many registers, so this project includes two software programs that allow you to investigate this device more thoroughly. The first is a program that allows the EMC1701 to be connected to the Arduino, and the registers accessed via the USB port and a serial terminal program like RealTerm. This simple program enables the user to read and write the registers of the EMC1701 through simple commands typed into the serial terminal.
I designed a circuit using the EMC1701 SMOP device that can be used with any other circuit you wish to monitor, so it’s only about an inch square. The schematic of this circuit is shown in Figure 2. With a 4-wire connection to +5, ground, SCK and SDA, this can be used with any micro that has a I2C port available. I decided to connect an Arduino so I could quickly begin communicating with the EMC1701’s registers. Listing 1 shows the simple Arduino program I used.
String SignOn = “EMC1701”;
byte I2CAddress=0x4C; //R3 shorted
Wire.begin(); // join i2c bus
if (inByte==0x0D && index0)
// transmit to device #8
Wire.write(I2CRegister); // sends one byte
Serial.println(“Writing “ + String(I2CRegister,HEX) +”:” + String(I2CData,HEX));
Wire.write(I2CData); // sends one byte
Wire.endTransmission(); // stop transmitting
// transmit to device #8
Wire.write(I2CRegister); // sends one byte
Wire.endTransmission(); // stop transmitting
Serial.print(“Reading “ + String(I2CRegister,HEX) + “:”);
// request a bytes from slave device
byte c = Wire.read(); // receive a byte as character
Serial.print(c,HEX); // print the character
LISTING 1 – I decided to connect an Arduino so I could quickly begin communicating with the EMC1701’s registers. Shown here is the simple Arduino program I used.
Once programmed, with the EMC1701 attached and a USB connection made to my PC, I can open the terminal program and “see” the sign-on message. Figure 3 shows a write command, which sends “0x57 0x6A 0x09 0x0D”, W(rite) (register)6A (value)09 (CR) and receives back “Writing 6a:9”, changing the Source Voltage Critical Hysteresis Register. Meanwhile, the read command sends “0x52 0xFF 0x0D”, R(ead) (register)FF (CR) and receives back “Reading ff:82”, reading the (Revision Register).
While this quickie does the basics of reading and writing registers, it’s a bit hard on the user to figure out what data value to send and how to interpret the returning data. I chose to add a second program written in Liberty Basic to help display all the registers and interpret the results. I think you’ll agree that this improved user interface makes all the difference in being able to investigate this device.
A BETTER WAY
The trick is to display as much information as possible without having to scroll through dumps of data. Liberty Basic (LB) is great at communicating via a serial port with another device, and allows a user to interact in a much friendlier way. I designed this LB program to have three tabs in the menu bar: Exit to quit the program, Comm, to choose the communication port, and Registers, to select the group of registers you wish to work with. There is only one selection on the Comm tab—Change Comm—and this will pop up a box listing all the COMM ports on the right and attempt to open each, to give you a listing on the left of the active ones from which to choose. Once all have been tested, you pick one (it will be the same port you used when you programmed the Arduino), and the pop-up is closed and the port is opened.
Because there are a lot of registers to work with, I divided them into three groups: read-only, write-only, and read/write. The group is chosen via the third menu tab, Registers. The group defaults to the read-only group, and you will see a list of all the read-Only Registers. Each row contains the Register Name, Number, and Value, plus a read and definition buttons (Figure 4). If you click Read, the screen is updated with the new value for that register. If you click Definition, you get a new display with the information of what the register value means (Figure 5).
The write-only group has a single register. There is no value associated with the register, just a Write button. This register is used if the device is in a stop or sleep mode via the Configuration register. In this case, the one-shot write-only register will activate the device to take one reading and then go back to sleep. The device interface stays active even when no samples are being taken.
The read/write register group looks similar to the read-only group. The big difference is that Liberty Basic allows controls to be enabled and disabled. For read-only these are disabled and cannot be changed by the user. To write to a register you click the Definition button and this time the data are enabled and can be modified. When data are bit-oriented like a configuration register, the bits are presented on a bit basis. Clicking on a bit will toggle the logic state of the bit. A new byte value is then calculated, based on the present bit states, and the display is updated. When data are a quantity—such as temperature—the data are byte-oriented. You can change byte value by clicking on the present value. To exit the definition screen, just choose one of the groups from the Register menu tab.
Let’s say we want to monitor the battery power used by a circuit. The circuit consists of some voltage regulator and a microcontroller and sensor. First, we need to know what range the current will be in, so we can choose the correct external series current sense resistor. From our earlier discussion we found that using a 0.1 Ω external resistor would provide us with a full-scale range of 0.8 A. Through the Current Sense Sampling Configuration Register we could change this default from 80 mV to 40 mV, 20 mV or 10 mV. This would lower the full-scale range to 0.4 V, 0.2 V or 0.1 V, respectively, and we could improve the resolution of the samples if our maximum current requirement didn’t exceed the choice. Let’s leave it at the default for now.
Assuming the battery voltage is less than the EMC1701’s maximum of 24 V, we’re ready to begin measuring. The first register of interest is the Source Voltage. This is the voltage from SENSE+ to ground, the battery voltage applied to the external sense resister. Registers 0x58 and 0x59 combine for a word value of 0x3480. We are interested in the upper 11-bit. The lower five will always read 0x0 and are not used. The register value is 0x3340 (Decimal 13,120), 13,120 / 32 = 410 bits. With a maximum voltage of 24 V and 11 bits that means a resolution of 24 V / 2,048 = 0.0117 V/bit. A value of 410 bits × 0.0117 V/bit = 4.79 V (VSOURCE). Strange battery you say? I’m actually plugging into a USB port, and the series resistor is between the port and the Arduino, which is communicating with the ECM1701 (Figure 6).
The next register of interest is the Sense Voltage. This is the difference in voltage between the VSOURCE and the SENSE- to ground, the voltage applied to the external circuitry–in this case the Arduino. Registers 0x54 and 0x55 combine for a signed word value of 0x0C60. We are interested in the upper 12- bit. The lower four will always read 0x0 and are not used. The register value is 0x0C60 (Decimal 3,168), 3,168 / 16 = 198 bits. As this is a signed word, should the twelfth bit be a 1, we would need to take the 2’s complement of the original register value to get bits. A negative register value would indicate the measured current is going the other way through the resistor. With a maximum RSENSE voltage of 0.08 V across the external 0.1 Ω resistor, the maximum current would be 0.8 A. 11-bits would give a resolution of 0.8 A / 2,048 = 0.00038 A/bit. A value of 198 bits × 0.00038 A/bit = 0.075 A or 75 mA (ISENSE).
Finally, the important register is the Power Ratio Register. This is a 16-bit result of VSENSE and VSENSE. From the computations we did earlier we found the maximum VSOURCE(max) = 24 V and the ISENSE(max) = 0.8 A. Therefore, the PRATIO(max) = 24 V × 0.8 A = 19.2 W. Using 16-bits, the resolution would be 19.2 W / 65,535 = 0.000292 W/bit. PSOURCE is therefore the value of the Power Ratio Register × W/bit = 1,299 bits × 0.000292 W/bit = 0.379 W. This is also VSOURCE × ISENSE = 4.79 V × 0.075 A = 0.359 W or 359 mW.
AND IN THE END
I find that whenever I come across a new device that I would like to use, getting familiar with it before using it helps me gain the confidence I need to use it effectively. There is nothing that stings more than writing all your code, only to discover that the device really doesn’t work that way. A quick way to get started with a device is to make it accessible. Because the EMC1701 is SMBus and for the most part I2C compatible, using a support board like Arduino makes sense. It already has I2C support, which means you can get going quickly with just a few lines of code.
Once you can read and write to registers, you still must fumble with the datasheet and calculate the right values for a register, or decode bit values to understand status or configuration. The second tool used Liberty Basic, which enables the user to interface with the Arduino’s ability to read and write registers, and presents data in a more user friendly way. There is so much more that can be done with a graphical interface than just seeing a register value. You can get creative and supply all kinds of support information that eliminates the need to handle the datasheet.
One last note on how this might be used in a battery situation. As previously mentioned, because the EMC1701 can monitor bidirectional current and power, you can keep track of the net state of the battery by including a charging circuit. Determining the capacity left in the battery is crucial to your program, so you can manage operational parameters correctly.
So, if a future project requires monitoring power usage, take a look at the EMC1701. It might simplify your task. Meanwhile, I’m hoping our abundance of rain isn’t foreshadowing a heavy snowfall for this winter. If there’s anything I dislike more than mushrooms, it’s shoveling snow!
Additional materials from the author are available at:
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • JANUARY 2019 #342 – Get a PDF of the issue