add port selection
- add log view - interpolate string with code and DAC values
This commit is contained in:
46
README.md
46
README.md
@@ -2,4 +2,48 @@
|
||||
|
||||
install arduino-cli
|
||||
|
||||
https://arduino.github.io/arduino-cli/0.33/installation/
|
||||
https://arduino.github.io/arduino-cli/0.33/installation/
|
||||
|
||||
|
||||
### prerequisites
|
||||
|
||||
arduino-cli
|
||||
|
||||
python
|
||||
|
||||
pyinstaller
|
||||
|
||||
### install
|
||||
|
||||
pip install -r requirements.txt
|
||||
|
||||
### run
|
||||
|
||||
python hemocube.py
|
||||
|
||||
|
||||
### build
|
||||
|
||||
pyinstaller --noconfirm --noconsole -i "smi.ico" --windowed --clean hemocube.py
|
||||
|
||||
### build error
|
||||
|
||||
>fqdn error: replace the check with nano fqdn explictly.
|
||||
In Sketch.py of everywhereml/arduino replace line 167 and 228 with:
|
||||
|
||||
|
||||
self.fqbn = 'arduino:avr:nano:cpu=atmega328old'`
|
||||
|
||||
|
||||
>arduino library not found: manually copy all required libary in the same folder
|
||||
|
||||
|
||||
### installation after release
|
||||
|
||||
> first install the `arduino-cli.exe` and add it to path. verify it using terminal/cmd.
|
||||
|
||||
> then, connect the device and run the app exe. the port selection should have show an entry
|
||||
|
||||
> enter the values and select the port to upload the new dac values for QC
|
||||
|
||||
> the status will be show in the logging box. device will be ready, only if the upload sccuess is shown.
|
||||
214
hemocube.py
214
hemocube.py
@@ -1,5 +1,136 @@
|
||||
import sys
|
||||
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QLineEdit
|
||||
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QLineEdit, QPlainTextEdit, QComboBox, QMessageBox
|
||||
from PyQt5.QtCore import QProcess, QSize
|
||||
from everywhereml.arduino import Sketch, Ino, H
|
||||
import platform
|
||||
import os
|
||||
|
||||
class LogView(QPlainTextEdit):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setReadOnly(True)
|
||||
self._process = QProcess()
|
||||
self._process.readyReadStandardOutput.connect(self.handle_stdout)
|
||||
self._process.readyReadStandardError.connect(self.handle_stderr)
|
||||
|
||||
def start_log(self, program, arguments=None):
|
||||
if arguments is None:
|
||||
arguments = []
|
||||
self._process.start(program, arguments)
|
||||
|
||||
def add_log(self, message):
|
||||
self.appendPlainText(message.rstrip())
|
||||
|
||||
def handle_stdout(self):
|
||||
message = self._process.readAllStandardOutput().data().decode()
|
||||
self.add_log(message)
|
||||
|
||||
def handle_stderr(self):
|
||||
message = self._process.readAllStandardError().data().decode()
|
||||
self.add_log(message)
|
||||
|
||||
|
||||
def flash(log_view, led1, led2, port):
|
||||
"""
|
||||
Create a sketch object.
|
||||
A sketch is defined by:
|
||||
- a name (required)
|
||||
- a folder (optional)
|
||||
|
||||
If you leave the folder empty, the current working directory will be used.
|
||||
You can use the special name ':system:' to use the default Arduino sketches folder
|
||||
(as reported by the command `arduino-cli config dump`)
|
||||
"""
|
||||
|
||||
showdialog()
|
||||
|
||||
sketch = Sketch(name="hemocube", folder=":system:")
|
||||
|
||||
"""
|
||||
Then you can add files to the project (either the .ino main file or
|
||||
C++ header files)
|
||||
"""
|
||||
sketch += Ino("""
|
||||
|
||||
void setup() {{
|
||||
// put your setup code here, to run once:
|
||||
Serial.begin(115200);
|
||||
}}
|
||||
|
||||
void loop() {{
|
||||
// put your main code here, to run repeatedly:
|
||||
|
||||
|
||||
}}
|
||||
|
||||
|
||||
""".format(led1dac=led1, led2dac=led2))
|
||||
|
||||
sketch += H("hello.h", """
|
||||
void hello() {
|
||||
Serial.println("hello smi7");
|
||||
}
|
||||
""")
|
||||
|
||||
"""
|
||||
Compile sketch for Arduino Nano 33 BLE board.
|
||||
The board you target must appear in the `arduino-cli board listall` command.
|
||||
If you know the FQBN (Fully Qualified Board Name), you can use that too.
|
||||
"""
|
||||
if sketch.compile(board='arduino:avr:nano:cpu=atmega328old').is_successful:
|
||||
# log_view.add_log("Log: \n\n" + sketch.output)
|
||||
# log_view.add_log("Sketch stats: \n\n" + sketch.stats)
|
||||
print('Log', sketch.output)
|
||||
print('Sketch stats', sketch.stats)
|
||||
else:
|
||||
log_view.add_log("ERROR: \n\n" + sketch.output)
|
||||
print('ERROR', sketch.output)
|
||||
|
||||
"""
|
||||
You can specify the exact port
|
||||
"""
|
||||
# sketch.upload(port='/dev/cu.usbmodem14201')
|
||||
|
||||
sketch.upload(port=port)
|
||||
|
||||
# """
|
||||
# Or even part of it.
|
||||
# The library will look for the best match.
|
||||
# """
|
||||
# sketch.upload(port='ttyUSB')
|
||||
# sketch.upload(port='/dev/cu.usbserial-1420') #/dev/cu.usbmodem
|
||||
|
||||
log_view.add_log("upload: \n\n" + sketch.output)
|
||||
print(sketch.output)
|
||||
|
||||
def showdialog():
|
||||
msg = QMessageBox()
|
||||
msg.setIcon(QMessageBox.Information)
|
||||
|
||||
msg.setText("HemoCube flashing")
|
||||
msg.setInformativeText("HemoCube device will be flashed with new values")
|
||||
msg.setWindowTitle("Flashing")
|
||||
msg.setDetailedText("The LED dac values will be set. Wait for sometime.")
|
||||
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
|
||||
msg.buttonClicked.connect(msgbtn)
|
||||
|
||||
retval = msg.exec_()
|
||||
print("value of pressed message box button:", retval)
|
||||
|
||||
def msgbtn(i):
|
||||
print("Button pressed is:",i.text())
|
||||
|
||||
def get_port():
|
||||
ports = []
|
||||
if platform.system() == 'Darwin':
|
||||
ports = list(filter(lambda x: "cu" in x, os.listdir("/dev")))
|
||||
else:
|
||||
import serial.tools.list_ports
|
||||
# ports = ['COM%s' % (i + 1) for i in range(256)]
|
||||
serial_ports = list(serial.tools.list_ports.comports())
|
||||
for port, desc, hwid in sorted(serial_ports):
|
||||
ports.append(port)
|
||||
return ports
|
||||
|
||||
# 1. Import QApplication and all the required widgets
|
||||
# from PyQt5.QtWidgets import QApplication, QLabel, QWidget
|
||||
@@ -8,33 +139,74 @@ def addLabel(layout, text):
|
||||
layout.addWidget(QLabel(text))
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication([])
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
window = QWidget()
|
||||
layout = QVBoxLayout(window)
|
||||
# Create a label Widget and add it to the layout
|
||||
label = QLabel('Enter some text!')
|
||||
layout.addWidget(label)
|
||||
window = QWidget()
|
||||
layout = QVBoxLayout(window)
|
||||
|
||||
line_edit = QLineEdit()
|
||||
layout.addWidget(line_edit)
|
||||
# Create a label Widget and add it to the layout
|
||||
labelLed1 = QLabel('Enter LED1 value (1500-3000)')
|
||||
layout.addWidget(labelLed1)
|
||||
|
||||
# Create a QPushButton object with a caption on it
|
||||
qbtn= QPushButton('Add Label')
|
||||
line_edit_led1 = QLineEdit()
|
||||
line_edit_led1.setFixedSize(QSize(150, 30))
|
||||
layout.addWidget(line_edit_led1)
|
||||
|
||||
# Add the QPushButton to the layout
|
||||
layout.addWidget(qbtn)
|
||||
labelLed2 = QLabel('Enter LED2 value (1500-3000)')
|
||||
left = 0
|
||||
top = 25
|
||||
right = 0
|
||||
bottom = 0
|
||||
labelLed2.setContentsMargins(left, top, right, bottom)
|
||||
layout.addWidget(labelLed2)
|
||||
|
||||
line_edit_led2 = QLineEdit()
|
||||
line_edit_led2.setFixedSize(QSize(150, 30))
|
||||
layout.addWidget(line_edit_led2)
|
||||
|
||||
|
||||
labelPort = QLabel('Select a port')
|
||||
layout.addWidget(labelPort)
|
||||
|
||||
cb = QComboBox()
|
||||
cb.setFixedSize(QSize(150, 30))
|
||||
ports = get_port()
|
||||
for port in ports:
|
||||
cb.addItem(port)
|
||||
layout.addWidget(cb)
|
||||
|
||||
flash_port = ""
|
||||
def selectionchange(i):
|
||||
flash_port = cb.currentText()
|
||||
cb.currentIndexChanged.connect(selectionchange)
|
||||
|
||||
# Create a QPushButton object with a caption on it
|
||||
qbtn = QPushButton('Flash')
|
||||
qbtn.setFixedSize(QSize(150, 40))
|
||||
|
||||
# Add the QPushButton to the layout
|
||||
layout.addWidget(qbtn)
|
||||
|
||||
w = LogView()
|
||||
w.resize(640, 480)
|
||||
# w.show()
|
||||
# w.start_log("adb", ["logcat", "*:I"])
|
||||
# w.start_log("arduino-cli", ["monitor", "-p /dev/cu.Bluetooth-Incoming-Port"])
|
||||
# w.start_log("arduino-cli", ["lib", "install", "ADS1X15"])
|
||||
w.handle_stdout()
|
||||
layout.addWidget(w)
|
||||
|
||||
# Close the application when the button is pressed
|
||||
# Here I am using slots & signals, which I will demonstrate later in this tutorial
|
||||
qbtn.clicked.connect(lambda:addLabel(layout, line_edit.text()))
|
||||
# qbtn.clicked.connect(lambda:addLabel(layout, "Flashing..."))
|
||||
qbtn.clicked.connect(lambda:flash(w, line_edit_led1.text(), line_edit_led2.text(), flash_port))
|
||||
|
||||
window.setWindowTitle("PyQt App")
|
||||
window.setGeometry(100, 100, 280, 80)
|
||||
# helloMsg = QLabel("<h1>Hello, World!</h1>", parent=window)
|
||||
# helloMsg.move(60, 15)
|
||||
window.setWindowTitle("HemoCube QC")
|
||||
window.setGeometry(400, 400, 800, 600)
|
||||
# helloMsg = QLabel("<h1>Hello, World!</h1>", parent=window)
|
||||
# helloMsg.move(60, 15)
|
||||
|
||||
window.show()
|
||||
window.show()
|
||||
|
||||
# 5. Run your application's event loop
|
||||
sys.exit(app.exec())
|
||||
# 5. Run your application's event loop
|
||||
sys.exit(app.exec())
|
||||
|
||||
56
requirements.txt
Normal file
56
requirements.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
altgraph==0.17.3
|
||||
cached-property==1.5.2
|
||||
certifi==2023.5.7
|
||||
charset-normalizer==3.2.0
|
||||
contourpy==1.1.0
|
||||
cycler==0.11.0
|
||||
everywhereml==0.2.21
|
||||
fonttools==4.41.0
|
||||
hexdump==3.3
|
||||
idna==3.4
|
||||
imageio==2.31.1
|
||||
Jinja2==3.1.2
|
||||
jinja2-workarounds==0.1.0
|
||||
joblib==1.3.1
|
||||
kiwisolver==1.4.4
|
||||
lazy_loader==0.3
|
||||
llvmlite==0.40.1
|
||||
macholib==1.16.2
|
||||
MarkupSafe==2.1.3
|
||||
matplotlib==3.7.2
|
||||
networkx==3.1
|
||||
numba==0.57.1
|
||||
numpy==1.24.4
|
||||
packaging==23.1
|
||||
pandas==2.0.3
|
||||
pefile==2023.2.7
|
||||
Pillow==10.0.0
|
||||
pyinstaller==5.13.0
|
||||
pyinstaller-hooks-contrib==2023.5
|
||||
pynndescent==0.5.10
|
||||
pyparsing==3.0.9
|
||||
PyQt5==5.15.9
|
||||
PyQt5-Qt5==5.15.2
|
||||
PyQt5-sip==12.12.1
|
||||
PyQt6==6.5.1
|
||||
PyQt6-Qt6==6.5.1
|
||||
PyQt6-sip==13.5.1
|
||||
pyserial==3.5
|
||||
python-dateutil==2.8.2
|
||||
python-slugify==8.0.1
|
||||
pytz==2023.3
|
||||
pyudev==0.24.1
|
||||
PyWavelets==1.4.1
|
||||
requests==2.31.0
|
||||
scikit-image==0.21.0
|
||||
scikit-learn==1.3.0
|
||||
scipy==1.11.1
|
||||
seaborn==0.12.2
|
||||
six==1.16.0
|
||||
text-unidecode==1.3
|
||||
threadpoolctl==3.2.0
|
||||
tifffile==2023.7.10
|
||||
tqdm==4.65.0
|
||||
tzdata==2023.3
|
||||
umap-learn==0.5.3
|
||||
urllib3==2.0.3
|
||||
Reference in New Issue
Block a user