Profiling i.MX Application Power Consumption with Kinetis

Document created by David G Dicarlo Employee on Oct 31, 2017Last modified by David G Dicarlo Employee on Mar 8, 2018
Version 27Show Document
  • View in full screen mode


Measuring the power consumed an i.MX application processor can be a challenging undertaking. This document describes several boards designed to instrument i.MX application boards for current measurements. While this system does not offer many digits of accuracy, it can be used to quantify power consumed by application use cases as well as while in low power modes.

The system can be used to instrument up to four power supply rails and measure current in two ranges. Range switching on the sensor boards is controlled via software running on the Kinetis K20 at the heard of the profiler board. Measured data is sent to a host computer over a virtual serial link over USB. Power for the profiler system is obtained from the USB connection although a external 5V supply may be used.


Dual-Range Current Sensors

INA250 + INA21x Sensor

Circuit Description:

The INA250 + INA21x Sensor board can measure two ranges using the INA250 and INA21x current sense amplifiers. The high range is measured with an INA250, which has an integrated 0.002 Ohm shunt, and is available in four output gains. The low range is measured with shunt R1 and the INA21x sense amp. The low range shunt is taken out of the circuit (by shorting it) with two paralleled, very low-Rds(on) FETs, Q1 and Q1. VCC_SENSE powers the two sense amplifiers. VCC_FET supplies the gate voltage on Q1 and Q2. The DMN1019 device has a Vgs max of 8V. The sources of both FETs are tied to the i.MX side of the current sense loop, so the gate voltage Q1 and Q2 see is VCC_FET-(rail voltage). The signal /LOW_EN controls the state of both Q1 and Q2. The sense amplifier outputs (HIGH_OUT1 and LOW_OUT1) and rail voltage (V_RAIL_MEASURE) are sent down the ribbon cable (X2) to the profiler board for measurement. When not used for a wire loop for a Hall-effect current probe, resistor R3 should be shorted with a solder bridge, a piece of wire, or a 0.001 Ohm resistor.




Board Layout:

The two large vias by the current sense connection points are provided for use with a 0.1" header and jumper to short the low range shunt, allowing normal operation of the target board when the profiler is not powered. It should be noted a jumper will not be as effective for relatively large currents.



Part   Device

C1,C2  0.1uF 0805
Q1,Q2  DMN1019USN-13 SOT23
R1     2 1% 0805 (resize to change low range)
R2     10k 0805
R3     Solder bridge/wire loop (see schematic)
U1     INA250 TSSOP16 (choose gain, A3 [0.8V/A] or A4 [2.0V/A])
U2     INA21X SC70 (choose desired gain)
X2     WM6769CT/0527460871 (bottom contacts)


Dual INA21x Sensor

Circuit Description:

The Dual INA21x Sensor board can measure two ranges using two INA21x current sense amplifiers and two different shunts. The high range shunt (R1) is always in place. The low range shunt is taken out of the circuit (by shorting it) with two paralleled, very low-Rds(on) FETs, Q1 and Q1. VCC_SENSE powers the two sense amplifiers. VCC_FET supplies the gate voltage on Q1 and Q2. The DMN1019 device has a Vgs max of 8V. The sources of both FETs are tied to the i.MX side of the current sense loop, so the gate voltage Q1 and Q2 see is VCC_FET-(rail voltage). The signal /LOW_EN controls the state of both Q1 and Q2. The sense amplifier outputs (HIGH_OUT1 and LOW_OUT1) and rail voltage (V_RAIL_MEASURE) are sent down the ribbon cable (X2) to the profiler board for measurement.




Board Layout:

The two large vias by the current sense connection points are provided for use with a 0.1" header and jumper to short the low range shunt, allowing normal operation of the target board when the profiler is not powered. It should be noted a jumper will not be as effective for relatively large currents.



Part   Device

C1,C2  0.1uF 0805
Q1,Q2  DMN1019USN-13 SOT23
R1     0.002 1% 0805 (resize to change high range)
R2     0.05 1% 0805 (resize to change low range)
R3     10k 0805
U1,U2  INA21X SC70 (choose desired gain)
X2     WM6769CT/0527460871  (bottom contacts)


Four-Channel Power Profiler

Circuit Description:

The Four-Channel Power Profiler board has at its heart a Kinetis K20 on a Teensy3.2 board. The ADCs of the K20 measure all the current sense amplifier's outputs, the voltage of each instrumented rail. There is provision for measuring temperature using up to three thermistors. GPIO provide control each sensor board's current range, and optionally, a hardware wake-up signal for the instrumented target board. Up to four dual-range sensor boards can be connected (either sensor board mentioned above). A micro-SD card socket is included for storing measured data (the SD card functionality has been tested but not implemented for use with measurements). Measured data is sent to the host computer over a virtual serial port using the Teensy's USB.

Charge pump U1 boosts the 5V supply to 12V. The output is regulated down to 8V on VCC_FET via regulator U2. R2 and C5 provide filtering for the 3.3V supply from the Teensy that feeds the sensor boards through VCC_SENSE. FETs Q1 through Q4 provide voltage level translation which protect the Teensy's GPIO pins from the 8V that's placed on the gates of the shorting FETs on the sensor boards. Regulator IC2 provides power for the micro-SD socket, since the 3.3V regulator on the Teensy does not provide enough capacity.

Since there are not "smarts" on the sensor boards, the Teensy has no way of knowing what kind of sensor board is connected or what shunt values and sense amplifier gains are in use. As currently implemented, current and voltage calculations are hard coded in the Teensy application code.




Board Layout:



Part    Device

C1,C2   0.22uF 0805
C3-C7   1uF 0805

C10,C12 1uF 0805
C11     0.1uF 0805
IC2     MCP1825ST-3302 SOT223
Q1-Q4   DMN1019USN SOT23
R2-R4   20k 1% 0805
R5-R8   10k 0805
R9      Ferrite bead 0805
S1-S4   WM6769CT/0527460871 (bottom contacts)
U$1     101-00660-68-6-1-ND MICROSD
U1      MAX662CPASO8 SO08
U2      78L08SMD SO08

Use mating Molex cables: 8in: 0150200087 or 10in: 0151660091


Using the Power Profiler

Obtaining Sensor and Profiler Boards:

Bare boards may be ordered directly from OSH Park using these links:

INA250 + INA21x Sensor board (order with 2oz copper option selected)

Dual INA21x Sensor board (order with 2oz copper option selected)

Power Profiler board

The sensor boards should be ordered with the 2oz copper option selected to reduce the trace resistance of the target board's current path. No special option is needed for the profiler board. Teensy3.2 boards may be ordered from OSH Park as well, and at a slightly lower price than the manufacturer (PJRC) sells them.


Choosing Current Ranges:

To choose the value of a shunt resistor, use the following equation:

Rsh = Vfs / (Ifs * gain)


Rsh is the shunt resistance

Vfs is the full scale sense amplifier output voltage (3.3V here)

Ifs is the full scale current to be measured

gain is the gain of the sense amp to be used

For example, to measure a 66mA full scale current with a sense amp of gain 1000, Rsh = 3.3V / (0.066A * 1000) = 0.050 Ohms. For sleep/leakage current, say 1mA full scale: Rsh = 3.3V / (0.001 * 1000) = 3.3 Ohms.

The pads on both sensor boards for the shunt resistors have been laid out for 0805 SMT resistors. Precision resistors should be used, 1% or better. The highest power dissipation resistor available should be used to minimize resistance change from the shunt resistor heating up; 0805 resistors are typically available with 1/8, 1/4, 1/2 and 1 Watt dissipation.


Building and Testing:

These boards were designed to be assembled by hand in small quantities. The most difficult components to solder are the ribbon connectors and the SC70 packaged sense amplifiers. A fine tip soldering iron and a microscope are required. Solder wick is helpful for removing solder bridges from between pins (typically the ribbon connector and the sense amplifiers). 

Early versions of the profiler board were assembled with header pins soldered to the Teensy and mating female recepticles soldered to the profiler board. Later versions (like in the example below) were assembled with male header pins between the Teensy and the profiler board. 

To test the boards after assembly, check for the presence of 8V on the pull-up resistors R5-R8 when a USB cable is plugged into the Teensy. Program the Teensy with suitable application code. Connect the sensor boards to the profiler. Connect all the sensor boards together in series, positive of one to negative of the next and connect to a calibrated current source. (The image below shows an early prototype of the profiler with the sensor boards connected in series. Current is forced through them via the Kelvin contact clips.)

Open a terminal window on the host computer. Force known currents and toggle the ranges of each sensor to verify that each sensor operates correctly in both ranges.

To check that the profiler measures rail voltage correctly, disconnect the current source and apply the positive side of a voltage source to either side of the sensors still connected in series and connect the ground of the voltage source to a ground point on the profiler. The rail voltage measured by each sensor should match the supplied voltage (0 to 3.3V max).



