Skip to content

Commit 4cb756b

Browse files
committed
v1.6.1
1 parent 1903cf1 commit 4cb756b

File tree

4 files changed

+186
-31
lines changed

4 files changed

+186
-31
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,18 @@ The selected firmware is then uploaded to the connected SparkFun RTK product. Up
3333

3434
![Firmware Upload](images/RTK_Uploader_Windows.gif)
3535

36+
## Extras
37+
38+
From version 1.6.1, the ```Extras``` pull-down menu contains options to: read the ESP32 WiFi MAC address; reset the ESP32; erase the ESP32.
39+
3640
## Reset ESP32
3741

3842
Clicking the ```Reset ESP32``` button will reset the ESP32 processor. This is helpful when the firmware update succeeds but does not reset the RTK correctly.
3943
If your RTK 'freezes' after the update, pressing ```Reset ESP32``` will get it going again.
4044

41-
![Reset ESP32](images/RTK_Uploader_Windows_3.png)
45+
**Note:** from version 1.6.1, ```Reset ESP32``` can be found in the ```Extras``` pull-down menu.
4246

47+
![Reset ESP32](images/RTK_Uploader_Windows_3.png)
4348

4449
## Installation
4550

RTK_Firmware_Uploader/RTK_Firmware_Uploader.py

Lines changed: 143 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
# import action things - the .syntax is used since these are part of the package
1111
from .au_worker import AUxWorker
1212
from .au_action import AxJob
13-
from .au_act_esptool import AUxEsptoolDetectFlash, AUxEsptoolUploadFirmware, AUxEsptoolResetESP32
13+
from .au_act_esptool import AUxEsptoolDetectFlash, AUxEsptoolUploadFirmware, AUxEsptoolResetESP32, \
14+
AUxEsptoolEraseFlash, AUxEsptoolReadMAC
1415

1516
import darkdetect
1617
import sys
@@ -116,10 +117,33 @@ class MainWidget(QWidget):
116117
sig_message = pyqtSignal(str)
117118
sig_finished = pyqtSignal(int, str, int)
118119

120+
def _createMenuBar(self):
121+
self.menuBar = QMenuBar(self)
122+
123+
self.extrasReadMACAction = QAction("Read WiFi MAC", self)
124+
self.extrasResetAction = QAction("Reset ESP32", self)
125+
self.extrasEraseAction = QAction("Erase Flash", self)
126+
127+
extrasMenu = self.menuBar.addMenu("Extras")
128+
extrasMenu.addAction(self.extrasReadMACAction)
129+
extrasMenu.addAction(self.extrasResetAction)
130+
extrasMenu.addAction(self.extrasEraseAction)
131+
132+
self.extrasReadMACAction.triggered.connect(self.readMAC)
133+
self.extrasResetAction.triggered.connect(self.tera_term_reset)
134+
self.extrasEraseAction.triggered.connect(self.eraseChip)
135+
136+
self.extrasReadMACAction.setDisabled(False)
137+
self.extrasResetAction.setDisabled(False)
138+
self.extrasEraseAction.setDisabled(False)
139+
119140
def __init__(self, parent: QWidget = None) -> None:
120141
super().__init__(parent)
121142

122143
self.flashSize = 0
144+
self.macAddress = "UNKNOWN"
145+
146+
self._createMenuBar()
123147

124148
# File location line edit
125149
self.file_label = QLabel(self.tr('Firmware File:'))
@@ -152,10 +176,6 @@ def __init__(self, parent: QWidget = None) -> None:
152176
self.update_com_ports()
153177
self.port_combobox.popupAboutToBeShown.connect(self.on_port_combobox)
154178

155-
# Reset Button
156-
self.reset_btn = QPushButton(self.tr('Reset ESP32'))
157-
self.reset_btn.clicked.connect(self.tera_term_reset)
158-
159179
# Baudrate Combobox
160180
self.baud_label = QLabel(self.tr('Baud Rate:'))
161181
self.baud_combobox = QComboBox()
@@ -181,25 +201,26 @@ def __init__(self, parent: QWidget = None) -> None:
181201

182202
# Arrange Layout
183203
layout = QGridLayout()
184-
185-
layout.addWidget(self.file_label, 1, 0)
186-
layout.addWidget(self.fileLocation_lineedit, 1, 1)
187-
layout.addWidget(self.browse_btn, 1, 2)
188204

189-
# layout.addWidget(self.partition_label, 2, 0)
190-
# layout.addWidget(self.partitionFileLocation_lineedit, 2, 1)
191-
# layout.addWidget(self.partition_browse_btn, 2, 2)
205+
layout.addWidget(self.menuBar, 1, 0)
206+
207+
layout.addWidget(self.file_label, 2, 0)
208+
layout.addWidget(self.fileLocation_lineedit, 2, 1)
209+
layout.addWidget(self.browse_btn, 2, 2)
210+
211+
# layout.addWidget(self.partition_label, 3, 0)
212+
# layout.addWidget(self.partitionFileLocation_lineedit, 3, 1)
213+
# layout.addWidget(self.partition_browse_btn, 3, 2)
192214

