Close
0%
0%

MetaShunt: High Dynamic Range Current Measurement

A low-cost and accurate tool for analyzing the power consumption of ultra-low power and IoT devices with rapidly changing current usage

Public Chat
Similar projects worth following
Starting from
$299.00
jacobwachlin has 15 orders / 0reviews
Ships from United States of America
MetaShunt is an electronic instrument designed for high-bandwidth, very high dynamic range measurements of the instantaneous current and power and accumulated energy use of low-power and IoT devices between 50 nanoamps and 500 milliamps

MetaShunt leverages a simple idea - by quickly and accurately measuring the voltage across a current shunt resistor and engaging additional shunt stages when needed, MetaShunt ensures that it can provide accurate current measurement across a range of approximately 10,000,000:1 (from 50nA to 500 mA) without providing significant voltage burden. This range of current is specifically targeted for use with ultra-low power and IoT systems. By measuring current rapidly over time, the total energy use during a given portion of your code can be determined. MetaShunt acts as a virtual ground for your system, so that you can use your battery. Or, MetaShunt can provide 3.3V or 5V to the system under test if desired.


Q: Why do you need this tool?

  • You are developing low power electronic projects, and need to know how much power you are using during short wake-up cycles
  • You develop IoT systems, and the power consumption changes drastically during data transmission and you want to measure it
  • You are testing components to validate them against the datasheet, and the current is lower than your multi-meter can measure reliably

Q: Isn't this basically a JouleScope or Otii Arc?

Yes, it is designed for very similar use, but does have significant differences. MetaShunt is designed more for DIY hobbyists than those products are, and that can be seen in price, capabilities, and openness. MetaShunt has an open USB serial interface protocol and example Python interfacing scripts so that users can build their own testing scripts with it. There are no subscriptions or features behind paywalls. In addition, all of the resistors in the feedback and sensing path come with open solder jumpers so that the user can measure the resistance with their multi-meter and provide it to the system for calibration. This allows for accurate measurements without needing expensive high-precision resistors.


Q: Can I buy one?

