Modified UI

Change the option on the UI, as well as some changes on read_arduino to make it more compatible for the current hardware. As well as some minor improvements
This commit is contained in:
Eric Yu 2022-08-07 23:47:03 -07:00
parent 20093c52d5
commit 6773d3c134
12 changed files with 185 additions and 117 deletions

View File

@ -8,6 +8,7 @@
- pyserial - pyserial
- wxPython - wxPython
- PlatformIO IDE, which could be downloaded as an extension in vs code - PlatformIO IDE, which could be downloaded as an extension in vs code
- ESP32 WROOM-32 Development Board
### Recommended ### Recommended
- Code Runner (for VSCode only) - Code Runner (for VSCode only)
- wxFormBuilder - wxFormBuilder
@ -15,28 +16,32 @@
## How to use ## How to use
### Direct use ### Direct use
First download the `.ino` file from `ReadRaw` folder using Arduino IDE. Or if you are using Arduino Mega 2560 you can First download the `.ino` file from `espVoltmeter` folder using Arduino IDE. ~~Or if you are using Arduino Mega 2560 you can
use the code in `ReadAnalog` folder by open the folder in VSCode and run with PlatformIO, or just run `flash.py` in a terminal use the code in `ReadAnalog` folder by open the folder in VSCode and run with PlatformIO, or just run `flash.py` in a terminal~~
Then you can just run `python toplevel.py` and start from the UI. Enter the relevant information and start collect and measuring data. (Arduino Mega and Uno boards are no longer supported. Please use [this link](https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html) to
use on Arduino IDE or PlatformIO for VSCode)
Then you can just run `python test.py` and start from the UI. Enter the relevant information and start collect and measuring data.
### develop & build ### develop & build
Beside the c-based code for the Arduino board to read raw data from the board, everything has now been done in the python Beside the c-based code for the Arduino board to read raw data from the board, everything has now been done in the python
files. The main program is `toplevel.py`, which calls `UI.py` to prompt for input. It is NOT recommended modifying the `ui.py` files. The main program is `test.py`, which calls `UI.py` to prompt for input. It is NOT recommended modifying the `ui.py`
as it is generated from wxFormBuilder from `sealammonia.fbp`, which could be modified if any frontend feature need to change. as it is generated from wxFormBuilder from `sealammonia.fbp`, which could be modified if any frontend feature need to change.
the main program will generate `settings.json` which saves all required parameters needed to calculate and graph and save the the main program will generate `settings.json` which saves all required parameters needed to calculate and graph and save the
sensor's values. It also creates a .csv file under `RecordedData` directory to save all recorded+calculated data. sensor's values. It also creates a .csv file under `RecordedData` directory to save all recorded+calculated data.
`read_arduino.pyw` read raw data from Arduino board and convert it to the correct resistance, which could be plotted out `read_arduino.pyw` read raw data from Arduino board and convert it to the correct resistance, which could be plotted out
using `serial_plot.pyw`. Note that all .pyw are still Python files and should be correctly opened using any IDE/text edtiors using `serial_plot.pyw`. Note that all .pyw are still Python files and should be correctly opened using any IDE/text edtiors
as .py file does, except not going to pop up a black terminal when running directly. `test.py` is the alternative version of the frontend writting using `tkinter`. as .py file does, except not going to pop up a black terminal when running directly. `frontend.py` is the alternative version of the frontend writting using `tkinter`
and is not longer supported.
## Issues ## Issues
- Currently can only use 5V as input voltage. May need to change the algorithm in `read_arduino.py`. Newer hardware will require 3.3V. - Newer hardware will require 3.3V. ~~Currently can only use 5V as input voltage.~~ May need to change the algorithm in `read_arduino.py`.
- Should call `writerandomvalues.py` to simulate Arduino data when nothing is connected but user still want to run. Currently just pop up error(fixed) - Should call `writerandomvalues.py` to simulate Arduino data when nothing is connected but user still want to run. Currently just pop up error(fixed)
- "plot" button is completely disabled, should be enabled whenever is not plotting but is reading data - "plot" button is completely disabled, should be enabled whenever is not plotting but is reading data
- Matplotlib cannot really run in multithread, this might going to be an issue for packing the program into an executable - Matplotlib cannot really run in multithread, this might going to be an issue for packing the program into an executable
- Csv file is only created after you close the UI - Csv file is only created after you close the UI
## Todos & [Specs](https://docs.google.com/document/d/1Km2HZel7rILOvgHG5iXlUcXFx4Of1ot2I7Dbnq8aTwY/edit?usp=sharing): ## Todos & [Old Specs](https://docs.google.com/document/d/1Km2HZel7rILOvgHG5iXlUcXFx4Of1ot2I7Dbnq8aTwY/edit?usp=sharing):
- [ ] Fix Issues - [ ] Fix Issues
- [ ] Automatically setup the driver for ESP32
- [ ] display sensor value in either the UI or on the plot - [ ] display sensor value in either the UI or on the plot
- [ ] Reopen plot window from the UI when closed - [ ] Reopen plot window from the UI when closed
- [x] Need to continue writing to file when graphing window is closed - [x] Need to continue writing to file when graphing window is closed
@ -48,6 +53,7 @@ as .py file does, except not going to pop up a black terminal when running direc
- [x] Write random values to simulate a sensor if no sensor available (this feature might be removed in the future) - [x] Write random values to simulate a sensor if no sensor available (this feature might be removed in the future)
- [ ] Advanced option menu in the UI to allow user to make more adjustments - [ ] Advanced option menu in the UI to allow user to make more adjustments
- [ ] Add resolution option in the UI to allow interchange between arduino (10bit) and esp32 (12 bits) - [ ] Add resolution option in the UI to allow interchange between arduino (10bit) and esp32 (12 bits)
- [ ] Possibly adding new module to support ESP32 - [x] Possibly adding new module to support ESP32
- [ ] Support for non-Windows platforms - [ ] Support for non-Windows platforms (and maybe mobile)
- [ ] Make it into one executable - [ ] Make it into one executable
- [ ] Possibly adding new module to support Arduino MEGA and older firmwares

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,57 @@
// manually define all the An ports on ESP32 board
#if defined(ESP32)
#define A0 (36)
#define A1 (39)
#define A2 (34)
#define A3 (35)
#define A4 (32)
#define A5 (33)
#endif
// define the divident of sizeof()'s return value
#if defined(ESP32)
#define SIZE_DIV 4 // for esp32, the resolution is doubled than the usual arduino board, so we double the factor, too
#else
#define SIZE_DIV 2
#endif
#define WAIT_TIME 1000UL
#define SENSOR1 36
// FILE *f = fopen("file.txt", "w");
int pins[] = {A0, A1, A2, A3, A4, A5};
int i, j;
unsigned long currTime; // non-blocking time tracker
void setup() {
Serial.begin(19200);
currTime = millis();
analogReadResolution(12);
// adcAttachPin(A0);
// analogSetClockDiv(255);
}
void loop() {
// we might need analogSetAttenuation to make the measurement more accurate and less noisy?
if (millis() - currTime >= WAIT_TIME) { // non-blocking time delay
// Serial.println();
Serial.print("[");
for (i = 0; i < sizeof(pins)/SIZE_DIV; i++) {
// float volts = analogRead(pins[i]);
// float result = volts * 3.3 / 4095;
// Serial.print(result);
float volts = analogReadMilliVolts(pins[i]);
Serial.print(volts);
// Serial.print(61319 * (3.3/volts - 1));
if (i != sizeof(pins)/SIZE_DIV - 1) {
Serial.print(", ");
}
}
Serial.println("]");
// Serial.println(analogReadMilliVolts(SENSOR1));
currTime = millis();
}
}

54
read_arduino.py Normal file
View File

@ -0,0 +1,54 @@
"""
Read raw data from Arduino and then converted into actual resistance using parameters provided from top level
"""
from datetime import datetime
import serial, os, json
import serial.tools.list_ports
import numpy as np
# constant settings
SENSORS_MAX = 4 # maximum sensor ports
def read():
baud = 19200
settings = json.load(open('settings.json', 'r'))
resolution = settings["resolution"] # this is not in use, but just in case if we decide to switch back to analogRead() instead of ESP32's analogReadMiliVolts() on the firmware
v_in = settings["v_in"]
refRes = np.array(settings["refRes"])
sensor_ports = np.array(settings["sensor_ports"]) # ports that sensor(s) are connected to
file_name = settings["file_name"]
port = settings["port"]
if "- No Device -" in port:
# TODO: set to writerandomvalues.py thing instead raise error
print("this should generate random values base on # sensors given")
exit(0)
else:
controller = serial.Serial(port, baudrate=baud)
if np.any(sensor_ports >= SENSORS_MAX):
raise ValueError("Port range is 0-3!")
# TODO: separate data in each run but still keep them in one csv file
while controller.isOpen():
try:
read_data = controller.readline().decode("utf-8")
# use numpy so it can make list calculations easier (and possibly faster)
dat_list = np.asarray(json.loads(read_data), dtype=np.uint32)[:SENSORS_MAX]
# if we decided to switch back to analogRead(), replace this line of comment to the algorithm to something like the commented line below
# dat_sel = np.take(dat_list, sensor_ports) * v_in / resolution
# take only the nonzero indices, and truncated to two decimal places to "filter" out some hardware errors
dat_sel = np.trunc((np.take(dat_list, sensor_ports) / 1000) * 10**2) / 10**2
r_arr = np.take(refRes, sensor_ports) * (v_in / dat_sel - 1)
# write + export values as .csv format
dat = f", ".join(np.insert(r_arr.astype(str), 0, datetime.now().strftime('%H:%M:%S')))
print(dat)
f = open(file_name, "a", newline="", encoding="utf-8")
f.write(dat + '\n')
f.close()
# except KeyboardInterrupt as e:
# print(e.__class__.__name__)
# break
except (json.decoder.JSONDecodeError, UnicodeDecodeError):
print('decoder error')

View File

@ -1,49 +0,0 @@
"""
Read raw data from Arduino and then converted into actual resistance using parameters provided from top level
"""
from datetime import datetime
import serial, os, json
import serial.tools.list_ports
import numpy as np
# constant settings
SENSORS_MAX = 4 # maximum sensor ports
baud = 19200
settings = json.load(open('settings.json', 'r'))
resolution = settings["resolution"]
v_src = settings["v_src"]
v_in = settings["v_in"]
refRes = np.array(settings["refRes"])
sensor_ports = np.array(settings["sensor_ports"]) # ports that sensor(s) are connected to
file_name = settings["file_name"]
port = settings["port"]
if "- No Device -" in port:
# TODO: set to writerandomvalues.py thing instead raise error
print("this should generate random values base on # sensors given")
exit(0)
else:
controller = serial.Serial(port, baudrate=baud)
if np.any(sensor_ports >= SENSORS_MAX):
raise ValueError("Port range is 0-3!")
# TODO: separate data in each run but still keep them in one csv file
while controller.isOpen():
try:
read_data = controller.readline().decode("utf-8")
# use numpy so it can make list calculations easier (and possibly faster)
dat_list = np.asarray(json.loads(read_data), dtype=np.int16)[:SENSORS_MAX]
dat_sel = np.take(dat_list, sensor_ports) * v_in / resolution
r_arr = np.take(refRes, sensor_ports) * (v_in / dat_sel - 1)
# write + export values as .csv format
dat = f", ".join(np.insert(r_arr.astype(str), 0, datetime.now().strftime('%H:%M:%S')))
print(dat)
f = open(file_name, "a", newline="", encoding="utf-8")
f.write(dat + '\n')
f.close()
# except KeyboardInterrupt as e:
# print(e.__class__.__name__)
# break
except json.decoder.JSONDecodeError:
print('decoder error')

View File

@ -507,7 +507,7 @@
<property name="validator_style">wxFILTER_NONE</property> <property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property> <property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property> <property name="validator_variable"></property>
<property name="value"></property> <property name="value">0</property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
@ -598,7 +598,7 @@
<property name="validator_style">wxFILTER_NONE</property> <property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property> <property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property> <property name="validator_variable"></property>
<property name="value"></property> <property name="value">0</property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
@ -689,7 +689,7 @@
<property name="validator_style">wxFILTER_NONE</property> <property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property> <property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property> <property name="validator_variable"></property>
<property name="value"></property> <property name="value">0</property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
@ -780,7 +780,7 @@
<property name="validator_style">wxFILTER_NONE</property> <property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property> <property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property> <property name="validator_variable"></property>
<property name="value"></property> <property name="value">0</property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
@ -823,7 +823,7 @@
<property name="proportion">1</property> <property name="proportion">1</property>
<object class="wxStaticBoxSizer" expanded="0"> <object class="wxStaticBoxSizer" expanded="0">
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Additional Parameters</property> <property name="label">Additional Parameters (Do not change unless you know what you are doing!)</property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">v_entre</property> <property name="name">v_entre</property>
<property name="orient">wxVERTICAL</property> <property name="orient">wxVERTICAL</property>
@ -986,12 +986,12 @@
<property name="style"></property> <property name="style"></property>
<property name="subclass">; ; forward_declare</property> <property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property> <property name="toolbar_pane">0</property>
<property name="tooltip"></property> <property name="tooltip">Input voltage of the resistors, default 3.3 volts</property>
<property name="validator_data_type"></property> <property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property> <property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property> <property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property> <property name="validator_variable"></property>
<property name="value">5</property> <property name="value">3.3</property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
@ -1059,7 +1059,7 @@
<property name="gripper">0</property> <property name="gripper">0</property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">ADC Output Voltage</property> <property name="label">ADC bit rate</property>
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
@ -1166,12 +1166,12 @@
<property name="style"></property> <property name="style"></property>
<property name="subclass">; ; forward_declare</property> <property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property> <property name="toolbar_pane">0</property>
<property name="tooltip"></property> <property name="tooltip">Bit size of the board&apos;s ADC, default is 12 bits (4096) minus 1</property>
<property name="validator_data_type"></property> <property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property> <property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property> <property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property> <property name="validator_variable"></property>
<property name="value">5</property> <property name="value">4095</property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
@ -1419,7 +1419,7 @@
<property name="gripper">0</property> <property name="gripper">0</property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Volts</property> <property name="label"></property>
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
@ -1974,7 +1974,7 @@
<property name="caption"></property> <property name="caption"></property>
<property name="caption_visible">1</property> <property name="caption_visible">1</property>
<property name="center_pane">0</property> <property name="center_pane">0</property>
<property name="checked">0</property> <property name="checked">1</property>
<property name="close_button">1</property> <property name="close_button">1</property>
<property name="context_help"></property> <property name="context_help"></property>
<property name="context_menu">1</property> <property name="context_menu">1</property>

View File

@ -4,7 +4,7 @@ import math, json, traceback
try: try:
import matplotlib import matplotlib
matplotlib.use("QtAgg") # to force use one of the matplot's UI backend instead of an IDE's choice matplotlib.use("WXAgg") # to force use one of the matplot's UI backend instead of an IDE's choice
except ImportError: except ImportError:
traceback.print_exc() traceback.print_exc()

View File

@ -4,7 +4,7 @@ import math, json, traceback
try: try:
import matplotlib import matplotlib
matplotlib.use("QtAgg") # to force use one of the matplot's UI backend instead of an IDE's choice matplotlib.use("WXAgg") # to force use one of the matplot's UI backend instead of an IDE's choice
except ImportError: except ImportError:
traceback.print_exc() traceback.print_exc()

65
test.py
View File

@ -1,11 +1,14 @@
from ui import Frame from ui import Frame
from datetime import datetime from datetime import datetime
from threading import * from threading import *
import os, json, sys, wx, subprocess from read_arduino import *
import os, json, sys, wx, subprocess, warnings
import serial.tools.list_ports import serial.tools.list_ports
from serial_plot import * from serial_plot import *
import numpy as np import numpy as np
warnings.filterwarnings("ignore", category=DeprecationWarning)
HEIGHT = 800 HEIGHT = 800
WIDTH = 800 WIDTH = 800
@ -13,12 +16,12 @@ WIDTH = 800
def main(): def main():
#################### USER INPUTS ########################### #################### USER INPUTS ###########################
# TODO: if there is already a setting.json exist, loads all inputs from there as 'default' # TODO: if there is already a setting.json exist, loads all inputs from there as 'default'
# 9840
resistors = [float(frame.r_ref_1.GetValue()), float(frame.r_ref_2.GetValue()), float(frame.r_ref_3.GetValue()), resistors = [float(frame.r_ref_1.GetValue()), float(frame.r_ref_2.GetValue()), float(frame.r_ref_3.GetValue()),
float(frame.r_ref_4.GetValue()), float(frame.r_ref_4.GetValue()),
0] # resisters for each An port, where n is an integer from 0-3. Use 0 if none. in Ohms 0] # resisters for each An port, where n is an integer from 0-3. Use 0 if none. in Ohms
input_voltage = float(frame.input_voltage.GetValue()) input_voltage = float(frame.input_voltage.GetValue())
adjusted_volt = float(frame.adjusted_volt.GetValue()) bit_rate = float(frame.adjusted_volt.GetValue())
port = frame.dev_list.GetValue() port = frame.dev_list.GetValue()
# typical window size: 480 # typical window size: 480
window_size = int(frame.m_textCtrl26.GetValue()) window_size = int(frame.m_textCtrl26.GetValue())
@ -30,16 +33,15 @@ def main():
dat_folder = "RecordedData" dat_folder = "RecordedData"
os.makedirs(dat_folder, exist_ok=True) os.makedirs(dat_folder, exist_ok=True)
filename = os.path.join(os.getcwd(), dat_folder, f"{datetime.now().strftime('%Y-%m-%d_%H%M%S')}.csv") filename = os.path.join(os.getcwd(), dat_folder, f"{datetime.now().strftime('%Y-%m-%d_%H%M%S')}.csv")
resolution = 1023 # Arduino's analogRead()'s input resolution. We don't change this number usually.
delay = 1000 # millisec pe r data, defined in the firmware delay = 1000 # millisec pe r data, defined in the firmware
if not (len(resistors) == 5): if not (len(resistors) == 5):
raise ValueError(f"expecting 5 resistor values, but got {len(resistors)}!!!") raise ValueError(f"expecting 5 resistor values, but got {len(resistors)}!!!")
gen_settings(resistors, input_voltage, adjusted_volt, port, filename, resolution, window_size, delay) gen_settings(resistors, input_voltage, bit_rate, port, filename, window_size, delay)
return filename return filename
def gen_settings(resistors, input_voltage, adjusted_volt, port, filename, resolution, window_size, delay): def gen_settings(resistors, input_voltage, bits, port, filename, window_size, delay):
""" """
export all inputs from main() to a .json file export all inputs from main() to a .json file
""" """
@ -47,10 +49,9 @@ def gen_settings(resistors, input_voltage, adjusted_volt, port, filename, resolu
settings = {} settings = {}
settings["refRes"] = resistors settings["refRes"] = resistors
settings["sensor_ports"] = np.where(np.array(resistors) > 0)[0].tolist() settings["sensor_ports"] = np.where(np.array(resistors) > 0)[0].tolist()
settings["v_src"] = input_voltage settings["v_in"] = input_voltage
settings["v_in"] = adjusted_volt
settings["port"] = port settings["port"] = port
settings["resolution"] = resolution settings["resolution"] = bits
settings["winSize"] = window_size settings["winSize"] = window_size
settings["file_name"] = filename settings["file_name"] = filename
settings["delay"] = delay settings["delay"] = delay
@ -66,29 +67,8 @@ def get_devices():
frame.dev_list.AppendItems(ports) frame.dev_list.AppendItems(ports)
# return ports
# for scheduler maybe? # for scheduler maybe?
def task1(): def task1():
print("run task 1")
run_t1 = ["start", sys.executable, "read_arduino.pyw"]
out1 = subprocess.Popen(run_t1, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
running = True
init = 0
while running:
cline = out1.stdout.readline()
print(cline.decode())
if not cline and init > 0:
print(cline.decode())
running = False
init += 1
if out1.returncode:
print('Something went wrong:', out1.returncode)
def task2():
print("run task 2") print("run task 2")
run_t2 = ["start", os.path.join(sys.exec_prefix, 'pythonw'), "serial_plot.pyw"] run_t2 = ["start", os.path.join(sys.exec_prefix, 'pythonw'), "serial_plot.pyw"]
out2 = subprocess.Popen(run_t2, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) out2 = subprocess.Popen(run_t2, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
@ -109,17 +89,20 @@ def task2():
def run(e): def run(e):
file = main() file = main()
save_diag = f"File has saved as {os.path.split(file)[1]} under {os.path.split(file)[0]} directory!\n" save_diag = f"File has saved as {os.path.split(file)[1]} under {os.path.split(file)[0]} directory!\n"
t1 = Thread(target=task1, args=())
t1 = Thread(target=read, args=())
t1.setDaemon(True) t1.setDaemon(True)
t1.start() t1.start()
t2 = Thread(target=task2, args=()) t2 = Thread(target=task1, args=())
t2.setDaemon(True) t2.setDaemon(True)
t2.start() t2.start()
frame.plot_but.Enable(True) # this might have some problem ... what happen if user spamming the plot button?
if not frame.show_msg.GetValue(): if not frame.show_msg.GetValue():
frame.Close() frame.Hide()
wx.MessageBox(save_diag, "Info", style=wx.ICON_INFORMATION) wx.MessageBox(save_diag, "Info", style=wx.ICON_INFORMATION)
def runPlot(e): def runPlot(e):
plotter() plotter()
wx.MessageBox("Your data is being plotted", "Info", style=wx.ICON_INFORMATION) wx.MessageBox("Your data is being plotted", "Info", style=wx.ICON_INFORMATION)
@ -129,9 +112,21 @@ if __name__ == '__main__':
app = wx.App() app = wx.App()
frame = Frame(None) frame = Frame(None)
get_devices() get_devices()
frame.SetTitle("Cease your resistance! - a0.0.0") frame.SetTitle("Cease your resistance! - alpha 0.1.0")
frame.btLaunch.Bind(wx.EVT_BUTTON, run) frame.btLaunch.Bind(wx.EVT_BUTTON, run)
frame.plot_but.Bind(wx.EVT_BUTTON, runPlot) # There is one problem with this approch: what happen if user spamming the plot button? frame.plot_but.Bind(wx.EVT_BUTTON,
runPlot) # There is one problem with this approch: what happen if user spamming the plot button?
if os.path.isfile("settings.json"):
print("Found existing settings.json, auto-fill previous inputs!")
settings = json.load(open('settings.json', 'r'))
frame.r_ref_1.SetValue(str(settings["refRes"][0]))
frame.r_ref_2.SetValue(str(settings["refRes"][1]))
frame.r_ref_3.SetValue(str(settings["refRes"][2]))
frame.r_ref_4.SetValue(str(settings["refRes"][3]))
frame.input_voltage.SetValue(str(settings["v_in"]))
frame.adjusted_volt.SetValue(str(settings["resolution"]))
frame.m_textCtrl26.SetValue(str(settings["winSize"]))
frame.Show() frame.Show()
frame.m_textCtrl26.SetValue("480") frame.m_textCtrl26.SetValue("480")
app.MainLoop() app.MainLoop()

23
ui.py
View File

@ -46,16 +46,16 @@ class Frame ( wx.Frame ):
self.r4_prompt.Wrap( -1 ) self.r4_prompt.Wrap( -1 )
res_grid.Add( self.r4_prompt, 0, wx.ALIGN_BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, 5 ) res_grid.Add( self.r4_prompt, 0, wx.ALIGN_BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, 5 )
self.r_ref_1 = wx.TextCtrl( ref_entre.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 ) self.r_ref_1 = wx.TextCtrl( ref_entre.GetStaticBox(), wx.ID_ANY, u"0", wx.DefaultPosition, wx.DefaultSize, 0 )
res_grid.Add( self.r_ref_1, 0, wx.ALIGN_CENTER_HORIZONTAL, 5 ) res_grid.Add( self.r_ref_1, 0, wx.ALIGN_CENTER_HORIZONTAL, 5 )
self.r_ref_2 = wx.TextCtrl( ref_entre.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 ) self.r_ref_2 = wx.TextCtrl( ref_entre.GetStaticBox(), wx.ID_ANY, u"0", wx.DefaultPosition, wx.DefaultSize, 0 )
res_grid.Add( self.r_ref_2, 0, wx.ALIGN_CENTER_HORIZONTAL, 5 ) res_grid.Add( self.r_ref_2, 0, wx.ALIGN_CENTER_HORIZONTAL, 5 )
self.r_ref_3 = wx.TextCtrl( ref_entre.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 ) self.r_ref_3 = wx.TextCtrl( ref_entre.GetStaticBox(), wx.ID_ANY, u"0", wx.DefaultPosition, wx.DefaultSize, 0 )
res_grid.Add( self.r_ref_3, 0, wx.ALIGN_CENTER_HORIZONTAL, 5 ) res_grid.Add( self.r_ref_3, 0, wx.ALIGN_CENTER_HORIZONTAL, 5 )
self.r_ref_4 = wx.TextCtrl( ref_entre.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 ) self.r_ref_4 = wx.TextCtrl( ref_entre.GetStaticBox(), wx.ID_ANY, u"0", wx.DefaultPosition, wx.DefaultSize, 0 )
res_grid.Add( self.r_ref_4, 0, wx.ALIGN_CENTER_HORIZONTAL, 5 ) res_grid.Add( self.r_ref_4, 0, wx.ALIGN_CENTER_HORIZONTAL, 5 )
@ -64,7 +64,7 @@ class Frame ( wx.Frame ):
bSizer1.Add( ref_entre, 0, wx.EXPAND, 5 ) bSizer1.Add( ref_entre, 0, wx.EXPAND, 5 )
v_entre = wx.StaticBoxSizer( wx.StaticBox( self, wx.ID_ANY, u"Additional Parameters" ), wx.VERTICAL ) v_entre = wx.StaticBoxSizer( wx.StaticBox( self, wx.ID_ANY, u"Additional Parameters (Do not change unless you know what you are doing!)" ), wx.VERTICAL )
gbSizer8 = wx.GridBagSizer( 0, 0 ) gbSizer8 = wx.GridBagSizer( 0, 0 )
gbSizer8.SetFlexibleDirection( wx.BOTH ) gbSizer8.SetFlexibleDirection( wx.BOTH )
@ -74,14 +74,18 @@ class Frame ( wx.Frame ):
self.vin_prompt.Wrap( -1 ) self.vin_prompt.Wrap( -1 )
gbSizer8.Add( self.vin_prompt, wx.GBPosition( 0, 0 ), wx.GBSpan( 1, 1 ), wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5 ) gbSizer8.Add( self.vin_prompt, wx.GBPosition( 0, 0 ), wx.GBSpan( 1, 1 ), wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5 )
self.input_voltage = wx.TextCtrl( v_entre.GetStaticBox(), wx.ID_ANY, u"5", wx.DefaultPosition, wx.DefaultSize, 0 ) self.input_voltage = wx.TextCtrl( v_entre.GetStaticBox(), wx.ID_ANY, u"3.3", wx.DefaultPosition, wx.DefaultSize, 0 )
self.input_voltage.SetToolTipString( u"Input voltage of the resistors, default 3.3 volts" )
gbSizer8.Add( self.input_voltage, wx.GBPosition( 0, 1 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5 ) gbSizer8.Add( self.input_voltage, wx.GBPosition( 0, 1 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5 )
self.vadc_prompt = wx.StaticText( v_entre.GetStaticBox(), wx.ID_ANY, u"ADC Output Voltage", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT|wx.ST_ELLIPSIZE_END ) self.vadc_prompt = wx.StaticText( v_entre.GetStaticBox(), wx.ID_ANY, u"ADC bit rate", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT|wx.ST_ELLIPSIZE_END )
self.vadc_prompt.Wrap( -1 ) self.vadc_prompt.Wrap( -1 )
gbSizer8.Add( self.vadc_prompt, wx.GBPosition( 1, 0 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, 5 ) gbSizer8.Add( self.vadc_prompt, wx.GBPosition( 1, 0 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, 5 )
self.adjusted_volt = wx.TextCtrl( v_entre.GetStaticBox(), wx.ID_ANY, u"5", wx.DefaultPosition, wx.DefaultSize, 0 ) self.adjusted_volt = wx.TextCtrl( v_entre.GetStaticBox(), wx.ID_ANY, u"4095", wx.DefaultPosition, wx.DefaultSize, 0 )
self.adjusted_volt.SetToolTipString( u"Bit size of the board's ADC, default is 12 bits (4096) minus 1" )
gbSizer8.Add( self.adjusted_volt, wx.GBPosition( 1, 1 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5 ) gbSizer8.Add( self.adjusted_volt, wx.GBPosition( 1, 1 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5 )
self.sizer_prompt = wx.StaticText( v_entre.GetStaticBox(), wx.ID_ANY, u"Window Size", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT|wx.ST_ELLIPSIZE_END ) self.sizer_prompt = wx.StaticText( v_entre.GetStaticBox(), wx.ID_ANY, u"Window Size", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT|wx.ST_ELLIPSIZE_END )
@ -93,7 +97,7 @@ class Frame ( wx.Frame ):
gbSizer8.Add( self.m_textCtrl26, wx.GBPosition( 2, 1 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.TOP|wx.RIGHT|wx.LEFT, 5 ) gbSizer8.Add( self.m_textCtrl26, wx.GBPosition( 2, 1 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.TOP|wx.RIGHT|wx.LEFT, 5 )
self.unit2 = wx.StaticText( v_entre.GetStaticBox(), wx.ID_ANY, u"Volts", wx.DefaultPosition, wx.DefaultSize, 0 ) self.unit2 = wx.StaticText( v_entre.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
self.unit2.Wrap( -1 ) self.unit2.Wrap( -1 )
gbSizer8.Add( self.unit2, wx.GBPosition( 1, 2 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL, 5 ) gbSizer8.Add( self.unit2, wx.GBPosition( 1, 2 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL, 5 )
@ -142,6 +146,7 @@ class Frame ( wx.Frame ):
bSizer1.Add( launch_opt, 0, wx.ALIGN_CENTER_HORIZONTAL, 5 ) bSizer1.Add( launch_opt, 0, wx.ALIGN_CENTER_HORIZONTAL, 5 )
self.show_msg = wx.CheckBox( self, wx.ID_ANY, u"Make launcher stays open after started", wx.DefaultPosition, wx.DefaultSize, 0 ) self.show_msg = wx.CheckBox( self, wx.ID_ANY, u"Make launcher stays open after started", wx.DefaultPosition, wx.DefaultSize, 0 )
self.show_msg.SetValue(True)
bSizer1.Add( self.show_msg, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 ) bSizer1.Add( self.show_msg, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )