diff options
author | Daniel Friesel <derf@finalrewind.org> | 2018-11-02 10:49:02 +0100 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2018-11-02 10:49:02 +0100 |
commit | 471b17b7abbd82854c9239a15148b0cae854a686 (patch) | |
tree | 67d36c6db912322b7ede6c406211d522d9ef3e07 /bin | |
parent | 90eeeaf798b267c42e50a1b7e9c98fe2e278dde4 (diff) |
tabs -> spaces
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/msp430-etv | 236 |
1 files changed, 127 insertions, 109 deletions
diff --git a/bin/msp430-etv b/bin/msp430-etv index 5fe896f..810c7ce 100755 --- a/bin/msp430-etv +++ b/bin/msp430-etv @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +# vim:tabstop=4:softtabstop=4:shiftwidth=4:textwidth=160:smarttab:expandtab import getopt import matplotlib.pyplot as plt @@ -11,22 +12,22 @@ import sys opt = dict() def measure_data(time): - if not 'LD_LIBRARY_PATH' in os.environ: - os.environ['LD_LIBRARY_PATH'] = '{}/var/projects/msp430/MSP430Flasher_1.3.7'.format(os.environ['HOME']) + if not 'LD_LIBRARY_PATH' in os.environ: + os.environ['LD_LIBRARY_PATH'] = '{}/var/projects/msp430/MSP430Flasher_1.3.7'.format(os.environ['HOME']) - energytrace_cmd = '{}/var/source/energytrace-util/energytrace'.format(os.environ['HOME']) + energytrace_cmd = '{}/var/source/energytrace-util/energytrace'.format(os.environ['HOME']) - res = subprocess.run([energytrace_cmd, str(duration)], stdout = subprocess.PIPE, universal_newlines = True) + res = subprocess.run([energytrace_cmd, str(duration)], stdout = subprocess.PIPE, universal_newlines = True) - return res.stdout + return res.stdout def show_help(): - print('''msp430-etv - MSP430 EnergyTrace Visualizer + print('''msp430-etv - MSP430 EnergyTrace Visualizer USAGE msp430-etv [--load <file> | <measurement duration>] [--save <file>] - [--skip <count>] [--threshold <power>] [--plot] [--stat] + [--skip <count>] [--threshold <power>] [--plot] [--stat] DESCRIPTION @@ -44,111 +45,128 @@ OPTIONS --skip <count> Skip <count> data samples. This is useful to avoid startup code influencing the results of a long-running measurement + --threshold <watts>|auto + Partition data into points with mean power >= <watts> and points with + mean power < <watts>, and print some statistics. higher power is handled + as peaks, whereas low-power measurements constitute the baseline. + If the threshold is set to "auto", the mean power of all measurements + will be used --plot Show power/time plot --stat Show mean voltage, current, and power as well as total energy consumption. - ''') + ''') if __name__ == '__main__': - try: - optspec = ('help load= save= skip= threshold= plot stat') - raw_opts, args = getopt.getopt(sys.argv[1:], "", optspec.split(' ')) - - for option, parameter in raw_opts: - optname = re.sub(r'^--', '', option) - opt[optname] = parameter - - if 'help' in opt: - show_help() - sys.exit(0) - - if not 'load' in opt: - duration = int(args[0]) - - if 'skip' in opt: - opt['skip'] = int(opt['skip']) - else: - opt['skip'] = 0 - - if 'threshold' in opt: - opt['threshold'] = float(opt['threshold']) - - except getopt.GetoptError as err: - print(err) - sys.exit(2) - except IndexError: - print('Usage: msp430-etv <duration>') - sys.exit(2) - except ValueError: - print('Error: duration or skip is not a number') - sys.exit(2) - - if 'load' in opt: - with open(opt['load'], 'r') as f: - log_data = f.read() - else: - log_data = measure_data(duration) - - lines = log_data.split('\n') - data_count = sum(map(lambda x: len(x) > 0 and x[0] != '#', lines)) - data_lines = filter(lambda x: len(x) > 0 and x[0] != '#', lines) - - data = np.empty((data_count - opt['skip'], 4)) - - for i, line in enumerate(data_lines): - if i >= opt['skip']: - timestamp, current, voltage, total_energy = map(float, line.split(' ')) - data[i - opt['skip']] = [timestamp, current, voltage, total_energy] - - m_duration = data[-1, 0] - data[0, 0] - m_energy = data[-1, 3] - data[0, 3] - m_calc_energy = np.sum(data[1:, 1] * data[1:, 2] * (data[1:, 0] - data[:-1, 0])) - m_energy_deviation = np.abs(m_energy - m_calc_energy) / np.max([m_energy, m_calc_energy]) - - print('{:d} measurements in {:.2f} s = {:.0f} Hz sample rate'.format( - data_count, m_duration, data_count / m_duration)) - - print('Reported energy: E = {:f} J'.format(m_energy)) - print('Calculated energy: U*I*t = {:f} J'.format(m_calc_energy)) - print('Energy deviation: {:.1f}%'.format(m_energy_deviation * 100)) - - - if 'threshold' in opt: - power = data[:, 1] * data[:, 2] - - peaks = [] - peak_start = -1 - for i, dp in enumerate(power): - if dp >= opt['threshold'] and peak_start == -1: - peak_start = i - elif dp < opt['threshold'] and peak_start != -1: - peaks.append((peak_start, i)) - peak_start = -1 - - for peak in peaks: - duration = data[peak[1]-1, 0] - data[peak[0], 0] - print('{:.2f}ms peak ({:f} -> {:f})'.format(duration * 1000, - data[peak[0], 0], data[peak[1]-1, 0])) - print(' {:f} µJ / mean {:f} µW'.format( - np.mean(power[peak[0] : peak[1]]) * duration * 1e6, - np.mean(power[peak[0] : peak[1]]) * 1e6 )) - - if 'save' in opt: - with open(opt['save'], 'w') as f: - f.write(log_data) - - if 'stat' in opt: - print('Mean voltage: {:f}'.format(np.mean(data[:, 2]))) - print('Mean current: {:f}'.format(np.mean(data[:, 1]))) - print('Mean power: {:f}'.format(np.mean(data[:, 1] * data[:, 2]))) - print('Total energy: {:f}'.format(m_energy)) - - if 'plot' in opt: - pwrhandle, = plt.plot(data[:, 0], data[:, 1] * data[:, 2], 'b-', label='U*I', markersize=1) - #energyhandle, = plt.plot(data[1:, 0], (data[1:, 3] - data[:-1, 3]) / (data[1:, 0] - data[:-1, 0]), 'r-', label='E/Δt', markersize=1) - plt.legend(handles=[pwrhandle]) - plt.xlabel('Time [s]') - plt.ylabel('Power [W]') - plt.grid(True) - plt.show() + try: + optspec = ('help load= save= skip= threshold= plot stat') + raw_opts, args = getopt.getopt(sys.argv[1:], "", optspec.split(' ')) + + for option, parameter in raw_opts: + optname = re.sub(r'^--', '', option) + opt[optname] = parameter + + if 'help' in opt: + show_help() + sys.exit(0) + + if not 'load' in opt: + duration = int(args[0]) + + if 'skip' in opt: + opt['skip'] = int(opt['skip']) + else: + opt['skip'] = 0 + + if 'threshold' in opt and opt['threshold'] != 'auto': + opt['threshold'] = float(opt['threshold']) + + except getopt.GetoptError as err: + print(err) + sys.exit(2) + except IndexError: + print('Usage: msp430-etv <duration>') + sys.exit(2) + except ValueError: + print('Error: duration or skip is not a number') + sys.exit(2) + + if 'load' in opt: + with open(opt['load'], 'r') as f: + log_data = f.read() + else: + log_data = measure_data(duration) + + lines = log_data.split('\n') + data_count = sum(map(lambda x: len(x) > 0 and x[0] != '#', lines)) + data_lines = filter(lambda x: len(x) > 0 and x[0] != '#', lines) + + data = np.empty((data_count - opt['skip'], 4)) + + for i, line in enumerate(data_lines): + if i >= opt['skip']: + timestamp, current, voltage, total_energy = map(float, line.split(' ')) + data[i - opt['skip']] = [timestamp, current, voltage, total_energy] + + m_duration = data[-1, 0] - data[0, 0] + m_energy = data[-1, 3] - data[0, 3] + m_calc_energy = np.sum(data[1:, 1] * data[1:, 2] * (data[1:, 0] - data[:-1, 0])) + m_energy_deviation = np.abs(m_energy - m_calc_energy) / np.max([m_energy, m_calc_energy]) + + print('{:d} measurements in {:.2f} s = {:.0f} Hz sample rate'.format( + data_count, m_duration, data_count / m_duration)) + + print('Reported energy: E = {:f} J'.format(m_energy)) + print('Calculated energy: U*I*t = {:f} J'.format(m_calc_energy)) + print('Energy deviation: {:.1f}%'.format(m_energy_deviation * 100)) + + + if 'threshold' in opt: + power = data[:, 1] * data[:, 2] + + if opt['threshold'] == 'auto': + opt['threshold'] = np.mean(power) + print('Threshold set to {:.0f} µW'.format(opt['threshold'] * 1e6)) + + if np.any(power < opt['threshold']): + print('Baseline mean: {:.0f} µW'.format( + np.mean(power[power < opt['threshold']]) * 1e6 )) + if np.any(power >= opt['threshold']): + print('Peak mean: {:.0f} µW'.format( + np.mean(power[power >= opt['threshold']]) * 1e6)) + + peaks = [] + peak_start = -1 + for i, dp in enumerate(power): + if dp >= opt['threshold'] and peak_start == -1: + peak_start = i + elif dp < opt['threshold'] and peak_start != -1: + peaks.append((peak_start, i)) + peak_start = -1 + + for peak in peaks: + duration = data[peak[1]-1, 0] - data[peak[0], 0] + print('{:.2f}ms peak ({:f} -> {:f})'.format(duration * 1000, + data[peak[0], 0], data[peak[1]-1, 0])) + print(' {:f} µJ / mean {:f} µW'.format( + np.mean(power[peak[0] : peak[1]]) * duration * 1e6, + np.mean(power[peak[0] : peak[1]]) * 1e6 )) + + if 'save' in opt: + with open(opt['save'], 'w') as f: + f.write(log_data) + + if 'stat' in opt: + print('Mean voltage: {:f}'.format(np.mean(data[:, 2]))) + print('Mean current: {:f}'.format(np.mean(data[:, 1]))) + print('Mean power: {:f}'.format(np.mean(data[:, 1] * data[:, 2]))) + print('Total energy: {:f}'.format(m_energy)) + + if 'plot' in opt: + pwrhandle, = plt.plot(data[:, 0], data[:, 1] * data[:, 2], 'b-', label='U*I', markersize=1) + #energyhandle, = plt.plot(data[1:, 0], (data[1:, 3] - data[:-1, 3]) / (data[1:, 0] - data[:-1, 0]), 'r-', label='E/Δt', markersize=1) + plt.legend(handles=[pwrhandle]) + plt.xlabel('Time [s]') + plt.ylabel('Power [W]') + plt.grid(True) + plt.show() |