Yes! It is available in Tindie here!

  • New MetaShunt Interface Feature - Comparison Tools

    Jake Wachlin5 days ago 0 comments

    MetaShunt was designed for high dynamic range current measurement of embedded systems, particularly ultra-low power and IoT systems. These measurements help verify the functionality of a project or product. They tie in nicely with the power budgeting tools I've also developed, hosted on Hackaday.io here. However, I previously hadn't connected the two. This log demonstrates the new comparison tools I've added to the MetaShunt Interface Github repo, how they work, and provides some examples of their use.


    First, lets look at the basic use of these tools - where they are located and what the interface looks like. The comparison tools are included in a folder on the MetaShunt interface. The key Python file to look for is metashunt_profile_processing.py. This can be used to set up the comparison plots between the outputs of MetaShunt V1, MetaShunt V2, Otii Arc, and my modeling tools. Each has its own enumeration to tell the parser what type of file it is, and the files can be temporally aligned manually, with no alignment, or by attempting cross-correlation (which may or may not work depending on what your signal looks like).


    Next, let's look at an example. In this example, my Nanosleeper development board is operating between run mode, run mode with LEDs on, and deep sleep mode. The script to view this example is in the Examples/Nanosleeper folder for the Comparison Tools on the metashunt_interface repo. The code is very simple.

    import sys
    
    sys.path.append('../../')
    
    import metashunt_profile_processing as mpp
    
    if __name__ == "__main__":
        metashunt_profile_1 = mpp.PROFILE(filename="metashunt_v1_nanosleeper.csv", filetype=mpp.FILETYPE.METASHUNT_LOG, 
                                          alignment_type=mpp.ALIGNMENTTYPE.TIMESHIFT, label="MetaShunt V1", t_shift=-6.1659)
    
        metashunt_profile_2 = mpp.PROFILE(filename="metashunt_v2_nanosleeper.csv", filetype=mpp.FILETYPE.METASHUNT_LOG, 
                                          alignment_type=mpp.ALIGNMENTTYPE.TIMESHIFT, label="MetaShunt V2", t_shift=3.26803)
        
        arc_profile_1 = mpp.PROFILE(filename="otii_arc_nanosleeper.csv", filetype=mpp.FILETYPE.OTII_LOG, 
                                          alignment_type=mpp.ALIGNMENTTYPE.TIMESHIFT, label="Otii Log", t_shift=0.0)
        model_profile_1 = mpp.PROFILE(filename="Nanosleeper_sim.csv", filetype=mpp.FILETYPE.EMBEDDED_POWER_MODEL, 
                                          alignment_type=mpp.ALIGNMENTTYPE.TIMESHIFT, label="Model", t_shift=1.8979)
    
        
        profiles = [metashunt_profile_1, metashunt_profile_2, arc_profile_1, model_profile_1]
    
        mpp.plot_profiles(profiles)

    The four files are processed, manually timeshifted, and then plots are generated. This automatically generates plots of current, power, and accumulated energy use. Note that the power and energy calculations use a system voltage parameter that is part of the Profile class and defaults to 3.3V.

    The current plot, when zoomed to the first wakeup cycle, looks like the plot below. Note that the logs have different lengths and start at different points, so they don't fully overlap.

    This comparison tool is helpful for evaluating between firmware updates or for comparing to a predictive model of how much power your product or project should consume. For example, you can zoom into different sections and compare data from MetaShunt to data from the model (and in this case from an Otii Arc). Note that at higher current, the Otii Arc appears to have lower noise than MetaShunt V1 and V2, but appears to be much noisier at low current below 500nA.

  • Introducing: MetaShunt V2

    Jake Wachlin10/07/2024 at 12:59 0 comments

    MetaShunt V1 has been functional and available for a while now, and while it is still a wonderfully effective tool for examining the current consumption of a project across a wide range of operational modes, there were several improvements I wanted to make. This led me to develop MetaShunt V2! Thank you to my early customers on Tindie - your feedback and bug finding has helped make the original MetaShunt and now MetaShunt V2 that much better!


    Goals and Updates of MetaShunt V2

    MetaShunt V2 was developed to fix or improve a few key features of the original MetaShunt, as well as to add a key new feature:

    • The MetaShunt V2 LT Version can operate as a standalone unit, continually monitoring the total energy used by your product, project, or prototype.
      • Once powered by USB, it continually measures current at the usual high rate and high accuracy used when streaming data to your computer over USB. At approximately 1Hz, it updates the onboard LCD display with the current *ahem* current, and displays the total on time in seconds and the total "current x time" in nAh, uAh, or mAh. Care is taken in the accumulation and math to ensure no overflow or underflow occurs across such a wide range of power levels.
      • The accumulated data can be reset with the touch of a button.
    • MetaShunt V2 provides a major step up in performance across the board. 
      • The internal sample/loop rate is nearly doubled to >700 kHz.
      • The ADC resolution is 4X better, going from 12-bit to 14-bit.
      • The burst measurements can be made 5X faster, and more data is saved during the burst read than could be before.
      • The continuous data outputs are about 20% faster.
      • The shunt MOSFETs have lower on-state resistance, leading to better accuracy.
      • The gain stage has higher gain-bandwidth product, improving sensing bandwidth and reducing burden voltage.
    • The calibration approach is very different. 
      • A fixed, high accuracy 50:1 amplification stage is used in the measurement path, so there are no resistors in the amplification stage that must be measured accurately and configured.
      • High accuracy resistors are used in all shunt stages, to reduce the need for individual calibration of MetaShunt devices (although calibration can be performed to improve accuracy beyond a baseline).
    • The physical form factor is improved.
      • More care was taken on the aesthetics of the design, as well as making the outer dimensions and mounting holes fit a desired pattern. This makes it easier to incorporate into an enclosure or mount onto a test bench.
      • The screw terminals are replaced by spring-pin terminals, enabling the user to swap in and out the DUT without tools.
      • The programming pins are more accessible and labeled better.
    • A button has been added which can be used to manually trigger burst measurements.


    First Look at the Hardware

    MetaShunt V2 LT is shown below, with its new LCD display. Note also the additions of spring-lock connectors for the DUT, an improved shape, and two buttons. One button is used to reset long term data and the other is used as a trigger for burst measurements.

    The base version of MetaShunt V2 is shown below. It has all of the features of the original MetaShunt along with significantly improved performance.


    Interface Updates

    Updates have been made to the open source MetaShunt Interface on GitHub. MetaShunt V2 is mostly backwards compatible with the original interface, but some changes were needed to support new capabilities. Specifically, check out the new realtime interface at Realtime Interface/metashunt_v2_realtime_interface.py. Also, check out the V2 version of the user guide for updates on how to use MetaShunt V2.


    Available Now!

    MetaShunt V2 is available now on my Tindie store here! Thank you for all the support from this community! 

  • Nanosleeper - Sub 100nA Deep Sleep Dev Board

    Jake Wachlin01/28/2024 at 18:24 0 comments

    I used MetaShunt to test my new ultra-low power development board, called Nanosleeper. The goal with Nanosleeper was to achieve <100nA deep sleep current with the ability to wake up at a selected time. It was built in the Adafruit Feather form factor, but does not 100% match the Feather specification. It has support for controlling external power and I2C pullups for external devices so that very, VERY low power systems can be prototyped.

    Debugging and testing a product like Nanosleeper is difficult without a tool like MetaShunt. The power used when on is over 8,000X times higher than when in deep sleep, so measuring current with a simple shunt is not likely to work. However, MetaShunt has no issues with this.

    Pictures of an assembled Nanosleeper and it connected to MetaShunt are shown below. Nanosleeper is powered by the 3.3V supply from MetaShunt into the BAT input of Nanosleeper. Because Nanosleeper uses an extremely low power linear voltage regulator (1.8V logic level), this gives the same current results as it would if powered by a 3V coin cell battery.

    The firmware used during this test is shown below. The two onboard LEDs are turned on for 5 seconds, then turned off. A 2 second busy wait then occurs. Next, the RTC is set up using I2C, and set to wake the system after 15 seconds. The wakeup pins are then configured and shutdown sleep mode is entered.

      // Toggle LED to indicate awake
      HAL_GPIO_WritePin(D12_GPIO_Port, D12_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(D13_GPIO_Port, D13_Pin, GPIO_PIN_SET);
      HAL_Delay(5000);
      HAL_GPIO_WritePin(D12_GPIO_Port, D12_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(D13_GPIO_Port, D13_Pin, GPIO_PIN_RESET);
      HAL_Delay(2000);
    
      // Set up RTC, checking if it's already been set up
      bool is_initial_setup = true;
      uint32_t current_time_utc = 1705968815;
      bool rv_3028_setup_ok = init_rv_3028_c7(hi2c1, current_time_utc, is_initial_setup);
    
    
      // Go to shutdown mode, with pin wakeup.
      HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
    
    
      /* Enable wakeup pin WKUP1 */
      HAL_PWREx_EnableGPIOPullDown(PWR_GPIO_C, PWR_GPIO_BIT_14);
      HAL_PWREx_EnableGPIOPullDown(PWR_GPIO_C, PWR_GPIO_BIT_15);
      HAL_PWREx_EnableGPIOPullUp(PWR_GPIO_A, PWR_GPIO_BIT_0);
      HAL_PWREx_EnablePullUpPullDownConfig();
      HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1_LOW);
      HAL_PWREx_DisableInternalWakeUpLine();
    
      /* enter shutdown */
      __HAL_RCC_PWR_CLK_ENABLE();
      __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF1);
      HAL_PWREx_EnterSHUTDOWNMode();

    Each of those sections of the firmware are very clear in the power profile below. The system starts up (the current spike off the chart is due to plugging in Nanosleeper to power) and with both LEDs on the current is steady at about  800uA. With the LEDs off, the current drops to about 600uA. There is a current spike to about 1.15mA during the I2C communication with the RTC, and then the system goes into deep sleep. After 15 seconds, the system starts up again and turns on the LEDs.

    The deep sleep current is shown in higher detail below, and is steady just under 95nA.


    This example shows MetaShunt's performance for an ultra-low power design, with ~8,000X variation in power consumption during operation.

  • Example: ESP32 WiFi and Low Power Modes

    Jake Wachlin11/29/2023 at 01:33 0 comments

    The ESP32 is a commonly used wifi and Bluetooth enabled microcontroller which nicely demonstrates the usefulness of MetaShunt as a measurement and debugging tool. When connected to WiFi and operating at full speed, the ESP32 can consume a lot of power (some sources report up to 240mA maximum). However, it also has low power modes that can get the current consumption down to about 5uA, a level 48,000 times lower than its maximum! MetaShunt is the perfect tool for analyzing the power of such a system. A multimeter is incapable of keeping up with the rapid changes in power consumption, and multiple ranges would likely be needed. A simple current shunt monitored by an oscilloscope would suffer from resolution issues - a shunt sized for 240mA will not be useful at 5uA, and a shunt sized for 5uA will not work at 240mA (the system would brown out). MetaShunt can easily measure current across these ranges without browning out the system.


    This test was completed with an ESP32 Huzzah development board from Adafruit, since it is what I had on-hand. This is not the ideal board to test low-power consumption with, because it has a UART to USB adapter component and a battery charger on board, neither of which can be put into low power mode. Nonetheless, the microcontroller portion of it can be controlled to enter and exit low power modes, as well as connect to WiFi, and I will demonstrate monitoring this system using MetaShunt.

    The board was connected to MetaShunt by the 5V and VSNS pins, just like in the prior log. Note that the measurements will therefore also include quiescent current from the voltage regulator.

    The following Arduino sketch was used in this test. Various active busy waits, waits while connected to WiFi, online data queries, and low power modes are demonstrated. Care is taken before entering deep sleep to turn on the RTC for wakeup later and to set all GPIO into the best power saving mode (this is really important for getting the last few uA out of a low power system).

    #include <WiFi.h>
    #include "time.h"
    #include "driver/rtc_io.h"
    #include "driver/gpio.h"
    #include "esp_wifi.h"
    #include "driver/adc.h"
    
    //#define USE_SERIAL      1
    
    RTC_DATA_ATTR int bootCount = 0;
    
    const char* ssid       = "MYSSID";
    const char* password   = "MYPASSWORD";
    
    const char* ntpServer = "pool.ntp.org";
    const long  gmtOffset_sec = 3600;
    const int   daylightOffset_sec = 3600;
    
    
    void printLocalTime()
    {
      struct tm timeinfo;
      if(!getLocalTime(&timeinfo)){
        Serial.println("Failed to obtain time");
        return;
      }
      Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
    }
    
    void setup() {
      #ifdef USE_SERIAL
      Serial.begin(115200);
      #endif
      
      pinMode(13,OUTPUT);
      delay(500);
      
      digitalWrite(13,HIGH);
      
      delay(2500);
    
      digitalWrite(13,LOW);
    
      //connect to WiFi
      #ifdef USE_SERIAL
      Serial.printf("Connecting to %s ", ssid);
      #endif
      WiFi.begin(ssid, password);
      while (WiFi.status() != WL_CONNECTED) {
          delay(15);
          #ifdef USE_SERIAL
          Serial.print(".");
          #endif
      }
      #ifdef USE_SERIAL
      Serial.println(" CONNECTED");
      #endif
      
      //init and get the time
      configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
      delay(200);
      int i;
      for(i = 0; i < 10; i++)
      {
        digitalWrite(13,!digitalRead(13));
        delay(100);
      }
      digitalWrite(13,LOW);
      
      #ifdef USE_SERIAL
      printLocalTime();
      #endif
    
      //disconnect WiFi as it's no longer needed
      WiFi.disconnect(true);
      WiFi.mode(WIFI_OFF);
    
      esp_sleep_enable_timer_wakeup(3000000); // 3 sec
      esp_light_sleep_start();
      // we'll wake from light sleep here
    
      //Set things up for lower power
      // ESP32 docs say to isolate pin 12 in deep sleep to save power
      rtc_gpio_isolate(GPIO_NUM_12);  
    
      // Isolate other pins
      rtc_gpio_isolate(GPIO_NUM_39);
      rtc_gpio_isolate(GPIO_NUM_36);
      rtc_gpio_isolate(GPIO_NUM_35);
      rtc_gpio_isolate(GPIO_NUM_34);
      rtc_gpio_isolate(GPIO_NUM_32);
      rtc_gpio_isolate(GPIO_NUM_33);
      rtc_gpio_isolate(GPIO_NUM_27);
      rtc_gpio_isolate(GPIO_NUM_26);
      rtc_gpio_isolate(GPIO_NUM_25);
      rtc_gpio_isolate(GPIO_NUM_23);
      rtc_gpio_isolate(GPIO_NUM_22);
     rtc_gpio_isolate(GPIO_NUM_21);
    ...
    Read more »

  • Example: Power of Feather M0 Adalogger

    Jake Wachlin11/15/2023 at 01:37 0 comments

    As an example to show MetaShunt's capability, I created an Arduino sketch for the Adafruit Feather M0 Adalogger which would toggle the onboard LED and use various low power modes. This microcontroller development board was then connected to MetaShunt:

    Adalogger GND <----> VSNS

    Adalogger USB <----> 5V

    The code running on the Adalogger is the following:

    #include "LowPower.h"
    #include <RTCCounter.h>
    
    #define LED_PIN     13
    
    #define CONFIG_PINS     true
    #define DISABLE_TC_TCC  true
    #define DISABLE_CLOCKS  true
    #define DISABLE_ADC     true
    
    void setup() {
      pinMode(LED_PIN, OUTPUT);
      digitalWrite(LED_PIN, LOW);
    
      #ifdef CONFIG_PINS
      pinMode(0, OUTPUT);
      pinMode(1, OUTPUT);
      pinMode(4, OUTPUT);
      pinMode(5, OUTPUT);
      pinMode(6, OUTPUT);
      pinMode(7, OUTPUT);
      pinMode(8, OUTPUT);
      pinMode(9, OUTPUT);
      pinMode(10, OUTPUT);
      pinMode(11, OUTPUT);
      pinMode(12, OUTPUT);
      pinMode(A0, OUTPUT);
      pinMode(A1, OUTPUT);
      pinMode(A2, OUTPUT);
      pinMode(A3, OUTPUT);
      pinMode(A4, OUTPUT);
      pinMode(A5, OUTPUT);
    
      digitalWrite(0, LOW);
      digitalWrite(1, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      digitalWrite(9, LOW);
      digitalWrite(10, LOW);
      digitalWrite(11, LOW);
      digitalWrite(12, LOW);
      digitalWrite(A0, LOW);
      digitalWrite(A1, LOW);
      digitalWrite(A2, LOW);
      digitalWrite(A3, LOW);
      digitalWrite(A4, LOW);
      digitalWrite(A5, LOW);
      #endif
    
      #ifdef DISABLE_TC_TCC
      TC3->COUNT16.CTRLA.bit.ENABLE = 0;
      TC4->COUNT16.CTRLA.bit.ENABLE = 0;
      TC5->COUNT16.CTRLA.bit.ENABLE = 0;
    
      TCC0->CTRLA.bit.ENABLE = 0;
      TCC1->CTRLA.bit.ENABLE = 0;
      TCC2->CTRLA.bit.ENABLE = 0;
      #endif
    
      #ifdef DISABLE_CLOCKS
      SYSCTRL->DFLLCTRL.bit.RUNSTDBY = 0;
      SYSCTRL->VREG.bit.RUNSTDBY = 0;
      #endif
    
      #ifdef DISABLE_ADC
      ADC->CTRLA.bit.SWRST = 1;
      #endif
    
      rtcCounter.begin();
    
    }
    
    void loop() {
    
      // Busy wait
      delay(2000);
    
      int i;
    
      for(i=0; i<10; i++)
      {
        delay(250);
        digitalWrite(LED_PIN, HIGH);
        delay(250);
        digitalWrite(LED_PIN, LOW);
      }
    
      // Another type of sleep
      rtcCounter.setPeriodicAlarm(2);
      SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;  // Disable SysTick interrupts
      LowPower.idle(IDLE_2); 
      SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;   // Enable SysTick interrupts  
      if (rtcCounter.getFlag()) {
        rtcCounter.clearFlag();
      }
    
      delay(500);
    
      // Then standby
      rtcCounter.setPeriodicAlarm(5);
      LowPower.standby(); 
      if (rtcCounter.getFlag()) {
        rtcCounter.clearFlag();
      }
    
      delay(1000);
    
      for(i=0; i<2; i++)
      {
        delay(500);
        digitalWrite(LED_PIN, HIGH);
        delay(500);
        digitalWrite(LED_PIN, LOW);
      }
    
    }

    This code toggles LEDs and uses active mode (in delays), idle, and standby power modes. 

    Using the Python interface script that will be released soon, data was recorded for 20 seconds. The output data was provided at 4kHz (the onboard measurement is much faster, but USB bandwidth limits the output data rate to this level). The overall data cycle is shown below.

    Let's look specifically at sections of the code and see how they match to the current profile shown here. The first section involves a 2 second busy wait followed by toggling the LED pin 10 times with a 0.5s period.

    // Busy wait
      delay(2000);
    
      int i;
    
      for(i=0; i<10; i++)
      {
        delay(250);
        digitalWrite(LED_PIN, HIGH);
        delay(250);
        digitalWrite(LED_PIN, LOW);
      }

     The plot below shows the measurements during this portion of the program. During the busy wait, the current is ~11.6mA, and it increases to about 12.2mA when the LED is turned on.

    In the next section, the Idle 2 sleep mode is used. This sleep mode is set for about 2 seconds. Then a 500ms busy wait occurs.

    // Another type of sleep  
    rtcCounter.setPeriodicAlarm(2);
    SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;  // Disable SysTick interrupts
    LowPower.idle(IDLE_2);   
    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;   // Enable SysTick interrupts    
    if (rtcCounter.getFlag()) {    
        rtcCounter.clearFlag();  
    }
    
    delay(500);

    The measurement profile for this portion of the code is shown...

    Read more »

View all 5 project logs

Enjoy this project?

Share

Discussions

Stephan Walter wrote 02/03/2024 at 17:42 point

I'm certainly looking forward to Metashunt being available on Tindie. I wonder how this compares to Nordic's Power Profiler Kit II which is another hobbyist-friendly (<$100) current measurement tool.

What's nice about the PPK2 is that it can supply an arbitrary voltage to the target (0.8V-5V) and also that it has digital inputs, so that you can easily attribute a measured current to a certain device state using GPIOs.

  Are you sure? yes | no

Jake Wachlin wrote 02/21/2024 at 14:46 point

Hi Stephan! MetaShunt is now listed on Tindie here: https://www.tindie.com/products/energylabs/metashunt-hdr-current-measurement-tool/. I am still working on getting units ready for shipment, but if you are interested you can sign up for the waitlist there!

  Are you sure? yes | no

Jake Wachlin wrote 12/11/2023 at 19:55 point

Hey @Dan Julio thanks! I am thinking I will make the schematic open source so people can understand the implications of its approach on their measurements. 

The AA battery is used to provide a stable below ground rail for the op-amps so they don't have to operate near their negative rail with all the inconsistencies that can come from operating near a rail of a "rail-to-rail" op-amp

  Are you sure? yes | no

Dan Julio wrote 12/11/2023 at 01:17 point

Good luck with this project, Jack.  It could definitely fill an important niche.  Will any parts of this be open-source?  Certainly would be nice to look at the schematic and understand how you're switching since that's so important in a device like this.  Also, just curious, what does the AA battery do?

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates