From 6773d3c134944195828d64d42e93adb16f0aced6 Mon Sep 17 00:00:00 2001 From: Eric Yu Date: Sun, 7 Aug 2022 23:47:03 -0700 Subject: [PATCH] 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 --- README.md | 24 +++++---- __pycache__/read_arduino.cpython-39.pyc | Bin 0 -> 1576 bytes __pycache__/serial_plot.cpython-39.pyc | Bin 0 -> 1723 bytes __pycache__/ui.cpython-39.pyc | Bin 0 -> 4515 bytes espVoltmeter/espVoltmeter.ino | 57 ++++++++++++++++++++ read_arduino.py | 54 +++++++++++++++++++ read_arduino.pyw | 49 ----------------- sealammonia.fbp | 24 ++++----- serial_plot.py | 2 +- serial_plot.pyw | 2 +- test.py | 67 +++++++++++------------- ui.py | 23 ++++---- 12 files changed, 185 insertions(+), 117 deletions(-) create mode 100644 __pycache__/read_arduino.cpython-39.pyc create mode 100644 __pycache__/serial_plot.cpython-39.pyc create mode 100644 __pycache__/ui.cpython-39.pyc create mode 100644 espVoltmeter/espVoltmeter.ino create mode 100644 read_arduino.py delete mode 100644 read_arduino.pyw diff --git a/README.md b/README.md index f5e2c87..00a7af4 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ - pyserial - wxPython - PlatformIO IDE, which could be downloaded as an extension in vs code +- ESP32 WROOM-32 Development Board ### Recommended - Code Runner (for VSCode only) - wxFormBuilder @@ -15,28 +16,32 @@ ## How to use ### Direct use - First download the `.ino` file from `ReadRaw` 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 -Then you can just run `python toplevel.py` and start from the UI. Enter the relevant information and start collect and measuring data. + 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~~ + (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 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. 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. `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 -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 -- 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) - "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 - 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 +- [ ] Automatically setup the driver for ESP32 - [ ] display sensor value in either the UI or on the plot - [ ] Reopen plot window from the UI when 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) - [ ] 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) -- [ ] Possibly adding new module to support ESP32 -- [ ] Support for non-Windows platforms +- [x] Possibly adding new module to support ESP32 +- [ ] Support for non-Windows platforms (and maybe mobile) - [ ] Make it into one executable +- [ ] Possibly adding new module to support Arduino MEGA and older firmwares diff --git a/__pycache__/read_arduino.cpython-39.pyc b/__pycache__/read_arduino.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d00f49cfb86e41009d8d47169f212737f1ece2cb GIT binary patch literal 1576 zcmYim$!;4rl;kWLjV0N!9j|G^qV>T*ZKQD#6h=`rXaWQ+;uI0O4FU+XNZF%|NtLAJ zSQuUE_Lv}_ARPOj+h zFwM?{7242&R->GQLS@jZ0WHKx6zLVjk9M(3z?-o7nK-%%LDKc&|Gz~bpa|$oSf<2~ zFrFZbrq~ircyLK(c!EpJ!%Z|HfFrmb!(-X9wSH38O2nIQ$Rq(P^)j;Qt7wMxTf4wpm-uH~Cey|Yy~FzT_z$3) zGc;}SMetg;L4OhATq^4`4D>C&^oDR`(_aaAO~KkStd%k?qZ#41wh>=mg=qQmHkvF{ zJE7kxgK`1(RyNQonl$+8bQSh)myPL~U5C>RyD{AapIiL)49^1a+q6;Htnwgb%-8rj zU*sEa!bz)aO}EP?-&_YT7y)-@hA{db{q#13diLMz-?jI8tMbal67UVDiE(w4WTcpTB5#o;~`( zrQi8npLokzoSWy~TB6~3R&m7Fu3e3pxpnWpZ^Wn z?qU}D;)At$f9ME2=-7jr2Z;y%J!?PXvJ{4i)v73j&gwq9jvqWQnV9VqFi&7k0cAvy zMY;o-!aQTv;ofgZKLGuIKYo1p@+7yX!{e8JbnUgPR@;NNn-3%Nva-sqhuHq$!i8SY z0A=$K0Ky?&!U_B>_&rWYf>Y8Wzy&ELxJB;9cku@K5cZbfOe0*w`V-LHOnq;3N)=|`Co_KmksO{4F7z54(sw-Y#;SB~fCFzL`Rq*bVIe;E RooRf`VbH)EKFA;>{{gM{!kPd8 literal 0 HcmV?d00001 diff --git a/__pycache__/serial_plot.cpython-39.pyc b/__pycache__/serial_plot.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4a9168396d1fd626fba75fe198c524d003f95375 GIT binary patch literal 1723 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 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(); + } + +} \ No newline at end of file diff --git a/read_arduino.py b/read_arduino.py new file mode 100644 index 0000000..919fe9b --- /dev/null +++ b/read_arduino.py @@ -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') diff --git a/read_arduino.pyw b/read_arduino.pyw deleted file mode 100644 index a318b39..0000000 --- a/read_arduino.pyw +++ /dev/null @@ -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') diff --git a/sealammonia.fbp b/sealammonia.fbp index 0a3328a..af73cfe 100644 --- a/sealammonia.fbp +++ b/sealammonia.fbp @@ -507,7 +507,7 @@ wxFILTER_NONE wxDefaultValidator - + 0 @@ -598,7 +598,7 @@ wxFILTER_NONE wxDefaultValidator - + 0 @@ -689,7 +689,7 @@ wxFILTER_NONE wxDefaultValidator - + 0 @@ -780,7 +780,7 @@ wxFILTER_NONE wxDefaultValidator - + 0 @@ -823,7 +823,7 @@ 1 wxID_ANY - Additional Parameters + Additional Parameters (Do not change unless you know what you are doing!) v_entre wxVERTICAL @@ -986,12 +986,12 @@ ; ; forward_declare 0 - + Input voltage of the resistors, default 3.3 volts wxFILTER_NONE wxDefaultValidator - 5 + 3.3 @@ -1059,7 +1059,7 @@ 0 0 wxID_ANY - ADC Output Voltage + ADC bit rate 0 @@ -1166,12 +1166,12 @@ ; ; forward_declare 0 - + Bit size of the board's ADC, default is 12 bits (4096) minus 1 wxFILTER_NONE wxDefaultValidator - 5 + 4095 @@ -1419,7 +1419,7 @@ 0 0 wxID_ANY - Volts + 0 @@ -1974,7 +1974,7 @@ 1 0 - 0 + 1 1 1 diff --git a/serial_plot.py b/serial_plot.py index 0b25086..301516b 100644 --- a/serial_plot.py +++ b/serial_plot.py @@ -4,7 +4,7 @@ import math, json, traceback try: 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: traceback.print_exc() diff --git a/serial_plot.pyw b/serial_plot.pyw index 82ae3ef..fa498eb 100644 --- a/serial_plot.pyw +++ b/serial_plot.pyw @@ -4,7 +4,7 @@ import math, json, traceback try: 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: traceback.print_exc() diff --git a/test.py b/test.py index 219151f..e5f0964 100644 --- a/test.py +++ b/test.py @@ -1,11 +1,14 @@ from ui import Frame from datetime import datetime 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 from serial_plot import * import numpy as np +warnings.filterwarnings("ignore", category=DeprecationWarning) + HEIGHT = 800 WIDTH = 800 @@ -13,12 +16,12 @@ WIDTH = 800 def main(): #################### USER INPUTS ########################### # 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()), 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 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() # typical window size: 480 window_size = int(frame.m_textCtrl26.GetValue()) @@ -30,16 +33,15 @@ def main(): dat_folder = "RecordedData" 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") - 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 if not (len(resistors) == 5): 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 -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 """ @@ -47,10 +49,9 @@ def gen_settings(resistors, input_voltage, adjusted_volt, port, filename, resolu settings = {} settings["refRes"] = resistors settings["sensor_ports"] = np.where(np.array(resistors) > 0)[0].tolist() - settings["v_src"] = input_voltage - settings["v_in"] = adjusted_volt + settings["v_in"] = input_voltage settings["port"] = port - settings["resolution"] = resolution + settings["resolution"] = bits settings["winSize"] = window_size settings["file_name"] = filename settings["delay"] = delay @@ -66,29 +67,8 @@ def get_devices(): frame.dev_list.AppendItems(ports) -# return ports - - # for scheduler maybe? 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") 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) @@ -109,29 +89,44 @@ def task2(): def run(e): file = main() 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.start() - t2 = Thread(target=task2, args=()) + t2 = Thread(target=task1, args=()) t2.setDaemon(True) 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(): - frame.Close() + frame.Hide() wx.MessageBox(save_diag, "Info", style=wx.ICON_INFORMATION) + def runPlot(e): 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) if __name__ == '__main__': app = wx.App() frame = Frame(None) 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.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.m_textCtrl26.SetValue("480") app.MainLoop() diff --git a/ui.py b/ui.py index 4304a85..6cac331 100644 --- a/ui.py +++ b/ui.py @@ -46,16 +46,16 @@ class Frame ( wx.Frame ): self.r4_prompt.Wrap( -1 ) 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 ) - 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 ) - 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 ) - 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 ) @@ -64,7 +64,7 @@ class Frame ( wx.Frame ): 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.SetFlexibleDirection( wx.BOTH ) @@ -74,14 +74,18 @@ class Frame ( wx.Frame ): 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 ) - 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 ) - 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 ) 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 ) 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 ) - 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 ) 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 ) 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 )