MSP430 reflash working
This commit is contained in:
parent
3dd5789800
commit
76c12726e8
16 changed files with 144 additions and 445 deletions
|
|
@ -187,12 +187,23 @@ static struct jtag_img_descriptor {
|
|||
} jtag_img = {
|
||||
.devmem_img_start = 0x00c000,
|
||||
.spiflash_img_start = 0x000000,
|
||||
.img_len = 0x060000,
|
||||
.img_len = 0x004000,
|
||||
};
|
||||
|
||||
const char fw_dump[0x4000] = {
|
||||
#include "EasyMeter_Q3DA1002_V3.03_fw_dump_0xc000.h"
|
||||
};
|
||||
|
||||
ssize_t jt_spi_flash_read_block(void *usr, int addr, size_t len, uint8_t *out) {
|
||||
/*
|
||||
struct jtag_img_descriptor *desc = (struct jtag_img_descriptor *)usr;
|
||||
return spif_read(&spif, desc->spiflash_img_start + addr, len, (char *)out);
|
||||
*/
|
||||
|
||||
for (size_t i=0; i<len; i++)
|
||||
out[i] = fw_dump[addr - 0xc000 + i];
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static unsigned int measurement_errors = 0;
|
||||
|
|
@ -240,15 +251,16 @@ int main(void)
|
|||
int i=0;
|
||||
while (23) {
|
||||
mspd_jtag_init();
|
||||
con_printf("%d flash result: %d\r\n", i,
|
||||
mspd_jtag_flash_and_reset(jtag_img.devmem_img_start, jtag_img.img_len, jt_spi_flash_read_block, &jtag_img));
|
||||
for (int i=0; i<168*1000*5; i++)
|
||||
int rv = mspd_jtag_flash_and_reset(jtag_img.devmem_img_start, jtag_img.img_len, jt_spi_flash_read_block, &jtag_img);
|
||||
con_printf("%d flash result: %d\r\n", i, rv);
|
||||
while (!rv) {}
|
||||
for (int j=0; j<168*1000*5; j++)
|
||||
asm volatile ("nop");
|
||||
i++;
|
||||
}
|
||||
while (23) {
|
||||
if (adc_fft_buf_ready_idx != -1) {
|
||||
for (int i=0; i<168*1000*2; i++)
|
||||
for (int j=0; j<168*1000*2; j++)
|
||||
asm volatile ("nop");
|
||||
GPIOA->BSRR = 1<<11;
|
||||
memcpy(adc_fft_buf[!adc_fft_buf_ready_idx], adc_fft_buf[adc_fft_buf_ready_idx] + FMEAS_FFT_LEN/2, sizeof(adc_fft_buf[0][0]) * FMEAS_FFT_LEN/2);
|
||||
|
|
@ -257,8 +269,8 @@ int main(void)
|
|||
|
||||
bool clip_low=false, clip_high=false;
|
||||
const int clip_thresh = 100;
|
||||
for (size_t i=FMEAS_FFT_LEN/2; i<FMEAS_FFT_LEN; i++) {
|
||||
int val = adc_fft_buf[adc_fft_buf_ready_idx][i];
|
||||
for (size_t j=FMEAS_FFT_LEN/2; j<FMEAS_FFT_LEN; j++) {
|
||||
int val = adc_fft_buf[adc_fft_buf_ready_idx][j];
|
||||
if (val < clip_thresh)
|
||||
clip_low = true;
|
||||
if (val > FMEAS_ADC_MAX-clip_thresh)
|
||||
|
|
@ -266,7 +278,7 @@ int main(void)
|
|||
}
|
||||
GPIOB->ODR = (GPIOB->ODR & ~(3<<11)) | (!clip_low<<11) | (!clip_high<<12);
|
||||
|
||||
for (int i=0; i<168*1000*2; i++)
|
||||
for (int j=0; j<168*1000*2; j++)
|
||||
asm volatile ("nop");
|
||||
|
||||
GPIOA->BSRR = 1<<11;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "output.h"
|
||||
#include "jtaglib.h"
|
||||
|
|
@ -53,6 +54,18 @@ void mspd_jtag_init() {
|
|||
gpio_pin_setup(gpios[i].gpio, gpios[i].pin, gpios[i].mode, 3, 0, 0);
|
||||
}
|
||||
|
||||
static void sr_gpio_write(int num, int out) {
|
||||
if (out)
|
||||
gpios[num].gpio->BSRR = 1<<gpios[num].pin;
|
||||
else
|
||||
gpios[num].gpio->BSRR = 1<<gpios[num].pin<<16;
|
||||
}
|
||||
|
||||
static void sr_jtdev_rst(struct jtdev *p, int out) {
|
||||
UNUSED(p);
|
||||
sr_gpio_write(SR_GPIO_RST, out);
|
||||
}
|
||||
|
||||
int mspd_jtag_flash_and_reset(size_t img_start, size_t img_len, ssize_t (*read_block)(void *usr, int addr, size_t len, uint8_t *out), void *usr)
|
||||
{
|
||||
union {
|
||||
|
|
@ -73,18 +86,17 @@ int mspd_jtag_flash_and_reset(size_t img_start, size_t img_len, ssize_t (*read_b
|
|||
if (jtag_id != 0x89 && jtag_id != 0x91)
|
||||
return -EINVAL;
|
||||
|
||||
/* FIXME DEBUG */
|
||||
|
||||
#if 0
|
||||
con_printf("Memory dump:\r\n");
|
||||
for (size_t i=0; i<256;) {
|
||||
for (size_t i=0x1000; i<=0x10ff;) {
|
||||
con_printf("%04x: ", i);
|
||||
for (size_t j=0; j<16; i+=2, j+=2) {
|
||||
con_printf("%04x ", jtag_read_mem(&sr_jtdev, 16, 0xc000 + i));
|
||||
for (size_t j=0; j<16; i+=1, j+=1) {
|
||||
con_printf("%02x ", jtag_read_mem(&sr_jtdev, 8, i));
|
||||
}
|
||||
con_printf("\r\n");
|
||||
}
|
||||
return 0;
|
||||
/* END DEBUG */
|
||||
#endif
|
||||
|
||||
/* Clear flash */
|
||||
jtag_erase_flash(&sr_jtdev, JTAG_ERASE_MAIN, 0);
|
||||
|
|
@ -93,6 +105,7 @@ int mspd_jtag_flash_and_reset(size_t img_start, size_t img_len, ssize_t (*read_b
|
|||
|
||||
/* Write flash */
|
||||
for (size_t p = img_start; p < img_start + img_len; p += BLOCK_SIZE) {
|
||||
con_printf("Writing block %04zx\r\n", p);
|
||||
ssize_t nin = read_block(usr, p, BLOCK_SIZE, block.bytes);
|
||||
|
||||
if (nin < 0)
|
||||
|
|
@ -122,6 +135,8 @@ int mspd_jtag_flash_and_reset(size_t img_start, size_t img_len, ssize_t (*read_b
|
|||
if (sr_jtdev.failed)
|
||||
return -EPIPE;
|
||||
|
||||
jtag_release_device(&sr_jtdev, 0xfffe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -153,13 +168,6 @@ static void sr_jtdev_connect(struct jtdev *p) {
|
|||
/* ignore */
|
||||
}
|
||||
|
||||
static void sr_gpio_write(int num, int out) {
|
||||
if (out)
|
||||
gpios[num].gpio->BSRR = 1<<gpios[num].pin;
|
||||
else
|
||||
gpios[num].gpio->BSRR = 1<<gpios[num].pin<<16;
|
||||
}
|
||||
|
||||
static void sr_jtdev_tck(struct jtdev *p, int out) {
|
||||
UNUSED(p);
|
||||
sr_gpio_write(SR_GPIO_TCK, out);
|
||||
|
|
@ -175,11 +183,6 @@ static void sr_jtdev_tdi(struct jtdev *p, int out) {
|
|||
sr_gpio_write(SR_GPIO_TDI, out);
|
||||
}
|
||||
|
||||
static void sr_jtdev_rst(struct jtdev *p, int out) {
|
||||
UNUSED(p);
|
||||
sr_gpio_write(SR_GPIO_RST, out);
|
||||
}
|
||||
|
||||
static void sr_jtdev_tst(struct jtdev *p, int out) {
|
||||
UNUSED(p);
|
||||
sr_gpio_write(SR_GPIO_TST, out);
|
||||
|
|
|
|||
|
|
@ -1,372 +0,0 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import math\n",
|
||||
"import struct\n",
|
||||
"\n",
|
||||
"import numpy as np\n",
|
||||
"from scipy import signal, optimize\n",
|
||||
"from matplotlib import pyplot as plt\n",
|
||||
"\n",
|
||||
"import rocof_test_data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib widget"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fs = 1000 # Hz\n",
|
||||
"ff = 50 # Hz\n",
|
||||
"duration = 60 # seconds\n",
|
||||
"# test_data = rocof_test_data.sample_waveform(rocof_test_data.test_close_interharmonics_and_flicker(),\n",
|
||||
"# duration=20,\n",
|
||||
"# sampling_rate=fs,\n",
|
||||
"# frequency=ff)[0]\n",
|
||||
"# test_data = rocof_test_data.sample_waveform(rocof_test_data.gen_noise(fmin=10, amplitude=1),\n",
|
||||
"# duration=20,\n",
|
||||
"# sampling_rate=fs,\n",
|
||||
"# frequency=ff)[0]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#gen = rocof_test_data.gen_noise(fmin=10, amplitude=1)\n",
|
||||
"# gen = rocof_test_data.gen_noise(fmin=60, amplitude=0.2)\n",
|
||||
"# gen = rocof_test_data.test_harmonics()\n",
|
||||
"# gen = rocof_test_data.gen_interharmonic(*rocof_test_data.test_interharmonics)\n",
|
||||
"# gen = rocof_test_data.test_amplitude_steps()\n",
|
||||
"# gen = rocof_test_data.test_amplitude_and_phase_steps()\n",
|
||||
"test_data = []\n",
|
||||
"test_labels = [ fun.__name__.replace('test_', '') for fun in rocof_test_data.all_tests ]\n",
|
||||
"for gen in rocof_test_data.all_tests:\n",
|
||||
" test_data.append(rocof_test_data.sample_waveform(gen(),\n",
|
||||
" duration=duration,\n",
|
||||
" sampling_rate=fs,\n",
|
||||
" frequency=ff)[0])\n",
|
||||
"# d = 10 # seconds\n",
|
||||
"# test_data = np.sin(2*np.pi * ff * np.linspace(0, d, int(d*fs)))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"spr_fmt = f'{fs}Hz' if fs<1000 else f'{fs/1e3:f}'.rstrip('.0') + 'kHz'\n",
|
||||
"for label, data in zip(test_labels, test_data):\n",
|
||||
" with open(f'rocof_test_data/rocof_test_{label}_{spr_fmt}.bin', 'wb') as f:\n",
|
||||
" for sample in data:\n",
|
||||
" f.write(struct.pack('<f', sample))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"analysis_periods = 10\n",
|
||||
"window_len = 256 # fs * analysis_periods/ff\n",
|
||||
"nfft_factor = 1\n",
|
||||
"sigma = window_len/8 # samples\n",
|
||||
"quantization_bits = 14\n",
|
||||
"\n",
|
||||
"ffts = []\n",
|
||||
"for item in test_data:\n",
|
||||
" f, t, Zxx = signal.stft((item * (2**(quantization_bits-1) - 1)).round().astype(np.int16).astype(float),\n",
|
||||
" fs = fs,\n",
|
||||
" window=('gaussian', sigma),\n",
|
||||
" nperseg = window_len,\n",
|
||||
" nfft = window_len * nfft_factor)\n",
|
||||
" #boundary = 'zeros')\n",
|
||||
" ffts.append((f, t, Zxx))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(129, 470)"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"Zxx.shape"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3.90625"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"1000/256"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "1bae03315efe4ed7a72b911fed0056ae",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"fig, ax = plt.subplots(len(test_data), figsize=(8, 20), sharex=True)\n",
|
||||
"fig.tight_layout(pad=2, h_pad=0.1)\n",
|
||||
"\n",
|
||||
"for fft, ax, label in zip(test_data, ax.flatten(), test_labels):\n",
|
||||
" ax.plot((item * (2**(quantization_bits-1) - 1)).round())\n",
|
||||
" \n",
|
||||
" ax.set_title(label, pad=-20, color='white', bbox=dict(boxstyle=\"square\", ec=(0,0,0,0), fc=(0,0,0,0.8)))\n",
|
||||
" ax.grid()\n",
|
||||
" ax.set_ylabel('f [Hz]')\n",
|
||||
"ax.set_xlabel('simulation time t [s]')\n",
|
||||
"ax.set_xlim([5000, 5200])\n",
|
||||
"None"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "7182190a6bbc4481a792d5f6b7d390a0",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"fig, ax = plt.subplots(len(test_data), figsize=(8, 20), sharex=True)\n",
|
||||
"fig.tight_layout(pad=2, h_pad=0.1)\n",
|
||||
"\n",
|
||||
"for fft, ax, label in zip(ffts, ax.flatten(), test_labels):\n",
|
||||
" f, t, Zxx = fft\n",
|
||||
" ax.pcolormesh(t[1:], f[:250], np.abs(Zxx[:250,1:]))\n",
|
||||
" ax.set_title(label, pad=-20, color='white')\n",
|
||||
" ax.grid()\n",
|
||||
" ax.set_ylabel('f [Hz]')\n",
|
||||
" ax.set_ylim([30, 75]) # Hz\n",
|
||||
"ax.set_xlabel('simulation time t [s]')\n",
|
||||
"None"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([ 0. , 3.90625, 7.8125 , 11.71875, 15.625 , 19.53125,\n",
|
||||
" 23.4375 , 27.34375, 31.25 , 35.15625, 39.0625 , 42.96875,\n",
|
||||
" 46.875 , 50.78125, 54.6875 , 58.59375, 62.5 , 66.40625,\n",
|
||||
" 70.3125 , 74.21875, 78.125 , 82.03125, 85.9375 , 89.84375,\n",
|
||||
" 93.75 , 97.65625, 101.5625 , 105.46875, 109.375 , 113.28125,\n",
|
||||
" 117.1875 , 121.09375, 125. , 128.90625, 132.8125 , 136.71875,\n",
|
||||
" 140.625 , 144.53125, 148.4375 , 152.34375, 156.25 , 160.15625,\n",
|
||||
" 164.0625 , 167.96875, 171.875 , 175.78125, 179.6875 , 183.59375,\n",
|
||||
" 187.5 , 191.40625, 195.3125 , 199.21875, 203.125 , 207.03125,\n",
|
||||
" 210.9375 , 214.84375, 218.75 , 222.65625, 226.5625 , 230.46875,\n",
|
||||
" 234.375 , 238.28125, 242.1875 , 246.09375, 250. , 253.90625,\n",
|
||||
" 257.8125 , 261.71875, 265.625 , 269.53125, 273.4375 , 277.34375,\n",
|
||||
" 281.25 , 285.15625, 289.0625 , 292.96875, 296.875 , 300.78125,\n",
|
||||
" 304.6875 , 308.59375, 312.5 , 316.40625, 320.3125 , 324.21875,\n",
|
||||
" 328.125 , 332.03125, 335.9375 , 339.84375, 343.75 , 347.65625,\n",
|
||||
" 351.5625 , 355.46875, 359.375 , 363.28125, 367.1875 , 371.09375,\n",
|
||||
" 375. , 378.90625, 382.8125 , 386.71875, 390.625 , 394.53125,\n",
|
||||
" 398.4375 , 402.34375, 406.25 , 410.15625, 414.0625 , 417.96875,\n",
|
||||
" 421.875 , 425.78125, 429.6875 , 433.59375, 437.5 , 441.40625,\n",
|
||||
" 445.3125 , 449.21875, 453.125 , 457.03125, 460.9375 , 464.84375,\n",
|
||||
" 468.75 , 472.65625, 476.5625 , 480.46875, 484.375 , 488.28125,\n",
|
||||
" 492.1875 , 496.09375, 500. ])"
|
||||
]
|
||||
},
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"f"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "d26336c7e27c44c7894919fdeb614891",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"fig, axs = plt.subplots(len(test_data), figsize=(8, 20), sharex=True)\n",
|
||||
"fig.tight_layout(pad=2.2, h_pad=0, w_pad=1)\n",
|
||||
"\n",
|
||||
"for fft, ax, label in zip(ffts, axs.flatten(), test_labels):\n",
|
||||
" f, f_t, Zxx = fft\n",
|
||||
" \n",
|
||||
" n_f, n_t = Zxx.shape\n",
|
||||
" # start, stop = 180, 220\n",
|
||||
" # start, stop = 90, 110\n",
|
||||
" # start, stop = 15, 35\n",
|
||||
" # bounds_f = slice(start // 4 * nfft_factor, stop // 4 * nfft_factor)\n",
|
||||
" f_min, f_max = 30, 70 # Hz\n",
|
||||
" bounds_f = slice(np.argmax(f > f_min), np.argmin(f < f_max))\n",
|
||||
" \n",
|
||||
"\n",
|
||||
" f_mean = np.zeros(Zxx.shape[1])\n",
|
||||
" for t in range(1, Zxx.shape[1] - 1):\n",
|
||||
" frame_f = f[bounds_f]\n",
|
||||
" frame_step = frame_f[1] - frame_f[0]\n",
|
||||
" time_step = f_t[1] - f_t[0]\n",
|
||||
" #if t == 10:\n",
|
||||
" # axs[-1].plot(frame_f, frame_Z)\n",
|
||||
" frame_Z = np.abs(Zxx[bounds_f, t])\n",
|
||||
" # frame_f = f[180:220]\n",
|
||||
" # frame_Z = np.abs(Zxx[180:220, 40])\n",
|
||||
" # frame_f = f[15:35]\n",
|
||||
" # frame_Z = np.abs(Zxx[15:35, 40])\n",
|
||||
" # plt.plot(frame_f, frame_Z)\n",
|
||||
"\n",
|
||||
" # peak_f = frame_f[np.argmax(frame)]\n",
|
||||
" # plt.axvline(peak_f, color='red')\n",
|
||||
"\n",
|
||||
"# def gauss(x, *p):\n",
|
||||
"# A, mu, sigma, o = p\n",
|
||||
"# return A*np.exp(-(x-mu)**2/(2.*sigma**2)) + o\n",
|
||||
" \n",
|
||||
" def gauss(x, *p):\n",
|
||||
" A, mu, sigma = p\n",
|
||||
" return A*np.exp(-(x-mu)**2/(2.*sigma**2))\n",
|
||||
" \n",
|
||||
" f_start = frame_f[np.argmax(frame_Z)]\n",
|
||||
" A_start = np.max(frame_Z)\n",
|
||||
" p0 = [A_start, f_start, 1.]\n",
|
||||
" try:\n",
|
||||
" coeff, var = optimize.curve_fit(gauss, frame_f, frame_Z, p0=p0)\n",
|
||||
" # plt.plot(frame_f, gauss(frame_f, *coeff))\n",
|
||||
" #print(coeff)\n",
|
||||
" A, mu, sigma, *_ = coeff\n",
|
||||
" f_mean[t] = mu\n",
|
||||
" except RuntimeError:\n",
|
||||
" f_mean[t] = np.nan\n",
|
||||
" ax.plot(f_t[1:-1], f_mean[1:-1])\n",
|
||||
" \n",
|
||||
"# b, a = signal.butter(3,\n",
|
||||
"# 1/5, # Hz\n",
|
||||
"# btype='lowpass',\n",
|
||||
"# fs=1/time_step)\n",
|
||||
"# filtered = signal.lfilter(b, a, f_mean[1:-1], axis=0)\n",
|
||||
"# ax.plot(f_t[1:-1], filtered)\n",
|
||||
" \n",
|
||||
" ax.set_title(label, pad=-20)\n",
|
||||
" ax.set_ylabel('f [Hz]')\n",
|
||||
" ax.grid()\n",
|
||||
" if not label in ['off_frequency', 'sweep_phase_steps']:\n",
|
||||
" ax.set_ylim([49.90, 50.10])\n",
|
||||
" var = np.var(f_mean[1:-1])\n",
|
||||
" ax.text(0.5, 0.1, f'σ²={var * 1e3:.3g} mHz²', transform=ax.transAxes, ha='center')\n",
|
||||
" ax.text(0.5, 0.25, f'σ={np.sqrt(var) * 1e3:.3g} mHz', transform=ax.transAxes, ha='center')\n",
|
||||
"# ax.text(0.5, 0.2, f'filt. σ²={np.var(filtered) * 1e3:.3g} mHz', transform=ax.transAxes, ha='center')\n",
|
||||
" else:\n",
|
||||
" f_min, f_max = min(f_mean[1:-1]), max(f_mean[1:-1])\n",
|
||||
" delta = f_max - f_min\n",
|
||||
" ax.set_ylim(f_min - delta * 0.1, f_max + delta * 0.3)\n",
|
||||
" \n",
|
||||
"ax.set_xlabel('simulation time t [s]')\n",
|
||||
"None"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "labenv",
|
||||
"language": "python",
|
||||
"name": "labenv"
|
||||
},
|
||||
"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.8.2"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
BIN
lab-windows/fig_out/freq_meas_feedback.pdf
Normal file
BIN
lab-windows/fig_out/freq_meas_feedback.pdf
Normal file
Binary file not shown.
BIN
lab-windows/fig_out/freq_meas_rocof_reference.pdf
Normal file
BIN
lab-windows/fig_out/freq_meas_rocof_reference.pdf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -13,6 +13,7 @@ all: safety_reset.pdf
|
|||
safety_reset.pdf: resources/grid_freq_estimation.pdf
|
||||
safety_reset.pdf: resources/gps_clock_jitter_analysis.pdf
|
||||
safety_reset.pdf: resources/dsss_experiments-ber.pdf
|
||||
safety_reset.pdf: resources/freq_meas_validation_rocof_testsuite.pdf
|
||||
|
||||
%.pdf: %.tex %.bib
|
||||
pdflatex -shell-escape $<
|
||||
|
|
|
|||
|
|
@ -1214,9 +1214,38 @@ with IO contention on the raspberry PI/linux side causing only 16 skipped sample
|
|||
|
||||
Captured raw waveform data is processed in the Jupyter Lab environment\cite{kluyver01} and grid frequency estimates are
|
||||
extracted as described in sec. \ref{frequency_estimation} using the \textcite{gasior01} technique. Appendix
|
||||
\ref{grid_freq_estimation_notebook} contains the Jupyter notebook we used for frequency measurement.
|
||||
\ref{grid_freq_estimation_notebook} contains the Jupyter notebook we used for frequency measurement. In fig.\
|
||||
\ref{freq_meas_feedback} we fed back to the frequency estimator its own output giving us an indication of its numerical
|
||||
performance. The result was \SI{1.3}{\milli\hertz} of RMS noise over a \SI{3600}{\second} simulation time. This
|
||||
indicates performance is good enough for our purposes. In addition to this we validated our algorithm's performance by
|
||||
applying it to the test waveforms from \textcite{wright01}. In this test we got errors of \SI{4.4}{\milli\hertz} for the
|
||||
\emph{noise} test waveform, \SI{0.027}{\milli\hertz} for the \emph{interharmonics} test waveform and
|
||||
\SI{46}{\milli\hertz} for the \emph{amplitude and phase step} test waveform. Full results can be found in fig.\
|
||||
\ref{freq_meas_rocof_reference}.
|
||||
|
||||
% TODO comparison against reference measurements?
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{../lab-windows/fig_out/freq_meas_feedback}
|
||||
\caption{
|
||||
The frequency estimation algorithm applied to a synthetic noise-less mains waveform generated from its own
|
||||
output. This feedback simulation gives an indication of numerical errors in our estimation algorithm. The top
|
||||
four graphs show a comparison of the original trace (blue) and the re-calculated trace (orange). The bottom
|
||||
trace shows the difference between the two. As we can tell both traces agree very well with an overall RMS
|
||||
deviation of about \SI{1.3}{\milli\hertz}. The bottom trace shows deviation growing over time. This is very
|
||||
likely an effect of numerical errors in our ad-hoc waveform generator.
|
||||
}
|
||||
\label{freq_meas_feedback}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{../lab-windows/fig_out/freq_meas_rocof_reference}
|
||||
\caption{
|
||||
Performance of our frequency estimation algorithm against the test suite specified in \textcite{wright01}. Shown
|
||||
are standard deviation and variance measurements as well as time-domain traces of differences.
|
||||
}
|
||||
\label{freq_meas_rocof_reference}
|
||||
\end{figure}
|
||||
|
||||
\section{Channel simulation and parameter validation}
|
||||
|
||||
|
|
@ -1409,10 +1438,13 @@ indicates SER is related fairly monotonically to the signal-to-noise margins ins
|
|||
\end{figure}
|
||||
|
||||
\section{Implementation of a demonstrator unit}
|
||||
%FIXME
|
||||
|
||||
\section{Experimental results}
|
||||
%FIXME
|
||||
|
||||
\section{Lessons learned}
|
||||
%FIXME
|
||||
|
||||
|
||||
|
||||
|
|
@ -1444,6 +1476,7 @@ managing root keys for other government systems to also manage safety reset keys
|
|||
of safety reset keys do not differ significantly from those for other types of root keys.
|
||||
|
||||
\section{Practical implementation}
|
||||
%FIXME
|
||||
|
||||
|
||||
\section{Zones of trust}
|
||||
|
|
@ -1490,23 +1523,29 @@ microcontroller providing this type of virtualization on the one hand and the co
|
|||
virtualization on the other hand. Virtualization systems such as TrustZone are still orders of magnitude more complex to
|
||||
correctly configure than it is to simply use separate hardware and secure the interfaces in between.
|
||||
|
||||
\chapter{Alternative use of grid frequency modulation}
|
||||
% FIXME random beacons? funky consensus protocols? proof of knowledge/cryptographic notary service?
|
||||
|
||||
\chapter{Conclusion}
|
||||
%FIXME
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
\chapter{Acknowledgements}
|
||||
%FIXME
|
||||
\newpage
|
||||
|
||||
\chapter{References}
|
||||
\nocite{*}
|
||||
\nocite{*} % FIXME
|
||||
\printbibliography
|
||||
\newpage
|
||||
|
||||
\chapter{Transcripts of Jupyter notebooks used in this thesis}
|
||||
|
||||
\includenotebook{Grid frequency estimation}{grid_freq_estimation}
|
||||
\includenotebook{Frequency sensor clock stability analysis}{gps_clock_jitter_analysis}
|
||||
\includenotebook{DSSS modulation experiments}{dsss_experiments-ber}
|
||||
%\includenotebook{Grid frequency estimation}{grid_freq_estimation}
|
||||
%\includenotebook{Grid frequency estimation validation against ROCOF test suite}{freq_meas_validation_rocof_testsuite}
|
||||
%\includenotebook{Frequency sensor clock stability analysis}{gps_clock_jitter_analysis}
|
||||
%\includenotebook{DSSS modulation experiments}{dsss_experiments-ber}
|
||||
|
||||
\chapter{Demonstrator schematics and code}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue