Reset/Clear Statistics Accumulators

Hi I am new to Joulescope (JS220) and maybe have not understood all the details.
So far I was successful to create a Python script that captures a statistics stream and analyses the data. This is working as expected.

At the start of each measurement I want to reset the charge accumulator to get a fresh start of values. I found out that this will be done via a call with this topic:

self.driver.publish(f’{self.device_path}/s/stats/!clear’, 1)

I also learned that it seems that one can only clear if the stream is active. Well I think I followed both rules, but in my script the accumulators increase steadily.

Does anybody have a hint what I do wrong here?
Thanks and best regards,
Andreas

Hi Anko, and welcome to the Joulescope forum!

I took a look, and it seems that s/stats/!clear is incorrectly retaining the value. The workaround is to publish value 0, followed by 1 as shown here:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Copyright 2026 Jetperch LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from pyjoulescope_driver import Driver, time64
import sys
import queue


def _print_statistics_value(topic, value):
    sample_id = value['time']['samples']['value'][0]
    i_avg = value['signals']['current']['avg']['value']
    v_avg = value['signals']['voltage']['avg']['value']
    p_avg = value['signals']['power']['avg']['value']
    charge = value['accumulators']['charge']['value']
    energy = value['accumulators']['energy']['value']
    print(f'{sample_id},{i_avg},{v_avg},{p_avg},{charge},{energy}')


def run():
    # Use a queue to synchronize statistics to the main thread
    q = queue.Queue()
    def _on_statistics_value(topic, value):
        q.put((topic, value), block=False)
    
    
    with Driver() as d:
        # JS220 only, one at a time
        devices = d.device_paths()
        devices = [device for device in devices if 'js220' in device]
        if len(devices) != 1:
            print(f'Only support one device at a time, found {devices}')
            return 1
        device = devices[0]
            
        # display the column header
        print("#sampled_id,i,v,p,charge,energy")
        d.open(device)
        try:
            d.publish(device + '/s/i/range/mode', 'auto')
            d.subscribe(device + '/s/stats/value', 'pub', _on_statistics_value)
            d.publish(device + '/s/stats/ctrl', 1)
            d.publish(device + '/s/stats/!clear', 0)
            d.publish(device + '/s/stats/!clear', 1)
            while True:
                topic, value = q.get(block=True, timeout=1.0)
                _print_statistics_value(topic, value)
        except KeyboardInterrupt:
            sys.stdout.flush()
        finally:
            d.publish(device + '/s/stats/ctrl', 0)
            d.close(device)
    return 0


if __name__ == '__main__':
    sys.exit(run())

Does this fix the issue for you?

Hi mliberty,
thanks for the fast reply. Yes it does the trick. Values for charge and energy are reasonable now.
What about the max/min values for current/voltage/energy? It seems that they are not reset by this
!clear command. The values are true, but seem to stem from measurements before I started the stream. Is there a way to clear them as well?
Thanks!

Hi @Anko - Only charge and energy accumulate, and !clear only affects those two quantities. The average, standard deviation, min, and max are only computed over that window of statistics from the full 1 MSPS samples.

I modified the code above to print current min and max, and you can see that max definitely is not held:

PS C:\project\Joulescope\support\2026\02\20260213> python stats_clear.py
#sampled_id,i,i_min,i_max,v,p,charge,energy
143189524997,0.023,-0.008,0.105,0.991,0.023,0.012,0.012
143190524997,0.008,-0.006,0.053,0.991,0.008,0.016,0.015
143191524997,0.004,0.000,0.011,0.991,0.004,0.018,0.017
143192524997,0.000,-0.002,0.001,0.991,0.000,0.018,0.018
143193524997,0.000,-0.002,0.000,0.991,0.000,0.018,0.018
143194524997,0.000,0.000,0.000,0.991,0.000,0.018,0.018
143195524997,0.000,0.000,0.000,0.991,0.000,0.018,0.018
143196524997,0.062,-0.006,0.139,0.990,0.061,0.049,0.048
143197524997,0.046,-0.009,0.105,0.991,0.046,0.072,0.071
143198524997,0.005,-0.004,0.057,0.991,0.005,0.075,0.074
143199524997,0.006,-0.000,0.011,0.991,0.006,0.078,0.077
143200524997,0.001,-0.001,0.001,0.991,0.001,0.078,0.077

Here is the updated code:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Copyright 2026 Jetperch LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from pyjoulescope_driver import Driver, time64
import sys
import queue


def _print_statistics_value(topic, value):
    sample_id = value['time']['samples']['value'][0]
    i_avg = value['signals']['current']['avg']['value']
    i_min = value['signals']['current']['min']['value']
    i_max = value['signals']['current']['max']['value']
    v_avg = value['signals']['voltage']['avg']['value']
    p_avg = value['signals']['power']['avg']['value']
    charge = value['accumulators']['charge']['value']
    energy = value['accumulators']['energy']['value']
    print(f'{sample_id},{i_avg:.3f},{i_min:.3f},{i_max:.3f},{v_avg:.3f},{p_avg:.3f},{charge:.3f},{energy:.3f}')


def run():
    # Use a queue to synchronize statistics to the main thread
    q = queue.Queue()
    def _on_statistics_value(topic, value):
        q.put((topic, value), block=False)
    
    
    with Driver() as d:
        # JS220 only, one at a time
        devices = d.device_paths()
        devices = [device for device in devices if 'js220' in device]
        if len(devices) != 1:
            print(f'Only support one device at a time, found {devices}')
            return 1
        device = devices[0]
            
        # display the column header
        print("#sampled_id,i,i_min,i_max,v,p,charge,energy")
        d.open(device)
        try:
            d.publish(device + '/s/i/range/mode', 'auto')
            d.subscribe(device + '/s/stats/value', 'pub', _on_statistics_value)
            d.publish(device + '/s/stats/ctrl', 1)
            d.publish(device + '/s/stats/!clear', 0)
            d.publish(device + '/s/stats/!clear', 1)
            while True:
                topic, value = q.get(block=True, timeout=1.0)
                _print_statistics_value(topic, value)
        except KeyboardInterrupt:
            sys.stdout.flush()
        finally:
            d.publish(device + '/s/stats/ctrl', 0)
            d.close(device)
    return 0


if __name__ == '__main__':
    sys.exit(run())

If you want to better understand min and max with your circuit, you can use the Oscilloscope view (Waveform widget) in the Joulescope UI.

Understood, thanks for the help

1 Like