diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 73f69e0..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index de3e67e..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -SeeDatResistance \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 961c692..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 3dce9c6..52a4323 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -1,11 +1,14 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index de3fcfe..ec57077 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 8b8c221..1d67470 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..41ec093 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1675750856334 + + + + + + + + + + + + \ No newline at end of file diff --git a/ReadAnalog/.gitignore b/OldFirmware/ReadAnalog/.gitignore similarity index 100% rename from ReadAnalog/.gitignore rename to OldFirmware/ReadAnalog/.gitignore diff --git a/ReadAnalog/.vscode/extensions.json b/OldFirmware/ReadAnalog/.vscode/extensions.json similarity index 100% rename from ReadAnalog/.vscode/extensions.json rename to OldFirmware/ReadAnalog/.vscode/extensions.json diff --git a/ReadAnalog/flash.py b/OldFirmware/ReadAnalog/flash.py similarity index 100% rename from ReadAnalog/flash.py rename to OldFirmware/ReadAnalog/flash.py diff --git a/ReadAnalog/include/README b/OldFirmware/ReadAnalog/include/README similarity index 100% rename from ReadAnalog/include/README rename to OldFirmware/ReadAnalog/include/README diff --git a/ReadAnalog/lib/README b/OldFirmware/ReadAnalog/lib/README similarity index 100% rename from ReadAnalog/lib/README rename to OldFirmware/ReadAnalog/lib/README diff --git a/ReadAnalog/platformio.ini b/OldFirmware/ReadAnalog/platformio.ini similarity index 100% rename from ReadAnalog/platformio.ini rename to OldFirmware/ReadAnalog/platformio.ini diff --git a/ReadAnalog/src/main.cpp b/OldFirmware/ReadAnalog/src/main.cpp similarity index 100% rename from ReadAnalog/src/main.cpp rename to OldFirmware/ReadAnalog/src/main.cpp diff --git a/ReadAnalog/test/README b/OldFirmware/ReadAnalog/test/README similarity index 100% rename from ReadAnalog/test/README rename to OldFirmware/ReadAnalog/test/README diff --git a/espVoltmeter/espVoltmeter.ino b/OldFirmware/espVoltmeter/espVoltmeter.ino similarity index 100% rename from espVoltmeter/espVoltmeter.ino rename to OldFirmware/espVoltmeter/espVoltmeter.ino diff --git a/README.md b/README.md index 10bde68..59d4e39 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Read Resistances -Read the resistance of a voltage divider using ESP32 +Read the resistance of a voltage divider using Arduino boards ## Required & Dependencies ### Required @@ -8,20 +8,23 @@ Read the resistance of a voltage divider using ESP32 - matplotlib - pyserial - wxPython -- PlatformIO IDE, which could be downloaded as an extension in vs code -- ESP32 WROOM-32 Development Board +- PlatformIO extension, if you use VSCode for embedded programmings +- An Arduino-based microcontroller +- ADS1115 16-bit ADC chip ### Recommended - Code Runner (for VSCode only) - wxFormBuilder - [Arduino IDE](https://makeabilitylab.github.io/physcomp/arduino/arduino-ide.html) ## How to use +To get a general idea of this project as well as hardware setup, please refer to [this video demo](https://youtu.be/vbVPXj8gbmI) ### Direct use - First download the `.ino` file from `espVoltmeter` folder using Arduino IDE. ~~Or if you are using Arduino Mega 2560 you can + First open the `.ino` file from `nano_c_mk1` directory using Arduino IDE and download it onto an Arduino board. ~~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) -For Windows you can just [download the released executable](https://github.com/Seal-Ammonia/Read-Sensor-Resistances/releases/download/beta/SeeDatResistance.exe) to use. Make sure to disable any virus-scanning software when download as Microsoft incorrectly recognized PyInstaller as virus. For non-Windows systems you can just run `python test.py` and start from the UI. Enter the relevant information and start collect and measuring data. If you do not have a board avaliable, leave the dropdown menu in the UI as "no device" and it will run a simulation. + ~~(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)~~ (There's a hardware upgrade so that the firmware has been re-written for the new hardware. + Therefore the old hardware are no longer in use. You may still find them in `OldFirmware` directory for reference but we are not using them anymore) +For Windows you can just [download the released executable](https://github.com/Seal-Ammonia/Read-Sensor-Resistances/releases/download/beta/SeeDatResistance.exe) from the release section to use. Make sure to disable any virus-scanning software when download as Microsoft incorrectly recognized PyInstaller as virus. For non-Windows systems you can just run `python test.py` and start from the UI. Enter the relevant information and start collect and measuring data. If you do not have a board avaliable, leave the dropdown menu in the UI as "no device" and it will run a simulation. ### 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 `test.py`, which calls `UI.py` to prompt for input. It is NOT recommended modifying the `ui.py` @@ -29,22 +32,22 @@ as it is generated from wxFormBuilder from `sealammonia.fbp`, which could be mod 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.py` read raw data from Arduino board and convert it to the correct resistance, which could be plotted out -using `serial_plotter.py`. `frontend.py` is the alternative version of the frontend writting using `tkinter`, and `serial_plot.py` -was an older version of `serial_plotter.py`. They are not longer supported. +using `serial_plotter.py`. To make your own executable, use `PyInstaller` using this command in your python environment: +`pyinstaller build.spec`. ATTENTION MAC USER: currently the software cannot correctly functional on mac (especially arm-based ones). You might need to consider to use it on a windows VM or using parallel desktop ## Issues - Newer hardware will require 3.3V. ~~Currently can only use 5V as input voltage.~~ May need to change the algorithm in `read_arduino.py`. - axis window size is not correct -- on PyInstaller, windows misdetected our executable as a virus +- on PyInstaller, windows misdetected our executable as a virus (seems resolved) - change the scale on Y-axis so that graph looks smoother -- Errors thrown when >1 reference resistances entered +- ~~Errors thrown when >1 reference resistances entered~~ -## Todos & [Old Specs](https://docs.google.com/document/d/1Km2HZel7rILOvgHG5iXlUcXFx4Of1ot2I7Dbnq8aTwY/edit?usp=sharing): +## Todos: - [ ] Fix Issues - [ ] Automatically setup the driver for ESP32 - [ ] programically to stablize the graph (change the y-scale of the graph to make the less dramatic) -- [ ] (not urgent) make if runnable on Mac +- [ ] (not urgent) make it runnable on Mac - [x] display sensor value in either the UI or on the plot - [x] Reopen plot window from the UI when closed - [x] Need to continue writing to file when graphing window is closed @@ -55,8 +58,8 @@ ATTENTION MAC USER: currently the software cannot correctly functional on mac (e - [x] Accept any inputs (such as resistor values, plot window size, base voltage etc.) as either command line argument or as input at beginning of program - [x] Write random values to simulate a sensor if no sensor available (this feature might be removed in the future) - [x] 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) +- [X] Add resolution option in the UI to allow interchange between arduino (10bit) and esp32 (12 bits) (Not Applicable in new hardware) - [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 +- [ ] Possibly adding new module to support Arduino MEGA and older firmwares (Need testing) diff --git a/Read-Sensor-Resistances.iml b/Read-Sensor-Resistances.iml new file mode 100644 index 0000000..ad3c0a3 --- /dev/null +++ b/Read-Sensor-Resistances.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/build.spec b/build.spec new file mode 100644 index 0000000..abfe6d8 --- /dev/null +++ b/build.spec @@ -0,0 +1,42 @@ +# -*- mode: python ; coding: utf-8 -*- + + +block_cipher = None + + +a = Analysis(['test.py', 'serial_plotter.py', 'read_arduino.py', 'ui.py'], + pathex=['D:\\github\\Read-Sensor-Resistances'], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + noarchive=False) +splash = Splash('splash.png', + binaries=a.binaries, + datas=a.datas, + text_pos=(145, 142), + text_size=8, + text_color='black') +pyz = PYZ(a.pure, a.zipped_data, + cipher=block_cipher) +exe = EXE(pyz, + a.scripts, + splash, # <-- both, splash target + splash.binaries, # <-- and splash binaries + a.binaries, + a.zipfiles, + a.datas, + [], + name='SeeDatResistance', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False ) diff --git a/read_arduino.py b/read_arduino.py index 2b66669..6aeff99 100644 --- a/read_arduino.py +++ b/read_arduino.py @@ -16,7 +16,7 @@ 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 + # resolution = settings["resolution"] # this is not in use, but just in case if we decide to switch back to analogRead() v_in = settings["v_in"] refRes = np.array(settings["refRes"]) sensor_ports = np.array(settings["sensor_ports"]) # ports that sensor(s) are connected to @@ -44,19 +44,9 @@ def read(): writer.writerow(header) f.close() while True: - #dat_list = np.random.randint(0, v_in * 1000, SENSORS_MAX) # create a randomized voltage data + dat_list = np.random.randint(0, v_in * 1000, SENSORS_MAX) # create a randomized voltage data # 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 - '''ser = serial.Serial(port) - ser.flushInput() - while True: - try: - ser_bytes = ser.readline() - decoded_bytes = float(ser_bytes[0:len(ser_bytes)-2].decode("utf-8")) - except: - print("Keyboard Interrupt") - break''' - #dat_sel = np.trunc((np.take(decoded_bytes, sensor_ports) / 1000) * 10**2) / 10**2 + 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) # *2 <-- change with actual formula for ammonia concentration # created a new array to convert resistance values to sci notation r_arr2 = np.empty(len(r_arr), dtype=object) @@ -81,7 +71,7 @@ def read(): # headers based on number of ports used if len(sensor_ports) == 1: header = ['Time', 'Resistance'] - if len(sensor_ports)== 2: + if len(sensor_ports) == 2: header = ['Time', 'Resistance1', 'Resistance2'] if len(sensor_ports) == 3: header = ['Time', 'Resistance1', 'Resistance2', 'Resistance3'] @@ -91,19 +81,14 @@ def read(): f.close() while controller.isOpen(): try: - #controller.flushInput() 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.float32)[:SENSORS_MAX] - #ser_bytes = controller.readline() - #decoded_bytes = float(ser_bytes[0:len(ser_bytes)-2].decode("utf-8")) - #dat_sel = np.trunc((np.take(dat_list, sensor_ports) / 1000) * 10**2) / 10**2 dat_sel = np.take(dat_list, sensor_ports) # 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) # *2 <-- change with actual formula for ammonia concentration # created a new array to convert resistance values to sci notation r_arr2 = np.empty(len(r_arr), dtype=object) diff --git a/requirements.txt b/requirements.txt index c8006ed..c1a5388 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,12 +1,6 @@ matplotlib pyserial wxPython -os requests -urllib.requests -zipfile -datetime -serial -time -json numpy +pyinstaller \ No newline at end of file diff --git a/sealammonia.fbp b/sealammonia.fbp index ca02bd8..2c93af7 100644 --- a/sealammonia.fbp +++ b/sealammonia.fbp @@ -1024,186 +1024,6 @@ - - 5 - 1 - 0 - wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT - 1 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - ADC bit rate - - 0 - - - 0 - - 1 - vadc_prompt - 1 - - - protected - 1 - - Resizable - 1 - - wxALIGN_RIGHT|wxST_ELLIPSIZE_END - ; ; forward_declare - 0 - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - 1 - 1 - wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL - 1 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - - 0 - - 1 - adjusted_volt - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - Bit size of the board's ADC, default is 12 bits (4096) minus 1 - - wxFILTER_NONE - wxDefaultValidator - - 4095 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 1 @@ -1351,7 +1171,7 @@ wxFILTER_NONE wxDefaultValidator - 480 + 50 @@ -1883,7 +1703,7 @@ 1 0 - 1 + 0 1 1 diff --git a/serial_plot.py b/serial_plot.py deleted file mode 100644 index e88a9ac..0000000 --- a/serial_plot.py +++ /dev/null @@ -1,69 +0,0 @@ -import matplotlib.pyplot as plt -import matplotlib.animation as animate -import math, json, traceback - -try: - import matplotlib - - matplotlib.use("WXAgg") # to force use one of the matplot's UI backend instead of an IDE's choice -except ImportError: - traceback.print_exc() - - -def plotter(): - a = json.load(open('settings.json', 'r')) - sensors = len(a['sensor_ports']) - windowsize = a['winSize'] - delay = a["delay"] / 1000 - file = open(a["file_name"], "r") - - colors = ['blue', 'orange', 'green', 'yellow'] - - fig, axs = plt.subplots(1, 1) - - timeStamps = [] - sensorsData = [] - - i = 0 - while i <= sensors: - sensorsData.append([]) - i = i + 1 - - def animation(t): - next_line = file.readline() - if next_line: - line = next_line.split(',') - if len(line) >= sensors: - i = 1 - timeStamps.append(line[0]) - # get rid of the zeroth value if it exceeds pre-defined window size - if windowsize != 0 and len(timeStamps) > windowsize: - timeStamps.pop(0) - val_lists = [] - while i <= sensors: - if not line[i]: # pass on invalid values - continue - sensorsData[i - 1].append(float(line[i])) # cast it to float so the y-axis will not jump around - # get rid of the zeroth value if it exceeds pre-defined window size - if windowsize != 0 and len(sensorsData[i - 1]) > windowsize: - sensorsData[i - 1].pop(0) - val_lists.append(sensorsData[i - 1]) - i += 1 - for j in range(len(val_lists)): - axs.plot(timeStamps, val_lists[j], color=colors[j], - label=f'sensor {j + 1}') # TODO: display sensor number to the actual arduino's port & - # axs.annotate('%0.2f' % val_lists[j][-1], xy=(1, val_lists[j][-1]), xytext=(8, 0), - # xycoords=('axes fraction', 'data'), textcoords='offset points') - - # Acknowledgement: https://stackoverflow.com/a/13589144 - handles, labels = plt.gca().get_legend_handles_labels() - by_label = dict(zip(labels, handles)) - axs.legend(by_label.values(), by_label.keys(), loc='best') - print(by_label.items()) - - return animate.FuncAnimation(plt.gcf(), func=animation) # , interval=delay * 500) - # ani.save("plot.gif") - # plt.ion() - # plt.show(block=True) - -# plotter() diff --git a/splash.png b/splash.png new file mode 100644 index 0000000..b9f6e02 Binary files /dev/null and b/splash.png differ diff --git a/test.py b/test.py index dfeca40..0ed72e9 100644 --- a/test.py +++ b/test.py @@ -29,9 +29,9 @@ def main(): r_ref[r_ref == ''] = '0' # correcting the emply values resistors = r_ref.astype(np.float32).tolist() # convert string to numbers input_voltage = float(frame.input_voltage.GetValue()) - bit_rate = float(frame.adjusted_volt.GetValue()) + # bit_rate = float(frame.adjusted_volt.GetValue()) port = frame.dev_list.GetValue() - # typical window size: 480 + # typical window size: 50 window_size = int(frame.m_textCtrl26.GetValue()) #################### END USER INPUTS ######################## @@ -46,10 +46,10 @@ def main(): if not (len(resistors) == 5): raise ValueError(f"expecting 5 resistor values, but got {len(resistors)}!!!") - gen_settings(resistors, input_voltage, bit_rate, port, filename, window_size, delay) + gen_settings(resistors, input_voltage, port, filename, window_size, delay) -def gen_settings(resistors, input_voltage, bits, port, filename, window_size, delay): +def gen_settings(resistors, input_voltage, port, filename, window_size, delay): """ export all inputs from main() to a .json file :param resistors: list of reference resistances of the sensors @@ -66,7 +66,7 @@ def gen_settings(resistors, input_voltage, bits, port, filename, window_size, de settings["sensor_ports"] = np.where(np.array(resistors) > 0)[0].tolist() settings["v_in"] = input_voltage settings["port"] = port - settings["resolution"] = bits + # settings["resolution"] = bits settings["winSize"] = window_size settings["file_name"] = filename settings["delay"] = delay @@ -104,7 +104,6 @@ if __name__ == '__main__': if sys.platform.startswith('win'): # On Windows calling this function is necessary. freeze_support() - #global t1 app = wx.App(useBestVisual=True) frame = Frame(None) app.SetTopWindow(frame) @@ -115,7 +114,7 @@ if __name__ == '__main__': sys.stdout.write("this is an alpha version of the design. This debug terminal will be gone on official release\n") ports = [comport.device for comport in serial.tools.list_ports.comports()] # get all available ports frame.dev_list.AppendItems(ports) - frame.SetTitle("SeeDatResistance - Beta 0.1.0 RC2") + frame.SetTitle("SeeDatResistance - Beta 0.1.1") frame.btLaunch.Bind(wx.EVT_BUTTON, run) if os.path.isfile("settings.json"): try: @@ -126,7 +125,7 @@ if __name__ == '__main__': 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.adjusted_volt.SetValue(str(settings["resolution"])) frame.m_textCtrl26.SetValue(str(settings["winSize"])) if settings["port"] in ports: # auto-select device port if exist frame.dev_list.SetValue(settings["port"]) diff --git a/toplevel.py b/toplevel.py deleted file mode 100644 index 949bc50..0000000 --- a/toplevel.py +++ /dev/null @@ -1,183 +0,0 @@ -""" - Top level script to prompt user for inputs, and then make those input as a .json file so that other modules can use it. - to run stuff. This module can have the frontend UI merged into, or can have separate one but should be the first things - to call from frontend before running other stuff. -""" -from datetime import datetime -from threading import * -import os, json, sys, subprocess -import serial.tools.list_ports -import numpy as np -import tkinter as tk - -HEIGHT = 800 -WIDTH = 800 - - -def main(): - #################### USER INPUTS ########################### - # TODO: if there is already a setting.json exist, loads all inputs from there as 'default' - # 9840 - resistors = [int(text3.get()), int(text4.get()), 0, 0, 0] # resisters for each An port, where n is an integer from 0-3. Use 0 if none. in Ohms - input_voltage = 5 - adjusted_volt = 5 - port = get_devices()[0] - # typical window size: 480 - window_size = 480 - - #################### END USER INPUTS ######################## - - # filename, disable customize name but should inform the user the current name of the data file on the front end - # alternatively, could be default input if no other input given. But if there is might have problem... - 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) - return filename - - -def gen_settings(resistors, input_voltage, adjusted_volt, port, filename, resolution, window_size, delay): - name = "settings.json" - 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["port"] = port - settings["resolution"] = resolution - settings["winSize"] = window_size - settings["file_name"] = filename - settings["delay"] = delay - open(name, 'w').write(json.dumps(settings, indent=4)) - open(filename, "a", newline="", encoding="utf-8") - - -def get_devices(): - ports = [comport.device for comport in serial.tools.list_ports.comports()] # get all available ports - if not ports: - raise ConnectionError("No devices detected!") # TODO: set to writerandomvalues.py thing instead raise error - return ports - - -# for scheduler maybe? -def task1(): - print("run task 1") - # exec(open("read_arduino.py").read()) - 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) - running = True - init = 0 - while running: - cline = out2.stdout.readline() - print(cline.decode()) - if not cline and init > 0: - print(cline.decode()) - running = False - init += 1 - - if out2.returncode: - print('Something went wrong:', out2.returncode) - - -def test_func(): - file = main() - label['text'] = f"File has saved as {os.path.split(file)[1]} under {os.path.split(file)[0]} directory!\n" - t1 = Thread(target=task1, args=()) - t1.setDaemon(True) - t1.start() - - t2 = Thread(target=task2, args=()) - t2.setDaemon(True) - t2.start() - - -if __name__ == '__main__': - # file = main() - # print(f"File has saved as {os.path.split(file)[1]} under {os.path.split(file)[0]} directory!") - # t1 = Thread(target=task1, args=()) - # t1.setDaemon(True) - # t1.start() - # - # t2 = Thread(target=task2, args=()) - # t2.setDaemon(True) - # t2.start() - # # while True: - # # pass - # t1.join() - # t2.join() - root = tk.Tk() - - canvas = tk.Canvas(root, height=HEIGHT, width=WIDTH) - canvas.pack() - - # backgroud_image = tk.PhotoImage(file='im1.gif') - backIm = tk.Label(root, bg='#80c1ff') - backIm.place(relwidth=1, relheight=1) - - frame = tk.Frame(root, bg="#80c1ff", bd=5) - frame.place(relx=0.5, rely=0.1, relwidth=0.75, relheight=0.1, anchor='n') - - button1 = tk.Button(frame, text="update", font=50, fg='green', bg='grey', command=lambda: test_func()) - button1.place(relx=0.8, relheight=0.5, relwidth=0.2) - - button2 = tk.Button(frame, text="clear", font=50, fg='red', bg='grey') - button2.place(relx=0.8, rely=0.5, relheight=0.5, relwidth=0.2) - - lb1 = tk.Label(frame, text="filename") - lb1.place(relx=0.1, relheight=0.4, relwidth=0.2) - - text1 = tk.StringVar() - box1 = tk.Entry(frame, textvariable=text1) - box1.place(relx=0.1, rely=0.5, relheight=0.5, relwidth=0.2) - - lb2 = tk.Label(frame, text="num of sensor") - lb2.place(relx=0.3, relheight=0.4, relwidth=0.2) - - text2 = tk.StringVar() - box2 = tk.Entry(frame, textvariable=text2) - box2.place(relx=0.3, rely=0.5, relheight=0.5, relwidth=0.2) - - lb3 = tk.Label(frame, text="res1") - lb3.place(relx=0.5, relheight=0.4, relwidth=0.1) - - text3 = tk.StringVar() - box3 = tk.Entry(frame, textvariable=text3) - box3.place(relx=0.5, rely=0.5, relheight=0.5, relwidth=0.1) - - lb4 = tk.Label(frame, text="res2") - lb4.place(relx=0.6, relheight=0.4, relwidth=0.1) - - text4 = tk.StringVar() - box4 = tk.Entry(frame, textvariable=text4) - box4.place(relx=0.6, rely=0.5, relheight=0.5, relwidth=0.1) - - lower_frame = tk.Frame(root, bg="#80c1ff", bd=10) - lower_frame.place(relx=0.5, rely=0.25, relwidth=0.75, relheight=0.6, anchor='n') - - label = tk.Label(lower_frame, font=40) - label.place(relwidth=1, relheight=1) - - root.mainloop() diff --git a/ui.py b/ui.py index e3deca0..d561251 100644 --- a/ui.py +++ b/ui.py @@ -8,6 +8,7 @@ ########################################################################### import wx +import wx.xrc ########################################################################### ## Class Frame @@ -16,7 +17,7 @@ import wx class Frame ( wx.Frame ): def __init__( self, parent ): - wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 470,337 ), style = wx.DEFAULT_FRAME_STYLE ) + wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 470,330 ), style = wx.DEFAULT_FRAME_STYLE ) self.SetSizeHintsSz( wx.Size( 470,330 ), wx.DefaultSize ) self.SetForegroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNTEXT ) ) @@ -32,11 +33,11 @@ class Frame ( wx.Frame ): self.r1_prompt = wx.StaticText( ref_entre.GetStaticBox(), wx.ID_ANY, u"Resistor 1", wx.DefaultPosition, wx.DefaultSize, 0 ) self.r1_prompt.Wrap( -1 ) res_grid.Add( self.r1_prompt, 0, wx.ALIGN_BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, 5 ) - + self.r2_prompt = wx.StaticText( ref_entre.GetStaticBox(), wx.ID_ANY, u"Resistor 2", wx.DefaultPosition, wx.DefaultSize, 0 ) self.r2_prompt.Wrap( -1 ) res_grid.Add( self.r2_prompt, 0, wx.ALIGN_BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, 5 ) - + self.r3_prompt = wx.StaticText( ref_entre.GetStaticBox(), wx.ID_ANY, u"Resistor 3", wx.DefaultPosition, wx.DefaultSize, 0 ) self.r3_prompt.Wrap( -1 ) res_grid.Add( self.r3_prompt, 0, wx.ALIGN_BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, 5 ) @@ -78,15 +79,6 @@ class Frame ( wx.Frame ): 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 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"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 ) self.sizer_prompt.Wrap( -1 ) gbSizer8.Add( self.sizer_prompt, wx.GBPosition( 2, 0 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, 5 ) @@ -140,7 +132,6 @@ 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 )