Chris Drake 2024-04-09 10:08:09 +10:00 zatwierdzone przez GitHub
commit 969969c36a
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
11 zmienionych plików z 375 dodań i 9 usunięć

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 84 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 51 KiB

Wyświetl plik

@ -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

Wyświetl plik

@ -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"
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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()

Wyświetl plik

@ -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

Wyświetl plik

@ -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([])

Wyświetl plik

@ -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"

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1 @@
CONFIG_FREERTOS_UNICORE=y

Wyświetl plik

@ -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)