Dead short current measurement: Arduino VS Scope

Summary
When comparing measurements of a given constant voltage of 700mV between Arduino (via analogread ADC), scope, and DMM, then the values are nicely within approx 1% of each other. However, when measuring an (aprox) 700mV voltage drop over a shunt caused by a battery DC dead short, then the voltage measured by the scope is roughly 200mV higher than the Arduino. Apparently, the change from a static voltage to a dynamic one changed something. The Question: What could be the reason for this and how to possibly correct this? Note that the "Waveform" of the short circuit current (or corresponding shunt voltage) matches well between Arduino and scope.

Context
This project. Edit: based on comments below (limitations to link access), more context here: The goal is to measure the dead-short-circuit current and fuse clearing time with an LFP battery.






Graph notes: I manually horizontally shifted the two curves to align them. Also, 1V corresponds to 10kA.

Hardware (with voltage accuracy):

  • Shunt: 500A 50mV Victon SmartShunt; Made of Manganin | has enough thermal mass to withstand the short, trust me.
  • Genuine Arduino UNO R3 with ATMEL ATMEGA328P. (ADC accuracy: 2 LSB); Calibrated reference voltage.
  • Oscilloscope: Siglent SDS1202X (DC Gain Accuracy for 5mV/div to 10V/div: ≤ +/-3%; offset accuracy for ≥2 mV/div: +/- (1%·Offset + 1.5%·8·V/div + 2mV); warmed up 30min; brand new.
  • DMM: Klein Tools CL380 (accuracy: 1% + 8 digits).
  • Probes (used for both scope and arduino): Siglent PP215 probes. The probes for Arduino and scope hook up at the same points on the shunt.

Code

/*
Goal: Log the smartshunt current (using the voltage drop accross the shunt) during a DC dead short.
Event duration: Roughly a millisecond. The sampling interval should be at least an order smaller than that.
The code below uses "fast sampling" until the dynamic mem is full.
After that, "slow sampling" is done due to the time needed to transfer through serial to a PC USB port.
*/
const float vref = 3.304; // -- 3.304V (internal Arduino); the actual reference voltage may deviate a bit; See also: https://skillbank.co.uk/arduino/measure2.htm
const float voltageResolution = vref / 1024; // -- vref / 1024; 
const float shuntSensitivity = 500.0 / 50e-3; // -- 500A / 50mV; shunt hardware specs 
const int totNumSamples = 4096; // -- 4096; the chosen total number of samples
const int maxMemSamples = 350; // -- 350 seems to be the max, leaving ample dynamic memory for local variables and prevent unexpected behavior.
const int numCurrentDecimals = 0; // -- 0; The current resolution is >1A, so no decimals needed Zero decimals. Set to 3 for directly checking ADC voltage measurement accuracy.
float currentArr[maxMemSamples] = { 0 }; // -- max allowed array size is 32767 bytes / 4 bytes per float = 8191 floats, but due tot dynamic mem restrictions, really only 2048b / 4b = 512 floats.
int curSampleID = 0; // -- 0; current sample ID
int analogPinReading; // -- value ranging from 0 to 1023
float curCurrent; // -- The current current (Amperes) value .
bool triggered = false; // -- true once the voltage is above zero. Before triggering, no mem is wasted to store zero-valued samples.
bool memFull = false; // -- true once currentArr is full
bool finished = false; // -- true once all samples have been taken
unsigned long startTimeMicros = 0; // -- 0; start time, assigned final value when triggered (us)
unsigned long memFullTimeMicros; // -- time at which currentArr[] is full (us)

void setup()
{ // -- setup code to run once:
  analogReference(EXTERNAL); // -- EXTERNAL; Add jumper between internal 3.3V output pin and AREF pin. See also: https://www.arduino.cc/reference/en/language/functions/analog-io/analogreference/
  Serial.begin(1000000); // -- 1000000; default is 9600; use same value in Serial Monitor and/or Putty!

  // -- https://www.gammon.com.au/adc
  ADCSRA &= ~(bit (ADPS0) | bit (ADPS1) | bit (ADPS2)); // -- Clears prescaler bits.
  ADCSRA |= bit (ADPS2);                               //  16 -- use this one 
}

void loop() { // -- main code, run infinitely:
  if (finished) return; // -- stops sampling
  analogPinReading = analogRead(A0); // -- accuracy: 2 LSB; see also https://arduino.stackexchange.com/questions/9384/uno-analog-input-voltage-reading-not-accurate

  if (!triggered && analogPinReading <= 8) // -- idle && "zero" current. If "&& analogPinReading == 0) would be used instead, then ADC inaccuracies immediately result in true. See also the measurement results: <= 7 is noise.
  { // -- Sitting idle *and* still zero current. Current has not yet started flowing. After current flow start, a zero-value current will not stop sampling.
    return;
  } // -- else: dead short current has started to flow
  if (!triggered)
  { // -- Sitting idle, *but* current just started to flow. The following code is executed only once:
    startTimeMicros = micros(); // -- Stores start time, and not any earlier, i.e. not in setup(), bc then the irrelevant pre-trigger idle time would be counted too.
    triggered = true; // -- Causes sampling to start.
  }

  curCurrent = (analogPinReading + 0.5) * voltageResolution * shuntSensitivity; // -- Units: bits x (bits/V) x (A/V) = A; See also https://skillbank.co.uk/arduino/measure2.htm
  if (!memFull) currentArr[curSampleID] = curCurrent;
  else Serial.println(String(micros()) + "\t" + String(curCurrent, numCurrentDecimals)); // -- mem is full
  
  if (curSampleID == maxMemSamples - 1)
  { // -- memory (or, actually, the *array*) is full:
    memFullTimeMicros = micros(); // -- Logs the memory full time before spending time exporting data.
    memFull = true; // -- Causes the next sample to be no longer stored in memory.
  }

  curSampleID++;

  if (curSampleID == totNumSamples) // -- Post-processing:
  { // -- All samples have been taken; the "slow samples" have already been transferred to serial.
    unsigned long finishTimeMicros = micros(); // -- stores the finish time
    delay(100); // -- Attempt to prevent random serial output.
    // -- Transfer samples from dynamic mem to USB and log how long that takes:
    for (int i = 0; i < maxMemSamples; i++) Serial.println("\t" + String(currentArr[i], numCurrentDecimals)); // -- The tab char is added here for consistency with "fast samples" and make import into Excel easier.
    Serial.println("Mem xfer time: " + String((micros() - finishTimeMicros) * 0.001, 0) + " ms."); // -- Formats float with 3 decimals.
    // -- Calculate and log the "slow sample" time interval (sent out first to serial):
    float slowIntervalMillis = (finishTimeMicros - memFullTimeMicros) / float(totNumSamples - maxMemSamples) * 0.001;
    Serial.println("Avg time interval (non-mem): " + String(slowIntervalMillis,3) + " ms."); // -- Formats float with 3 decimals
    // -- Calculate and log the "fast sample" time interval (sent out last to serial):
    float fastIntervalMillis = (memFullTimeMicros - startTimeMicros) / float(maxMemSamples - 1) * 0.001; // -- calculates avg interval between fast samples.
    Serial.println("Avg time interval (    mem): " + String(fastIntervalMillis, 3) + " ms."); // -- Formats float with 3 decimals
    // -- Calculate and log the total sampling time:
    Serial.println("Total sampling time: " + String((finishTimeMicros - startTimeMicros) * 0.001, 0) + " ms."); // -- formats float with 3 decimals.

    finished = true;
    return;
  }
}
1 Like

I don't know the answer to your question but thank you for sharing an interesting project. I will watch this topic with interest.

1 Like

Hi, @johanvanr
Welcome to the forum.

Can you please explain what "This project" is?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Please no Fritzy cut/paste images.

Thanks.. Tom.. :grinning: :+1: :coffee: :australia:

1 Like

Tom, follow the link! It's all in there.

1 Like

Hi,

Sorry but Why?
Can't the OP give us a brief precis.
The reference looks like its referring to fuses.

A basic diagram showing what @johanvanr is talking about would help.

Tom... :grinning: :+1: :coffee: :australia:

3 Likes

Fair point. All I'll say is I followed it and found what I read very interesting. I agree though, others might not want to so a précis is always helpful.

2 Likes

I followed the link, and like you Perry, I found it interesting.

So interesting in fact, that I wanted to examine the photographs and graphs in more detail.
When I clicked on them to get an enlarged view, I got the message "You must be logged-in to do that".

After getting this response several times, I eventually decided to register with the forum.

I chose a username, and password, entered my date of birth and location, but then almost lost the will to live when asked questions such as:

What experience do you have with solar or electronics? Please be thorough and write a few sentences! Short responses will get spam cleaned!

and

What system do you currently have or plan to build? If you do not fill this out, you will be blocked from the forum. Please write out a few sentences. This is also used to filter out spam sign-ups, which we get a lot of.

I aborted the registration process, as I'm sure that i wouldn't get immediate access, but have to wait until my application was approved.

So, johanvanr, could you post some photographs of your set-up and the results on this forum, please?

2 Likes

I would imagine that the difference is due to the way that you have wired up the test circuit.

That current shunt has a resistance of only 100µΩ, so it is extremely easy to add extra resistance into your wiring which could skew the results.

As you are measuring a changing voltage, then the inductance of the wiring also comes into play.

2 Likes

For me the link doesn't open:

" Dead short fuse trip experiment using an MRBF fuse | DIY Solar Power Forum

1 Like

@PerryBebbington @TomGeorge @JohnLincoln @ruilviana
Thanks for your comments, I did not realize that diysolarforum.com imposed those barriers. I added a circuit diagram, pictures, and a plot comparing the Arduino and scope to the original post.

BTW:

Why does the voltage (and current) change sign (and "charge" the battery) after the dead short according to the scope? Capacitative effects? Note that I was able to reproduce this current "backflow" with the arduino in a previous measurement, but in the plot I only plot positive currents for better resolution purposes.

How long does that continue? Do you think the heat from a short circuit just might change the cell chemistry for a short time?

1 Like

I don't know, but applying -1.5V to an Arduino analog input will destroy it in short order. What are the time units on the horizontal axis of the posted plot?

Keep in mind that even short straight wires have inductance, and show ringing with sudden voltage transitions. There is plenty of capacitance in those long sensor leads. See

1 Like

About a tenth of a microsecond. I do not know the cause. Looks like some built up charge can no longer flow from plus to minus, so it flows back.

microseconds (see also the plot in the OP).

Hi.

I agree, back EMF from the wiring, especially at such high currents.

The act of connecting and disconnecting is when the magnetic field produced around the wiring is changing, a changing magnetic field induces an opposing EMF.

Tom... :grinning: :+1: :coffee: :australia:
PS. This link about inductive circuits and TRANSIENT response may help.

1 Like

Some simple things to verify, which you may already have 'put to bed', but I see no indication of it.

  1. you have a power connection on the computer - have you verified isolation between ground and your Arduino's GND, or do you have a sneak path, when considering the next question
  2. you have a power connection for the 'scope - have you verified isolation between ground and your scope GND...*

Significant current could be flowing not where expected, which could appear as a difference between the two measurements. Sneak parallel paths for high current flow can be tricky to identify, and sometimes only become evident when a smaller gauge wire disappears, or you smell smoke.

Again, you may have already investigated, and dismissed, the potential for a ground loop offset, but I offer it up as one possible explanation for your variance in measurement.

3 Likes

@camsysca

Thanks. I did not pay particular attention to grounding:

  • The Arduino GND is connected to the USB GND of the laptop as by default.
  • The laptop is not connected to the 120Vac mains ground as by default.
  • The Oscilloscope channels GND are connected to 120Vac mains ground as by default.

So the Arduino GND does not connect to the scope GND through the 120Vac mains GND, if that is what you mean, so I do not see a ground loop there. I verified this with a DMM.

Do you recommend a USB isolator?

@TomGeorge @jremington @Paul_KD7HB
Thanks to you guys I realize I may be damaging my Arduino. I tried using a voltage divider on a breadboard to measure negative voltages, but that added more noise and/or new problems. This is becoming rather complex. I think I can easily move the batteries closer together to reduce the surface area enclosed by the dead-short circuit and reduce the inductance this way.

Hi, @johanvanr

What are you trying to accomplish?
Apart from destroying some batteries.

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

@TomGeorge

Goals are, loosely stated:

  • The main goal is to see how fuses respond when blown above their interrupt rating.
  • Sub-goal is to design an experimental setup to accomplish said main goal.
  • A secondary goal is to measure the fuse clearing time and maximum current in order to make a statement about the internal resistance of the battery and to compare it to what the BMS MOSFETs can handle.

Do you mean that the DC measurement device ground conductors (Arduino and Oscilloscope) may have enough capacitance to cause a 16,000A reverse current (as shown in plot in OP)?