summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjaseg <git@jaseg.net>2018-04-21 16:22:41 +0200
committerjaseg <git@jaseg.net>2018-04-21 16:22:41 +0200
commit0d4dc7987da30bc648388a0138f1ef9793691564 (patch)
treee0a396ef301f7baa8d94a80bd3631b99bcad7d09
parent231ce4b2a22d2895ee0bf6db4536cc2a56dbbcbd (diff)
downloadolsndot-0d4dc7987da30bc648388a0138f1ef9793691564.tar.gz
olsndot-0d4dc7987da30bc648388a0138f1ef9793691564.tar.bz2
olsndot-0d4dc7987da30bc648388a0138f1ef9793691564.zip
Add bit error test scripts
-rw-r--r--firmware/Run_analysis.ipynb123
-rw-r--r--firmware/offset_test.py100
2 files changed, 223 insertions, 0 deletions
diff --git a/firmware/Run_analysis.ipynb b/firmware/Run_analysis.ipynb
new file mode 100644
index 0000000..ce6bab4
--- /dev/null
+++ b/firmware/Run_analysis.ipynb
@@ -0,0 +1,123 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "from matplotlib import pyplot as plt\n",
+ "%matplotlib inline\n",
+ "import numpy as np\n",
+ "\n",
+ "import itertools\n",
+ "import sqlite3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "db = sqlite3.connect('results.sqlite3')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "def fetch_run(run_name):\n",
+ " runs = db.execute('SELECT run_id FROM runs WHERE name LIKE ?', (run_name,)).fetchall()\n",
+ " if len(runs) > 1:\n",
+ " raise ValueError('Ambiguous run name {} matches run ids {}'.format(run_name, runs))\n",
+ " \n",
+ " (run_id,), = runs\n",
+ " data = db.execute('''\n",
+ " SELECT channel, duty_cycle, voltage, voltage_stdev FROM measurements WHERE run_id == ?\n",
+ " ''', (run_id,)).fetchall()\n",
+ " \n",
+ " grouped = {ch: [(duty, volt, stdev) for _ch, duty, volt, stdev in data]\n",
+ " for ch, data in itertools.groupby(data, lambda elem: elem[0])}\n",
+ " return grouped"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 76,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "def plot_run(name):\n",
+ " data = fetch_run(name)\n",
+ " \n",
+ " fig, ax = plt.subplots(figsize=(12,8))\n",
+ " ax.set_title('Run {}'.format(name))\n",
+ " ax.set_xscale('log')\n",
+ " min_x = min(duty for vals in data.values() for duty, volt, stdev in vals if duty > 0)\n",
+ " ax.set_xlim([min_x*0.9, 1.1])\n",
+ " ax.set_yscale('log')\n",
+ "\n",
+ " for ch in data:\n",
+ " (cal_duty, cal_volt, _cal_stdev), *ch_data = data[ch]\n",
+ " assert cal_duty == 0\n",
+ " duty, volt, stdev = zip(*ch_data)\n",
+ " #volt = np.array(volt) - cal_volt\n",
+ " ax.errorbar(duty, volt, yerr=stdev)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 77,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\nBGQAAADA4/8DuiqlUTjgcngAAAAASUVORK5CYII=\n",
+ "text/plain": [
+ "<matplotlib.figure.Figure at 0x7880f57ba5c0>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "plot_run('test02')"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.5.4"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
diff --git a/firmware/offset_test.py b/firmware/offset_test.py
new file mode 100644
index 0000000..5f87d20
--- /dev/null
+++ b/firmware/offset_test.py
@@ -0,0 +1,100 @@
+
+import time
+import statistics
+import sqlite3
+from olsndot import Olsndot, Driver
+from datetime import datetime
+
+from pyBusPirateLite import Buspirate
+
+AVERAGE_READINGS = 16
+
+if __name__ == '__main__':
+ import argparse
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('channels', type=str, help='olsndot channels to test, format: 0-3,5,7,8-10')
+ parser.add_argument('run_name')
+ parser.add_argument('olsndot_port', nargs='?', default='/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A50285BI-if00-port0')
+ parser.add_argument('buspirate_port', nargs='?', default='/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AD01W1RF-if00-port0') # FIXME
+ parser.add_argument('-d', '--database', nargs='?', default='results.sqlite3', help='sqlite3 database file to store results in')
+ parser.add_argument('-m', '--mac', type=int, nargs='?', default=0xDEBE10BB, help='olsndot MAC address')
+ args = parser.parse_args()
+
+ def parse_channels(channels):
+ for spec in channels.split(','):
+ if str.isnumeric(spec):
+ yield int(spec)
+ else:
+ low, high = spec.split('-')
+ yield from range(int(low), int(high)+1)
+ channels = list(parse_channels(args.channels))
+
+ db = sqlite3.connect(args.database)
+ db.execute("""
+ CREATE TABLE IF NOT EXISTS runs (
+ run_id INTEGER PRIMARY KEY,
+ name TEXT,
+ comment TEXT,
+ uut_mac TEXT, -- hex-string formatted 32-bit mac of the uut
+ timestamp REAL -- unix timestamp in fractional seconds
+ )""")
+ db.execute("""
+ CREATE TABLE IF NOT EXISTS measurements (
+ measurement_id INTEGER PRIMARY KEY,
+ run_id INTEGER,
+ channel INTEGER,
+ duty_cycle REAL, -- setpoint duty cycle as a float between 0.0 and 1.0
+ voltage REAL, -- volts
+ voltage_stdev REAL, -- volts
+ timestamp REAL, -- unix timestamp in fractional seconds
+ FOREIGN KEY (run_id) REFERENCES runs)""")
+
+ bp = Buspirate(args.buspirate_port)
+ bp.power_on = True
+
+ uut = Olsndot(args.mac)
+ d = Driver(args.olsndot_port, devices=[uut])
+
+ print('Connected to uut:', uut)
+
+ with db:
+ cur = db.cursor()
+ cur.execute('INSERT INTO runs(name, uut_mac, timestamp) VALUES (?, ?, ?)',
+ (args.run_name, args.mac, time.time()))
+ run_id = cur.lastrowid
+ print('Starting run {} at {:%y-%m-%d %H:%M:%S:%f}'.format(run_id, datetime.now()))
+ print('mac={:08x} channels={}'.format(args.mac, ','.join('{:02d}'.format(ch) for ch in channels)))
+ print('[measurement id] " " [hex setpoint value] "(" [float duty cycle] ")" " " [reading (V)]')
+
+ for ch in channels:
+ for i in range(-1, uut.nbits):
+ fb = [0]*uut.nchannels
+ if i == -1:
+ val = 0
+ else:
+ val = 1<<i
+ duty_cycle = val/(2**uut.nbits)
+ extra_shift = 16-uut.nbits
+ val <<= extra_shift
+
+ fb[ch] = val
+ uut.send_framebuf(fb)
+
+ time.sleep(0.2)
+ readings = [ bp.adc_value for _ in range(AVERAGE_READINGS) ]
+ mean, stdev = statistics.mean(readings), statistics.stdev(readings)
+
+ with db:
+ cur = db.cursor()
+ cur.execute('''
+ INSERT INTO measurements (
+ run_id, channel, duty_cycle, voltage, voltage_stdev, timestamp
+ ) VALUES (?, ?, ?, ?, ?, ?)''',
+ (run_id, ch, duty_cycle, mean, stdev, time.time()))
+ print('{:08d} ch={} {:04x}({:6.5f}): {:5.4f} stdev {:5.4}'.format(
+ cur.lastrowid, ch, val, duty_cycle, mean, stdev))
+
+ uut.send_framebuf([0]*uut.nchannels)
+ bp.power_on = False
+