193-
layout.addWidget(self.port_label, 2, 0)
194-
layout.addWidget(self.port_combobox, 2, 1)
195-
layout.addWidget(self.reset_btn, 2, 2)
215+
layout.addWidget(self.port_label, 3, 0)
216+
layout.addWidget(self.port_combobox, 3, 1)
196217

197-
layout.addWidget(self.baud_label, 3, 0)
198-
layout.addWidget(self.baud_combobox, 3, 1)
199-
layout.addWidget(self.upload_btn, 3, 2)
218+
layout.addWidget(self.baud_label, 4, 0)
219+
layout.addWidget(self.baud_combobox, 4, 1)
220+
layout.addWidget(self.upload_btn, 4, 2)
200221

201-
layout.addWidget(self.messages_label, 4, 0)
202-
layout.addWidget(self.messageBox, 5, 0, 5, 3)
222+
layout.addWidget(self.messages_label, 5, 0)
223+
layout.addWidget(self.messageBox, 6, 0, 6, 3)
203224

204225
self.setLayout(layout)
205226

@@ -222,7 +243,8 @@ def __init__(self, parent: QWidget = None) -> None:
222243

223244
# add the actions/commands for this app to the background processing thread.
224245
# These actions are passed jobs to execute.
225-
self._worker.add_action(AUxEsptoolDetectFlash(), AUxEsptoolUploadFirmware(), AUxEsptoolResetESP32())
246+
self._worker.add_action(AUxEsptoolDetectFlash(), AUxEsptoolUploadFirmware(), AUxEsptoolResetESP32(), \
247+
AUxEsptoolEraseFlash(), AUxEsptoolReadMAC())
226248

227249
#--------------------------------------------------------------
228250
# callback function for the background worker.
@@ -269,6 +291,10 @@ def appendMessage(self, msg: str) -> None:
269291
elif msg.find("Detected flash size: ") >= 0:
270292
self.flashSize = 0
271293

294+
macAddrPtr = msg.find("MAC: ")
295+
if macAddrPtr >= 0:
296+
self.macAddress = msg[macAddrPtr + len("MAC: "):]
297+
272298
@pyqtSlot(str)
273299
def writeMessage(self, msg: str) -> None:
274300
self.messageBox.moveCursor(QTextCursor.End)
@@ -287,18 +313,29 @@ def writeMessage(self, msg: str) -> None:
287313
@pyqtSlot(int, str, int)
288314
def on_finished(self, status, action_type, job_id) -> None:
289315

316+
# If the Read MAC is finished, re-enable the UX
317+
if action_type == AUxEsptoolReadMAC.ACTION_ID:
318+
self.writeMessage("Read MAC complete...")
319+
self.writeMessage("WiFi MAC Address is {}".format(self.macAddress))
320+
self.disable_interface(False)
321+
322+
# If the flash erase is finished, re-enable the UX
323+
if action_type == AUxEsptoolEraseFlash.ACTION_ID:
324+
self.writeMessage("Flash erase complete...")
325+
self.disable_interface(False)
326+
290327
# If the flash detection is finished, trigger the upload
291328
if action_type == AUxEsptoolDetectFlash.ACTION_ID:
292329
self.writeMessage("Flash detection complete. Uploading firmware...")
293330
self.do_upload()
294331

295332
# If the upload is finished, trigger a reset
296-
elif action_type == AUxEsptoolUploadFirmware.ACTION_ID:
333+
if action_type == AUxEsptoolUploadFirmware.ACTION_ID:
297334
self.writeMessage("Firmware upload complete. Resetting ESP32...")
298335
self.esptool_reset()
299336

300-
# re-enable the UX
301-
else:
337+
# If the reset is finished, re-enable the UX
338+
if action_type == AUxEsptoolResetESP32.ACTION_ID:
302339
self.writeMessage("Reset complete...")
303340
self.disable_interface(False)
304341

@@ -375,8 +412,7 @@ def update_baud_rates(self) -> None:
375412
# Highest speed first so code defaults to that
376413
# if settings.value(SETTING_BAUD_RATE) is None
377414
self.baud_combobox.clear()
378-
if (platform.system() != "Darwin"): # 921600 fails on MacOS
379-
self.baud_combobox.addItem("921600", 921600)
415+
self.baud_combobox.addItem("921600", 921600)
380416
self.baud_combobox.addItem("460800", 460800)
381417
self.baud_combobox.addItem("115200", 115200)
382418

@@ -444,7 +480,77 @@ def on_browse_btn_pressed(self) -> None:
444480
def disable_interface(self, bDisable=False):
445481

