Get actual input voltage

Hi,
I have a measurement loop:

  • get battery voltage
  • capture
  • analyze

for that I just need 1 single value of the input voltage(and if there are intermittend “outages” I would handle that myself).
In the capture and analyze loop I have changed from joulescope package to pyjoulescope_driver.
To get the battery voltage I have found multiple solutions:

I would prefer a simple method call if possible. Is there any I haven’t found?

Hi @lukGWF - The pyjoulescope_driver code does not have a “read present value” call. However, it is not hard to implement. How about something like this:

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

# Copyright 2024 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.

"""Implement an at-will block statistics read for pyjoulescope_driver.
"""

from pyjoulescope_driver import Driver
from queue import Queue, Empty
import sys
import time


class Measure:

    def __init__(self):
        self._queue = Queue()
        self._previous = None
        self._capture = True
        
    def on_statistics(self, topic, value):
        self._previous = value
        if self._capture:
            self._queue.put(value)
     
    def value(self):
        return self._previous

    def __call__(self):
        while True:
            try:
                self._queue.get(block=False)
            except Empty:
                break
        self._capture = True
        v0 = self._queue.get()  # wait for first value to avoid overlapping past time
        v1 = self._queue.get()
        self._capture = False
        return v1


def run():
    frequency = 1000
    with Driver() as jsdrv:
        jsdrv.log_level = 'WARNING'

        device_paths = sorted(jsdrv.device_paths())
        device_path = device_paths[0]
        jsdrv.open(device_path)
        
        measure = Measure()
        
        if 'js110' in device_path:
            jsdrv.publish(f'{device_path}/s/i/range/select', 'auto')
            jsdrv.publish(f'{device_path}/s/v/range/select', '15 V')
            # use host-side statistics
            jsdrv.publish(device_path + '/s/i/ctrl', 'on')
            jsdrv.publish(device_path + '/s/v/ctrl', 'on')
            jsdrv.publish(device_path + '/s/p/ctrl', 'on')
            scnt = int(round(2_000_000 / frequency))
            jsdrv.publish(device_path + '/s/stats/scnt', scnt)
            jsdrv.publish(device_path + '/s/stats/ctrl', 'on')
            jsdrv.subscribe(device_path + '/s/stats/value', 'pub', measure.on_statistics)            
        elif 'js220' in device_path:
            jsdrv.publish(f'{device_path}/s/i/range/mode', 'auto')
            jsdrv.publish(f'{device_path}/s/v/range/mode', 'auto')
            # JS220, always sensor-side statistics
            scnt = int(round(1_000_000 / frequency))
            jsdrv.publish(device_path + '/s/stats/scnt', scnt)
            jsdrv.publish(device_path + '/s/stats/ctrl', 1)
            jsdrv.subscribe(device_path + '/s/stats/value', 'pub', measure.on_statistics)            

        time.sleep(0.5)  # do something else in your code for a while
        print(measure()['signals']['voltage']['avg']['value'])
        time.sleep(1.0)  # do something else in your code for a while
        print(measure()['signals']['voltage']['avg']['value'])
    return 0


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

This script configures the Joulescope statistics streaming. The statistics go to the Measure instance, which normally just discards them. When you call the Measure instance using measure(), it gets the next two statistics values and discards the first. You could use measure.value() with the queue if you don’t care about potentially measuring the voltage prior to calling measure().

Does this make sense and work for you?

Hi @mliberty,
Thanks for this fast solution. This does fit my requirements.
BR

Luk

1 Like