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:
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().
If you call this method often enough, then yes, the queue should be empty. However, the original desire was to read the statistics value rarely. If you wait a few seconds between calls, it will not be empty as the Joulescope will have reported statistics data from the pyjoulescope_driver thread.
Correct. That was the desire for the original question. The next statistics value likely has measurement data from before the call to Measure. To ensure future data, this script discards the next update. If you want all of the statistics data, you do not want to use the Measure class in this sample. You can simply register your own statistics callback function, like this:
See the statistics pyjoulescope_driver entry point.
If you would rather use the joulescope package, see the statistics.py example. This example also puts the statistics values into a queue for processing from the main process thread.