446482
self.upload_btn.setDisabled(bDisable)
447-
self.reset_btn.setDisabled(bDisable)
483+
self.extrasEraseAction.setDisabled(bDisable)
484+
self.extrasReadMACAction.setDisabled(bDisable)
485+
self.extrasResetAction.setDisabled(bDisable)
486+
487+
def eraseChip(self) -> None:
488+
"""Perform erase_flash"""
489+
portAvailable = False
490+
for desc, name, sys in gen_serial_ports():
491+
if (sys == self.port):
492+
portAvailable = True
493+
if (portAvailable == False):
494+
self.writeMessage("Port No Longer Available")
495+
return
496+
497+
try:
498+
self._save_settings() # Save the settings in case the command fails
499+
except:
500+
pass
501+
502+
self.writeMessage("Erasing flash\n\n")
503+
504+
command = []
505+
command.extend(["--chip","esp32"])
506+
command.extend(["--port",self.port])
507+
command.extend(["--before","default_reset"])
508+
command.extend(["erase_flash"])
509+
510+
# Create a job and add it to the job queue. The worker thread will pick this up and
511+
# process the job. Can set job values using dictionary syntax, or attribute assignments
512+
#
513+
# Note - the job is defined with the ID of the target action
514+
theJob = AxJob(AUxEsptoolEraseFlash.ACTION_ID, {"command":command})
515+
516+
# Send the job to the worker to process
517+
self._worker.add_job(theJob)
518+
519+
self.disable_interface(True)
520+
521+
def readMAC(self) -> None:
522+
"""Perform read_mac"""
523+
portAvailable = False
524+
for desc, name, sys in gen_serial_ports():
525+
if (sys == self.port):
526+
portAvailable = True
527+
if (portAvailable == False):
528+
self.writeMessage("Port No Longer Available")
529+
return
530+
531+
try:
532+
self._save_settings() # Save the settings in case the command fails
533+
except:
534+
pass
535+
536+
self.writeMessage("Reading WiFi MAC address\n\n")
537+
538+
command = []
539+
command.extend(["--chip","esp32"])
540+
command.extend(["--port",self.port])
541+
command.extend(["--before","default_reset"])
542+
command.extend(["read_mac"])
543+
544+
# Create a job and add it to the job queue. The worker thread will pick this up and
545+
# process the job. Can set job values using dictionary syntax, or attribute assignments
546+
#
547+
# Note - the job is defined with the ID of the target action
548+
theJob = AxJob(AUxEsptoolReadMAC.ACTION_ID, {"command":command})
549+
550+
# Send the job to the worker to process
551+
self._worker.add_job(theJob)
552+
553+
self.disable_interface(True)
448554

449555
def on_upload_btn_pressed(self) -> None:
450556
"""Get ready to upload the firmware. First, detect the flash size"""
@@ -468,7 +574,6 @@ def on_upload_btn_pressed(self) -> None:
468574
command = []
469575
command.extend(["--chip","esp32"])
470576
command.extend(["--port",self.port])
471-
command.extend(["--baud",self.baudRate])
472577
command.extend(["--before","default_reset","--after","no_reset"])
473578
command.extend(["flash_id"])
474579

@@ -550,11 +655,20 @@ def do_upload(self) -> None:
550655
sleep(1.0);
551656
self.writeMessage("Uploading firmware\n")
552657

658+
baud = self.baudRate
659+
if baud == "921600":
660+
if (platform.system() == "Darwin"): # 921600 fails on MacOS
661+
self.writeMessage("MacOS detected. Limiting baud to 460800\n")
662+
baud = "460800"
663+
if (str(self.port_combobox.currentText()).find("CH342") >= 0): # 921600 fails on CH342
664+
self.writeMessage("CH342 detected. Limiting baud to 460800\n")
665+
baud = "460800"
666+
553667
command = []
554668
#command.extend(["--trace"]) # Useful for debugging
555669
command.extend(["--chip","esp32"])
556670
command.extend(["--port",self.port])
557-
command.extend(["--baud",self.baudRate])
671+
command.extend(["--baud",baud])
558672
command.extend(["--before","default_reset","--after","no_reset","write_flash","-z","--flash_mode","dio","--flash_freq","80m","--flash_size","detect"])
559673
command.extend(["0x1000",resource_path("RTK_Surveyor.ino.bootloader.bin")])
560674
command.extend(["0x8000",thePartitionFileName])

RTK_Firmware_Uploader/au_act_esptool.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,42 @@
2424

2525
#--------------------------------------------------------------------------------------
2626
# action testing
27+
class AUxEsptoolReadMAC(AxAction):
28+
29+
ACTION_ID = "esptool-read-mac"
30+
NAME = "ESP32 Read MAC"
31+
32+
def __init__(self) -> None:
33+
super().__init__(self.ACTION_ID, self.NAME)
34+
35+
def run_job(self, job:AxJob):
36+
37+
try:
38+
esptool.main(job.command)
39+
40+
except Exception:
41+
return 1
42+
43+
return 0
44+
45+
class AUxEsptoolEraseFlash(AxAction):
46+
47+
ACTION_ID = "esptool-erase-flash"
48+
NAME = "ESP32 Flash Erase"
49+
50+
def __init__(self) -> None:
51+
super().__init__(self.ACTION_ID, self.NAME)
52+
53+
def run_job(self, job:AxJob):
54+
55+
try:
56+
esptool.main(job.command)
57+
58+
except Exception:
59+
return 1
60+
61+
return 0
62+
2763
class AUxEsptoolDetectFlash(AxAction):
2864

2965
ACTION_ID = "esptool-detect-flash"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.6.0"
1+
__version__ = "1.6.1"

0 commit comments

Comments
 (0)