diff options
author | jaseg <git@jaseg.net> | 2018-04-21 16:22:41 +0200 |
---|---|---|
committer | jaseg <git@jaseg.net> | 2018-04-21 16:22:41 +0200 |
commit | 0d4dc7987da30bc648388a0138f1ef9793691564 (patch) | |
tree | e0a396ef301f7baa8d94a80bd3631b99bcad7d09 /firmware | |
parent | 231ce4b2a22d2895ee0bf6db4536cc2a56dbbcbd (diff) | |
download | olsndot-0d4dc7987da30bc648388a0138f1ef9793691564.tar.gz olsndot-0d4dc7987da30bc648388a0138f1ef9793691564.tar.bz2 olsndot-0d4dc7987da30bc648388a0138f1ef9793691564.zip |
Add bit error test scripts
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/Run_analysis.ipynb | 123 | ||||
-rw-r--r-- | firmware/offset_test.py | 100 |
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 + |