After building in excess of 20 sensor boards and 6 profiler boards and checking their measurements against a Keysight B2902 SMU forcing known currents, the profiler system is fairly accurate. Measurements are good down to about 2% of any range's full scale; lower than that gets into the input offset range of the sense amplifier. Individual readings within 1% of that range's full scale when compared against forced current values. No calibration or tuning has been necessary.

Measured values should only be considered good to at most 3 significant figures.



  • The maximum current through any sensor should be limited to a maximum of 4A.
  • The current limit when using the low range needs to avoid exceeding the power dissipation of the low range shunt resistor. Particularly, the dissipation in the low range shunt resistor can cause resistance changes that would affect measurement accuracy.
  • The voltage of any instrumented rail cannot be greater than 3.3V, the maximum input voltage of the K20's ADC inputs.
  • Minimum resistance the sensor introduces is in high range is about 0.012 to 0.015 Ohms with a 0.002 Ohm shunt. At least 0.005 Ohms comes from the two shorting FETs on the sensor board. The rest comes from the traces on the board as well as the interconnect wires. The bottom line is: the sensor board has to be mounted as closely as possible to the current sense point on the target board.
  • The maximum resistance the sensor introduces depends on the low range shunt. With a 0.020 Ohm low range shunt, the resistance is about 0.025 to 0.030 Ohms. With a 0.050 Ohm low range shunt, the resistance is about 0.065 to 0.075 Ohms.
  • The sensor board needs to be rigidly mounted to prevent ripping up the current sense points on the target board. This can be a challenge when many rails are instrumented.

Instrumenting Target Board:

When instrumenting a target board, the on-board current sense resistor should be removed. The sensor board should be attached to the target board placed as close as possible to the sense resistor pads. Connection wires to the sensor board should be as short as possible to minimize series resistance. Great care should be taken to prevent movement of the sensor boards that could in turn lift the sense resistor pads off the target board. Foam double sticky tape should be used over clear areas of the target board to avoid dislodging components when the tape is removed.

In the photos below, seven power supplies are instrumented on an interposer card. In this example, the sensor boards were affixed to perf board held in place by the headers. Because of the physical constraints of the target board and its power supply card, mounting the sensor boards directly to the interposer was not possible. Four sensors were mounted on one side and three on the other. Notches were cut in the perf board for the sensor's connection wires on the opposite side. Two profiler boards are required for simultaneous use. (Two were also required because the 0.1" headers and jumpers were not installed on the sensor boards to passively short the low-range shunts; all the sensor boards need to be powered to actively short the low-range shunts.) 

The positive input of the sensor board (the center of the three connection points) goes to the regulator side of the current sense resistor. The negative input (either of the two outside connections) goes to the i.MX side of the sense resistor.

[NOTE: In this example, the power profiler boards have not been fully populated: the thermistor-related components and the micro-SD card socket. The sensor boards were fully populated with the exception of the passive shorting jumper.]



Here is another example of a board with six instrumented rails. The sensors in this case are mounted directly on the target board. In this example, the 12V rail is instrumented, which required modding to add a voltage divider to V_RAIL_LOWSIDE on that sensor board. 


And here's yet another example of an instrumented i.MX6Q SDB (which still has wires on it from measuring it the old way...). Although it's difficult to see in this photo, all of the sensor boards have a jumper across the low range shunt which permits normal operation of the board without the profiler board attached to provide power to the shorting FETs.


Profiler Application Code for Kinetis/Teensy:

Below is sample application code for the Teensy for use with four INA250 + INA21x sensor boards populated with the INA250A3 (0.8V/A gain) for the high range and 0.05 Ohm shunts and INA212 (gain 1000). The current range of each channel can be independently changed. This code is also attached below as a file. Data is sent to the host computer over a USB virtual serial port.


