1
0
mirror of https://github.com/jonathanhogg/scopething synced 2025-07-13 10:52:08 +01:00

Extend README as people seem to be suddenly looking at this code; remove cruft from analysis test script.

This commit is contained in:
2020-07-20 13:58:10 +01:00
parent b62bffe631
commit 42bb240cc4
2 changed files with 58 additions and 16 deletions

View File

@ -8,3 +8,58 @@
- Also requires **NumPy** and **SciPy** if you want to do analog range calibration
- Having **Pandas** is useful for wrapping capture results for further processing
## Longer Notes
### Why have I written this?
BitScope helpfully provide applications and libraries for talking to their USB
capture devices, so one can just use those. I wrote this code because I want
to be able to grab the raw data and further process it in various ways. I'm
accustomed to working at a Python prompt with various toolkits like SciPy and
Matplotlib, so I wanted a simple way to just grab a trace as an array.
The BitScope library is pretty simple to use, but also requires you to
understand a fair amount about how the scope works and make a bunch of decisions
about what capture mode and rate to use. I want to just specify a time period,
voltage range and a rough number of samples and have all of that worked out for
me, same way as I'd use an actual oscilloscope: twiddle the knobs and look at
the trace.
Of course, I could have wrapped the BitScope library in something that would do
this, but after reading a bit about how the scope works I was fascinated with
understanding it further and so I decided to go back to first principles and
start with just talking to it with a serial library. This code thus serves as
(sort of) documentation for the VM registers, capture modes and how to use them.
It also has the advantage of being pure Python.
The code prefers the highest capture resolution possible and will do the mapping
from high/low/trigger voltages to the mysterious magic numbers that the device
needs. It can also do logic and mixed-signal capture.
In addition to capturing, the code can also generate waveforms at arbitrary
frequencies  something that is tricky to do as the device operates at specific
frequencies and so one has to massage the width of the waveform buffer to get a
frequency outside of these. It can also control the clock generator.
I've gone for an underlying async design as it makes it easy to integrate the
code into UI programs or network servers  both of which interest me as the end
purpose for this code. However, for shell use there are synchronous wrapper
functions. Of particular note is that the synchronous wrapper understands
keyboard interrupt and will cancel a capture returning the trace around the
cancel point. This is useful if your trigger doesn't fire and you want to
understand why.
### Where's the documentation, mate?
Yeah, yeah. I know.
### Also, I see no unit tests...
It's pretty hard to do unit tests for a physical device. That's my excuse and
I'm sticking to it.
### Long lines and ignoring E221, eh?
"A foolish consistency is the hobgoblin of little minds"
Also, I haven't used an 80 character wide terminal in this century.

19
test.py
View File

@ -1,26 +1,12 @@
import numpy as np
from pylab import figure, plot, show
from analysis import annotate_series
from scope import await_, capture, main
from utils import DotDict
await_(main())
# o = 400
# m = 5
# n = o * m
# samples = square_wave(o)
# samples = np.hstack([samples] * m) * 2
# samples = np.hstack([samples[100:], samples[:100]])
# samples += np.random.normal(size=n) * 0.1
# samples += np.linspace(4.5, 5.5, n)
# series = DotDict(samples=samples, sample_rate=1000000)
data = capture(['A'], period=20e-3, nsamples=2000)
series = data.A
series = capture(['A'], period=20e-3, nsamples=2000).A
figure(1)
plot(series.timestamps, series.samples)
@ -35,6 +21,7 @@ if annotate_series(series):
print(f"Found {waveform.frequency:.0f}Hz {waveform.shape} wave, "
f"with amplitude ±{waveform.amplitude:.2f}V and offset {waveform.offset:.2f}V")
plot(waveform.timestamps + waveform.capture_start - series.capture_start, waveform.samples * waveform.amplitude + waveform.offset)
plot(waveform.timestamps + waveform.capture_start - series.capture_start,
waveform.samples * waveform.amplitude + waveform.offset)
show()