kopia lustrzana https://github.com/micropython/micropython
Merge f27593e960
into 7b050b366b
commit
a85089a8aa
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 84 KiB Po Szerokość: | Wysokość: | Rozmiar: 51 KiB |
|
@ -25,7 +25,11 @@ Running ``pyboard.py --help`` gives the following output:
|
|||
.. code-block:: text
|
||||
|
||||
usage: pyboard [-h] [-d DEVICE] [-b BAUDRATE] [-u USER] [-p PASSWORD]
|
||||
[-c COMMAND] [-w WAIT] [--follow | --no-follow] [-f]
|
||||
[-c COMMAND] [-w WAIT] [--follow | --no-follow]
|
||||
|
||||
|
||||
|
||||
[-f]
|
||||
[files [files ...]]
|
||||
|
||||
Run scripts on the pyboard.
|
||||
|
@ -48,6 +52,10 @@ Running ``pyboard.py --help`` gives the following output:
|
|||
available
|
||||
--follow follow the output after running the scripts
|
||||
[default if no scripts given]
|
||||
--no-soft-reset Prevent performing a soft reset when connecting to MCU
|
||||
--hard-reset pulse the MCU reset pin to hard-reset the MCU (if your
|
||||
serial connection wires RTS to reset pin properly)
|
||||
--no-exclusive Open the serial device shared (not exclusive) access
|
||||
-f, --filesystem perform a filesystem action: cp local :device | cp
|
||||
:device local | cat path | ls [path] | rm path | mkdir
|
||||
path | rmdir path
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"deploy": [
|
||||
"../deploy.md"
|
||||
],
|
||||
"docs": "",
|
||||
"features": [
|
||||
"External Flash",
|
||||
"WiFi"
|
||||
],
|
||||
"images": [
|
||||
"esp32_cam.jpg"
|
||||
],
|
||||
"mcu": "esp32",
|
||||
"product": "ESP32 / CAM",
|
||||
"thumbnail": "",
|
||||
"url": "https://www.espressif.com/en/products/modules",
|
||||
"variants": {
|
||||
"IDF3": "Compiled with IDF 3.x",
|
||||
"D2WD": "ESP32 D2WD",
|
||||
"SPIRAM": "Support for SPIRAM / WROVER",
|
||||
"UNICORE": "ESP32 Unicore",
|
||||
"OTA": "Support for OTA"
|
||||
},
|
||||
"vendor": "Espressif"
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
The following files are firmware that work on the ESP32 CAM module using
|
||||
an OV2640 camera.
|
||||
|
||||
ESP32 CAM has PSRAM (aka spiram) but the ESP32-S chip on it does not support bluetooth
|
||||
|
||||
To build this from source, load your env vars:-
|
||||
|
||||
. $HOME/esp/esp-idf/export.sh
|
||||
|
||||
Open a shell in the folder micropython/ports/esp32
|
||||
|
||||
and run this command:-
|
||||
|
||||
git clone https://github.com/lemariva/micropython-camera-driver.git
|
||||
git clone https://github.com/espressif/esp32-camera
|
||||
make BOARD=ESP32_CAM submodules
|
||||
make USER_C_MODULES=../micropython-camera-driver/src/micropython.cmake BOARD=ESP32_CAM all
|
||||
|
||||
-or- (for ota support):-
|
||||
|
||||
make USER_C_MODULES=../micropython-camera-driver/src/micropython.cmake BOARD=ESP32_CAM MICROPY_BOARD_VARIANT=OTA
|
||||
|
||||
then flash is like this:-
|
||||
|
||||
esptool.py -p $PORT write_flash --flash_mode dio --flash_size 4MB --flash_freq 40m 0x1000 build-ESP32_CAM/bootloader/bootloader.bin 0x8000 build-ESP32_CAM/partition_table/partition-table.bin 0x10000 build-ESP32_CAM/micropython.bin
|
||||
|
||||
Note that these boards wire RTS and DSR to reset and gpio0 pins, so you need the fixed pyboard.py that includes the --hard-reset to talk to them. For example:-
|
||||
|
||||
pyboard.py --device $PORT --hard-reset -f ls
|
|
@ -0,0 +1,44 @@
|
|||
set(SDKCONFIG_DEFAULTS
|
||||
boards/sdkconfig.base
|
||||
boards/sdkconfig.spiram
|
||||
)
|
||||
|
||||
# boards/sdkconfig.ble
|
||||
# boards/ESP32_CAM/sdkconfig.esp32cam
|
||||
|
||||
list(APPEND MICROPY_DEF_BOARD
|
||||
MICROPY_HW_MCU_NAME="ESP32"
|
||||
# Disable some options to reduce firmware size.
|
||||
# MICROPY_OPT_COMPUTED_GOTO=0
|
||||
# MICROPY_PY_NETWORK_LAN=0
|
||||
# ESP32-CAMERA
|
||||
CONFIG_OV2640_SUPPORT=y
|
||||
MICROPY_HW_BOARD_NAME="ESP32S CAM module with SPIRAM and OV2640"
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=n
|
||||
CONFIG_COMPILER_OPTIMIZATION_PERF=y
|
||||
)
|
||||
|
||||
|
||||
if(MICROPY_BOARD_VARIANT STREQUAL "OTA")
|
||||
set(SDKCONFIG_DEFAULTS
|
||||
${SDKCONFIG_DEFAULTS}
|
||||
boards/ESP32_GENERIC/sdkconfig.ota
|
||||
)
|
||||
|
||||
list(APPEND MICROPY_DEF_BOARD
|
||||
MICROPY_HW_BOARD_NAME="Generic ESP32 module with OTA"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
if(MICROPY_BOARD_VARIANT STREQUAL "UNICORE")
|
||||
set(SDKCONFIG_DEFAULTS
|
||||
${SDKCONFIG_DEFAULTS}
|
||||
boards/ESP32_GENERIC/sdkconfig.unicore
|
||||
)
|
||||
|
||||
list(APPEND MICROPY_DEF_BOARD
|
||||
MICROPY_HW_MCU_NAME="ESP32-UNICORE"
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,13 @@
|
|||
// Both of these can be set by mpconfigboard.cmake if a BOARD_VARIANT is
|
||||
// specified.
|
||||
|
||||
#ifndef MICROPY_HW_BOARD_NAME
|
||||
#define MICROPY_HW_BOARD_NAME "ESP32S CAM module with PSRAM and OV2640"
|
||||
#endif
|
||||
|
||||
#define MICROPY_PY_BLUETOOTH (0)
|
||||
#define MODULE_CAMERA_ENABLED (1)
|
||||
|
||||
#ifndef MICROPY_HW_MCU_NAME
|
||||
#define MICROPY_HW_MCU_NAME "ESP32"
|
||||
#endif
|
|
@ -0,0 +1,171 @@
|
|||
# photo.py
|
||||
|
||||
__version__ = "1.0.3" # Major.Minor.Patch
|
||||
|
||||
# Ways to run this program:-
|
||||
|
||||
# 1. With ampy
|
||||
# ampy --port $PORT run bin/photo.py
|
||||
# example output:-
|
||||
# photo fn=out.jpg size=22((default)) quality=10
|
||||
# Length of buf: 23579
|
||||
|
||||
# 2. From REPL shell
|
||||
# >>> ARGV=["pic.jpg","5","10"];exec(open("bin/photo.py").read())
|
||||
# example output:-
|
||||
# photo fn=pic.jpg size=5(FRAME_QVGA) quality=10
|
||||
# Length of buf: 9495
|
||||
|
||||
# 3. using mipyshell
|
||||
# To run this program with arguments, install https://github.com/vsolina/mipyshell
|
||||
# and save this file as bin/photo.py - then (for size 5 and quality 10):-
|
||||
# photo outfile.jpg 5 10
|
||||
|
||||
|
||||
import camera
|
||||
|
||||
|
||||
def __main__(args):
|
||||
capture(args[2:]) # mipyshell first 2 arguments are "python" and "photo.py"
|
||||
|
||||
|
||||
def capture(args):
|
||||
fn = "out.jpg"
|
||||
quality = 10
|
||||
size = 22
|
||||
|
||||
camera_frames = {
|
||||
0: {"name": "FRAME_96X96", "value": camera.FRAME_96X96},
|
||||
1: {"name": "FRAME_QQVGA", "value": camera.FRAME_QQVGA},
|
||||
2: {"name": "FRAME_QCIF", "value": camera.FRAME_QCIF},
|
||||
3: {"name": "FRAME_HQVGA", "value": camera.FRAME_HQVGA},
|
||||
4: {"name": "FRAME_240X240", "value": camera.FRAME_240X240},
|
||||
5: {"name": "FRAME_QVGA", "value": camera.FRAME_QVGA},
|
||||
6: {"name": "FRAME_CIF", "value": camera.FRAME_CIF},
|
||||
7: {"name": "FRAME_HVGA", "value": camera.FRAME_HVGA},
|
||||
8: {"name": "FRAME_VGA", "value": camera.FRAME_VGA},
|
||||
9: {"name": "FRAME_SVGA", "value": camera.FRAME_SVGA},
|
||||
10: {"name": "FRAME_XGA", "value": camera.FRAME_XGA},
|
||||
11: {"name": "FRAME_HD", "value": camera.FRAME_HD},
|
||||
12: {"name": "FRAME_SXGA", "value": camera.FRAME_SXGA},
|
||||
13: {"name": "FRAME_UXGA", "value": camera.FRAME_UXGA},
|
||||
14: {"name": "FRAME_FHD", "value": camera.FRAME_FHD},
|
||||
15: {"name": "FRAME_P_HD", "value": camera.FRAME_P_HD},
|
||||
16: {"name": "FRAME_P_3MP", "value": camera.FRAME_P_3MP},
|
||||
17: {"name": "FRAME_QXGA", "value": camera.FRAME_QXGA},
|
||||
18: {"name": "FRAME_QHD", "value": camera.FRAME_QHD},
|
||||
19: {"name": "FRAME_WQXGA", "value": camera.FRAME_WQXGA},
|
||||
20: {"name": "FRAME_P_FHD", "value": camera.FRAME_P_FHD},
|
||||
21: {"name": "FRAME_QSXGA", "value": camera.FRAME_QSXGA},
|
||||
22: {"name": "(default)", "value": None},
|
||||
}
|
||||
|
||||
if len(args) > 0:
|
||||
fn = args[0]
|
||||
|
||||
## ESP32-CAM (default configuration) - https://bit.ly/2Ndn8tN
|
||||
camera.init(0, format=camera.JPEG, fb_location=camera.PSRAM)
|
||||
|
||||
if len(args) > 1:
|
||||
size = int(args[1])
|
||||
camera.framesize(camera_frames[size]["value"])
|
||||
|
||||
if len(args) > 2:
|
||||
quality = int(args[2])
|
||||
camera.quality(quality)
|
||||
|
||||
print(
|
||||
"photo fn={} size={}({}) quality={}".format(fn, size, camera_frames[size]["name"], quality)
|
||||
)
|
||||
|
||||
# AI-Thinker esp32-cam board
|
||||
# ai_thinker = {PIN_PWDN:32, PIN_RESET:-1, PIN_XCLK:0, PIN_SIOD:26, PIN_SIOC:27, PIN_D7:35, PIN_D6:34, PIN_D5:39, PIN_D4:36, PIN_D3:21, PIN_D2:19, PIN_D1:18, PIN_D0:5, PIN_VSYNC:25, PIN_HREF:23, PIN_PCLK:22, XCLK_MHZ:16, PIXFORMAT:5, FRAMESIZE:10, JPEG_QUALITY:10, FB_COUNT:1, }
|
||||
|
||||
## M5Camera (Version B) - https://bit.ly/317Xb74
|
||||
# camera.init(0, d0=32, d1=35, d2=34, d3=5, d4=39, d5=18, d6=36, d7=19, format=camera.JPEG, framesize=camera.FRAME_VGA, xclk_freq=camera.XCLK_10MHz, href=26, vsync=25, reset=15, sioc=23, siod=22, xclk=27, pclk=21, fb_location=camera.PSRAM) #M5CAMERA
|
||||
|
||||
## T-Camera Mini (green PCB) - https://bit.ly/31H1aaF
|
||||
# import axp202 # source https://github.com/lewisxhe/AXP202_PythonLibrary
|
||||
# USB current limit must be disabled (otherwise init fails)
|
||||
# axp=axp202.PMU( scl=22, sda=21, address=axp202.AXP192_SLAVE_ADDRESS )
|
||||
# limiting=axp.read_byte( axp202.AXP202_IPS_SET )
|
||||
# limiting &= 0xfc
|
||||
# axp.write_byte( axp202.AXP202_IPS_SET, limiting )
|
||||
|
||||
# camera.init(0, d0=5, d1=14, d2=4, d3=15, d4=18, d5=23, d6=36, d7=39, format=camera.JPEG, framesize=camera.FRAME_VGA, xclk_freq=camera.XCLK_20MHz, href=25, vsync=27, reset=-1, pwdn=-1, sioc=12, siod=13, xclk=32, pclk=19)
|
||||
|
||||
# The parameters: format=camera.JPEG, xclk_freq=camera.XCLK_10MHz are standard for all cameras.
|
||||
# You can try using a faster xclk (20MHz), this also worked with the esp32-cam and m5camera
|
||||
# but the image was pixelated and somehow green.
|
||||
|
||||
# ## Other settings:
|
||||
# # flip up side down
|
||||
# camera.flip(1)
|
||||
# # left / right
|
||||
# camera.mirror(1)
|
||||
|
||||
# # framesize
|
||||
# camera.framesize(camera.FRAME_240x240)
|
||||
# # The options are the following:
|
||||
# # FRAME_96X96 FRAME_QQVGA FRAME_QCIF FRAME_HQVGA FRAME_240X240
|
||||
# # FRAME_QVGA FRAME_CIF FRAME_HVGA FRAME_VGA FRAME_SVGA
|
||||
# # FRAME_XGA FRAME_HD FRAME_SXGA FRAME_UXGA FRAME_FHD
|
||||
# # FRAME_P_HD FRAME_P_3MP FRAME_QXGA FRAME_QHD FRAME_WQXGA
|
||||
# # FRAME_P_FHD FRAME_QSXGA
|
||||
# # Check this link for more information: https://bit.ly/2YOzizz
|
||||
#
|
||||
# # special effects
|
||||
# camera.speffect(camera.EFFECT_NONE)
|
||||
# # The options are the following:
|
||||
# # EFFECT_NONE (default) EFFECT_NEG EFFECT_BW EFFECT_RED EFFECT_GREEN EFFECT_BLUE EFFECT_RETRO
|
||||
#
|
||||
# # white balance
|
||||
# camera.whitebalance(camera.WB_NONE)
|
||||
# # The options are the following:
|
||||
# # WB_NONE (default) WB_SUNNY WB_CLOUDY WB_OFFICE WB_HOME
|
||||
#
|
||||
# # saturation
|
||||
# camera.saturation(0)
|
||||
# # -2,2 (default 0). -2 grayscale
|
||||
#
|
||||
# # brightness
|
||||
# camera.brightness(0)
|
||||
# # -2,2 (default 0). 2 brightness
|
||||
#
|
||||
# # contrast
|
||||
# camera.contrast(0)
|
||||
# #-2,2 (default 0). 2 highcontrast
|
||||
#
|
||||
# # quality
|
||||
# camera.quality(10)
|
||||
# # 10-63 lower number means higher quality
|
||||
#
|
||||
|
||||
buf = camera.capture()
|
||||
|
||||
if buf:
|
||||
print("Length of buf:", len(buf))
|
||||
|
||||
if fn:
|
||||
with open(fn, "wb") as f:
|
||||
f.write(buf)
|
||||
else:
|
||||
print("not written - no filename given")
|
||||
# print("Contents of buf in hex:", buf.hex())
|
||||
|
||||
else:
|
||||
print("Capture failed (too big for PSRAM?")
|
||||
|
||||
# print("open http://esp32-cam-05.local/foo.jpg")
|
||||
|
||||
camera.deinit()
|
||||
|
||||
|
||||
try:
|
||||
# if 'ARGV' in locals():
|
||||
eval(
|
||||
"capture(ARGV)"
|
||||
) # ARGV is supplied by caller thusly: ARGV=["pic.jpg","5","10"];exec(open("bin/photo.py").read())
|
||||
except: # Exception as e:
|
||||
# print(e) # name 'ARGV' isn't defined
|
||||
capture([])
|
|
@ -0,0 +1,17 @@
|
|||
# Optimise using -Os to reduce size
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_PERF=n
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
|
||||
# Change maximum log level to error, to reduce firmware size.
|
||||
CONFIG_LOG_MAXIMUM_LEVEL_ERROR=y
|
||||
CONFIG_LOG_MAXIMUM_LEVEL_INFO=n
|
||||
|
||||
# Disable SPI Ethernet driver to reduce firmware size.
|
||||
CONFIG_ETH_USE_SPI_ETHERNET=n
|
||||
|
||||
CONFIG_ESPTOOLPY_FLASHMODE_DIO=y
|
||||
CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-2MiB.csv"
|
|
@ -0,0 +1,7 @@
|
|||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-4MiB-ota.csv"
|
||||
|
||||
# Reduce firmware size to fit in the OTA partition.
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_PERF=n
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_FREERTOS_UNICORE=y
|
|
@ -265,7 +265,14 @@ class ProcessPtyToTerminal:
|
|||
|
||||
class Pyboard:
|
||||
def __init__(
|
||||
self, device, baudrate=115200, user="micro", password="python", wait=0, exclusive=True
|
||||
self,
|
||||
device,
|
||||
baudrate=115200,
|
||||
user="micro",
|
||||
password="python",
|
||||
wait=0,
|
||||
exclusive=True,
|
||||
hard_reset=False,
|
||||
):
|
||||
self.in_raw_repl = False
|
||||
self.use_raw_paste = True
|
||||
|
@ -281,7 +288,7 @@ class Pyboard:
|
|||
import serial.tools.list_ports
|
||||
|
||||
# Set options, and exclusive if pyserial supports it
|
||||
serial_kwargs = {"baudrate": baudrate, "interCharTimeout": 1}
|
||||
serial_kwargs = {"baudrate": baudrate, "interCharTimeout": 1, "rtscts": 0, "dsrdtr": 0}
|
||||
if serial.__version__ >= "3.3":
|
||||
serial_kwargs["exclusive"] = exclusive
|
||||
|
||||
|
@ -300,7 +307,28 @@ class Pyboard:
|
|||
self.serial.rts = False # RTS False = EN High = MCU enabled
|
||||
self.serial.open()
|
||||
else:
|
||||
self.serial = serial.Serial(device, **serial_kwargs)
|
||||
#self.serial = serial.Serial(device, **serial_kwargs)
|
||||
#Cannot do serial.Serial(device...) because below is only way to block a high-pulse on rts
|
||||
self.serial = serial.Serial()
|
||||
self.serial.dtr = False # DTR False = gpio0 High = Normal boot
|
||||
self.serial.rts = False # RTS False = EN High = MCU enabled
|
||||
self.serial.port = device
|
||||
self.serial.baudrate = serial_kwargs["baudrate"]
|
||||
self.serial.rtscts = 0
|
||||
self.serial.dsrdtr = 0
|
||||
self.serial.inter_byte_timeout = serial_kwargs["interCharTimeout"]
|
||||
self.serial.exclusive = serial_kwargs["exclusive"]
|
||||
self.serial.open()
|
||||
|
||||
|
||||
if hard_reset:
|
||||
time.sleep(0.2)
|
||||
# this is reset (setting this "high" resets the MCU)
|
||||
self.serial.rts = True
|
||||
time.sleep(0.2)
|
||||
self.serial.rts = False
|
||||
# must wait for the reset, otherwise the ctrl-A gets lost
|
||||
time.sleep(2.0)
|
||||
break
|
||||
except (OSError, IOError): # Py2 and Py3 have different errors
|
||||
if wait == 0:
|
||||
|
@ -325,7 +353,10 @@ class Pyboard:
|
|||
# if data_consumer is used then data is not accumulated and the ending must be 1 byte long
|
||||
assert data_consumer is None or len(ending) == 1
|
||||
|
||||
data = self.serial.read(min_num_bytes)
|
||||
if min_num_bytes > 0:
|
||||
data = self.serial.read(min_num_bytes)
|
||||
else:
|
||||
data = b""
|
||||
if data_consumer:
|
||||
data_consumer(data)
|
||||
timeout_count = 0
|
||||
|
@ -356,10 +387,17 @@ class Pyboard:
|
|||
self.serial.read(n)
|
||||
n = self.serial.inWaiting()
|
||||
|
||||
self.serial.write(b"\r\x01") # ctrl-A: enter raw REPL
|
||||
retry = 10
|
||||
while retry > 0: # resend every 1s (sends get lost while resetting)
|
||||
retry = retry - 1
|
||||
self.serial.write(b"\r\x01\x01") # ctrl-A: enter raw REPL (needs 2)
|
||||
data = self.read_until(0, b"raw REPL; CTRL-B to exit\r\n>", timeout=1)
|
||||
if data.endswith(b"raw REPL; CTRL-B to exit\r\n>"):
|
||||
retry = 0
|
||||
else:
|
||||
time.sleep(0.1)
|
||||
|
||||
if soft_reset:
|
||||
data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n>")
|
||||
if not data.endswith(b"raw REPL; CTRL-B to exit\r\n>"):
|
||||
print(data)
|
||||
raise PyboardError("could not enter raw repl")
|
||||
|
@ -374,7 +412,7 @@ class Pyboard:
|
|||
print(data)
|
||||
raise PyboardError("could not enter raw repl")
|
||||
|
||||
data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n")
|
||||
data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n", timeout=1)
|
||||
if not data.endswith(b"raw REPL; CTRL-B to exit\r\n"):
|
||||
print(data)
|
||||
raise PyboardError("could not enter raw repl")
|
||||
|
@ -783,6 +821,12 @@ def main():
|
|||
cmd_parser.add_argument("-u", "--user", default="micro", help="the telnet login username")
|
||||
cmd_parser.add_argument("-p", "--password", default="python", help="the telnet login password")
|
||||
cmd_parser.add_argument("-c", "--command", help="program passed in as string")
|
||||
cmd_parser.add_argument(
|
||||
"--hard-reset",
|
||||
action="store_true",
|
||||
dest="hard_reset",
|
||||
help="Perform a hard reset when connecting to the board (requires your serial programmer to properly wire RTS pin to reset)",
|
||||
)
|
||||
cmd_parser.add_argument(
|
||||
"-w",
|
||||
"--wait",
|
||||
|
@ -801,6 +845,7 @@ def main():
|
|||
"--no-soft-reset",
|
||||
action="store_false",
|
||||
dest="soft_reset",
|
||||
help="Whether to perform a soft reset when connecting to the board [default]",
|
||||
)
|
||||
group = cmd_parser.add_mutually_exclusive_group()
|
||||
group.add_argument(
|
||||
|
@ -839,7 +884,13 @@ def main():
|
|||
# open the connection to the pyboard
|
||||
try:
|
||||
pyb = Pyboard(
|
||||
args.device, args.baudrate, args.user, args.password, args.wait, args.exclusive
|
||||
args.device,
|
||||
args.baudrate,
|
||||
args.user,
|
||||
args.password,
|
||||
args.wait,
|
||||
args.exclusive,
|
||||
hard_reset=args.hard_reset,
|
||||
)
|
||||
except PyboardError as er:
|
||||
print(er)
|
||||
|
|
Ładowanie…
Reference in New Issue