MIT License (
Copyright 2017 NXP

Teensy Power Profiler v.2 (revised main board with individual Hi/Lo GPIO,
fixed voltage levels, and on-board uSD card socket.

Very basic code for the Teensy Power Profiler that sets up the
ADCs and controls the GPIO with very basic, single-character
serial commands...

This version for all INA250A3 on high range, and 0.05Ohms+INA212 (1000 gain) on low range.


// These constants won't change.  They're used to give names to the pins used:
const int LoHiEn1 = 0;
const int LoHiEn2 = 1;
const int LoHiEn3 = 2;
const int LoHiEn4 = 3;
const int WakeUp = 5;

const int Lo_1 = A0;
const int Vrail_1 = A1;
const int Hi_1 = A2;

const int Lo_2 = A3;
const int Vrail_2 = A4; 
const int Hi_2 = A5;

const int Lo_3 = A6;
const int Vrail_3 = A7;
const int Hi_3 = A8;

const int Lo_4 = A9;
const int Vrail_4 = A11;
const int Hi_4 = A10;

const int Therm1 = A14;

#include <math.h>

// thermistor temperature calculation stuff...
int sensorValue = 0;        // value read from the pot
float sensorValuef = 0.0;
int B = 4334; // B25/100 value for thermistor NXRT15WF104FA1B040

// other stuff...
int delayintvl = 20;
int incomingByte;

float vrefL = 3.3;
float vrefH = 3.3;
float vrefV = 3.3;

bool one=true;   bool dispone=true;
bool two=true;   bool disptwo=true;
bool three=true; bool dispthree=true;
bool four=true;  bool dispfour=true;

int i,j;
int num=100;
float v1, v2, v3, v4, i1, i2, i3, i4;
float il1, il2, il3, il4;

void setup() {
  // initialize serial communications at 115200 bps:

  // set analog resolution to 12 bits... (we want more than the 8 default bits...)

  // set up low/high range wakeup GPIO signals...
  pinMode(LoHiEn1, OUTPUT); digitalWrite(LoHiEn1, HIGH);
  pinMode(LoHiEn2, OUTPUT); digitalWrite(LoHiEn2, HIGH);
  pinMode(LoHiEn3, OUTPUT); digitalWrite(LoHiEn3, HIGH);
  pinMode(LoHiEn4, OUTPUT); digitalWrite(LoHiEn4, HIGH);
  pinMode(WakeUp, OUTPUT); digitalWrite(WakeUp, HIGH);


void loop() {

  // average voltages and currents...
  v1=0; v2=0; v3=0; v4=0;
  i1=0; i2=0; i3=0; i4=0;
  il1=0; il2=0; il3=0; il4=0;
  for (i=0; i<num; i++){
    v1 = v1+ analogRead(Vrail_1)/4095.*vrefV;
    i1 = i1+ analogRead(Hi_1)/4095.*vrefH/0.8*1000;
    il1 = il1+ analogRead(Lo_1)/4095.*vrefH/0.05;
    v2 = v2+ analogRead(Vrail_2)/4095.*vrefV;
    i2 = i2+ analogRead(Hi_2)/4095.*vrefH/0.8*1000;
    il2 = il2+ analogRead(Lo_2)/4095.*vrefH/0.05;
    v3 = v3+ analogRead(Vrail_3)/4095.*vrefV;
    i3 = i3+ analogRead(Hi_3)/4095.*vrefH/0.8*1000;
    il3 = il3+ analogRead(Lo_3)/4095.*vrefH/0.05;
    v4 = v4+ analogRead(Vrail_4)/4095.*vrefV;
    i4 = i4+ analogRead(Hi_4)/4095.*vrefH/0.8*1000;
    il4 = il4+ analogRead(Lo_4)/4095.*vrefH/0.05;
  v1 = v1/num; v2 = v2/num; v3 = v3/num; v4 = v4/num;
  i1 = i1/num; i2 = i2/num; i3 = i3/num; i4 = i4/num;
  il1 = il1/num; il2 = il2/num; il3 = il3/num; il4 = il4/num;

  // print the results to the serial monitor:
  if (dispone) {
  Serial.print(" RAIL1 (V)= ");  Serial.print(v1);  //Serial.print("\r\n");
  if (!one) {Serial.print("    L1 (mA)= ");  Serial.print(il1, 1);}  //Serial.print("\r\n");
  if (1==1) {Serial.print("    H1 (mA)= ");  Serial.print(i1, 1); }
  if (disptwo) {
  Serial.print(" RAIL2 (V)= ");  Serial.print(v2);  //Serial.print("\r\n");
  if (!two) {Serial.print("    L2 (mA)= ");  Serial.print(il2, 1);}  //Serial.print("\r\n");
  if (1==1) {Serial.print("    H2 (mA)= ");  Serial.print(i2, 1);} 
  if (dispthree) {
  Serial.print(" RAIL3 (V)= ");  Serial.print(v3);  //Serial.print("\r\n");
  if (!three) {Serial.print("    L3 (mA)= ");  Serial.print(il3, 1);}  //Serial.print("\r\n");
  if (1==1) {Serial.print("    H3 (mA)= ");  Serial.print(i3, 1);} 
  if (dispfour) {
  Serial.print(" RAIL4 (V)= ");  Serial.print(v4);  //Serial.print("\r\n");
  if (!four) {Serial.print("    L4 (mA)= ");  Serial.print(il4, 1);}  //Serial.print("\r\n");
  if (1==1) {Serial.print("    H4 (mA)= ");  Serial.print(i4, 1);} 


  while (Serial.available()) {  // while there are characters in the buffer, grab them all...
    incomingByte =;  // will not be -1
    Serial.print("Incoming byte: "); Serial.print(incomingByte);
    // Serial.print("    Delay interval:"); Serial.print(delayintvl);  Serial.print("\r\n");

    if (incomingByte == 'h' || incomingByte == 'H'){
      Serial.print("  +/= delay interval +/- 10mS\r\n");
      Serial.print("  /- delay interval 20msec/1sec\r\n");
      Serial.print("  l/L all rails low/high range in unison\r\n");
      Serial.print("  q/w/e/r toggle display of rail 1/2/3/4\r\n");
      Serial.print("  1/2/3/4 high range of rail 1/2/3/4\r\n");
      Serial.print("  !/@/#/$ low range of rail 1/2/3/4\r\n");
      Serial.print("  h print this help...\r\n");

    // change delay interval...
    if (incomingByte == '+') delayintvl = delayintvl + 10;
    if (incomingByte == '=') delayintvl = delayintvl - 10;
    if (incomingByte == '_') delayintvl = 20;
    if (incomingByte == '-') delayintvl = 1000;
    if (delayintvl<1) delayintvl = 20;

    // toggle low/high range of all rails in unison...
    if (incomingByte == 'L') {
      digitalWrite(LoHiEn1, LOW);
      digitalWrite(LoHiEn2, LOW);
      digitalWrite(LoHiEn3, LOW);
      digitalWrite(LoHiEn4, LOW);
      one = true; two = true; three = true; four = true;
    if (incomingByte == 'l') {
      digitalWrite(LoHiEn1, HIGH);
      digitalWrite(LoHiEn2, HIGH);
      digitalWrite(LoHiEn3, HIGH);
      digitalWrite(LoHiEn4, HIGH);
      one = false; two = false; three = false; four = false;

    // still unimplemented, but for wakeup of target board...
    if (incomingByte == 'w') digitalWrite(WakeUp, LOW);
    if (incomingByte == 'W') digitalWrite(WakeUp, HIGH);

    // toggle display of rail...
    if (incomingByte == 'q') dispone = !dispone;
    if (incomingByte == 'w') disptwo = !disptwo;
    if (incomingByte == 'e') dispthree = !dispthree;
    if (incomingByte == 'r') dispfour = !dispfour;

    // change between high/low range..
    if (incomingByte == '1') { digitalWrite(LoHiEn1, LOW);  one = true; }
    if (incomingByte == '!') { digitalWrite(LoHiEn1, HIGH); one = false;}
    if (incomingByte == '2') { digitalWrite(LoHiEn2, LOW);  two = true;}
    if (incomingByte == '@') { digitalWrite(LoHiEn2, HIGH); two = false;}
    if (incomingByte == '3') { digitalWrite(LoHiEn3, LOW);  three = true;}
    if (incomingByte == '#') { digitalWrite(LoHiEn3, HIGH); three = false;}
    if (incomingByte == '4') { digitalWrite(LoHiEn4, LOW);  four = true;}
    if (incomingByte == '$') { digitalWrite(LoHiEn4, HIGH); four = false;}

  // wait delayintvl mS after the last reading:

Future Work and Improvements

Work on a "smart" sensor with a local Kinetis device (KL02Z or KL05Z) on the sensor board itself that has three separate sense amplifiers (one run/high current and two low) has begun. There are several advantages to having a microcontroller on each sensor board:

  • All instrumented rails can be measured simultaneously
  • The sampling rate can be increase over current generation's round robin
  • Measured data is sent over I2C or UART, allowing arbitrary number of rails to be instrumented
  • Each sensor board can provide all its shunt and gain info
  • Sensor board can be used in isolation, i.e., without a master profiler board

A GUI interface for the serial data output by the profiler would be really nice...



Addditional Information

For more information on current measurements in general, see this tutorial series:

A Current Sensing Tutorial--Part 1: Fundamentals | EE Times 

A Current Sensing Tutorial-Part II: Devices | EE Times 

A Current Sensing Tutorial--Part III: Accuracy | EE Times 

A Current Sensing Tutorial-Part IV: Layout and Troubleshooting Guidelines | EE Times 

5 people found this helpful