aa7e24f8f5071b8081c09c859535c27fa4fa3865
Board-dat/ESP/ESP1000-dat/ESP1000-MP-dat/2640-1.py
| ... | ... | @@ -0,0 +1,73 @@ |
| 1 | +import camera |
|
| 2 | +import machine |
|
| 3 | +import time |
|
| 4 | + |
|
| 5 | + |
|
| 6 | + |
|
| 7 | +# Initialize camera with debug and smaller frame size |
|
| 8 | +print("Initializing camera...") |
|
| 9 | +try: |
|
| 10 | + camera.init(0, |
|
| 11 | + d0=5, d1=18, d2=19, d3=21, d4=36, d5=39, d6=34, d7=35, |
|
| 12 | + format=camera.JPEG, |
|
| 13 | + framesize=camera.FRAME_QQVGA, |
|
| 14 | + xclk_freq=camera.XCLK_20MHz, |
|
| 15 | + href=23, vsync=25, reset=-1, pwdn=32, sioc=27, siod=26, xclk=0, pclk=22 |
|
| 16 | + ) |
|
| 17 | + print("Camera initialized successfully.") |
|
| 18 | +except Exception as e: |
|
| 19 | + print("Camera init failed:", e) |
|
| 20 | + # Stop further execution |
|
| 21 | + while True: |
|
| 22 | + machine.idle() |
|
| 23 | + |
|
| 24 | + |
|
| 25 | +# Initialize IO4 (GPIO4) as output |
|
| 26 | +led = machine.Pin(4, machine.Pin.OUT) |
|
| 27 | + |
|
| 28 | + |
|
| 29 | +while True: |
|
| 30 | + print("Starting capture cycle...") |
|
| 31 | + # Blink LED for status |
|
| 32 | + for _ in range(2): |
|
| 33 | + led.value(1) |
|
| 34 | + machine.idle() |
|
| 35 | + time.sleep(0.05) |
|
| 36 | + machine.idle() |
|
| 37 | + led.value(0) |
|
| 38 | + machine.idle() |
|
| 39 | + time.sleep(0.05) |
|
| 40 | + machine.idle() |
|
| 41 | + |
|
| 42 | + machine.idle() |
|
| 43 | + print("Capturing image...") |
|
| 44 | + try: |
|
| 45 | + buf = camera.capture() |
|
| 46 | + print("Captured image, size =", len(buf)) |
|
| 47 | + except Exception as e: |
|
| 48 | + print("Capture failed:", e) |
|
| 49 | + # wait before retry |
|
| 50 | + time.sleep(1) |
|
| 51 | + continue |
|
| 52 | + machine.idle() |
|
| 53 | + |
|
| 54 | + # Generate a timestamped filename |
|
| 55 | + ts = time.localtime() |
|
| 56 | + filename = 'capture_{:04d}{:02d}{:02d}_{:02d}{:02d}{:02d}.jpg'.format(ts[0], ts[1], ts[2], ts[3], ts[4], ts[5]) |
|
| 57 | + print("Saving to file:", filename) |
|
| 58 | + try: |
|
| 59 | + with open(filename, 'wb') as f: |
|
| 60 | + f.write(buf) |
|
| 61 | + machine.idle() |
|
| 62 | + print("File saved.") |
|
| 63 | + except Exception as e: |
|
| 64 | + print("File write error:", e) |
|
| 65 | + machine.idle() |
|
| 66 | + print("Sleeping before next cycle...") |
|
| 67 | + for _ in range(50): |
|
| 68 | + time.sleep(0.05) |
|
| 69 | + machine.idle() |
|
| 70 | + |
|
| 71 | + |
|
| 72 | + |
|
| 73 | + |
Board-dat/ESP/ESP1000-dat/ESP1000-MP-dat/ESP1000-1-dat.py
| ... | ... | @@ -0,0 +1,51 @@ |
| 1 | + |
|
| 2 | +# mpremote connect COM6 fs cp esp1000-1-dat.py : |
|
| 3 | +# mpremote connect COM6 run esp1000-1-dat.py |
|
| 4 | + |
|
| 5 | +from machine import I2C, Pin, UART |
|
| 6 | +import ssd1306 |
|
| 7 | +from bmp280 import * |
|
| 8 | +import time |
|
| 9 | + |
|
| 10 | +# I2C setup (adjust pins as needed) |
|
| 11 | +i2c = I2C(0, scl=Pin(13), sda=Pin(15)) |
|
| 12 | + |
|
| 13 | +# OLED setup |
|
| 14 | +oled = ssd1306.SSD1306_I2C(128, 64, i2c) |
|
| 15 | + |
|
| 16 | +# BMP280 setup |
|
| 17 | +bmp = BMP280(i2c) |
|
| 18 | +bmp.use_case(BMP280_CASE_WEATHER) |
|
| 19 | +bmp.oversample(BMP280_OS_HIGH) |
|
| 20 | +bmp.temp_os = BMP280_TEMP_OS_8 |
|
| 21 | +bmp.press_os = BMP280_PRES_OS_4 |
|
| 22 | +bmp.standby = BMP280_STANDBY_250 |
|
| 23 | +bmp.iir = BMP280_IIR_FILTER_2 |
|
| 24 | +bmp.spi3w = BMP280_SPI3W_ON |
|
| 25 | +bmp.power_mode = BMP280_POWER_NORMAL |
|
| 26 | + |
|
| 27 | +# Deinit UART0 (GPIO3 is RX) |
|
| 28 | +# uart0 = UART(0) |
|
| 29 | +# uart0.deinit() |
|
| 30 | +# GPIO3 setup with internal pull-down |
|
| 31 | +gpio3 = Pin(3, Pin.IN, Pin.PULL_DOWN) |
|
| 32 | + |
|
| 33 | +while True: |
|
| 34 | + try: |
|
| 35 | + bmp.force_measure() |
|
| 36 | + temperature = bmp.temperature |
|
| 37 | + pressure = bmp.pressure |
|
| 38 | + gpio3_status = gpio3.value() |
|
| 39 | + |
|
| 40 | + oled.fill(0) |
|
| 41 | + oled.text("BMP280 Sensor:", 0, 0) |
|
| 42 | + oled.text("T={:.2f}C".format(temperature), 0, 16) |
|
| 43 | + oled.text("P={:.2f}hPa".format(pressure), 0, 32) |
|
| 44 | + oled.text("GPIO3: {}".format(gpio3_status), 0, 48) |
|
| 45 | + oled.show() |
|
| 46 | + except Exception as e: |
|
| 47 | + oled.fill(0) |
|
| 48 | + oled.text("Error:", 0, 0) |
|
| 49 | + oled.text(str(e), 0, 16) |
|
| 50 | + oled.show() |
|
| 51 | + time.sleep(2) |
|
| ... | ... | \ No newline at end of file |
Board-dat/ESP/ESP1000-dat/ESP1000-MP-dat/ESP1000-2-dat.py
| ... | ... | @@ -0,0 +1,141 @@ |
| 1 | +# mpremote connect COM6 fs cp esp1000-1-dat.py : |
|
| 2 | +# mpremote connect COM6 run esp1000-1-dat.py |
|
| 3 | + |
|
| 4 | +from machine import I2C, Pin, UART |
|
| 5 | +import machine # type: ignore |
|
| 6 | +import camera # type: ignore |
|
| 7 | +import ssd1306 |
|
| 8 | +from bmp280 import * |
|
| 9 | +import time |
|
| 10 | +import gc # type: ignore |
|
| 11 | + |
|
| 12 | +# init_i2c: use fixed bus without scanning devices |
|
| 13 | +def init_i2c(): |
|
| 14 | + # I2C setup (bus 1, 400kHz) |
|
| 15 | + i2c = I2C(1, scl=Pin(13), sda=Pin(15), freq=400000) |
|
| 16 | + return i2c |
|
| 17 | + |
|
| 18 | + |
|
| 19 | +def init_oled(i2c): |
|
| 20 | + # Use fixed address 0x3C for SSD1306 |
|
| 21 | + try: |
|
| 22 | + oled = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C) |
|
| 23 | + print("OLED initialized at 0x3C.") |
|
| 24 | + return oled |
|
| 25 | + except Exception as e: |
|
| 26 | + print("OLED init failed:", e) |
|
| 27 | + return None |
|
| 28 | + |
|
| 29 | + |
|
| 30 | +def init_bmp(i2c): |
|
| 31 | + print("Initializing BMP280 at fixed address 0x76...") |
|
| 32 | + try: |
|
| 33 | + bmp = BMP280(i2c, 0x76) |
|
| 34 | + bmp.use_case(BMP280_CASE_WEATHER) |
|
| 35 | + bmp.oversample(BMP280_OS_HIGH) |
|
| 36 | + bmp.temp_os = BMP280_TEMP_OS_8 |
|
| 37 | + bmp.press_os = BMP280_PRES_OS_4 |
|
| 38 | + bmp.standby = BMP280_STANDBY_250 |
|
| 39 | + bmp.iir = BMP280_IIR_FILTER_2 |
|
| 40 | + bmp.spi3w = BMP280_SPI3W_ON |
|
| 41 | + bmp.power_mode = BMP280_POWER_NORMAL |
|
| 42 | + print("BMP280 initialized.") |
|
| 43 | + return bmp |
|
| 44 | + except Exception as e: |
|
| 45 | + print("BMP280 init failed:", e) |
|
| 46 | + return None |
|
| 47 | + |
|
| 48 | + |
|
| 49 | +def read_bmp(bmp): |
|
| 50 | + try: |
|
| 51 | + bmp.force_measure() |
|
| 52 | + temp = bmp.temperature |
|
| 53 | + pressure = bmp.pressure |
|
| 54 | + # power down sensor after reading |
|
| 55 | + bmp.sleep() |
|
| 56 | + return temp, pressure |
|
| 57 | + except Exception as e: |
|
| 58 | + print("BMP read error:", e) |
|
| 59 | + return None, None |
|
| 60 | + |
|
| 61 | + |
|
| 62 | +def read_gpio(pin): |
|
| 63 | + return pin.value() |
|
| 64 | + |
|
| 65 | + |
|
| 66 | +def init_camera(): |
|
| 67 | + try: |
|
| 68 | + camera.init(0, |
|
| 69 | + d0=5, d1=18, d2=19, d3=21, d4=36, d5=39, d6=34, d7=35, |
|
| 70 | + format=camera.JPEG, |
|
| 71 | + framesize=camera.FRAME_QQVGA, |
|
| 72 | + xclk_freq=camera.XCLK_20MHz, |
|
| 73 | + href=23, vsync=25, reset=-1, pwdn=32, |
|
| 74 | + sioc=27, siod=26, xclk=0, pclk=22 |
|
| 75 | + ) |
|
| 76 | + print("Camera initialized.") |
|
| 77 | + return True |
|
| 78 | + except Exception as e: |
|
| 79 | + print("Camera init failed:", e) |
|
| 80 | + return False |
|
| 81 | + |
|
| 82 | + |
|
| 83 | +def capture_image(): |
|
| 84 | + buf = camera.capture() |
|
| 85 | + print("Captured image size:", len(buf)) |
|
| 86 | + ts = time.localtime() |
|
| 87 | + filename = 'capture_{:04d}{:02d}{:02d}_{:02d}{:02d}{:02d}.jpg'.format(*ts[:6]) |
|
| 88 | + with open(filename, 'wb') as f: |
|
| 89 | + f.write(buf) |
|
| 90 | + print("Saved file:", filename) |
|
| 91 | + return filename |
|
| 92 | + |
|
| 93 | + |
|
| 94 | +def update_display(oled, temp, pressure, gpio_status, filename=None): |
|
| 95 | + if not oled: |
|
| 96 | + return |
|
| 97 | + oled.fill(0) |
|
| 98 | + if filename: |
|
| 99 | + oled.text(filename[:16], 0, 0) |
|
| 100 | + oled.text(filename[16:], 0, 16) |
|
| 101 | + oled.text("GPIO3: {}".format(gpio_status), 0, 32) |
|
| 102 | + if temp is not None: |
|
| 103 | + oled.text("T={:.1f}C".format(temp), 0, 48) |
|
| 104 | + else: |
|
| 105 | + oled.text("BMP280 Sensor:", 0, 0) |
|
| 106 | + if temp is not None: |
|
| 107 | + oled.text("T={:.2f}C".format(temp), 0, 16) |
|
| 108 | + if pressure is not None: |
|
| 109 | + oled.text("P={:.2f}hPa".format(pressure), 0, 32) |
|
| 110 | + oled.text("GPIO3: {}".format(gpio_status), 0, 48) |
|
| 111 | + oled.show() |
|
| 112 | + |
|
| 113 | + |
|
| 114 | +def main(): |
|
| 115 | + i2c = init_i2c() |
|
| 116 | + # oled = init_oled(i2c) |
|
| 117 | + bmp = init_bmp(i2c) |
|
| 118 | + gpio3 = Pin(3, Pin.IN, Pin.PULL_DOWN) |
|
| 119 | + camera_ready = False |
|
| 120 | + |
|
| 121 | + while True: |
|
| 122 | + temp, pressure = (read_bmp(bmp) if bmp else (None, None)) |
|
| 123 | + gpio_status = read_gpio(gpio3) |
|
| 124 | + |
|
| 125 | + if gpio_status: |
|
| 126 | + if not camera_ready: |
|
| 127 | + camera_ready = init_camera() |
|
| 128 | + if camera_ready: |
|
| 129 | + filename = capture_image() |
|
| 130 | + else: |
|
| 131 | + filename = None |
|
| 132 | + update_display(oled, temp, pressure, gpio_status, filename) |
|
| 133 | + else: |
|
| 134 | + update_display(oled, temp, pressure, gpio_status) |
|
| 135 | + |
|
| 136 | + print("Loop end, free mem:", gc.mem_free()) |
|
| 137 | + time.sleep(2) |
|
| 138 | + |
|
| 139 | + |
|
| 140 | +# Entry point |
|
| 141 | +main() |
|
| ... | ... | \ No newline at end of file |
Board-dat/ESP/ESP1000-dat/ESP1000-MP-dat/ESP1000-MP-dat.md
| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | + |
|
| 2 | +# ESP1000-MP-dat.md |
|
| 3 | + |
|
| 4 | +- [[esp1000-dat]] - [[OV2640-lemariva-dat]] |
|
| 5 | + |
|
| 6 | +- [[micropython-dat]] |
|
| 7 | + |
|
| 8 | +- [[camera-sdk-dat]] |
|
| 9 | + |
|
| 10 | +flash camera driver firmware |
|
| 11 | + |
|
| 12 | + esptool --port COM6 erase_flash |
|
| 13 | + esptool --port COM6 --baud 460800 write-flash 0x1000 micropython_camera_feeeb5ea3_esp32_idf4_4.bin |
|
| 14 | + |
|
| 15 | + mpremote connect COM6 fs cp bmp280.py : |
|
| 16 | + mpremote connect COM6 fs cp ssd1306.py : |
|
| 17 | + mpremote connect COM6 fs cp esp1000-2-dat.py : |
|
| 18 | + |
|
| 19 | + |
|
| 20 | + mpremote connect COM6 run esp1000-2-dat.py |
|
| 21 | + |
|
| 22 | + mpremote connect COM6 fs cp 2640-1.py : |
|
| 23 | + mpremote connect COM6 run 2640-1.py |
|
| 24 | + |
|
| 25 | +- [[micropython_camera_feeeb5ea3_esp32_idf4_4.bin]] - micropython camera driver firmware, has memory error with [[BMP280-dat]] |
|
| 26 | + |
|
| 27 | + Guru Meditation Error: Core 1 panic'ed (StoreProhibited). Exception was unhandled. |
|
| 28 | + |
|
| 29 | + Core 1 register dump: |
|
| 30 | + PC : 0x400869fc PS : 0x00060031 A0 : 0x80086bb2 |
|
| 31 | + A1 : 0x3ffb1190 |
|
| 32 | + A2 : 0x3ffaf894 A3 : 0x00000000 A4 : 0x00000000 |
|
| 33 | + A5 : 0x00000800 |
|
| 34 | + A6 : 0x00060023 A7 : 0x00060021 A8 : 0x3ffbbf88 |
|
| 35 | + A9 : 0x00000901 |
|
| 36 | + A10 : 0x3ffb1208 A11 : 0x00000001 A12 : 0x00000001 |
|
| 37 | + A13 : 0x3ffbbf8c |
|
| 38 | + A14 : 0x00000000 A15 : 0x3ff53000 SAR : 0x0000000d |
|
| 39 | + EXCCAUSE: 0x0000001d |
|
| 40 | + EXCVADDR: 0x00000008 LBEG : 0x4008d9a0 LEND : 0x4008d9bc |
|
| 41 | + LCOUNT : 0x00000000 |
|
| 42 | + |
|
| 43 | + |
|
| 44 | + Backtrace:0x400869f9:0x3ffb11900x40086baf:0x3ffb11d0 0x40083f85:0x3ffb1200 0x40089ea9:0x3ffca150 0x40091141:0x3ffca170 0x4012628b:0x3ffca1b0 0x40119b16:0x3ffca200 0x401169a9:0x3ffca230 0x40116a21:0x3ffca270 0x400e20bd:0x3ffca2b0 0x400e8819:0x3ffca2e0 0x400e8951:0x3ffca300 0x40085ca5:0x3ffca320 0x400e205a:0x3ffca3c0 0x400e8819:0x3ffca430 0x400e8951:0x3ffca450 0x40085ca5:0x3ffca470 0x400e205a:0x3ffca510 0x400e8819:0x3ffca580 0x400e8951:0x3ffca5a0 0x400e7641:0x3ffca5c0 0x400e725e:0x3ffca620 0x400e8819:0x3ffca640 0x40085c29:0x3ffca660 0x400e205a:0x3ffca700 0x400e8819:0x3ffca730 0x400e8842:0x3ffca750 0x40118bdd:0x3ffca770 0x40118d9a:0x3ffca800 0x400f89b6:0x3ffca850 |
|
| ... | ... | \ No newline at end of file |
Board-dat/ESP/ESP1000-dat/ESP1000-MP-dat/bmp280.py
| ... | ... | @@ -0,0 +1,322 @@ |
| 1 | +from micropython import const |
|
| 2 | +from ustruct import unpack as unp |
|
| 3 | + |
|
| 4 | +# Author David Stenwall (david at stenwall.io) |
|
| 5 | + |
|
| 6 | +# Power Modes |
|
| 7 | +BMP280_POWER_SLEEP = const(0) |
|
| 8 | +BMP280_POWER_FORCED = const(1) |
|
| 9 | +BMP280_POWER_NORMAL = const(3) |
|
| 10 | + |
|
| 11 | +BMP280_SPI3W_ON = const(1) |
|
| 12 | +BMP280_SPI3W_OFF = const(0) |
|
| 13 | + |
|
| 14 | +BMP280_TEMP_OS_SKIP = const(0) |
|
| 15 | +BMP280_TEMP_OS_1 = const(1) |
|
| 16 | +BMP280_TEMP_OS_2 = const(2) |
|
| 17 | +BMP280_TEMP_OS_4 = const(3) |
|
| 18 | +BMP280_TEMP_OS_8 = const(4) |
|
| 19 | +BMP280_TEMP_OS_16 = const(5) |
|
| 20 | + |
|
| 21 | +BMP280_PRES_OS_SKIP = const(0) |
|
| 22 | +BMP280_PRES_OS_1 = const(1) |
|
| 23 | +BMP280_PRES_OS_2 = const(2) |
|
| 24 | +BMP280_PRES_OS_4 = const(3) |
|
| 25 | +BMP280_PRES_OS_8 = const(4) |
|
| 26 | +BMP280_PRES_OS_16 = const(5) |
|
| 27 | + |
|
| 28 | +# Standby settings in ms |
|
| 29 | +BMP280_STANDBY_0_5 = const(0) |
|
| 30 | +BMP280_STANDBY_62_5 = const(1) |
|
| 31 | +BMP280_STANDBY_125 = const(2) |
|
| 32 | +BMP280_STANDBY_250 = const(3) |
|
| 33 | +BMP280_STANDBY_500 = const(4) |
|
| 34 | +BMP280_STANDBY_1000 = const(5) |
|
| 35 | +BMP280_STANDBY_2000 = const(6) |
|
| 36 | +BMP280_STANDBY_4000 = const(7) |
|
| 37 | + |
|
| 38 | +# IIR Filter setting |
|
| 39 | +BMP280_IIR_FILTER_OFF = const(0) |
|
| 40 | +BMP280_IIR_FILTER_2 = const(1) |
|
| 41 | +BMP280_IIR_FILTER_4 = const(2) |
|
| 42 | +BMP280_IIR_FILTER_8 = const(3) |
|
| 43 | +BMP280_IIR_FILTER_16 = const(4) |
|
| 44 | + |
|
| 45 | +# Oversampling setting |
|
| 46 | +BMP280_OS_ULTRALOW = const(0) |
|
| 47 | +BMP280_OS_LOW = const(1) |
|
| 48 | +BMP280_OS_STANDARD = const(2) |
|
| 49 | +BMP280_OS_HIGH = const(3) |
|
| 50 | +BMP280_OS_ULTRAHIGH = const(4) |
|
| 51 | + |
|
| 52 | +# Oversampling matrix |
|
| 53 | +# (PRESS_OS, TEMP_OS, sample time in ms) |
|
| 54 | +_BMP280_OS_MATRIX = [ |
|
| 55 | + [BMP280_PRES_OS_1, BMP280_TEMP_OS_1, 7], |
|
| 56 | + [BMP280_PRES_OS_2, BMP280_TEMP_OS_1, 9], |
|
| 57 | + [BMP280_PRES_OS_4, BMP280_TEMP_OS_1, 14], |
|
| 58 | + [BMP280_PRES_OS_8, BMP280_TEMP_OS_1, 23], |
|
| 59 | + [BMP280_PRES_OS_16, BMP280_TEMP_OS_2, 44] |
|
| 60 | +] |
|
| 61 | + |
|
| 62 | +# Use cases |
|
| 63 | +BMP280_CASE_HANDHELD_LOW = const(0) |
|
| 64 | +BMP280_CASE_HANDHELD_DYN = const(1) |
|
| 65 | +BMP280_CASE_WEATHER = const(2) |
|
| 66 | +BMP280_CASE_FLOOR = const(3) |
|
| 67 | +BMP280_CASE_DROP = const(4) |
|
| 68 | +BMP280_CASE_INDOOR = const(5) |
|
| 69 | + |
|
| 70 | +_BMP280_CASE_MATRIX = [ |
|
| 71 | + [BMP280_POWER_NORMAL, BMP280_OS_ULTRAHIGH, BMP280_IIR_FILTER_4, BMP280_STANDBY_62_5], |
|
| 72 | + [BMP280_POWER_NORMAL, BMP280_OS_STANDARD, BMP280_IIR_FILTER_16, BMP280_STANDBY_0_5], |
|
| 73 | + [BMP280_POWER_FORCED, BMP280_OS_ULTRALOW, BMP280_IIR_FILTER_OFF, BMP280_STANDBY_0_5], |
|
| 74 | + [BMP280_POWER_NORMAL, BMP280_OS_STANDARD, BMP280_IIR_FILTER_4, BMP280_STANDBY_125], |
|
| 75 | + [BMP280_POWER_NORMAL, BMP280_OS_LOW, BMP280_IIR_FILTER_OFF, BMP280_STANDBY_0_5], |
|
| 76 | + [BMP280_POWER_NORMAL, BMP280_OS_ULTRAHIGH, BMP280_IIR_FILTER_16, BMP280_STANDBY_0_5] |
|
| 77 | +] |
|
| 78 | + |
|
| 79 | +_BMP280_REGISTER_ID = const(0xD0) |
|
| 80 | +_BMP280_REGISTER_RESET = const(0xE0) |
|
| 81 | +_BMP280_REGISTER_STATUS = const(0xF3) |
|
| 82 | +_BMP280_REGISTER_CONTROL = const(0xF4) |
|
| 83 | +_BMP280_REGISTER_CONFIG = const(0xF5) # IIR filter config |
|
| 84 | + |
|
| 85 | +_BMP280_REGISTER_DATA = const(0xF7) |
|
| 86 | + |
|
| 87 | + |
|
| 88 | +class BMP280: |
|
| 89 | + def __init__(self, i2c_bus, addr=0x76, use_case=BMP280_CASE_HANDHELD_DYN): |
|
| 90 | + self._bmp_i2c = i2c_bus |
|
| 91 | + self._i2c_addr = addr |
|
| 92 | + |
|
| 93 | + # read calibration data |
|
| 94 | + # < little-endian |
|
| 95 | + # H unsigned short |
|
| 96 | + # h signed short |
|
| 97 | + self._T1 = unp('<H', self._read(0x88, 2))[0] |
|
| 98 | + self._T2 = unp('<h', self._read(0x8A, 2))[0] |
|
| 99 | + self._T3 = unp('<h', self._read(0x8C, 2))[0] |
|
| 100 | + self._P1 = unp('<H', self._read(0x8E, 2))[0] |
|
| 101 | + self._P2 = unp('<h', self._read(0x90, 2))[0] |
|
| 102 | + self._P3 = unp('<h', self._read(0x92, 2))[0] |
|
| 103 | + self._P4 = unp('<h', self._read(0x94, 2))[0] |
|
| 104 | + self._P5 = unp('<h', self._read(0x96, 2))[0] |
|
| 105 | + self._P6 = unp('<h', self._read(0x98, 2))[0] |
|
| 106 | + self._P7 = unp('<h', self._read(0x9A, 2))[0] |
|
| 107 | + self._P8 = unp('<h', self._read(0x9C, 2))[0] |
|
| 108 | + self._P9 = unp('<h', self._read(0x9E, 2))[0] |
|
| 109 | + |
|
| 110 | + # output raw |
|
| 111 | + self._t_raw = 0 |
|
| 112 | + self._t_fine = 0 |
|
| 113 | + self._t = 0 |
|
| 114 | + |
|
| 115 | + self._p_raw = 0 |
|
| 116 | + self._p = 0 |
|
| 117 | + |
|
| 118 | + self.read_wait_ms = 0 # interval between forced measure and readout |
|
| 119 | + self._new_read_ms = 200 # interval between |
|
| 120 | + self._last_read_ts = 0 |
|
| 121 | + |
|
| 122 | + if use_case is not None: |
|
| 123 | + self.use_case(use_case) |
|
| 124 | + |
|
| 125 | + def _read(self, addr, size=1): |
|
| 126 | + return self._bmp_i2c.readfrom_mem(self._i2c_addr, addr, size) |
|
| 127 | + |
|
| 128 | + def _write(self, addr, b_arr): |
|
| 129 | + if not type(b_arr) is bytearray: |
|
| 130 | + b_arr = bytearray([b_arr]) |
|
| 131 | + return self._bmp_i2c.writeto_mem(self._i2c_addr, addr, b_arr) |
|
| 132 | + |
|
| 133 | + def _gauge(self): |
|
| 134 | + # TODO limit new reads |
|
| 135 | + # read all data at once (as by spec) |
|
| 136 | + d = self._read(_BMP280_REGISTER_DATA, 6) |
|
| 137 | + |
|
| 138 | + self._p_raw = (d[0] << 12) + (d[1] << 4) + (d[2] >> 4) |
|
| 139 | + self._t_raw = (d[3] << 12) + (d[4] << 4) + (d[5] >> 4) |
|
| 140 | + |
|
| 141 | + self._t_fine = 0 |
|
| 142 | + self._t = 0 |
|
| 143 | + self._p = 0 |
|
| 144 | + |
|
| 145 | + def reset(self): |
|
| 146 | + self._write(_BMP280_REGISTER_RESET, 0xB6) |
|
| 147 | + |
|
| 148 | + def load_test_calibration(self): |
|
| 149 | + self._T1 = 27504 |
|
| 150 | + self._T2 = 26435 |
|
| 151 | + self._T3 = -1000 |
|
| 152 | + self._P1 = 36477 |
|
| 153 | + self._P2 = -10685 |
|
| 154 | + self._P3 = 3024 |
|
| 155 | + self._P4 = 2855 |
|
| 156 | + self._P5 = 140 |
|
| 157 | + self._P6 = -7 |
|
| 158 | + self._P7 = 15500 |
|
| 159 | + self._P8 = -14600 |
|
| 160 | + self._P9 = 6000 |
|
| 161 | + |
|
| 162 | + def load_test_data(self): |
|
| 163 | + self._t_raw = 519888 |
|
| 164 | + self._p_raw = 415148 |
|
| 165 | + |
|
| 166 | + def print_calibration(self): |
|
| 167 | + print("T1: {} {}".format(self._T1, type(self._T1))) |
|
| 168 | + print("T2: {} {}".format(self._T2, type(self._T2))) |
|
| 169 | + print("T3: {} {}".format(self._T3, type(self._T3))) |
|
| 170 | + print("P1: {} {}".format(self._P1, type(self._P1))) |
|
| 171 | + print("P2: {} {}".format(self._P2, type(self._P2))) |
|
| 172 | + print("P3: {} {}".format(self._P3, type(self._P3))) |
|
| 173 | + print("P4: {} {}".format(self._P4, type(self._P4))) |
|
| 174 | + print("P5: {} {}".format(self._P5, type(self._P5))) |
|
| 175 | + print("P6: {} {}".format(self._P6, type(self._P6))) |
|
| 176 | + print("P7: {} {}".format(self._P7, type(self._P7))) |
|
| 177 | + print("P8: {} {}".format(self._P8, type(self._P8))) |
|
| 178 | + print("P9: {} {}".format(self._P9, type(self._P9))) |
|
| 179 | + |
|
| 180 | + def _calc_t_fine(self): |
|
| 181 | + # From datasheet page 22 |
|
| 182 | + self._gauge() |
|
| 183 | + if self._t_fine == 0: |
|
| 184 | + var1 = (((self._t_raw >> 3) - (self._T1 << 1)) * self._T2) >> 11 |
|
| 185 | + var2 = (((((self._t_raw >> 4) - self._T1) |
|
| 186 | + * ((self._t_raw >> 4) |
|
| 187 | + - self._T1)) >> 12) |
|
| 188 | + * self._T3) >> 14 |
|
| 189 | + self._t_fine = var1 + var2 |
|
| 190 | + |
|
| 191 | + @property |
|
| 192 | + def temperature(self): |
|
| 193 | + self._calc_t_fine() |
|
| 194 | + if self._t == 0: |
|
| 195 | + self._t = ((self._t_fine * 5 + 128) >> 8) / 100. |
|
| 196 | + return self._t |
|
| 197 | + |
|
| 198 | + @property |
|
| 199 | + def pressure(self): |
|
| 200 | + # From datasheet page 22 |
|
| 201 | + self._calc_t_fine() |
|
| 202 | + if self._p == 0: |
|
| 203 | + var1 = self._t_fine - 128000 |
|
| 204 | + var2 = var1 * var1 * self._P6 |
|
| 205 | + var2 = var2 + ((var1 * self._P5) << 17) |
|
| 206 | + var2 = var2 + (self._P4 << 35) |
|
| 207 | + var1 = ((var1 * var1 * self._P3) >> 8) + ((var1 * self._P2) << 12) |
|
| 208 | + var1 = (((1 << 47) + var1) * self._P1) >> 33 |
|
| 209 | + |
|
| 210 | + if var1 == 0: |
|
| 211 | + return 0 |
|
| 212 | + |
|
| 213 | + p = 1048576 - self._p_raw |
|
| 214 | + p = int((((p << 31) - var2) * 3125) / var1) |
|
| 215 | + var1 = (self._P9 * (p >> 13) * (p >> 13)) >> 25 |
|
| 216 | + var2 = (self._P8 * p) >> 19 |
|
| 217 | + |
|
| 218 | + p = ((p + var1 + var2) >> 8) + (self._P7 << 4) |
|
| 219 | + self._p = p / 256.0 |
|
| 220 | + return self._p |
|
| 221 | + |
|
| 222 | + def _write_bits(self, address, value, length, shift=0): |
|
| 223 | + d = self._read(address)[0] |
|
| 224 | + m = int('1' * length, 2) << shift |
|
| 225 | + d &= ~m |
|
| 226 | + d |= m & value << shift |
|
| 227 | + self._write(address, d) |
|
| 228 | + |
|
| 229 | + def _read_bits(self, address, length, shift=0): |
|
| 230 | + d = self._read(address)[0] |
|
| 231 | + return d >> shift & int('1' * length, 2) |
|
| 232 | + |
|
| 233 | + @property |
|
| 234 | + def standby(self): |
|
| 235 | + return self._read_bits(_BMP280_REGISTER_CONFIG, 3, 5) |
|
| 236 | + |
|
| 237 | + @standby.setter |
|
| 238 | + def standby(self, v): |
|
| 239 | + assert 0 <= v <= 7 |
|
| 240 | + self._write_bits(_BMP280_REGISTER_CONFIG, v, 3, 5) |
|
| 241 | + |
|
| 242 | + @property |
|
| 243 | + def iir(self): |
|
| 244 | + return self._read_bits(_BMP280_REGISTER_CONFIG, 3, 2) |
|
| 245 | + |
|
| 246 | + @iir.setter |
|
| 247 | + def iir(self, v): |
|
| 248 | + assert 0 <= v <= 4 |
|
| 249 | + self._write_bits(_BMP280_REGISTER_CONFIG, v, 3, 2) |
|
| 250 | + |
|
| 251 | + @property |
|
| 252 | + def spi3w(self): |
|
| 253 | + return self._read_bits(_BMP280_REGISTER_CONFIG, 1) |
|
| 254 | + |
|
| 255 | + @spi3w.setter |
|
| 256 | + def spi3w(self, v): |
|
| 257 | + assert v in (0, 1) |
|
| 258 | + self._write_bits(_BMP280_REGISTER_CONFIG, v, 1) |
|
| 259 | + |
|
| 260 | + @property |
|
| 261 | + def temp_os(self): |
|
| 262 | + return self._read_bits(_BMP280_REGISTER_CONTROL, 3, 5) |
|
| 263 | + |
|
| 264 | + @temp_os.setter |
|
| 265 | + def temp_os(self, v): |
|
| 266 | + assert 0 <= v <= 5 |
|
| 267 | + self._write_bits(_BMP280_REGISTER_CONTROL, v, 3, 5) |
|
| 268 | + |
|
| 269 | + @property |
|
| 270 | + def press_os(self): |
|
| 271 | + return self._read_bits(_BMP280_REGISTER_CONTROL, 3, 2) |
|
| 272 | + |
|
| 273 | + @press_os.setter |
|
| 274 | + def press_os(self, v): |
|
| 275 | + assert 0 <= v <= 5 |
|
| 276 | + self._write_bits(_BMP280_REGISTER_CONTROL, v, 3, 2) |
|
| 277 | + |
|
| 278 | + @property |
|
| 279 | + def power_mode(self): |
|
| 280 | + return self._read_bits(_BMP280_REGISTER_CONTROL, 2) |
|
| 281 | + |
|
| 282 | + @power_mode.setter |
|
| 283 | + def power_mode(self, v): |
|
| 284 | + assert 0 <= v <= 3 |
|
| 285 | + self._write_bits(_BMP280_REGISTER_CONTROL, v, 2) |
|
| 286 | + |
|
| 287 | + @property |
|
| 288 | + def is_measuring(self): |
|
| 289 | + return bool(self._read_bits(_BMP280_REGISTER_STATUS, 1, 3)) |
|
| 290 | + |
|
| 291 | + @property |
|
| 292 | + def is_updating(self): |
|
| 293 | + return bool(self._read_bits(_BMP280_REGISTER_STATUS, 1)) |
|
| 294 | + |
|
| 295 | + @property |
|
| 296 | + def chip_id(self): |
|
| 297 | + return self._read(_BMP280_REGISTER_ID, 1) |
|
| 298 | + |
|
| 299 | + @property |
|
| 300 | + def in_normal_mode(self): |
|
| 301 | + return self.power_mode == BMP280_POWER_NORMAL |
|
| 302 | + |
|
| 303 | + def force_measure(self): |
|
| 304 | + self.power_mode = BMP280_POWER_FORCED |
|
| 305 | + |
|
| 306 | + def normal_measure(self): |
|
| 307 | + self.power_mode = BMP280_POWER_NORMAL |
|
| 308 | + |
|
| 309 | + def sleep(self): |
|
| 310 | + self.power_mode = BMP280_POWER_SLEEP |
|
| 311 | + |
|
| 312 | + def use_case(self, uc): |
|
| 313 | + assert 0 <= uc <= 5 |
|
| 314 | + pm, oss, iir, sb = _BMP280_CASE_MATRIX[uc] |
|
| 315 | + p_os, t_os, self.read_wait_ms = _BMP280_OS_MATRIX[oss] |
|
| 316 | + self._write(_BMP280_REGISTER_CONFIG, (iir << 2) + (sb << 5)) |
|
| 317 | + self._write(_BMP280_REGISTER_CONTROL, pm + (p_os << 2) + (t_os << 5)) |
|
| 318 | + |
|
| 319 | + def oversample(self, oss): |
|
| 320 | + assert 0 <= oss <= 4 |
|
| 321 | + p_os, t_os, self.read_wait_ms = _BMP280_OS_MATRIX[oss] |
|
| 322 | + self._write_bits(_BMP280_REGISTER_CONTROL, p_os + (t_os << 3), 2) |
Board-dat/ESP/ESP1000-dat/ESP1000-MP-dat/micropython_camera_feeeb5ea3_esp32_idf4_4.bin
| ... | ... | Binary files /dev/null and b/Board-dat/ESP/ESP1000-dat/ESP1000-MP-dat/micropython_camera_feeeb5ea3_esp32_idf4_4.bin differ |
Board-dat/ESP/ESP1000-dat/ESP1000-MP-dat/ssd1306.py
| ... | ... | @@ -0,0 +1,154 @@ |
| 1 | +# MicroPython SSD1306 OLED driver, I2C and SPI interfaces |
|
| 2 | + |
|
| 3 | +from micropython import const |
|
| 4 | +import framebuf |
|
| 5 | + |
|
| 6 | +# register definitions |
|
| 7 | +SET_CONTRAST = const(0x81) |
|
| 8 | +SET_ENTIRE_ON = const(0xA4) |
|
| 9 | +SET_NORM_INV = const(0xA6) |
|
| 10 | +SET_DISP = const(0xAE) |
|
| 11 | +SET_MEM_ADDR = const(0x20) |
|
| 12 | +SET_COL_ADDR = const(0x21) |
|
| 13 | +SET_PAGE_ADDR = const(0x22) |
|
| 14 | +SET_DISP_START_LINE = const(0x40) |
|
| 15 | +SET_SEG_REMAP = const(0xA0) |
|
| 16 | +SET_MUX_RATIO = const(0xA8) |
|
| 17 | +SET_COM_OUT_DIR = const(0xC0) |
|
| 18 | +SET_DISP_OFFSET = const(0xD3) |
|
| 19 | +SET_COM_PIN_CFG = const(0xDA) |
|
| 20 | +SET_DISP_CLK_DIV = const(0xD5) |
|
| 21 | +SET_PRECHARGE = const(0xD9) |
|
| 22 | +SET_VCOM_DESEL = const(0xDB) |
|
| 23 | +SET_CHARGE_PUMP = const(0x8D) |
|
| 24 | + |
|
| 25 | +# Subclassing FrameBuffer provides support for graphics primitives |
|
| 26 | +# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html |
|
| 27 | +class SSD1306(framebuf.FrameBuffer): |
|
| 28 | + def __init__(self, width, height, external_vcc): |
|
| 29 | + self.width = width |
|
| 30 | + self.height = height |
|
| 31 | + self.external_vcc = external_vcc |
|
| 32 | + self.pages = self.height // 8 |
|
| 33 | + self.buffer = bytearray(self.pages * self.width) |
|
| 34 | + super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB) |
|
| 35 | + self.init_display() |
|
| 36 | + |
|
| 37 | + def init_display(self): |
|
| 38 | + for cmd in ( |
|
| 39 | + SET_DISP | 0x00, # off |
|
| 40 | + # address setting |
|
| 41 | + SET_MEM_ADDR, |
|
| 42 | + 0x00, # horizontal |
|
| 43 | + # resolution and layout |
|
| 44 | + SET_DISP_START_LINE | 0x00, |
|
| 45 | + SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 |
|
| 46 | + SET_MUX_RATIO, |
|
| 47 | + self.height - 1, |
|
| 48 | + SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 |
|
| 49 | + SET_DISP_OFFSET, |
|
| 50 | + 0x00, |
|
| 51 | + SET_COM_PIN_CFG, |
|
| 52 | + 0x02 if self.width > 2 * self.height else 0x12, |
|
| 53 | + # timing and driving scheme |
|
| 54 | + SET_DISP_CLK_DIV, |
|
| 55 | + 0x80, |
|
| 56 | + SET_PRECHARGE, |
|
| 57 | + 0x22 if self.external_vcc else 0xF1, |
|
| 58 | + SET_VCOM_DESEL, |
|
| 59 | + 0x30, # 0.83*Vcc |
|
| 60 | + # display |
|
| 61 | + SET_CONTRAST, |
|
| 62 | + 0xFF, # maximum |
|
| 63 | + SET_ENTIRE_ON, # output follows RAM contents |
|
| 64 | + SET_NORM_INV, # not inverted |
|
| 65 | + # charge pump |
|
| 66 | + SET_CHARGE_PUMP, |
|
| 67 | + 0x10 if self.external_vcc else 0x14, |
|
| 68 | + SET_DISP | 0x01, |
|
| 69 | + ): # on |
|
| 70 | + self.write_cmd(cmd) |
|
| 71 | + self.fill(0) |
|
| 72 | + self.show() |
|
| 73 | + |
|
| 74 | + def poweroff(self): |
|
| 75 | + self.write_cmd(SET_DISP | 0x00) |
|
| 76 | + |
|
| 77 | + def poweron(self): |
|
| 78 | + self.write_cmd(SET_DISP | 0x01) |
|
| 79 | + |
|
| 80 | + def contrast(self, contrast): |
|
| 81 | + self.write_cmd(SET_CONTRAST) |
|
| 82 | + self.write_cmd(contrast) |
|
| 83 | + |
|
| 84 | + def invert(self, invert): |
|
| 85 | + self.write_cmd(SET_NORM_INV | (invert & 1)) |
|
| 86 | + |
|
| 87 | + def show(self): |
|
| 88 | + x0 = 0 |
|
| 89 | + x1 = self.width - 1 |
|
| 90 | + if self.width == 64: |
|
| 91 | + # displays with width of 64 pixels are shifted by 32 |
|
| 92 | + x0 += 32 |
|
| 93 | + x1 += 32 |
|
| 94 | + self.write_cmd(SET_COL_ADDR) |
|
| 95 | + self.write_cmd(x0) |
|
| 96 | + self.write_cmd(x1) |
|
| 97 | + self.write_cmd(SET_PAGE_ADDR) |
|
| 98 | + self.write_cmd(0) |
|
| 99 | + self.write_cmd(self.pages - 1) |
|
| 100 | + self.write_data(self.buffer) |
|
| 101 | + |
|
| 102 | + |
|
| 103 | +class SSD1306_I2C(SSD1306): |
|
| 104 | + def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False): |
|
| 105 | + self.i2c = i2c |
|
| 106 | + self.addr = addr |
|
| 107 | + self.temp = bytearray(2) |
|
| 108 | + self.write_list = [b"\x40", None] # Co=0, D/C#=1 |
|
| 109 | + super().__init__(width, height, external_vcc) |
|
| 110 | + |
|
| 111 | + def write_cmd(self, cmd): |
|
| 112 | + self.temp[0] = 0x80 # Co=1, D/C#=0 |
|
| 113 | + self.temp[1] = cmd |
|
| 114 | + self.i2c.writeto(self.addr, self.temp) |
|
| 115 | + |
|
| 116 | + def write_data(self, buf): |
|
| 117 | + self.write_list[1] = buf |
|
| 118 | + self.i2c.writevto(self.addr, self.write_list) |
|
| 119 | + |
|
| 120 | + |
|
| 121 | +class SSD1306_SPI(SSD1306): |
|
| 122 | + def __init__(self, width, height, spi, dc, res, cs, external_vcc=False): |
|
| 123 | + self.rate = 10 * 1024 * 1024 |
|
| 124 | + dc.init(dc.OUT, value=0) |
|
| 125 | + res.init(res.OUT, value=0) |
|
| 126 | + cs.init(cs.OUT, value=1) |
|
| 127 | + self.spi = spi |
|
| 128 | + self.dc = dc |
|
| 129 | + self.res = res |
|
| 130 | + self.cs = cs |
|
| 131 | + import time |
|
| 132 | + |
|
| 133 | + self.res(1) |
|
| 134 | + time.sleep_ms(1) |
|
| 135 | + self.res(0) |
|
| 136 | + time.sleep_ms(10) |
|
| 137 | + self.res(1) |
|
| 138 | + super().__init__(width, height, external_vcc) |
|
| 139 | + |
|
| 140 | + def write_cmd(self, cmd): |
|
| 141 | + self.spi.init(baudrate=self.rate, polarity=0, phase=0) |
|
| 142 | + self.cs(1) |
|
| 143 | + self.dc(0) |
|
| 144 | + self.cs(0) |
|
| 145 | + self.spi.write(bytearray([cmd])) |
|
| 146 | + self.cs(1) |
|
| 147 | + |
|
| 148 | + def write_data(self, buf): |
|
| 149 | + self.spi.init(baudrate=self.rate, polarity=0, phase=0) |
|
| 150 | + self.cs(1) |
|
| 151 | + self.dc(1) |
|
| 152 | + self.cs(0) |
|
| 153 | + self.spi.write(buf) |
|
| 154 | + self.cs(1) |
|
| ... | ... | \ No newline at end of file |
Board-dat/ESP/ESP1000-dat/ESP1000-dat.md
| ... | ... | @@ -18,13 +18,24 @@ Module based on [[SCM1030-dat]] |
| 18 | 18 | | 34 | CAM | | CLK | | | 21 | CAM | | |
| 19 | 19 | | 35 | CAM | | SD0 | PSRAM | | -- | | | |
| 20 | 20 | | 32 | CAM_PWR | | SD1 | PSRAM | | 19 | CAM | | |
| 21 | -| 33 | | | 15 | microSD | SDA | 18 | CAM | | |
|
| 22 | -| 25 | | | 2 | microSD | I2S_WS | 5 | CAM | | |
|
| 21 | +| 33 | LED2 | | 15 | microSD | SDA | 18 | CAM | | |
|
| 22 | +| 25 | CAM | | 2 | microSD | I2S_WS | 5 | CAM | | |
|
| 23 | 23 | | 26 | CAM | | | | | 17 | PSRAM | | |
| 24 | 24 | | 27 | CAM | | | | | 16 | PSRAM | | |
| 25 | 25 | | 14 | microSD | I2S_SD | | | | 4 | microSD, flash | | |
| 26 | 26 | | 12 | microSD | I2S_SCLK | | | | 0 | CAM | | |
| 27 | 27 | |
| 28 | +pin definitions: |
|
| 29 | + |
|
| 30 | + #define I2S_WS 02 |
|
| 31 | + #define I2S_SD 14 |
|
| 32 | + #define I2S_SCK 12 |
|
| 33 | + SSD1306Wire display(0x3c, 15, 13); |
|
| 34 | + BMx280I2C bmx280(0x76, 15, 13); |
|
| 35 | + |
|
| 36 | + #define flash 4 |
|
| 37 | + #define PIR 3 |
|
| 38 | + #define obLED 33 |
|
| 28 | 39 | |
| 29 | 40 | ## Board map |
| 30 | 41 | |
| ... | ... | @@ -68,7 +79,7 @@ Verion 1.0 |
| 68 | 79 | |
| 69 | 80 | ## In Use |
| 70 | 81 | |
| 71 | -- [[I2S-dat]] - [[I2S-microphone-dat]] |
|
| 82 | +- [[I2S-dat]] - [[I2S-microphone-dat]] - [[MSM261S4030H0R-dat]] |
|
| 72 | 83 | |
| 73 | 84 | - [[PIR-sensor-dat]] - [[OLED-dat]] |
| 74 | 85 | |
| ... | ... | @@ -100,16 +111,7 @@ code test: |
| 100 | 111 | - T2: T2-CameraWebServer.ino == Camera test please use official code |
| 101 | 112 | - T3: T3-I2S-mem-mic.ino == test for [[I2S-microphone-dat]] |
| 102 | 113 | |
| 103 | -pin definitions: |
|
| 104 | - |
|
| 105 | - #define I2S_WS 02 |
|
| 106 | - #define I2S_SD 14 |
|
| 107 | - #define I2S_SCK 12 |
|
| 108 | - SSD1306Wire display(0x3c, 15, 13); |
|
| 109 | - BMx280I2C bmx280(0x76); |
|
| 110 | 114 | |
| 111 | - #define flash 4 |
|
| 112 | - #define PIR 3 |
|
| 113 | 115 | |
| 114 | 116 | ## Demo Video |
| 115 | 117 |
Board-dat/SCM/SCM1030-dat/SCM1030-dat.md
| ... | ... | @@ -91,7 +91,7 @@ pin define |
| 91 | 91 | module pin to board pin |
| 92 | 92 | |
| 93 | 93 | | L_Pin | custom | M_Pin | custom | R_Pin | custom | |
| 94 | -|-------|---------|-------|---------|-------|----------------| |
|
| 94 | +| ----- | ------- | ----- | ------- | ----- | -------------- | |
|
| 95 | 95 | | GND | | GND2 | | GND | | |
| 96 | 96 | | 3V3 | | 13 | microSD | 23 | CAM | |
| 97 | 97 | | EN | | SD2 | PSRAM | 22 | CAM | |
| ... | ... | @@ -100,7 +100,7 @@ module pin to board pin |
| 100 | 100 | | 34 | CAM | CLK | | 21 | CAM | |
| 101 | 101 | | 35 | CAM | SD0 | PSRAM | -- | | |
| 102 | 102 | | 32 | CAM_PWR | SD1 | PSRAM | 19 | CAM | |
| 103 | -| 33 | | 15 | microSD | 18 | CAM | |
|
| 103 | +| 33 | LED2 | 15 | microSD | 18 | CAM | |
|
| 104 | 104 | | 25 | | 2 | microSD | 5 | CAM | |
| 105 | 105 | | 26 | CAM | | | 17 | PSRAM | |
| 106 | 106 | | 27 | CAM | | | 16 | PSRAM | |
Chip-cn-dat/Espressif-dat/ESP32-dat/ESP32-HDK-dat/ESP32-HDK-dat.md
| ... | ... | @@ -4,6 +4,15 @@ |
| 4 | 4 | |
| 5 | 5 | - [[ESP32-modules-dat]] - [[ESP32-WROOM-DAT]] |
| 6 | 6 | |
| 7 | +- [[esp32-chip-error-dat]] |
|
| 8 | + |
|
| 9 | +## pins |
|
| 10 | + |
|
| 11 | +You can use almost any GPIO, except: |
|
| 12 | + |
|
| 13 | +GPIO6–11: used for flash |
|
| 14 | + |
|
| 15 | +GPIO34–39: input-only (not usable as output like SCL) |
|
| 7 | 16 | |
| 8 | 17 | ### RMT |
| 9 | 18 | |
| ... | ... | @@ -34,15 +43,6 @@ ref |
| 34 | 43 | |
| 35 | 44 | |
| 36 | 45 | |
| 37 | -## NC Pins |
|
| 38 | - |
|
| 39 | -V3 Chips |
|
| 40 | -- Pins GPIO6 to GPIO11 on the ESP32-D0WD-V3/ESP32-D0WDR2-V3 chip are connected to the SPI flash integrated on the module and are not led out. |
|
| 41 | - |
|
| 42 | -V2 Chips |
|
| 43 | -- Pins SCK/CLK, SDO/SD0, SDI/SD1, SHD/SD2, SWP/SD3, and SCS/CMD, i.e. GPIO6 to GPIO11 are used to connect to the module integrated SPI flash, not recommended for other functions. |
|
| 44 | - |
|
| 45 | - |
|
| 46 | 46 | ## Module Compare |
| 47 | 47 | |
| 48 | 48 |  |
Chip-cn-dat/Espressif-dat/ESP32-dat/ESP32-chip-error-dat.md
| ... | ... | @@ -21,6 +21,20 @@ https://github.com/orgs/micropython/discussions/10521 |
| 21 | 21 | solder a 10UF capacitor between EN and GND pins to prevent the watchdog timer from resetting the board. |
| 22 | 22 | |
| 23 | 23 | |
| 24 | + |
|
| 25 | + |
|
| 26 | +## NC Pins |
|
| 27 | + |
|
| 28 | +V3 Chips |
|
| 29 | +- Pins GPIO6 to GPIO11 on the ESP32-D0WD-V3/ESP32-D0WDR2-V3 chip are connected to the SPI flash integrated on the module and are not led out. |
|
| 30 | + |
|
| 31 | +V2 Chips |
|
| 32 | +- Pins SCK/CLK, SDO/SD0, SDI/SD1, SHD/SD2, SWP/SD3, and SCS/CMD, i.e. GPIO6 to GPIO11 are used to connect to the module integrated SPI flash, not recommended for other functions. |
|
| 33 | + |
|
| 34 | + |
|
| 35 | + |
|
| 36 | + |
|
| 37 | + |
|
| 24 | 38 | ## ref |
| 25 | 39 | |
| 26 | 40 | - [[ESP32-dat]] |
| ... | ... | \ No newline at end of file |
Chip-dat/NXP-dat/NXP-dat.md
| ... | ... | @@ -16,11 +16,15 @@ PCF85176 == 40 x 4 universal LCD driver for low multiplex rates |
| 16 | 16 | |
| 17 | 17 | [PCF8523 == Real-Time Clock (RTC) and calendar](https://www.nxp.com.cn/docs/en/data-sheet/PCF8523.pdf) |
| 18 | 18 | |
| 19 | -## PCF8566 |
|
| 19 | +### PCF8566 |
|
| 20 | 20 | |
| 21 | 21 |  |
| 22 | 22 | |
| 23 | 23 | |
| 24 | +## I2S |
|
| 25 | + |
|
| 26 | +- [[UDA1334-dat]] |
|
| 27 | + |
|
| 24 | 28 | ## ref |
| 25 | 29 | |
| 26 | 30 | - [[CAN-dat]] |
| ... | ... | \ No newline at end of file |
Chip-dat/NXP-dat/UDA1334-dat/UDA1334-dat.md
| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | + |
|
| 2 | +# UDA1334-dat |
|
| 3 | + |
|
| 4 | +Low power audio DAC with PLL |
|
| 5 | + |
|
| 6 | +https://www.nxp.com/docs/en/data-sheet/UDA1334ATS.pdf |
|
| 7 | + |
|
| 8 | +| UDA1334A board pin | Pyboard V1.1 pin | Pyboard D pin | ESP32 pin | Pico Pin | Teensy 4.1 pin | |
|
| 9 | +|--------------------|------------------|---------------|-----------|----------|-----------------| |
|
| 10 | +| 3V0 | 3V3 | 3V3 | 3V3 | 3V3 | 3.3V | |
|
| 11 | +| GND | GND | GND | GND | GND | GND | |
|
| 12 | +| BCLK | Y6 | Y6 | 32 | 16 | 4 | |
|
| 13 | +| WSEL | Y5 | Y5 | 25 | 17 | 3 | |
|
| 14 | +| DIN | Y8 | Y8 | 33 | 18 | 2 | |
|
| 15 | + |
|
| 16 | + |
|
| 17 | +## ref |
|
| 18 | + |
|
| 19 | +https://github.com/miketeachman/micropython-i2s-examples |
|
| ... | ... | \ No newline at end of file |
SDK-dat/microPython-dat/ESP32_GENERIC-20250415-v1.25.0.bin
| ... | ... | Binary files a/SDK-dat/microPython-dat/ESP32_GENERIC-20250415-v1.25.0.bin and /dev/null differ |
SDK-dat/microPython-dat/MP-ESP32-dat/ESP32_GENERIC-20250415-v1.25.0.bin
| ... | ... | Binary files /dev/null and b/SDK-dat/microPython-dat/MP-ESP32-dat/ESP32_GENERIC-20250415-v1.25.0.bin differ |
SDK-dat/microPython-dat/MP-ESP32-dat/MP-ESP32-dat.md
| ... | ... | @@ -9,6 +9,12 @@ https://micropython.org/resources/firmware/ESP32_GENERIC-20250415-v1.25.0.bin |
| 9 | 9 | |
| 10 | 10 | - [[ESP32-SDK-dat]] - [[ESP32-dat]] |
| 11 | 11 | |
| 12 | +esp32 |
|
| 13 | + |
|
| 14 | + esptool --port COM6 erase_flash |
|
| 15 | + esptool --port COM6 --baud 460800 write-flash 0x1000 ESP32_GENERIC-20250415-v1.25.0.bin |
|
| 16 | + |
|
| 17 | + |
|
| 12 | 18 | ## For ESP32-S3 |
| 13 | 19 | |
| 14 | 20 | - [[ESP32-S3-dat]] |
SDK-dat/microPython-dat/Thonny.md
| ... | ... | @@ -1,2 +1,4 @@ |
| 1 | 1 | |
| 2 | -# thonny |
|
| ... | ... | \ No newline at end of file |
| 0 | +# thonny |
|
| 1 | + |
|
| 2 | +https://thonny.org/ |
|
| ... | ... | \ No newline at end of file |
SDK-dat/microPython-dat/bmp280-1-dat.py
| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | + |
|
| 2 | + |
|
| 3 | +# mpremote connect COM6 fs cp bmp280-1-dat.py : |
|
| 4 | +# mpremote connect COM6 run bmp280-1-dat.py |
|
| 5 | + |
|
| 6 | +from machine import I2C, Pin |
|
| 7 | +from bmp280 import * |
|
| 8 | + |
|
| 9 | +bus = I2C(0, scl=Pin(13), sda=Pin(15)) |
|
| 10 | +bmp = BMP280(bus) |
|
| 11 | + |
|
| 12 | +bmp.use_case(BMP280_CASE_WEATHER) |
|
| 13 | +bmp.oversample(BMP280_OS_HIGH) |
|
| 14 | + |
|
| 15 | +bmp.temp_os = BMP280_TEMP_OS_8 |
|
| 16 | +bmp.press_os = BMP280_PRES_OS_4 |
|
| 17 | + |
|
| 18 | +bmp.standby = BMP280_STANDBY_250 |
|
| 19 | +bmp.iir = BMP280_IIR_FILTER_2 |
|
| 20 | + |
|
| 21 | +bmp.spi3w = BMP280_SPI3W_ON |
|
| 22 | + |
|
| 23 | +bmp.power_mode = BMP280_POWER_FORCED |
|
| 24 | +# or |
|
| 25 | +bmp.force_measure() |
|
| 26 | + |
|
| 27 | +bmp.power_mode = BMP280_POWER_NORMAL |
|
| 28 | +# or |
|
| 29 | +bmp.normal_measure() |
|
| 30 | +# also |
|
| 31 | +print("In normal mode:", bmp.in_normal_mode) |
|
| 32 | + |
|
| 33 | +bmp.power_mode = BMP280_POWER_SLEEP |
|
| 34 | +# or |
|
| 35 | +bmp.sleep() |
|
| 36 | + |
|
| 37 | +print(bmp.temperature) |
|
| 38 | +print(bmp.pressure) |
|
| 39 | + |
|
| 40 | +#True while measuring |
|
| 41 | +bmp.is_measuring |
|
| 42 | + |
|
| 43 | +#True while copying data to registers |
|
| 44 | +bmp.is_updating |
SDK-dat/microPython-dat/bmp280-2-dat.py
| ... | ... | @@ -0,0 +1,60 @@ |
| 1 | + |
|
| 2 | + |
|
| 3 | +# mpremote connect COM6 fs cp bmp280-2-dat.py : |
|
| 4 | +# mpremote connect COM6 run bmp280-2-dat.py |
|
| 5 | + |
|
| 6 | +from machine import I2C, Pin |
|
| 7 | +from bmp280 import * |
|
| 8 | +import time |
|
| 9 | + |
|
| 10 | +bus = I2C(0, scl=Pin(13), sda=Pin(15)) |
|
| 11 | +bmp = BMP280(bus) |
|
| 12 | + |
|
| 13 | +bmp.use_case(BMP280_CASE_WEATHER) |
|
| 14 | +bmp.oversample(BMP280_OS_HIGH) |
|
| 15 | + |
|
| 16 | +bmp.temp_os = BMP280_TEMP_OS_8 |
|
| 17 | +bmp.press_os = BMP280_PRES_OS_4 |
|
| 18 | + |
|
| 19 | +bmp.standby = BMP280_STANDBY_250 |
|
| 20 | +bmp.iir = BMP280_IIR_FILTER_2 |
|
| 21 | + |
|
| 22 | +bmp.spi3w = BMP280_SPI3W_ON |
|
| 23 | + |
|
| 24 | +bmp.power_mode = BMP280_POWER_FORCED |
|
| 25 | +# or |
|
| 26 | +bmp.force_measure() |
|
| 27 | + |
|
| 28 | +bmp.power_mode = BMP280_POWER_NORMAL |
|
| 29 | +# or |
|
| 30 | +bmp.normal_measure() |
|
| 31 | +# also |
|
| 32 | +print("In normal mode:", bmp.in_normal_mode) |
|
| 33 | + |
|
| 34 | +# Infinite loop to continuously read sensor data |
|
| 35 | +while True: |
|
| 36 | + try: |
|
| 37 | + print("Loop start: measuring:", bmp.is_measuring, "updating:", bmp.is_updating) |
|
| 38 | + # Force a measurement |
|
| 39 | + print("Before force_measure") |
|
| 40 | + bmp.force_measure() |
|
| 41 | + print("After force_measure") |
|
| 42 | + # Read temperature |
|
| 43 | + print("Before temperature read") |
|
| 44 | + temperature = bmp.temperature |
|
| 45 | + print("After temperature read, value:", temperature) |
|
| 46 | + # Read pressure |
|
| 47 | + print("Before pressure read") |
|
| 48 | + pressure = bmp.pressure |
|
| 49 | + print("After pressure read, value:", pressure) |
|
| 50 | + # Display the readings with simple string formatting |
|
| 51 | + print("Before printing readings") |
|
| 52 | + print("Temperature:", temperature, "°C") |
|
| 53 | + print("Pressure:", pressure, "hPa") |
|
| 54 | + print("Is measuring:", bmp.is_measuring) |
|
| 55 | + print("Is updating:", bmp.is_updating) |
|
| 56 | + print("------------------------------") |
|
| 57 | + except Exception as e: |
|
| 58 | + print("Exception occurred:", repr(e)) |
|
| 59 | + # Wait 2 seconds before next reading |
|
| 60 | + time.sleep(2) |
SDK-dat/microPython-dat/bmp280-3-dat.py
| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | +from machine import I2C, Pin |
|
| 2 | +import time |
|
| 3 | + |
|
| 4 | +import bmp280_1 as bmp280 |
|
| 5 | + |
|
| 6 | +b = bmp280.BMP280(I2C(1, scl=Pin(13), sda=Pin(15))) |
|
| 7 | + |
|
| 8 | +while True: |
|
| 9 | + time.sleep_ms(500) |
|
| 10 | + b.get() |
SDK-dat/microPython-dat/i2s-dat/i2s_recording.py
| ... | ... | @@ -0,0 +1,125 @@ |
| 1 | +# The MIT License (MIT) |
|
| 2 | +# Copyright (c) 2022 Mike Teachman |
|
| 3 | +# https://opensource.org/licenses/MIT |
|
| 4 | + |
|
| 5 | +# Purpose: Read audio samples from an I2S microphone and write to SD card |
|
| 6 | +# |
|
| 7 | +# - read 32-bit audio samples from I2S hardware, typically an I2S MEMS Microphone |
|
| 8 | +# - convert 32-bit samples to specified bit size |
|
| 9 | +# - write samples to a SD card file in WAV format |
|
| 10 | +# - samples will be continuously written to the WAV file |
|
| 11 | +# until a keyboard interrupt (ctrl-c) is detected |
|
| 12 | +# |
|
| 13 | +# Blocking version |
|
| 14 | +# - the readinto() method blocks until |
|
| 15 | +# the supplied buffer is filled |
|
| 16 | + |
|
| 17 | +import os |
|
| 18 | +from machine import Pin |
|
| 19 | +from machine import I2S |
|
| 20 | +from machine import AUDIO_I2S_98_MHZ, freq |
|
| 21 | + |
|
| 22 | +if os.uname().machine.count("CY8CPROTO-062-4343W"): |
|
| 23 | + |
|
| 24 | + # ======= I2S CONFIGURATION ======= |
|
| 25 | + SCK_PIN = "P5_4" |
|
| 26 | + WS_PIN = "P5_5" |
|
| 27 | + SD_PIN = "P5_6" |
|
| 28 | + I2S_ID = 0 |
|
| 29 | + BUFFER_LENGTH_IN_BYTES = 40000 |
|
| 30 | + # ======= I2S CONFIGURATION ======= |
|
| 31 | + |
|
| 32 | +else: |
|
| 33 | + print("Warning: program not tested with this board") |
|
| 34 | + |
|
| 35 | +# ======= AUDIO CONFIGURATION ======= |
|
| 36 | +WAV_FILE = "mic.wav" |
|
| 37 | +RECORD_TIME_IN_SECONDS = 10 |
|
| 38 | +WAV_SAMPLE_SIZE_IN_BITS = 32 |
|
| 39 | +FORMAT = I2S.STEREO |
|
| 40 | +SAMPLE_RATE_IN_HZ = 8000 |
|
| 41 | +# ======= AUDIO CONFIGURATION ======= |
|
| 42 | + |
|
| 43 | +format_to_channels = {I2S.MONO: 1, I2S.STEREO: 2} |
|
| 44 | +NUM_CHANNELS = format_to_channels[FORMAT] |
|
| 45 | +WAV_SAMPLE_SIZE_IN_BYTES = WAV_SAMPLE_SIZE_IN_BITS // 8 |
|
| 46 | +RECORDING_SIZE_IN_BYTES = ( |
|
| 47 | + RECORD_TIME_IN_SECONDS * SAMPLE_RATE_IN_HZ * WAV_SAMPLE_SIZE_IN_BYTES * NUM_CHANNELS |
|
| 48 | +) |
|
| 49 | + |
|
| 50 | +# Set the I2S clock frequency |
|
| 51 | +freq(AUDIO_I2S_98_MHZ) # Set clock frequency to 98 MHz for 8kHz sample rate |
|
| 52 | + |
|
| 53 | + |
|
| 54 | +def create_wav_header(sampleRate, bitsPerSample, num_channels, num_samples): |
|
| 55 | + datasize = num_samples * num_channels * bitsPerSample // 8 |
|
| 56 | + o = bytes("RIFF", "ascii") # (4byte) Marks file as RIFF |
|
| 57 | + o += (datasize + 36).to_bytes( |
|
| 58 | + 4, "little" |
|
| 59 | + ) # (4byte) File size in bytes excluding this and RIFF marker |
|
| 60 | + o += bytes("WAVE", "ascii") # (4byte) File type |
|
| 61 | + o += bytes("fmt ", "ascii") # (4byte) Format Chunk Marker |
|
| 62 | + o += (16).to_bytes(4, "little") # (4byte) Length of above format data |
|
| 63 | + o += (1).to_bytes(2, "little") # (2byte) Format type (1 - PCM) |
|
| 64 | + o += (num_channels).to_bytes(2, "little") # (2byte) |
|
| 65 | + o += (sampleRate).to_bytes(4, "little") # (4byte) |
|
| 66 | + o += (sampleRate * num_channels * bitsPerSample // 8).to_bytes(4, "little") # (4byte) |
|
| 67 | + o += (num_channels * bitsPerSample // 8).to_bytes(2, "little") # (2byte) |
|
| 68 | + o += (bitsPerSample).to_bytes(2, "little") # (2byte) |
|
| 69 | + o += bytes("data", "ascii") # (4byte) Data Chunk Marker |
|
| 70 | + o += (datasize).to_bytes(4, "little") # (4byte) Data size in bytes |
|
| 71 | + return o |
|
| 72 | + |
|
| 73 | + |
|
| 74 | +wav = open("/{}".format(WAV_FILE), "wb") |
|
| 75 | + |
|
| 76 | +# create header for WAV file and write to SD card |
|
| 77 | +wav_header = create_wav_header( |
|
| 78 | + SAMPLE_RATE_IN_HZ, |
|
| 79 | + WAV_SAMPLE_SIZE_IN_BITS, |
|
| 80 | + NUM_CHANNELS, |
|
| 81 | + SAMPLE_RATE_IN_HZ * RECORD_TIME_IN_SECONDS, |
|
| 82 | +) |
|
| 83 | +num_bytes_written = wav.write(wav_header) |
|
| 84 | + |
|
| 85 | +audio_in = I2S( |
|
| 86 | + I2S_ID, |
|
| 87 | + sck=SCK_PIN, |
|
| 88 | + ws=WS_PIN, |
|
| 89 | + sd=SD_PIN, |
|
| 90 | + mode=I2S.RX, |
|
| 91 | + bits=WAV_SAMPLE_SIZE_IN_BITS, |
|
| 92 | + format=FORMAT, |
|
| 93 | + rate=SAMPLE_RATE_IN_HZ, |
|
| 94 | + ibuf=BUFFER_LENGTH_IN_BYTES, |
|
| 95 | +) |
|
| 96 | + |
|
| 97 | +# allocate sample arrays |
|
| 98 | +# memoryview used to reduce heap allocation in while loop |
|
| 99 | +mic_samples = bytearray(10000) |
|
| 100 | +mic_samples_mv = memoryview(mic_samples) |
|
| 101 | + |
|
| 102 | +num_sample_bytes_written_to_wav = 0 |
|
| 103 | + |
|
| 104 | +print("Recording size: {} bytes".format(RECORDING_SIZE_IN_BYTES)) |
|
| 105 | +print("========== START RECORDING ==========") |
|
| 106 | +try: |
|
| 107 | + while num_sample_bytes_written_to_wav < RECORDING_SIZE_IN_BYTES: |
|
| 108 | + # read a block of samples from the I2S microphone |
|
| 109 | + num_bytes_read_from_mic = audio_in.readinto(mic_samples_mv) |
|
| 110 | + if num_bytes_read_from_mic > 0: |
|
| 111 | + num_bytes_to_write = min( |
|
| 112 | + num_bytes_read_from_mic, RECORDING_SIZE_IN_BYTES - num_sample_bytes_written_to_wav |
|
| 113 | + ) |
|
| 114 | + # write samples to WAV file |
|
| 115 | + num_bytes_written = wav.write(mic_samples_mv[:num_bytes_to_write]) |
|
| 116 | + num_sample_bytes_written_to_wav += num_bytes_written |
|
| 117 | + |
|
| 118 | + print("========== DONE RECORDING ==========") |
|
| 119 | +except (KeyboardInterrupt, Exception) as e: |
|
| 120 | + print("caught exception {} {}".format(type(e).__name__, e)) |
|
| 121 | + |
|
| 122 | +# cleanup |
|
| 123 | +wav.close() |
|
| 124 | + |
|
| 125 | +audio_in.deinit() |
|
| ... | ... | \ No newline at end of file |
SDK-dat/microPython-dat/micropython-dat.md
| ... | ... | @@ -2,6 +2,8 @@ |
| 2 | 2 | # micropython dat |
| 3 | 3 | |
| 4 | 4 | |
| 5 | +- [[CircuitPython-dat]] |
|
| 6 | + |
|
| 5 | 7 | - [[MP-ESP32-dat]] - [[MP-STM32-dat]] |
| 6 | 8 | |
| 7 | 9 | |
| ... | ... | @@ -45,37 +47,7 @@ Open the USB flash drive, edit the main.py file, click Save, and reset the MCU t |
| 45 | 47 | |
| 46 | 48 | ## relevant other useful tools |
| 47 | 49 | |
| 48 | -- [[ampy-dat]] |
|
| 49 | - |
|
| 50 | -pip install mpremote |
|
| 51 | - |
|
| 52 | -mpremote connect COM6 fs ls |
|
| 53 | - |
|
| 54 | -mpremote connect COM6 fs cp 2640-1.py : |
|
| 55 | -mpremote connect COM6 fs cp :capture.jpg . |
|
| 56 | - |
|
| 57 | -mpremote connect COM6 fs rm :capture.jpg |
|
| 58 | - |
|
| 59 | -mpremote connect COM6 |
|
| 60 | - |
|
| 61 | -mpremote connect COM6 run 2640-1.py |
|
| 62 | - |
|
| 63 | - mpremote connect COM6 |
|
| 64 | - Connected to MicroPython at COM6 |
|
| 65 | - Use Ctrl-] or Ctrl-x to exit this shell |
|
| 66 | - |
|
| 67 | -capture script run |
|
| 68 | - |
|
| 69 | - import test2 |
|
| 70 | - >>> print(os.listdir()) |
|
| 71 | - ['boot.py', 'capture.jpg', 'test2.py'] |
|
| 72 | - >>> |
|
| 73 | - |
|
| 74 | -rename a file == mpremote connect COM6 fs mv :2640-2.py :main.py |
|
| 75 | - |
|
| 76 | - mpremote connect COM6 fs cp :2640-2.py :main.py |
|
| 77 | - |
|
| 78 | -reboot == mpremote connect COM6 reset |
|
| 50 | +- [[ampy-dat]] - [[rshell-dat]] - [[mpremote-dat]] |
|
| 79 | 51 | |
| 80 | 52 | |
| 81 | 53 | ## flash |
| ... | ... | @@ -128,6 +100,27 @@ List Files in Current Directory |
| 128 | 100 | ↓ |
| 129 | 101 | Run main.py |
| 130 | 102 | |
| 103 | +- [[boot.py]] - [[main.py]] |
|
| 104 | + |
|
| 105 | +## hardware |
|
| 106 | + |
|
| 107 | +- [[I2C-dat]] - [[ESP32-HDK-dat]] |
|
| 108 | + |
|
| 109 | +📌 Common ESP32 I2C Pins |
|
| 110 | + |
|
| 111 | +| Function | GPIO | Notes | |
|
| 112 | +|----------|------|-------| |
|
| 113 | +| SDA | 21 | Common default SDA pin | |
|
| 114 | +| SCL | 22 | Common default SCL pin | |
|
| 115 | + |
|
| 116 | +- [[mp-i2c-1-dat.py]] |
|
| 117 | + |
|
| 118 | +- [[mp-ssd1306-1-dat.py]] |
|
| 119 | + |
|
| 120 | + |
|
| 121 | +## code library |
|
| 122 | + |
|
| 123 | +https://github.com/micropython-Chinese-Community/mpy-lib |
|
| 131 | 124 | |
| 132 | 125 | |
| 133 | 126 | ## ref |
SDK-dat/microPython-dat/mp-i2c-1-dat.py
| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | + |
|
| 2 | +# mpremote connect COM6 fs cp mp-i2c-1-dat.py : |
|
| 3 | +# mpremote connect COM6 run mp-i2c-1-dat.py |
|
| 4 | + |
|
| 5 | +# I2C devices found: ['0x3c', '0x76'] |
|
| 6 | +# I2C devices found: ['0x3c', '0x76'] |
|
| 7 | + |
|
| 8 | + |
|
| 9 | +from machine import Pin, I2C |
|
| 10 | +import time |
|
| 11 | + |
|
| 12 | +# Define I2C pins (adjust to your wiring) |
|
| 13 | +i2c = I2C(0, scl=Pin(13), sda=Pin(15), freq=100000) |
|
| 14 | + |
|
| 15 | +# Scan and print all detected device addresses |
|
| 16 | +while True: |
|
| 17 | + devices = i2c.scan() |
|
| 18 | + if devices: |
|
| 19 | + print("I2C devices found:", [hex(addr) for addr in devices]) |
|
| 20 | + else: |
|
| 21 | + print("No I2C devices found.") |
|
| 22 | + time.sleep(2) |
|
| ... | ... | \ No newline at end of file |
SDK-dat/microPython-dat/mp-ssd1306-1-dat.py
| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | + |
|
| 2 | +# mpremote connect COM6 fs cp mp-ssd1306-1-dat.py : |
|
| 3 | +# mpremote connect COM6 run mp-ssd1306-1-dat.py |
|
| 4 | + |
|
| 5 | +from machine import I2C, Pin |
|
| 6 | +import ssd1306 |
|
| 7 | + |
|
| 8 | +i2c = I2C(0, scl=Pin(13), sda=Pin(15)) |
|
| 9 | +oled = ssd1306.SSD1306_I2C(128, 64, i2c) |
|
| 10 | + |
|
| 11 | +oled.text("Hello, ESP32!", 0, 0) |
|
| 12 | +oled.show() |
|
| ... | ... | \ No newline at end of file |
SDK-dat/microPython-dat/mp-ssd1306-2-dat.py
| ... | ... | @@ -0,0 +1,48 @@ |
| 1 | + |
|
| 2 | +# mpremote connect COM6 fs cp mp-i2c-dat.py : |
|
| 3 | +# mpremote connect COM6 run mp-i2c-dat.py |
|
| 4 | + |
|
| 5 | +import machine |
|
| 6 | +import ssd1306 |
|
| 7 | +import time |
|
| 8 | + |
|
| 9 | +# create I2C interface |
|
| 10 | +i2c = machine.I2C(1, sda=machine.Pin(15), scl=machine.Pin(13)) # I have my display hooked up to pins 14 and 15 (for I2C) |
|
| 11 | +print(i2c.scan()) # 0x3c is the I2C address of the SSD1306. As an integer, 60. |
|
| 12 | + |
|
| 13 | +# create SSD1306 interface |
|
| 14 | +display_width:int = 128 |
|
| 15 | +display_height:int = 64 |
|
| 16 | +oled = ssd1306.SSD1306_I2C(128, 64, i2c) |
|
| 17 | + |
|
| 18 | +# turn on all pixels |
|
| 19 | +oled.fill(1) # make the change |
|
| 20 | +oled.show() # show the update |
|
| 21 | +time.sleep(1) |
|
| 22 | + |
|
| 23 | +# turn off all pixels (blank display) |
|
| 24 | +oled.fill(0) |
|
| 25 | +oled.show() |
|
| 26 | +time.sleep(1) |
|
| 27 | + |
|
| 28 | +# fill in a single pixel |
|
| 29 | +oled.pixel(0, 0, 1) # turn on pixel at (0, 0) (top left) |
|
| 30 | +oled.pixel(64, 0, 1) # turn on pixel at (64, 0), middle top |
|
| 31 | +oled.pixel(127, 63, 1) # turn on pixel at (127, 63) (absolute bottom right on my 128x64 display) |
|
| 32 | +oled.show() # show the update |
|
| 33 | +time.sleep(1) |
|
| 34 | + |
|
| 35 | +# turn off all pixels again |
|
| 36 | +oled.fill(0) |
|
| 37 | +oled.show() |
|
| 38 | +time.sleep(1) |
|
| 39 | + |
|
| 40 | +# display text |
|
| 41 | +oled.text("Hello, world!", 0, 0) # print text "Hello, world!" at position (0, 0) (top left) |
|
| 42 | +oled.show() |
|
| 43 | +time.sleep(1) |
|
| 44 | + |
|
| 45 | +# turn off all pixels again |
|
| 46 | +oled.fill(0) |
|
| 47 | +oled.show() |
|
| 48 | +time.sleep(1) |
|
| ... | ... | \ No newline at end of file |
SDK-dat/microPython-dat/mpremote-dat/mpremote-dat.md
| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | + |
|
| 2 | +# mpremote-dat.md |
|
| 3 | + |
|
| 4 | + |
|
| 5 | +pip install mpremote |
|
| 6 | + |
|
| 7 | +mpremote connect COM6 fs ls |
|
| 8 | + |
|
| 9 | +mpremote connect COM6 fs cp 2640-1.py : |
|
| 10 | +mpremote connect COM6 fs cp :capture.jpg . |
|
| 11 | + |
|
| 12 | +mpremote connect COM6 fs rm :capture.jpg |
|
| 13 | + |
|
| 14 | +mpremote connect COM6 |
|
| 15 | + |
|
| 16 | +mpremote connect COM6 run 2640-1.py |
|
| 17 | + |
|
| 18 | + mpremote connect COM6 |
|
| 19 | + Connected to MicroPython at COM6 |
|
| 20 | + Use Ctrl-] or Ctrl-x to exit this shell |
|
| 21 | + |
|
| 22 | +capture script run |
|
| 23 | + |
|
| 24 | + import test2 |
|
| 25 | + >>> print(os.listdir()) |
|
| 26 | + ['boot.py', 'capture.jpg', 'test2.py'] |
|
| 27 | + >>> |
|
| 28 | + |
|
| 29 | +rename a file == mpremote connect COM6 fs mv :2640-2.py :main.py |
|
| 30 | + |
|
| 31 | + mpremote connect COM6 fs cp :2640-2.py :main.py |
|
| 32 | + |
|
| 33 | +reboot == mpremote connect COM6 reset |
|
| 34 | + |
SDK-dat/python-dat/circuitpython-dat/adafruit_ov2640.py
| ... | ... | @@ -0,0 +1,1364 @@ |
| 1 | +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries |
|
| 2 | +# SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries |
|
| 3 | +# |
|
| 4 | +# SPDX-License-Identifier: MIT |
|
| 5 | +""" |
|
| 6 | +`adafruit_ov2640` |
|
| 7 | +================================================================================ |
|
| 8 | + |
|
| 9 | +CircuitPython driver for OV2640 Camera. |
|
| 10 | + |
|
| 11 | + |
|
| 12 | +* Author(s): Jeff Epler |
|
| 13 | + |
|
| 14 | +Implementation Notes |
|
| 15 | +-------------------- |
|
| 16 | + |
|
| 17 | +**Hardware:** |
|
| 18 | + |
|
| 19 | +* `ESP32-S2 Kaluga Dev Kit featuring ESP32-S2 WROVER <https://www.adafruit.com/product/4729>`_ |
|
| 20 | + |
|
| 21 | +**Software and Dependencies:** |
|
| 22 | + |
|
| 23 | +* Adafruit CircuitPython firmware for the supported boards: |
|
| 24 | + https://github.com/adafruit/circuitpython/releases |
|
| 25 | + |
|
| 26 | +* Adafruit's Bus Device library: https:# github.com/adafruit/Adafruit_CircuitPython_BusDevice |
|
| 27 | +""" |
|
| 28 | + |
|
| 29 | +# imports |
|
| 30 | + |
|
| 31 | +__version__ = "0.0.0+auto.0" |
|
| 32 | +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_OV7670.git" |
|
| 33 | + |
|
| 34 | +import time |
|
| 35 | + |
|
| 36 | +import digitalio |
|
| 37 | +import imagecapture |
|
| 38 | +import pwmio |
|
| 39 | +from adafruit_bus_device.i2c_device import I2CDevice |
|
| 40 | +from micropython import const |
|
| 41 | + |
|
| 42 | +try: |
|
| 43 | + from typing import List, Optional, Type, Union |
|
| 44 | + |
|
| 45 | + from busio import I2C |
|
| 46 | + from circuitpython_typing import WriteableBuffer |
|
| 47 | + from microcontroller import Pin |
|
| 48 | +except ImportError: |
|
| 49 | + pass |
|
| 50 | + |
|
| 51 | +CTRLI = const(0x50) |
|
| 52 | +_R_BYPASS = const(0x05) |
|
| 53 | +_QS = const(0x44) |
|
| 54 | +_CTRLI = const(0x50) |
|
| 55 | +_HSIZE = const(0x51) |
|
| 56 | +_VSIZE = const(0x52) |
|
| 57 | +_XOFFL = const(0x53) |
|
| 58 | +_YOFFL = const(0x54) |
|
| 59 | +_VHYX = const(0x55) |
|
| 60 | +_DPRP = const(0x56) |
|
| 61 | +_TEST = const(0x57) |
|
| 62 | +_ZMOW = const(0x5A) |
|
| 63 | +_ZMOH = const(0x5B) |
|
| 64 | +_ZMHH = const(0x5C) |
|
| 65 | +_BPADDR = const(0x7C) |
|
| 66 | +_BPDATA = const(0x7D) |
|
| 67 | +_CTRL2 = const(0x86) |
|
| 68 | +_CTRL3 = const(0x87) |
|
| 69 | +_SIZEL = const(0x8C) |
|
| 70 | +_HSIZE8 = const(0xC0) |
|
| 71 | +_VSIZE8 = const(0xC1) |
|
| 72 | +_CTRL0 = const(0xC2) |
|
| 73 | +_CTRL1 = const(0xC3) |
|
| 74 | +_R_DVP_SP = const(0xD3) |
|
| 75 | +_IMAGE_MODE = const(0xDA) |
|
| 76 | +_RESET = const(0xE0) |
|
| 77 | +_MS_SP = const(0xF0) |
|
| 78 | +_SS_ID = const(0xF7) |
|
| 79 | +_SS_CTRL = const(0xF7) |
|
| 80 | +_MC_BIST = const(0xF9) |
|
| 81 | +_MC_AL = const(0xFA) |
|
| 82 | +_MC_AH = const(0xFB) |
|
| 83 | +_MC_D = const(0xFC) |
|
| 84 | +_P_CMD = const(0xFD) |
|
| 85 | +_P_STATUS = const(0xFE) |
|
| 86 | +_BANK_SEL = const(0xFF) |
|
| 87 | + |
|
| 88 | +_CTRLI_LP_DP = const(0x80) |
|
| 89 | +_CTRLI_ROUND = const(0x40) |
|
| 90 | + |
|
| 91 | +_CTRL0_AEC_EN = const(0x80) |
|
| 92 | +_CTRL0_AEC_SEL = const(0x40) |
|
| 93 | +_CTRL0_STAT_SEL = const(0x20) |
|
| 94 | +_CTRL0_VFIRST = const(0x10) |
|
| 95 | +_CTRL0_YUV422 = const(0x08) |
|
| 96 | +_CTRL0_YUV_EN = const(0x04) |
|
| 97 | +_CTRL0_RGB_EN = const(0x02) |
|
| 98 | +_CTRL0_RAW_EN = const(0x01) |
|
| 99 | + |
|
| 100 | +_CTRL2_DCW_EN = const(0x20) |
|
| 101 | +_CTRL2_SDE_EN = const(0x10) |
|
| 102 | +_CTRL2_UV_ADJ_EN = const(0x08) |
|
| 103 | +_CTRL2_UV_AVG_EN = const(0x04) |
|
| 104 | +_CTRL2_CMX_EN = const(0x01) |
|
| 105 | + |
|
| 106 | +_CTRL3_BPC_EN = const(0x80) |
|
| 107 | +_CTRL3_WPC_EN = const(0x40) |
|
| 108 | + |
|
| 109 | +_R_DVP_SP_AUTO_MODE = const(0x80) |
|
| 110 | + |
|
| 111 | +_R_BYPASS_DSP_EN = const(0x00) |
|
| 112 | +_R_BYPASS_DSP_BYPAS = const(0x01) |
|
| 113 | + |
|
| 114 | +OV2640_COLOR_RGB = 0 |
|
| 115 | +OV2640_COLOR_YUV = 1 |
|
| 116 | +OV2640_COLOR_JPEG = 2 |
|
| 117 | + |
|
| 118 | +_IMAGE_MODE_Y8_DVP_EN = const(0x40) |
|
| 119 | +_IMAGE_MODE_JPEG_EN = const(0x10) |
|
| 120 | +_IMAGE_MODE_YUV422 = const(0x00) |
|
| 121 | +_IMAGE_MODE_RAW10 = const(0x04) |
|
| 122 | +_IMAGE_MODE_RGB565 = const(0x08) |
|
| 123 | +_IMAGE_MODE_HREF_VSYNC = const(0x02) |
|
| 124 | +_IMAGE_MODE_LBYTE_FIRST = const(0x01) |
|
| 125 | + |
|
| 126 | +_RESET_MICROC = const(0x40) |
|
| 127 | +_RESET_SCCB = const(0x20) |
|
| 128 | +_RESET_JPEG = const(0x10) |
|
| 129 | +_RESET_DVP = const(0x04) |
|
| 130 | +_RESET_IPU = const(0x02) |
|
| 131 | +_RESET_CIF = const(0x01) |
|
| 132 | + |
|
| 133 | +_MC_BIST_RESET = const(0x80) |
|
| 134 | +_MC_BIST_BOOT_ROM_SEL = const(0x40) |
|
| 135 | +_MC_BIST_12KB_SEL = const(0x20) |
|
| 136 | +_MC_BIST_12KB_MASK = const(0x30) |
|
| 137 | +_MC_BIST_512KB_SEL = const(0x08) |
|
| 138 | +_MC_BIST_512KB_MASK = const(0x0C) |
|
| 139 | +_MC_BIST_BUSY_BIT_R = const(0x02) |
|
| 140 | +_MC_BIST_MC_RES_ONE_SH_W = const(0x02) |
|
| 141 | +_MC_BIST_LAUNCH = const(0x01) |
|
| 142 | + |
|
| 143 | + |
|
| 144 | +_BANK_DSP = const(0) |
|
| 145 | +_BANK_SENSOR = const(1) |
|
| 146 | + |
|
| 147 | +# Sensor register bank FF=0x01 |
|
| 148 | +_GAIN = const(0x00) |
|
| 149 | +_COM1 = const(0x03) |
|
| 150 | +_REG04 = const(0x04) |
|
| 151 | +_REG08 = const(0x08) |
|
| 152 | +_COM2 = const(0x09) |
|
| 153 | +_REG_PID = const(0x0A) |
|
| 154 | +_REG_VER = const(0x0B) |
|
| 155 | +_COM3 = const(0x0C) |
|
| 156 | +_COM4 = const(0x0D) |
|
| 157 | +_AEC = const(0x10) |
|
| 158 | +_CLKRC = const(0x11) |
|
| 159 | +_COM7 = const(0x12) |
|
| 160 | +_COM8 = const(0x13) |
|
| 161 | +_COM9 = const(0x14) # AGC gain ceiling |
|
| 162 | +_COM10 = const(0x15) |
|
| 163 | +_HSTART = const(0x17) |
|
| 164 | +_HSTOP = const(0x18) |
|
| 165 | +_VSTART = const(0x19) |
|
| 166 | +_VSTOP = const(0x1A) |
|
| 167 | +_MIDH = const(0x1C) |
|
| 168 | +_MIDL = const(0x1D) |
|
| 169 | +_AEW = const(0x24) |
|
| 170 | +_AEB = const(0x25) |
|
| 171 | +_VV = const(0x26) |
|
| 172 | +_REG2A = const(0x2A) |
|
| 173 | +_FRARL = const(0x2B) |
|
| 174 | +_ADDVSL = const(0x2D) |
|
| 175 | +_ADDVSH = const(0x2E) |
|
| 176 | +_YAVG = const(0x2F) |
|
| 177 | +_HSDY = const(0x30) |
|
| 178 | +_HEDY = const(0x31) |
|
| 179 | +_REG32 = const(0x32) |
|
| 180 | +_ARCOM2 = const(0x34) |
|
| 181 | +_REG45 = const(0x45) |
|
| 182 | +_FLL = const(0x46) |
|
| 183 | +_FLH = const(0x47) |
|
| 184 | +_COM19 = const(0x48) |
|
| 185 | +_ZOOMS = const(0x49) |
|
| 186 | +_COM22 = const(0x4B) |
|
| 187 | +_COM25 = const(0x4E) |
|
| 188 | +_BD50 = const(0x4F) |
|
| 189 | +_BD60 = const(0x50) |
|
| 190 | +_REG5D = const(0x5D) |
|
| 191 | +_REG5E = const(0x5E) |
|
| 192 | +_REG5F = const(0x5F) |
|
| 193 | +_REG60 = const(0x60) |
|
| 194 | +_HISTO_LOW = const(0x61) |
|
| 195 | +_HISTO_HIGH = const(0x62) |
|
| 196 | + |
|
| 197 | +_REG04_DEFAULT = const(0x28) |
|
| 198 | +_REG04_HFLIP_IMG = const(0x80) |
|
| 199 | +_REG04_VFLIP_IMG = const(0x40) |
|
| 200 | +_REG04_VREF_EN = const(0x10) |
|
| 201 | +_REG04_HREF_EN = const(0x08) |
|
| 202 | +_REG04_SET = lambda x: (_REG04_DEFAULT | x) |
|
| 203 | + |
|
| 204 | +_COM2_STDBY = const(0x10) |
|
| 205 | +_COM2_OUT_DRIVE_1x = const(0x00) |
|
| 206 | +_COM2_OUT_DRIVE_2x = const(0x01) |
|
| 207 | +_COM2_OUT_DRIVE_3x = const(0x02) |
|
| 208 | +_COM2_OUT_DRIVE_4x = const(0x03) |
|
| 209 | + |
|
| 210 | +_COM3_DEFAULT = const(0x38) |
|
| 211 | +_COM3_BAND_50Hz = const(0x04) |
|
| 212 | +_COM3_BAND_60Hz = const(0x00) |
|
| 213 | +_COM3_BAND_AUTO = const(0x02) |
|
| 214 | +_COM3_BAND_SET = lambda x: (_COM3_DEFAULT | x) |
|
| 215 | + |
|
| 216 | +_COM7_SRST = const(0x80) |
|
| 217 | +_COM7_RES_UXGA = const(0x00) # UXGA |
|
| 218 | +_COM7_RES_SVGA = const(0x40) # SVGA |
|
| 219 | +_COM7_RES_CIF = const(0x20) # CIF |
|
| 220 | +_COM7_ZOOM_EN = const(0x04) # Enable Zoom |
|
| 221 | +_COM7_COLOR_BAR = const(0x02) # Enable Color Bar Test |
|
| 222 | + |
|
| 223 | +_COM8_DEFAULT = const(0xC0) |
|
| 224 | +_COM8_BNDF_EN = const(0x20) # Enable Banding filter |
|
| 225 | +_COM8_AGC_EN = const(0x04) # AGC Auto/Manual control selection |
|
| 226 | +_COM8_AEC_EN = const(0x01) # Auto/Manual Exposure control |
|
| 227 | +_COM8_SET = lambda x: (_COM8_DEFAULT | x) |
|
| 228 | + |
|
| 229 | +_COM9_DEFAULT = const(0x08) |
|
| 230 | +_COM9_AGC_GAIN_2x = const(0x00) # AGC: 2x |
|
| 231 | +_COM9_AGC_GAIN_4x = const(0x01) # AGC: 4x |
|
| 232 | +_COM9_AGC_GAIN_8x = const(0x02) # AGC: 8x |
|
| 233 | +_COM9_AGC_GAIN_16x = const(0x03) # AGC: 16x |
|
| 234 | +_COM9_AGC_GAIN_32x = const(0x04) # AGC: 32x |
|
| 235 | +_COM9_AGC_GAIN_64x = const(0x05) # AGC: 64x |
|
| 236 | +_COM9_AGC_GAIN_128x = const(0x06) # AGC: 128x |
|
| 237 | +_COM9_AGC_SET = lambda x: (_COM9_DEFAULT | (x << 5)) |
|
| 238 | + |
|
| 239 | +_COM10_HREF_EN = const(0x80) # HSYNC changes to HREF |
|
| 240 | +_COM10_HSYNC_EN = const(0x40) # HREF changes to HSYNC |
|
| 241 | +_COM10_PCLK_FREE = const(0x20) # PCLK output option: free running PCLK |
|
| 242 | +_COM10_PCLK_EDGE = const(0x10) # Data is updated at the rising edge of PCLK |
|
| 243 | +_COM10_HREF_NEG = const(0x08) # HREF negative |
|
| 244 | +_COM10_VSYNC_NEG = const(0x02) # VSYNC negative |
|
| 245 | +_COM10_HSYNC_NEG = const(0x01) # HSYNC negative |
|
| 246 | + |
|
| 247 | +_CTRL1_AWB = const(0x08) # Enable AWB |
|
| 248 | + |
|
| 249 | +_VV_AGC_TH_SET = lambda h, l: ((h << 4) | (l & 0x0F)) |
|
| 250 | + |
|
| 251 | +_REG32_UXGA = const(0x36) |
|
| 252 | +_REG32_SVGA = const(0x09) |
|
| 253 | +_REG32_CIF = const(0x89) |
|
| 254 | + |
|
| 255 | +_CLKRC_2X = const(0x80) |
|
| 256 | +_CLKRC_2X_UXGA = const(0x01 | _CLKRC_2X) |
|
| 257 | +_CLKRC_2X_SVGA = _CLKRC_2X |
|
| 258 | +_CLKRC_2X_CIF = _CLKRC_2X |
|
| 259 | + |
|
| 260 | +_OV2640_MODE_CIF = const(0) |
|
| 261 | +_OV2640_MODE_SVGA = const(1) |
|
| 262 | +_OV2640_MODE_UXGA = const(2) |
|
| 263 | + |
|
| 264 | +OV2640_SIZE_96X96 = 0 # 96x96 |
|
| 265 | +OV2640_SIZE_QQVGA = 1 # 160x120 |
|
| 266 | +OV2640_SIZE_QCIF = 2 # 176x144 |
|
| 267 | +OV2640_SIZE_HQVGA = 3 # 240x176 |
|
| 268 | +OV2640_SIZE_240X240 = 4 # 240x240 |
|
| 269 | +OV2640_SIZE_QVGA = 5 # 320x240 |
|
| 270 | +OV2640_SIZE_CIF = 6 # 400x296 |
|
| 271 | +OV2640_SIZE_HVGA = 7 # 480x320 |
|
| 272 | +OV2640_SIZE_VGA = 8 # 640x480 |
|
| 273 | +OV2640_SIZE_SVGA = 9 # 800x600 |
|
| 274 | +OV2640_SIZE_XGA = 10 # 1024x768 |
|
| 275 | +OV2640_SIZE_HD = 11 # 1280x720 |
|
| 276 | +OV2640_SIZE_SXGA = 12 # 1280x1024 |
|
| 277 | +OV2640_SIZE_UXGA = 13 # 1600x1200 |
|
| 278 | + |
|
| 279 | +_ASPECT_RATIO_4X3 = const(0) |
|
| 280 | +_ASPECT_RATIO_3X2 = const(1) |
|
| 281 | +_ASPECT_RATIO_16X10 = const(2) |
|
| 282 | +_ASPECT_RATIO_5X3 = const(3) |
|
| 283 | +_ASPECT_RATIO_16X9 = const(4) |
|
| 284 | +_ASPECT_RATIO_21X9 = const(5) |
|
| 285 | +_ASPECT_RATIO_5X4 = const(6) |
|
| 286 | +_ASPECT_RATIO_1X1 = const(7) |
|
| 287 | +_ASPECT_RATIO_9X16 = const(8) |
|
| 288 | + |
|
| 289 | +_resolution_info = [ |
|
| 290 | + [96, 96, _ASPECT_RATIO_1X1], # 96x96 |
|
| 291 | + [160, 120, _ASPECT_RATIO_4X3], # QQVGA |
|
| 292 | + [176, 144, _ASPECT_RATIO_5X4], # QCIF |
|
| 293 | + [240, 176, _ASPECT_RATIO_4X3], # HQVGA |
|
| 294 | + [240, 240, _ASPECT_RATIO_1X1], # 240x240 |
|
| 295 | + [320, 240, _ASPECT_RATIO_4X3], # QVGA |
|
| 296 | + [400, 296, _ASPECT_RATIO_4X3], # CIF |
|
| 297 | + [480, 320, _ASPECT_RATIO_3X2], # HVGA |
|
| 298 | + [640, 480, _ASPECT_RATIO_4X3], # VGA |
|
| 299 | + [800, 600, _ASPECT_RATIO_4X3], # SVGA |
|
| 300 | + [1024, 768, _ASPECT_RATIO_4X3], # XGA |
|
| 301 | + [1280, 720, _ASPECT_RATIO_16X9], # HD |
|
| 302 | + [1280, 1024, _ASPECT_RATIO_5X4], # SXGA |
|
| 303 | + [1600, 1200, _ASPECT_RATIO_4X3], # UXGA |
|
| 304 | +] |
|
| 305 | + |
|
| 306 | +_ratio_table = [ |
|
| 307 | + # ox, oy, mx, my |
|
| 308 | + [0, 0, 1600, 1200], # 4x3 |
|
| 309 | + [8, 72, 1584, 1056], # 3x2 |
|
| 310 | + [0, 100, 1600, 1000], # 16x10 |
|
| 311 | + [0, 120, 1600, 960], # 5x3 |
|
| 312 | + [0, 150, 1600, 900], # 16x9 |
|
| 313 | + [2, 258, 1596, 684], # 21x9 |
|
| 314 | + [50, 0, 1500, 1200], # 5x4 |
|
| 315 | + [200, 0, 1200, 1200], # 1x1 |
|
| 316 | + [462, 0, 676, 1200], # 9x16 |
|
| 317 | +] |
|
| 318 | + |
|
| 319 | +# 30fps@24MHz |
|
| 320 | +_ov2640_settings_cif = bytes( |
|
| 321 | + [ |
|
| 322 | + _BANK_SEL, |
|
| 323 | + _BANK_DSP, |
|
| 324 | + 0x2C, |
|
| 325 | + 0xFF, |
|
| 326 | + 0x2E, |
|
| 327 | + 0xDF, |
|
| 328 | + _BANK_SEL, |
|
| 329 | + _BANK_SENSOR, |
|
| 330 | + 0x3C, |
|
| 331 | + 0x32, |
|
| 332 | + _CLKRC, |
|
| 333 | + 0x01, |
|
| 334 | + _COM2, |
|
| 335 | + _COM2_OUT_DRIVE_3x, |
|
| 336 | + _REG04, |
|
| 337 | + _REG04_DEFAULT, |
|
| 338 | + _COM8, |
|
| 339 | + _COM8_DEFAULT | _COM8_BNDF_EN | _COM8_AGC_EN | _COM8_AEC_EN, |
|
| 340 | + _COM9, |
|
| 341 | + _COM9_AGC_SET(_COM9_AGC_GAIN_8x), |
|
| 342 | + 0x2C, |
|
| 343 | + 0x0C, |
|
| 344 | + 0x33, |
|
| 345 | + 0x78, |
|
| 346 | + 0x3A, |
|
| 347 | + 0x33, |
|
| 348 | + 0x3B, |
|
| 349 | + 0xFB, |
|
| 350 | + 0x3E, |
|
| 351 | + 0x00, |
|
| 352 | + 0x43, |
|
| 353 | + 0x11, |
|
| 354 | + 0x16, |
|
| 355 | + 0x10, |
|
| 356 | + 0x39, |
|
| 357 | + 0x92, |
|
| 358 | + 0x35, |
|
| 359 | + 0xDA, |
|
| 360 | + 0x22, |
|
| 361 | + 0x1A, |
|
| 362 | + 0x37, |
|
| 363 | + 0xC3, |
|
| 364 | + 0x23, |
|
| 365 | + 0x00, |
|
| 366 | + _ARCOM2, |
|
| 367 | + 0xC0, |
|
| 368 | + 0x06, |
|
| 369 | + 0x88, |
|
| 370 | + 0x07, |
|
| 371 | + 0xC0, |
|
| 372 | + _COM4, |
|
| 373 | + 0x87, |
|
| 374 | + 0x0E, |
|
| 375 | + 0x41, |
|
| 376 | + 0x4C, |
|
| 377 | + 0x00, |
|
| 378 | + 0x4A, |
|
| 379 | + 0x81, |
|
| 380 | + 0x21, |
|
| 381 | + 0x99, |
|
| 382 | + _AEW, |
|
| 383 | + 0x40, |
|
| 384 | + _AEB, |
|
| 385 | + 0x38, |
|
| 386 | + _VV, |
|
| 387 | + _VV_AGC_TH_SET(8, 2), |
|
| 388 | + 0x5C, |
|
| 389 | + 0x00, |
|
| 390 | + 0x63, |
|
| 391 | + 0x00, |
|
| 392 | + _HISTO_LOW, |
|
| 393 | + 0x70, |
|
| 394 | + _HISTO_HIGH, |
|
| 395 | + 0x80, |
|
| 396 | + 0x7C, |
|
| 397 | + 0x05, |
|
| 398 | + 0x20, |
|
| 399 | + 0x80, |
|
| 400 | + 0x28, |
|
| 401 | + 0x30, |
|
| 402 | + 0x6C, |
|
| 403 | + 0x00, |
|
| 404 | + 0x6D, |
|
| 405 | + 0x80, |
|
| 406 | + 0x6E, |
|
| 407 | + 0x00, |
|
| 408 | + 0x70, |
|
| 409 | + 0x02, |
|
| 410 | + 0x71, |
|
| 411 | + 0x94, |
|
| 412 | + 0x73, |
|
| 413 | + 0xC1, |
|
| 414 | + 0x3D, |
|
| 415 | + 0x34, |
|
| 416 | + 0x5A, |
|
| 417 | + 0x57, |
|
| 418 | + _BD50, |
|
| 419 | + 0xBB, |
|
| 420 | + _BD60, |
|
| 421 | + 0x9C, |
|
| 422 | + _COM7, |
|
| 423 | + _COM7_RES_CIF, |
|
| 424 | + _HSTART, |
|
| 425 | + 0x11, |
|
| 426 | + _HSTOP, |
|
| 427 | + 0x43, |
|
| 428 | + _VSTART, |
|
| 429 | + 0x00, |
|
| 430 | + _VSTOP, |
|
| 431 | + 0x25, |
|
| 432 | + _REG32, |
|
| 433 | + 0x89, |
|
| 434 | + 0x37, |
|
| 435 | + 0xC0, |
|
| 436 | + _BD50, |
|
| 437 | + 0xCA, |
|
| 438 | + _BD60, |
|
| 439 | + 0xA8, |
|
| 440 | + 0x6D, |
|
| 441 | + 0x00, |
|
| 442 | + 0x3D, |
|
| 443 | + 0x38, |
|
| 444 | + _BANK_SEL, |
|
| 445 | + _BANK_DSP, |
|
| 446 | + 0xE5, |
|
| 447 | + 0x7F, |
|
| 448 | + _MC_BIST, |
|
| 449 | + _MC_BIST_RESET | _MC_BIST_BOOT_ROM_SEL, |
|
| 450 | + 0x41, |
|
| 451 | + 0x24, |
|
| 452 | + _RESET, |
|
| 453 | + _RESET_JPEG | _RESET_DVP, |
|
| 454 | + 0x76, |
|
| 455 | + 0xFF, |
|
| 456 | + 0x33, |
|
| 457 | + 0xA0, |
|
| 458 | + 0x42, |
|
| 459 | + 0x20, |
|
| 460 | + 0x43, |
|
| 461 | + 0x18, |
|
| 462 | + 0x4C, |
|
| 463 | + 0x00, |
|
| 464 | + _CTRL3, |
|
| 465 | + _CTRL3_WPC_EN | 0x10, |
|
| 466 | + 0x88, |
|
| 467 | + 0x3F, |
|
| 468 | + 0xD7, |
|
| 469 | + 0x03, |
|
| 470 | + 0xD9, |
|
| 471 | + 0x10, |
|
| 472 | + _R_DVP_SP, |
|
| 473 | + _R_DVP_SP_AUTO_MODE | 0x02, |
|
| 474 | + 0xC8, |
|
| 475 | + 0x08, |
|
| 476 | + 0xC9, |
|
| 477 | + 0x80, |
|
| 478 | + _BPADDR, |
|
| 479 | + 0x00, |
|
| 480 | + _BPDATA, |
|
| 481 | + 0x00, |
|
| 482 | + _BPADDR, |
|
| 483 | + 0x03, |
|
| 484 | + _BPDATA, |
|
| 485 | + 0x48, |
|
| 486 | + _BPDATA, |
|
| 487 | + 0x48, |
|
| 488 | + _BPADDR, |
|
| 489 | + 0x08, |
|
| 490 | + _BPDATA, |
|
| 491 | + 0x20, |
|
| 492 | + _BPDATA, |
|
| 493 | + 0x10, |
|
| 494 | + _BPDATA, |
|
| 495 | + 0x0E, |
|
| 496 | + 0x90, |
|
| 497 | + 0x00, |
|
| 498 | + 0x91, |
|
| 499 | + 0x0E, |
|
| 500 | + 0x91, |
|
| 501 | + 0x1A, |
|
| 502 | + 0x91, |
|
| 503 | + 0x31, |
|
| 504 | + 0x91, |
|
| 505 | + 0x5A, |
|
| 506 | + 0x91, |
|
| 507 | + 0x69, |
|
| 508 | + 0x91, |
|
| 509 | + 0x75, |
|
| 510 | + 0x91, |
|
| 511 | + 0x7E, |
|
| 512 | + 0x91, |
|
| 513 | + 0x88, |
|
| 514 | + 0x91, |
|
| 515 | + 0x8F, |
|
| 516 | + 0x91, |
|
| 517 | + 0x96, |
|
| 518 | + 0x91, |
|
| 519 | + 0xA3, |
|
| 520 | + 0x91, |
|
| 521 | + 0xAF, |
|
| 522 | + 0x91, |
|
| 523 | + 0xC4, |
|
| 524 | + 0x91, |
|
| 525 | + 0xD7, |
|
| 526 | + 0x91, |
|
| 527 | + 0xE8, |
|
| 528 | + 0x91, |
|
| 529 | + 0x20, |
|
| 530 | + 0x92, |
|
| 531 | + 0x00, |
|
| 532 | + 0x93, |
|
| 533 | + 0x06, |
|
| 534 | + 0x93, |
|
| 535 | + 0xE3, |
|
| 536 | + 0x93, |
|
| 537 | + 0x05, |
|
| 538 | + 0x93, |
|
| 539 | + 0x05, |
|
| 540 | + 0x93, |
|
| 541 | + 0x00, |
|
| 542 | + 0x93, |
|
| 543 | + 0x04, |
|
| 544 | + 0x93, |
|
| 545 | + 0x00, |
|
| 546 | + 0x93, |
|
| 547 | + 0x00, |
|
| 548 | + 0x93, |
|
| 549 | + 0x00, |
|
| 550 | + 0x93, |
|
| 551 | + 0x00, |
|
| 552 | + 0x93, |
|
| 553 | + 0x00, |
|
| 554 | + 0x93, |
|
| 555 | + 0x00, |
|
| 556 | + 0x93, |
|
| 557 | + 0x00, |
|
| 558 | + 0x96, |
|
| 559 | + 0x00, |
|
| 560 | + 0x97, |
|
| 561 | + 0x08, |
|
| 562 | + 0x97, |
|
| 563 | + 0x19, |
|
| 564 | + 0x97, |
|
| 565 | + 0x02, |
|
| 566 | + 0x97, |
|
| 567 | + 0x0C, |
|
| 568 | + 0x97, |
|
| 569 | + 0x24, |
|
| 570 | + 0x97, |
|
| 571 | + 0x30, |
|
| 572 | + 0x97, |
|
| 573 | + 0x28, |
|
| 574 | + 0x97, |
|
| 575 | + 0x26, |
|
| 576 | + 0x97, |
|
| 577 | + 0x02, |
|
| 578 | + 0x97, |
|
| 579 | + 0x98, |
|
| 580 | + 0x97, |
|
| 581 | + 0x80, |
|
| 582 | + 0x97, |
|
| 583 | + 0x00, |
|
| 584 | + 0x97, |
|
| 585 | + 0x00, |
|
| 586 | + 0xA4, |
|
| 587 | + 0x00, |
|
| 588 | + 0xA8, |
|
| 589 | + 0x00, |
|
| 590 | + 0xC5, |
|
| 591 | + 0x11, |
|
| 592 | + 0xC6, |
|
| 593 | + 0x51, |
|
| 594 | + 0xBF, |
|
| 595 | + 0x80, |
|
| 596 | + 0xC7, |
|
| 597 | + 0x10, |
|
| 598 | + 0xB6, |
|
| 599 | + 0x66, |
|
| 600 | + 0xB8, |
|
| 601 | + 0xA5, |
|
| 602 | + 0xB7, |
|
| 603 | + 0x64, |
|
| 604 | + 0xB9, |
|
| 605 | + 0x7C, |
|
| 606 | + 0xB3, |
|
| 607 | + 0xAF, |
|
| 608 | + 0xB4, |
|
| 609 | + 0x97, |
|
| 610 | + 0xB5, |
|
| 611 | + 0xFF, |
|
| 612 | + 0xB0, |
|
| 613 | + 0xC5, |
|
| 614 | + 0xB1, |
|
| 615 | + 0x94, |
|
| 616 | + 0xB2, |
|
| 617 | + 0x0F, |
|
| 618 | + 0xC4, |
|
| 619 | + 0x5C, |
|
| 620 | + _CTRL1, |
|
| 621 | + 0xFD, |
|
| 622 | + 0x7F, |
|
| 623 | + 0x00, |
|
| 624 | + 0xE5, |
|
| 625 | + 0x1F, |
|
| 626 | + 0xE1, |
|
| 627 | + 0x67, |
|
| 628 | + 0xDD, |
|
| 629 | + 0x7F, |
|
| 630 | + _IMAGE_MODE, |
|
| 631 | + 0x00, |
|
| 632 | + _RESET, |
|
| 633 | + 0x00, |
|
| 634 | + _R_BYPASS, |
|
| 635 | + _R_BYPASS_DSP_EN, |
|
| 636 | + ] |
|
| 637 | +) |
|
| 638 | + |
|
| 639 | +_ov2640_settings_to_cif = bytes( |
|
| 640 | + [ |
|
| 641 | + _BANK_SEL, |
|
| 642 | + _BANK_SENSOR, |
|
| 643 | + _COM7, |
|
| 644 | + _COM7_RES_CIF, |
|
| 645 | + # Set the sensor output window |
|
| 646 | + _COM1, |
|
| 647 | + 0x0A, |
|
| 648 | + _REG32, |
|
| 649 | + _REG32_CIF, |
|
| 650 | + _HSTART, |
|
| 651 | + 0x11, |
|
| 652 | + _HSTOP, |
|
| 653 | + 0x43, |
|
| 654 | + _VSTART, |
|
| 655 | + 0x00, |
|
| 656 | + _VSTOP, |
|
| 657 | + 0x25, |
|
| 658 | + # _CLKRC, 0x00, |
|
| 659 | + _BD50, |
|
| 660 | + 0xCA, |
|
| 661 | + _BD60, |
|
| 662 | + 0xA8, |
|
| 663 | + 0x5A, |
|
| 664 | + 0x23, |
|
| 665 | + 0x6D, |
|
| 666 | + 0x00, |
|
| 667 | + 0x3D, |
|
| 668 | + 0x38, |
|
| 669 | + 0x39, |
|
| 670 | + 0x92, |
|
| 671 | + 0x35, |
|
| 672 | + 0xDA, |
|
| 673 | + 0x22, |
|
| 674 | + 0x1A, |
|
| 675 | + 0x37, |
|
| 676 | + 0xC3, |
|
| 677 | + 0x23, |
|
| 678 | + 0x00, |
|
| 679 | + _ARCOM2, |
|
| 680 | + 0xC0, |
|
| 681 | + 0x06, |
|
| 682 | + 0x88, |
|
| 683 | + 0x07, |
|
| 684 | + 0xC0, |
|
| 685 | + _COM4, |
|
| 686 | + 0x87, |
|
| 687 | + 0x0E, |
|
| 688 | + 0x41, |
|
| 689 | + 0x4C, |
|
| 690 | + 0x00, |
|
| 691 | + _BANK_SEL, |
|
| 692 | + _BANK_DSP, |
|
| 693 | + _RESET, |
|
| 694 | + _RESET_DVP, |
|
| 695 | + # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 696 | + _HSIZE8, |
|
| 697 | + 0x32, |
|
| 698 | + _VSIZE8, |
|
| 699 | + 0x25, |
|
| 700 | + _SIZEL, |
|
| 701 | + 0x00, |
|
| 702 | + # Set the image window size >= output size |
|
| 703 | + _HSIZE, |
|
| 704 | + 0x64, |
|
| 705 | + _VSIZE, |
|
| 706 | + 0x4A, |
|
| 707 | + _XOFFL, |
|
| 708 | + 0x00, |
|
| 709 | + _YOFFL, |
|
| 710 | + 0x00, |
|
| 711 | + _VHYX, |
|
| 712 | + 0x00, |
|
| 713 | + _TEST, |
|
| 714 | + 0x00, |
|
| 715 | + _CTRL2, |
|
| 716 | + _CTRL2_DCW_EN | 0x1D, |
|
| 717 | + _CTRLI, |
|
| 718 | + _CTRLI_LP_DP | 0x00, |
|
| 719 | + # _R_DVP_SP, 0x08, |
|
| 720 | + ] |
|
| 721 | +) |
|
| 722 | + |
|
| 723 | +_ov2640_settings_to_svga = bytes( |
|
| 724 | + [ |
|
| 725 | + _BANK_SEL, |
|
| 726 | + _BANK_SENSOR, |
|
| 727 | + _COM7, |
|
| 728 | + _COM7_RES_SVGA, |
|
| 729 | + # Set the sensor output window |
|
| 730 | + _COM1, |
|
| 731 | + 0x0A, |
|
| 732 | + _REG32, |
|
| 733 | + _REG32_SVGA, |
|
| 734 | + _HSTART, |
|
| 735 | + 0x11, |
|
| 736 | + _HSTOP, |
|
| 737 | + 0x43, |
|
| 738 | + _VSTART, |
|
| 739 | + 0x00, |
|
| 740 | + _VSTOP, |
|
| 741 | + 0x4B, |
|
| 742 | + # _CLKRC, 0x00, |
|
| 743 | + 0x37, |
|
| 744 | + 0xC0, |
|
| 745 | + _BD50, |
|
| 746 | + 0xCA, |
|
| 747 | + _BD60, |
|
| 748 | + 0xA8, |
|
| 749 | + 0x5A, |
|
| 750 | + 0x23, |
|
| 751 | + 0x6D, |
|
| 752 | + 0x00, |
|
| 753 | + 0x3D, |
|
| 754 | + 0x38, |
|
| 755 | + 0x39, |
|
| 756 | + 0x92, |
|
| 757 | + 0x35, |
|
| 758 | + 0xDA, |
|
| 759 | + 0x22, |
|
| 760 | + 0x1A, |
|
| 761 | + 0x37, |
|
| 762 | + 0xC3, |
|
| 763 | + 0x23, |
|
| 764 | + 0x00, |
|
| 765 | + _ARCOM2, |
|
| 766 | + 0xC0, |
|
| 767 | + 0x06, |
|
| 768 | + 0x88, |
|
| 769 | + 0x07, |
|
| 770 | + 0xC0, |
|
| 771 | + _COM4, |
|
| 772 | + 0x87, |
|
| 773 | + 0x0E, |
|
| 774 | + 0x41, |
|
| 775 | + 0x42, |
|
| 776 | + 0x03, |
|
| 777 | + 0x4C, |
|
| 778 | + 0x00, |
|
| 779 | + _BANK_SEL, |
|
| 780 | + _BANK_DSP, |
|
| 781 | + _RESET, |
|
| 782 | + _RESET_DVP, |
|
| 783 | + # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 784 | + _HSIZE8, |
|
| 785 | + 0x64, |
|
| 786 | + _VSIZE8, |
|
| 787 | + 0x4B, |
|
| 788 | + _SIZEL, |
|
| 789 | + 0x00, |
|
| 790 | + # Set the image window size >= output size |
|
| 791 | + _HSIZE, |
|
| 792 | + 0xC8, |
|
| 793 | + _VSIZE, |
|
| 794 | + 0x96, |
|
| 795 | + _XOFFL, |
|
| 796 | + 0x00, |
|
| 797 | + _YOFFL, |
|
| 798 | + 0x00, |
|
| 799 | + _VHYX, |
|
| 800 | + 0x00, |
|
| 801 | + _TEST, |
|
| 802 | + 0x00, |
|
| 803 | + _CTRL2, |
|
| 804 | + _CTRL2_DCW_EN | 0x1D, |
|
| 805 | + _CTRLI, |
|
| 806 | + _CTRLI_LP_DP | 0x00, |
|
| 807 | + # _R_DVP_SP, 0x08, |
|
| 808 | + ] |
|
| 809 | +) |
|
| 810 | + |
|
| 811 | +_ov2640_settings_to_uxga = bytes( |
|
| 812 | + [ |
|
| 813 | + _BANK_SEL, |
|
| 814 | + _BANK_SENSOR, |
|
| 815 | + _COM7, |
|
| 816 | + _COM7_RES_UXGA, |
|
| 817 | + # Set the sensor output window |
|
| 818 | + _COM1, |
|
| 819 | + 0x0F, |
|
| 820 | + _REG32, |
|
| 821 | + _REG32_UXGA, |
|
| 822 | + _HSTART, |
|
| 823 | + 0x11, |
|
| 824 | + _HSTOP, |
|
| 825 | + 0x75, |
|
| 826 | + _VSTART, |
|
| 827 | + 0x01, |
|
| 828 | + _VSTOP, |
|
| 829 | + 0x97, |
|
| 830 | + # _CLKRC, 0x00, |
|
| 831 | + 0x3D, |
|
| 832 | + 0x34, |
|
| 833 | + _BD50, |
|
| 834 | + 0xBB, |
|
| 835 | + _BD60, |
|
| 836 | + 0x9C, |
|
| 837 | + 0x5A, |
|
| 838 | + 0x57, |
|
| 839 | + 0x6D, |
|
| 840 | + 0x80, |
|
| 841 | + 0x39, |
|
| 842 | + 0x82, |
|
| 843 | + 0x23, |
|
| 844 | + 0x00, |
|
| 845 | + 0x07, |
|
| 846 | + 0xC0, |
|
| 847 | + 0x4C, |
|
| 848 | + 0x00, |
|
| 849 | + 0x35, |
|
| 850 | + 0x88, |
|
| 851 | + 0x22, |
|
| 852 | + 0x0A, |
|
| 853 | + 0x37, |
|
| 854 | + 0x40, |
|
| 855 | + _ARCOM2, |
|
| 856 | + 0xA0, |
|
| 857 | + 0x06, |
|
| 858 | + 0x02, |
|
| 859 | + _COM4, |
|
| 860 | + 0xB7, |
|
| 861 | + 0x0E, |
|
| 862 | + 0x01, |
|
| 863 | + 0x42, |
|
| 864 | + 0x83, |
|
| 865 | + _BANK_SEL, |
|
| 866 | + _BANK_DSP, |
|
| 867 | + _RESET, |
|
| 868 | + _RESET_DVP, |
|
| 869 | + # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 870 | + _HSIZE8, |
|
| 871 | + 0xC8, |
|
| 872 | + _VSIZE8, |
|
| 873 | + 0x96, |
|
| 874 | + _SIZEL, |
|
| 875 | + 0x00, |
|
| 876 | + # Set the image window size >= output size |
|
| 877 | + _HSIZE, |
|
| 878 | + 0x90, |
|
| 879 | + _VSIZE, |
|
| 880 | + 0x2C, |
|
| 881 | + _XOFFL, |
|
| 882 | + 0x00, |
|
| 883 | + _YOFFL, |
|
| 884 | + 0x00, |
|
| 885 | + _VHYX, |
|
| 886 | + 0x88, |
|
| 887 | + _TEST, |
|
| 888 | + 0x00, |
|
| 889 | + _CTRL2, |
|
| 890 | + _CTRL2_DCW_EN | 0x1D, |
|
| 891 | + _CTRLI, |
|
| 892 | + 0x00, |
|
| 893 | + # _R_DVP_SP, 0x06, |
|
| 894 | + ] |
|
| 895 | +) |
|
| 896 | + |
|
| 897 | +_ov2640_color_settings = { |
|
| 898 | + OV2640_COLOR_JPEG: bytes( |
|
| 899 | + [ |
|
| 900 | + _BANK_SEL, |
|
| 901 | + _BANK_DSP, |
|
| 902 | + _RESET, |
|
| 903 | + _RESET_JPEG | _RESET_DVP, |
|
| 904 | + _IMAGE_MODE, |
|
| 905 | + _IMAGE_MODE_JPEG_EN | _IMAGE_MODE_HREF_VSYNC, |
|
| 906 | + 0xD7, |
|
| 907 | + 0x03, |
|
| 908 | + 0xE1, |
|
| 909 | + 0x77, |
|
| 910 | + 0xE5, |
|
| 911 | + 0x1F, |
|
| 912 | + 0xD9, |
|
| 913 | + 0x10, |
|
| 914 | + 0xDF, |
|
| 915 | + 0x80, |
|
| 916 | + 0x33, |
|
| 917 | + 0x80, |
|
| 918 | + 0x3C, |
|
| 919 | + 0x10, |
|
| 920 | + 0xEB, |
|
| 921 | + 0x30, |
|
| 922 | + 0xDD, |
|
| 923 | + 0x7F, |
|
| 924 | + _RESET, |
|
| 925 | + 0x00, |
|
| 926 | + ] |
|
| 927 | + ), |
|
| 928 | + OV2640_COLOR_YUV: bytes( |
|
| 929 | + [ |
|
| 930 | + _BANK_SEL, |
|
| 931 | + _BANK_DSP, |
|
| 932 | + _RESET, |
|
| 933 | + _RESET_DVP, |
|
| 934 | + _IMAGE_MODE, |
|
| 935 | + _IMAGE_MODE_YUV422, |
|
| 936 | + 0xD7, |
|
| 937 | + 0x01, |
|
| 938 | + 0xE1, |
|
| 939 | + 0x67, |
|
| 940 | + _RESET, |
|
| 941 | + 0x00, |
|
| 942 | + ] |
|
| 943 | + ), |
|
| 944 | + OV2640_COLOR_RGB: bytes( |
|
| 945 | + [ |
|
| 946 | + _BANK_SEL, |
|
| 947 | + _BANK_DSP, |
|
| 948 | + _RESET, |
|
| 949 | + _RESET_DVP, |
|
| 950 | + _IMAGE_MODE, |
|
| 951 | + _IMAGE_MODE_RGB565, |
|
| 952 | + 0xD7, |
|
| 953 | + 0x03, |
|
| 954 | + 0xE1, |
|
| 955 | + 0x77, |
|
| 956 | + _RESET, |
|
| 957 | + 0x00, |
|
| 958 | + ] |
|
| 959 | + ), |
|
| 960 | +} |
|
| 961 | + |
|
| 962 | + |
|
| 963 | +class _RegBits: |
|
| 964 | + def __init__(self, bank: int, reg: int, shift: int, mask: int) -> None: |
|
| 965 | + self.bank = bank |
|
| 966 | + self.reg = reg |
|
| 967 | + self.shift = shift |
|
| 968 | + self.mask = mask |
|
| 969 | + |
|
| 970 | + def __get__(self, obj: "_SCCBCameraBase", objtype: Optional[Type] = None) -> int: |
|
| 971 | + reg_value = obj._read_bank_register(self.bank, self.reg) |
|
| 972 | + return (reg_value >> self.shift) & self.mask |
|
| 973 | + |
|
| 974 | + def __set__(self, obj: "_SCCBCameraBase", value: Union[bool, int]) -> None: |
|
| 975 | + if value & ~self.mask: |
|
| 976 | + raise ValueError(f"Value 0x{value:02x} does not fit in mask 0x{self.mask:02x}") |
|
| 977 | + reg_value = obj._read_bank_register(self.bank, self.reg) |
|
| 978 | + reg_value &= ~(self.mask << self.shift) |
|
| 979 | + reg_value |= value << self.shift |
|
| 980 | + obj._write_register(self.reg, reg_value) |
|
| 981 | + |
|
| 982 | + |
|
| 983 | +class _SCCBCameraBase: |
|
| 984 | + def __init__(self, i2c_bus: I2C, i2c_address: int) -> None: |
|
| 985 | + self._i2c_device = I2CDevice(i2c_bus, i2c_address) |
|
| 986 | + self._bank = None |
|
| 987 | + |
|
| 988 | + def _get_reg_bits(self, bank: int, reg: int, shift: int, mask: int) -> int: |
|
| 989 | + return (self._read_bank_register(bank, reg) >> shift) & mask |
|
| 990 | + |
|
| 991 | + def _set_reg_bits(self, bank: int, reg: int, shift: int, mask: int, value: int) -> None: |
|
| 992 | + reg_value = self._read_bank_register(bank, reg) |
|
| 993 | + reg_value &= ~(mask << shift) |
|
| 994 | + reg_value |= value << shift |
|
| 995 | + self._write_register(reg, reg_value) |
|
| 996 | + |
|
| 997 | + def _write_list(self, reg_list: List[int]) -> None: |
|
| 998 | + for i in range(0, len(reg_list), 2): |
|
| 999 | + self._write_register(reg_list[i], reg_list[i + 1]) |
|
| 1000 | + time.sleep(0.001) |
|
| 1001 | + |
|
| 1002 | + def _write_bank_register(self, bank: int, reg: int, value: int) -> None: |
|
| 1003 | + if self._bank != bank: |
|
| 1004 | + self._write_register(_BANK_SEL, bank) |
|
| 1005 | + self._write_register(reg, value) |
|
| 1006 | + |
|
| 1007 | + def _read_bank_register(self, bank: int, reg: int) -> int: |
|
| 1008 | + if self._bank != bank: |
|
| 1009 | + self._write_register(_BANK_SEL, bank) |
|
| 1010 | + result = self._read_register(reg) |
|
| 1011 | + return result |
|
| 1012 | + |
|
| 1013 | + def _write_register(self, reg: int, value: int) -> None: |
|
| 1014 | + if reg == _BANK_SEL: |
|
| 1015 | + if self._bank == value: |
|
| 1016 | + return |
|
| 1017 | + self._bank = value |
|
| 1018 | + # print(f"write_register {reg:02x} {value:02x}") |
|
| 1019 | + b = bytearray(2) |
|
| 1020 | + b[0] = reg |
|
| 1021 | + b[1] = value |
|
| 1022 | + with self._i2c_device as i2c: |
|
| 1023 | + i2c.write(b) |
|
| 1024 | + |
|
| 1025 | + def _read_register(self, reg: int) -> int: |
|
| 1026 | + b = bytearray(1) |
|
| 1027 | + b[0] = reg |
|
| 1028 | + with self._i2c_device as i2c: |
|
| 1029 | + i2c.write(b) |
|
| 1030 | + i2c.readinto(b) |
|
| 1031 | + return b[0] |
|
| 1032 | + |
|
| 1033 | + |
|
| 1034 | +class OV2640(_SCCBCameraBase): |
|
| 1035 | + """Library for the OV2640 digital camera""" |
|
| 1036 | + |
|
| 1037 | + test_pattern = _RegBits(_BANK_SENSOR, _COM7, 1, 1) |
|
| 1038 | + gain_ceiling = _RegBits(_BANK_SENSOR, _COM9, 5, 7) |
|
| 1039 | + bpc = _RegBits(_BANK_DSP, _CTRL3, 7, 1) |
|
| 1040 | + wpc = _RegBits(_BANK_DSP, _CTRL3, 6, 1) |
|
| 1041 | + lenc = _RegBits(_BANK_DSP, _CTRL1, 1, 1) |
|
| 1042 | + |
|
| 1043 | + def __init__( |
|
| 1044 | + self, |
|
| 1045 | + i2c_bus: I2C, |
|
| 1046 | + data_pins: Pin, |
|
| 1047 | + clock: Pin, |
|
| 1048 | + vsync: Pin, |
|
| 1049 | + href: Pin, |
|
| 1050 | + shutdown: Optional[Pin] = None, |
|
| 1051 | + reset: Optional[Pin] = None, |
|
| 1052 | + mclk: Optional[Pin] = None, |
|
| 1053 | + mclk_frequency: int = 20_000_000, |
|
| 1054 | + i2c_address: int = 0x30, |
|
| 1055 | + size: int = OV2640_SIZE_QQVGA, |
|
| 1056 | + ): |
|
| 1057 | + """ |
|
| 1058 | + Args: |
|
| 1059 | + i2c_bus (busio.I2C): The I2C bus used to configure the OV2640 |
|
| 1060 | + data_pins (List[microcontroller.Pin]): A list of 8 data pins, in order. |
|
| 1061 | + clock (microcontroller.Pin): The pixel clock from the OV2640. |
|
| 1062 | + vsync (microcontroller.Pin): The vsync signal from the OV2640. |
|
| 1063 | + href (microcontroller.Pin): The href signal from the OV2640, \ |
|
| 1064 | + sometimes inaccurately called hsync. |
|
| 1065 | + shutdown (Optional[microcontroller.Pin]): If not None, the shutdown |
|
| 1066 | + signal to the camera, also called the powerdown or enable pin. |
|
| 1067 | + reset (Optional[microcontroller.Pin]): If not None, the reset signal |
|
| 1068 | + to the camera. |
|
| 1069 | + mclk (Optional[microcontroller.Pin]): The pin on which to create a |
|
| 1070 | + master clock signal, or None if the master clock signal is |
|
| 1071 | + already being generated. |
|
| 1072 | + mclk_frequency (int): The frequency of the master clock to generate, \ |
|
| 1073 | + ignored if mclk is None, requred if it is specified |
|
| 1074 | + i2c_address (int): The I2C address of the camera. |
|
| 1075 | + """ |
|
| 1076 | + |
|
| 1077 | + # Initialize the master clock |
|
| 1078 | + if mclk: |
|
| 1079 | + self._mclk_pwm = pwmio.PWMOut(mclk, frequency=mclk_frequency) |
|
| 1080 | + self._mclk_pwm.duty_cycle = 32768 |
|
| 1081 | + else: |
|
| 1082 | + self._mclk_pwm = None |
|
| 1083 | + |
|
| 1084 | + if shutdown: |
|
| 1085 | + self._shutdown = digitalio.DigitalInOut(shutdown) |
|
| 1086 | + self._shutdown.switch_to_output(True) |
|
| 1087 | + time.sleep(0.1) |
|
| 1088 | + self._shutdown.switch_to_output(False) |
|
| 1089 | + time.sleep(0.3) |
|
| 1090 | + else: |
|
| 1091 | + self._shutdown = None |
|
| 1092 | + |
|
| 1093 | + if reset: |
|
| 1094 | + self._reset = digitalio.DigitalInOut(reset) |
|
| 1095 | + self._reset.switch_to_output(False) |
|
| 1096 | + time.sleep(0.1) |
|
| 1097 | + self._reset.switch_to_output(True) |
|
| 1098 | + time.sleep(0.1) |
|
| 1099 | + |
|
| 1100 | + super().__init__(i2c_bus, i2c_address) |
|
| 1101 | + |
|
| 1102 | + self._write_bank_register(_BANK_SENSOR, _COM7, _COM7_SRST) |
|
| 1103 | + time.sleep(0.001) |
|
| 1104 | + |
|
| 1105 | + self._write_list(_ov2640_settings_cif) |
|
| 1106 | + |
|
| 1107 | + self._colorspace = OV2640_COLOR_RGB |
|
| 1108 | + self._w = None |
|
| 1109 | + self._h = None |
|
| 1110 | + self._size = None |
|
| 1111 | + self._test_pattern = False |
|
| 1112 | + self.size = size |
|
| 1113 | + |
|
| 1114 | + self._flip_x = False |
|
| 1115 | + self._flip_y = False |
|
| 1116 | + |
|
| 1117 | + self.gain_ceiling = _COM9_AGC_GAIN_2x |
|
| 1118 | + self.bpc = False |
|
| 1119 | + self.wpc = True |
|
| 1120 | + self.lenc = True |
|
| 1121 | + |
|
| 1122 | + # self._sensor_init() |
|
| 1123 | + |
|
| 1124 | + self._imagecapture = imagecapture.ParallelImageCapture( |
|
| 1125 | + data_pins=data_pins, clock=clock, vsync=vsync, href=href |
|
| 1126 | + ) |
|
| 1127 | + |
|
| 1128 | + def capture(self, buf: WriteableBuffer) -> Optional[memoryview]: |
|
| 1129 | + """Capture an image into the buffer. |
|
| 1130 | + |
|
| 1131 | + Args: |
|
| 1132 | + buf (WriteableBuffer): A WritableBuffer to contain the \ |
|
| 1133 | + captured image. Note that this can be a ulab array or a displayio Bitmap. |
|
| 1134 | + """ |
|
| 1135 | + self._imagecapture.capture(buf) |
|
| 1136 | + if self.colorspace == OV2640_COLOR_JPEG: |
|
| 1137 | + eoi = buf.find(b"\xff\xd9") |
|
| 1138 | + if eoi != -1: |
|
| 1139 | + # terminate the JPEG data just after the EOI marker |
|
| 1140 | + return memoryview(buf)[: eoi + 2] |
|
| 1141 | + return None |
|
| 1142 | + |
|
| 1143 | + @property |
|
| 1144 | + def capture_buffer_size(self) -> int: |
|
| 1145 | + """Return the size of capture buffer to use with current resolution & colorspace settings""" |
|
| 1146 | + if self.colorspace == OV2640_COLOR_JPEG: |
|
| 1147 | + return self.width * self.height // 5 |
|
| 1148 | + return self.width * self.height * 2 |
|
| 1149 | + |
|
| 1150 | + @property |
|
| 1151 | + def mclk_frequency(self) -> Optional[int]: |
|
| 1152 | + """Get the actual frequency the generated mclk, or None""" |
|
| 1153 | + return self._mclk_pwm.frequency if self._mclk_pwm else None |
|
| 1154 | + |
|
| 1155 | + @property |
|
| 1156 | + def width(self) -> int: |
|
| 1157 | + """Get the image width in pixels. A buffer of 2*width*height bytes \ |
|
| 1158 | + stores a whole image.""" |
|
| 1159 | + return self._w |
|
| 1160 | + |
|
| 1161 | + @property |
|
| 1162 | + def height(self) -> int: |
|
| 1163 | + """Get the image height in pixels. A buffer of 2*width*height bytes \ |
|
| 1164 | + stores a whole image.""" |
|
| 1165 | + return self._h |
|
| 1166 | + |
|
| 1167 | + @property |
|
| 1168 | + def colorspace(self) -> bytes: |
|
| 1169 | + """Get or set the colorspace, one of the ``OV2640_COLOR_`` constants.""" |
|
| 1170 | + return self._colorspace |
|
| 1171 | + |
|
| 1172 | + @colorspace.setter |
|
| 1173 | + def colorspace(self, colorspace: bytes) -> None: |
|
| 1174 | + self._colorspace = colorspace |
|
| 1175 | + self._set_size_and_colorspace() |
|
| 1176 | + |
|
| 1177 | + def _set_colorspace(self) -> None: |
|
| 1178 | + colorspace = self._colorspace |
|
| 1179 | + settings = _ov2640_color_settings[colorspace] |
|
| 1180 | + |
|
| 1181 | + self._write_list(settings) |
|
| 1182 | + # written twice? |
|
| 1183 | + self._write_list(settings) |
|
| 1184 | + time.sleep(0.01) |
|
| 1185 | + |
|
| 1186 | + def deinit(self) -> None: |
|
| 1187 | + """Deinitialize the camera""" |
|
| 1188 | + self._imagecapture.deinit() |
|
| 1189 | + if self._mclk_pwm: |
|
| 1190 | + self._mclk_pwm.deinit() |
|
| 1191 | + if self._shutdown: |
|
| 1192 | + self._shutdown.deinit() |
|
| 1193 | + if self._reset: |
|
| 1194 | + self._reset.deinit() |
|
| 1195 | + |
|
| 1196 | + @property |
|
| 1197 | + def size(self) -> int: |
|
| 1198 | + """Get or set the captured image size, one of the ``OV2640_SIZE_`` constants.""" |
|
| 1199 | + return self._size |
|
| 1200 | + |
|
| 1201 | + def _set_size_and_colorspace(self) -> None: |
|
| 1202 | + size = self._size |
|
| 1203 | + width, height, ratio = _resolution_info[size] |
|
| 1204 | + offset_x, offset_y, max_x, max_y = _ratio_table[ratio] |
|
| 1205 | + mode = _OV2640_MODE_UXGA |
|
| 1206 | + if size <= OV2640_SIZE_CIF: |
|
| 1207 | + mode = _OV2640_MODE_CIF |
|
| 1208 | + max_x //= 4 |
|
| 1209 | + max_y //= 4 |
|
| 1210 | + offset_x //= 4 |
|
| 1211 | + offset_y //= 4 |
|
| 1212 | + max_y = min(max_y, 296) |
|
| 1213 | + |
|
| 1214 | + elif size <= OV2640_SIZE_SVGA: |
|
| 1215 | + mode = _OV2640_MODE_SVGA |
|
| 1216 | + max_x //= 2 |
|
| 1217 | + max_y //= 2 |
|
| 1218 | + offset_x //= 2 |
|
| 1219 | + offset_y //= 2 |
|
| 1220 | + |
|
| 1221 | + self._set_window(mode, offset_x, offset_y, max_x, max_y, width, height) |
|
| 1222 | + |
|
| 1223 | + @size.setter |
|
| 1224 | + def size(self, size: int) -> None: |
|
| 1225 | + self._size = size |
|
| 1226 | + self._set_size_and_colorspace() |
|
| 1227 | + |
|
| 1228 | + def _set_flip(self) -> None: |
|
| 1229 | + bits = 0 |
|
| 1230 | + if self._flip_x: |
|
| 1231 | + bits |= _REG04_HFLIP_IMG |
|
| 1232 | + if self._flip_y: |
|
| 1233 | + bits |= _REG04_VFLIP_IMG | _REG04_VREF_EN |
|
| 1234 | + self._write_bank_register(_BANK_SENSOR, _REG04, _REG04_SET(bits)) |
|
| 1235 | + |
|
| 1236 | + @property |
|
| 1237 | + def flip_x(self) -> bool: |
|
| 1238 | + """Get or set the X-flip flag""" |
|
| 1239 | + return self._flip_x |
|
| 1240 | + |
|
| 1241 | + @flip_x.setter |
|
| 1242 | + def flip_x(self, value: bool) -> None: |
|
| 1243 | + self._flip_x = bool(value) |
|
| 1244 | + self._set_flip() |
|
| 1245 | + |
|
| 1246 | + @property |
|
| 1247 | + def flip_y(self) -> bool: |
|
| 1248 | + """Get or set the Y-flip flag""" |
|
| 1249 | + return self._flip_y |
|
| 1250 | + |
|
| 1251 | + @flip_y.setter |
|
| 1252 | + def flip_y(self, value: bool) -> None: |
|
| 1253 | + self._flip_y = bool(value) |
|
| 1254 | + self._set_flip() |
|
| 1255 | + |
|
| 1256 | + @property |
|
| 1257 | + def product_id(self) -> int: |
|
| 1258 | + """Get the product id (PID) register. The expected value is 0x26.""" |
|
| 1259 | + return self._read_bank_register(_BANK_SENSOR, _REG_PID) |
|
| 1260 | + |
|
| 1261 | + @property |
|
| 1262 | + def product_version(self) -> int: |
|
| 1263 | + """Get the version (VER) register. The expected value is 0x41.""" |
|
| 1264 | + return self._read_bank_register(_BANK_SENSOR, _REG_VER) |
|
| 1265 | + |
|
| 1266 | + def _set_window( |
|
| 1267 | + self, |
|
| 1268 | + mode: int, |
|
| 1269 | + offset_x: int, |
|
| 1270 | + offset_y: int, |
|
| 1271 | + max_x: int, |
|
| 1272 | + max_y: int, |
|
| 1273 | + width: int, |
|
| 1274 | + height: int, |
|
| 1275 | + ) -> None: |
|
| 1276 | + self._w = width |
|
| 1277 | + self._h = height |
|
| 1278 | + |
|
| 1279 | + max_x //= 4 |
|
| 1280 | + max_y //= 4 |
|
| 1281 | + width //= 4 |
|
| 1282 | + height //= 4 |
|
| 1283 | + |
|
| 1284 | + win_regs = [ |
|
| 1285 | + _BANK_SEL, |
|
| 1286 | + _BANK_DSP, |
|
| 1287 | + _HSIZE, |
|
| 1288 | + max_x & 0xFF, |
|
| 1289 | + _VSIZE, |
|
| 1290 | + max_y & 0xFF, |
|
| 1291 | + _XOFFL, |
|
| 1292 | + offset_x & 0xFF, |
|
| 1293 | + _YOFFL, |
|
| 1294 | + offset_y & 0xFF, |
|
| 1295 | + _VHYX, |
|
| 1296 | + ((max_y >> 1) & 0x80) |
|
| 1297 | + | ((offset_y >> 4) & 0x70) |
|
| 1298 | + | ((max_x >> 5) & 0x08) |
|
| 1299 | + | ((offset_y >> 8) & 0x07), |
|
| 1300 | + _TEST, |
|
| 1301 | + (max_x >> 2) & 0x80, |
|
| 1302 | + _ZMOW, |
|
| 1303 | + (width) & 0xFF, |
|
| 1304 | + _ZMOH, |
|
| 1305 | + (height) & 0xFF, |
|
| 1306 | + _ZMHH, |
|
| 1307 | + ((height >> 6) & 0x04) | ((width >> 8) & 0x03), |
|
| 1308 | + ] |
|
| 1309 | + |
|
| 1310 | + pclk_auto = 0 |
|
| 1311 | + pclk_div = 8 |
|
| 1312 | + clk_2x = 0 |
|
| 1313 | + clk_div = 0 |
|
| 1314 | + |
|
| 1315 | + if self._colorspace != OV2640_COLOR_JPEG: |
|
| 1316 | + pclk_auto = 1 |
|
| 1317 | + clk_div = 7 |
|
| 1318 | + |
|
| 1319 | + if mode == _OV2640_MODE_CIF: |
|
| 1320 | + regs = _ov2640_settings_to_cif |
|
| 1321 | + if self._colorspace != OV2640_COLOR_JPEG: |
|
| 1322 | + clk_div = 3 |
|
| 1323 | + elif mode == _OV2640_MODE_SVGA: |
|
| 1324 | + regs = _ov2640_settings_to_svga |
|
| 1325 | + else: |
|
| 1326 | + regs = _ov2640_settings_to_uxga |
|
| 1327 | + pclk_div = 12 |
|
| 1328 | + |
|
| 1329 | + clk = clk_div | (clk_2x << 7) |
|
| 1330 | + pclk = pclk_div | (pclk_auto << 7) |
|
| 1331 | + |
|
| 1332 | + self._write_bank_register(_BANK_DSP, _R_BYPASS, _R_BYPASS_DSP_BYPAS) |
|
| 1333 | + self._write_list(regs) |
|
| 1334 | + self._write_list(win_regs) |
|
| 1335 | + self._write_bank_register(_BANK_SENSOR, _CLKRC, clk) |
|
| 1336 | + self._write_bank_register(_BANK_DSP, _R_DVP_SP, pclk) |
|
| 1337 | + self._write_register(_R_BYPASS, _R_BYPASS_DSP_EN) |
|
| 1338 | + time.sleep(0.01) |
|
| 1339 | + |
|
| 1340 | + # Reestablish colorspace |
|
| 1341 | + self._set_colorspace() |
|
| 1342 | + |
|
| 1343 | + # Reestablish test pattern |
|
| 1344 | + if self._test_pattern: |
|
| 1345 | + self.test_pattern = self._test_pattern |
|
| 1346 | + |
|
| 1347 | + @property |
|
| 1348 | + def exposure(self) -> int: |
|
| 1349 | + """The exposure level of the sensor""" |
|
| 1350 | + aec_9_2 = self._get_reg_bits(_BANK_SENSOR, _AEC, 0, 0xFF) |
|
| 1351 | + aec_15_10 = self._get_reg_bits(_BANK_SENSOR, _REG45, 0, 0b111111) |
|
| 1352 | + aec_1_0 = self._get_reg_bits(_BANK_SENSOR, _REG04, 0, 0b11) |
|
| 1353 | + |
|
| 1354 | + return aec_1_0 | (aec_9_2 << 2) | (aec_15_10 << 10) |
|
| 1355 | + |
|
| 1356 | + @exposure.setter |
|
| 1357 | + def exposure(self, exposure: int) -> None: |
|
| 1358 | + aec_1_0 = exposure & 0x11 |
|
| 1359 | + aec_9_2 = (exposure >> 2) & 0b11111111 |
|
| 1360 | + aec_15_10 = exposure >> 10 |
|
| 1361 | + |
|
| 1362 | + self._set_reg_bits(_BANK_SENSOR, _AEC, 0, 0xFF, aec_9_2) |
|
| 1363 | + self._set_reg_bits(_BANK_SENSOR, _REG45, 0, 0b111111, aec_15_10) |
|
| 1364 | + self._set_reg_bits(_BANK_SENSOR, _REG04, 0, 0b11, aec_1_0) |
SDK-dat/python-dat/circuitpython-dat/circuitpython-dat.md
| ... | ... | @@ -4,4 +4,92 @@ |
| 4 | 4 | circuitpython |
| 5 | 5 | - board |
| 6 | 6 | - digitalio |
| 7 | -- wws_74hc165 |
|
| ... | ... | \ No newline at end of file |
| 0 | +- wws_74hc165 |
|
| 1 | + |
|
| 2 | + |
|
| 3 | +https://github.com/adafruit/circuitpython |
|
| 4 | + |
|
| 5 | + |
|
| 6 | +Start the UF2 Bootloader |
|
| 7 | + |
|
| 8 | +Nearly all CircuitPython boards ship with a bootloader called UF2 (USB Flashing Format) that makes installing and updating CircuitPython a quick and easy process. The bootloader is the mode your board needs to be in for the CircuitPython .uf2 file you downloaded to work. If the file you downloaded that matches the board name ends in uf2 then you want to continue with this section. However, if the file ends in .bin, you have to do a more complex installation - go to this page for details. |
|
| 9 | + |
|
| 10 | +Espressif Boards without UF2 Bootloaders |
|
| 11 | + |
|
| 12 | +See [this page](https://learn.adafruit.com/circuitpython-with-esp32-quick-start/installing-circuitpython) for how to load a .bin file on an ESP32 or ESP32-C3 board. |
|
| 13 | + |
|
| 14 | +https://learn.adafruit.com/welcome-to-circuitpython/non-uf2-installation |
|
| 15 | + |
|
| 16 | +https://circuitpython.org/board/doit_esp32_devkit_v1/ |
|
| 17 | + |
|
| 18 | +https://downloads.circuitpython.org/bin/doit_esp32_devkit_v1/en_US/adafruit-circuitpython-doit_esp32_devkit_v1-en_US-9.2.8.bin |
|
| 19 | + |
|
| 20 | +The next step is to write your credentials to settings.toml. Make sure your board is running CircuitPython. If you just installed CircuitPython, you may to reset the board first. |
|
| 21 | + |
|
| 22 | +Successfully Completed |
|
| 23 | + |
|
| 24 | +You can edit files by going to http://000.0.0.0/code/. |
|
| 25 | + |
|
| 26 | +If the keys CIRCUITPY_WIFI_SSID and CIRCUITPY_WIFI_PASSWORD are set in settings.toml, CircuitPython will automatically connect to the given Wi-Fi network on boot and upon reload. |
|
| 27 | + |
|
| 28 | +## CircuitPython on ESP32 Quick Start |
|
| 29 | + |
|
| 30 | +https://learn.adafruit.com/circuitpython-with-esp32-quick-start |
|
| 31 | + |
|
| 32 | + esptool.py --port COM13 erase_flash |
|
| 33 | + esptool.py --chip esp32 --port /dev/tty.usbserial-1144440 erase_flash |
|
| 34 | + esptool.py --port /dev/tty.usbserial-1144440 write_flash -z 0x0 firmware.bin |
|
| 35 | + |
|
| 36 | +repl |
|
| 37 | + |
|
| 38 | + rst:0x1� �]I=9}IMQ�,boot:0x13 (SPI_FAST_FLASH_BOOT) |
|
| 39 | + configsip: 0, SPIWP:0xee |
|
| 40 | + �G��DIO, 덭LC!�+��0x3fff0040,len:400s0_drv:0x00,hd_drv80x00 7�E�v���0 |
|
| 41 | + load:0x40078000,len:14048 |
|
| 42 | + load:0x40080400,len:4 |
|
| 43 | + lod:0x40080404,len: �z |
|
| 44 | + Adafruit CircuitPython 10.0.0-beta.0 on 2025-07-15; ESP32 Devkit V1 with ESP32 |
|
| 45 | + Board ID:doit_esp32_devkit_v1 |
|
| 46 | + UID:0125C196358A |
|
| 47 | + MAC:18:0E:FD:3F:20:38 |
|
| 48 | + |
|
| 49 | + Auto-reload is on. Simply save files over USB to run them or enter REPL to disable. |
|
| 50 | + code.py output: |
|
| 51 | + Hello World! |
|
| 52 | + |
|
| 53 | + Code done running. |
|
| 54 | + |
|
| 55 | + Press any key to enter the REPL. Use CTRL-D to reload. |
|
| 56 | + |
|
| 57 | +installing [[settings.toml]] and using wifi |
|
| 58 | + |
|
| 59 | + import wifi |
|
| 60 | + |
|
| 61 | + print("My MAC addr: %02X:%02X:%02X:%02X:%02X:%02X" % tuple(wifi.radio.mac_address)) |
|
| 62 | + print("My IP address is", wifi.radio.ipv4_address) |
|
| 63 | + |
|
| 64 | + |
|
| 65 | +mpremote connect COM6 fs cp settings.toml : |
|
| 66 | + |
|
| 67 | + mpremote connect COM6 fs put w.py : |
|
| 68 | + put :w.py |
|
| 69 | + put : |
|
| 70 | + |
|
| 71 | + mpremote connect COM6 run w.py |
|
| 72 | + My MAC addr: 10:52:1C:69:53:A8 |
|
| 73 | + My IP address is 192.168.79.226 |
|
| 74 | + |
|
| 75 | + |
|
| 76 | + |
|
| 77 | +## OV2640 |
|
| 78 | + |
|
| 79 | +- https://github.com/adafruit/Adafruit_CircuitPython_OV2640 |
|
| 80 | + |
|
| 81 | +- https://docs.circuitpython.org/projects/ov2640/en/latest/ |
|
| 82 | + |
|
| 83 | + |
|
| 84 | + |
|
| 85 | +## reference code |
|
| 86 | + |
|
| 87 | +- https://github.com/adafruit/Adafruit_Learning_System_Guides/tree/main/CircuitPython_Essentials |
|
| 88 | + |
SDK-dat/python-dat/circuitpython-dat/ov2640_micropython_test.py
| ... | ... | @@ -0,0 +1,49 @@ |
| 1 | +# mpremote connect COM6 fs cp ov2640_micropython_test.py : |
|
| 2 | +# mpremote connect COM6 run ov2640_micropython_test.py |
|
| 3 | + |
|
| 4 | +import camera # type: ignore |
|
| 5 | +import time |
|
| 6 | +import sys |
|
| 7 | + |
|
| 8 | +# Initialize camera with ESP1000 pin definitions |
|
| 9 | +try: |
|
| 10 | + camera.init(0, |
|
| 11 | + d0=5, d1=18, d2=19, d3=21, d4=36, d5=39, d6=34, d7=35, |
|
| 12 | + format=camera.JPEG, |
|
| 13 | + framesize=camera.FRAME_QQVGA, # 160x120 |
|
| 14 | + xclk_freq=camera.XCLK_20MHz, |
|
| 15 | + href=23, vsync=25, reset=-1, pwdn=32, |
|
| 16 | + sioc=27, siod=26, xclk=0, pclk=22 |
|
| 17 | + ) |
|
| 18 | + print("Camera initialized successfully") |
|
| 19 | +except Exception as e: |
|
| 20 | + print("Camera init failed:", e) |
|
| 21 | + sys.exit() |
|
| 22 | + |
|
| 23 | +# Simple test - capture and save images |
|
| 24 | +count = 0 |
|
| 25 | +while True: |
|
| 26 | + try: |
|
| 27 | + print("Capturing image", count) |
|
| 28 | + buf = camera.capture() |
|
| 29 | + print("Image size:", len(buf), "bytes") |
|
| 30 | + |
|
| 31 | + # Save image |
|
| 32 | + filename = f"test_{count:03d}.jpg" |
|
| 33 | + with open(filename, 'wb') as f: |
|
| 34 | + f.write(buf) |
|
| 35 | + print("Saved:", filename) |
|
| 36 | + |
|
| 37 | + count += 1 |
|
| 38 | + time.sleep(2) |
|
| 39 | + |
|
| 40 | + # Stop after 5 images for testing |
|
| 41 | + if count >= 5: |
|
| 42 | + break |
|
| 43 | + |
|
| 44 | + except Exception as e: |
|
| 45 | + print("Capture error:", e) |
|
| 46 | + break |
|
| 47 | + |
|
| 48 | +print("Test completed") |
|
| 49 | +camera.deinit() |
SDK-dat/python-dat/circuitpython-dat/ov2640_simpletest.py
| ... | ... | @@ -0,0 +1,74 @@ |
| 1 | +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries |
|
| 2 | +# SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries |
|
| 3 | +# |
|
| 4 | +# SPDX-License-Identifier: Unlicense |
|
| 5 | + |
|
| 6 | +"""Capture an image from the camera and display it as ASCII art. |
|
| 7 | + |
|
| 8 | +This demo is designed to run on the Kaluga, but you can adapt it |
|
| 9 | +to other boards by changing the constructors for `bus` and `cam` |
|
| 10 | +appropriately. |
|
| 11 | + |
|
| 12 | +The camera is placed in YUV mode, so the top 8 bits of each color |
|
| 13 | +value can be treated as "greyscale". |
|
| 14 | + |
|
| 15 | +It's important that you use a terminal program that can interpret |
|
| 16 | +"ANSI" escape sequences. The demo uses them to "paint" each frame |
|
| 17 | +on top of the prevous one, rather than scrolling. |
|
| 18 | + |
|
| 19 | +Remember to take the lens cap off, or un-comment the line setting |
|
| 20 | +the test pattern! |
|
| 21 | +""" |
|
| 22 | + |
|
| 23 | +import sys |
|
| 24 | +import time |
|
| 25 | + |
|
| 26 | +import board |
|
| 27 | +import busio |
|
| 28 | + |
|
| 29 | +import adafruit_ov2640 |
|
| 30 | + |
|
| 31 | +# mpremote connect COM6 fs put adafruit_ov2640.py : |
|
| 32 | +# mpremote connect COM6 fs put ov2640_simpletest.py : |
|
| 33 | +# mpremote connect COM6 fs run ov2640_simpletest.py |
|
| 34 | + |
|
| 35 | + |
|
| 36 | +# Pin definitions adapted from ESP1000-2-dat.py |
|
| 37 | +# d0=5, d1=18, d2=19, d3=21, d4=36, d5=39, d6=34, d7=35 |
|
| 38 | +# href=23, vsync=25, sioc=27, siod=26, xclk=0, pclk=22 |
|
| 39 | +data_pins = [board.GP5, board.GP18, board.GP19, board.GP21, board.GP36, board.GP39, board.GP34, board.GP35] |
|
| 40 | + |
|
| 41 | +bus = busio.I2C(scl=board.GP27, sda=board.GP26) # sioc=27, siod=26 |
|
| 42 | + |
|
| 43 | +cam = adafruit_ov2640.OV2640( |
|
| 44 | + bus, |
|
| 45 | + data_pins=data_pins, |
|
| 46 | + clock=board.GP22, # pclk=22 |
|
| 47 | + vsync=board.GP25, # vsync=25 |
|
| 48 | + href=board.GP23, # href=23 |
|
| 49 | + mclk=board.GP0, # xclk=0 |
|
| 50 | + mclk_frequency=20_000_000, |
|
| 51 | + size=adafruit_ov2640.OV2640_SIZE_QQVGA, |
|
| 52 | +) |
|
| 53 | +cam.colorspace = adafruit_ov2640.OV2640_COLOR_YUV |
|
| 54 | +cam.flip_y = True |
|
| 55 | +# cam.test_pattern = True |
|
| 56 | + |
|
| 57 | +buf = bytearray(2 * cam.width * cam.height) |
|
| 58 | +chars = b" .:-=+*#%@" |
|
| 59 | +remap = [chars[i * (len(chars) - 1) // 255] for i in range(256)] |
|
| 60 | + |
|
| 61 | +width = cam.width |
|
| 62 | +row = bytearray(2 * width) |
|
| 63 | + |
|
| 64 | +sys.stdout.write("\033[2J") |
|
| 65 | +while True: |
|
| 66 | + cam.capture(buf) |
|
| 67 | + for j in range(cam.height // 2): |
|
| 68 | + sys.stdout.write(f"\033[{j}H") |
|
| 69 | + for i in range(cam.width // 2): |
|
| 70 | + row[i * 2] = row[i * 2 + 1] = remap[buf[4 * (width * j + i)]] |
|
| 71 | + sys.stdout.write(row) |
|
| 72 | + sys.stdout.write("\033[K") |
|
| 73 | + sys.stdout.write("\033[J") |
|
| 74 | + time.sleep(0.05) |
|
| ... | ... | \ No newline at end of file |
SDK-dat/python-dat/circuitpython-dat/settings.toml
| ... | ... | @@ -0,0 +1,3 @@ |
| 1 | +CIRCUITPY_WIFI_SSID = "111" |
|
| 2 | +CIRCUITPY_WIFI_PASSWORD = "electrodragon" |
|
| 3 | +CIRCUITPY_WEB_API_PASSWORD= "electrodragon" |
|
| ... | ... | \ No newline at end of file |
SDK-dat/python-dat/circuitpython-dat/w.py
| ... | ... | @@ -0,0 +1,4 @@ |
| 1 | +import wifi |
|
| 2 | + |
|
| 3 | +print("My MAC addr: %02X:%02X:%02X:%02X:%02X:%02X" % tuple(wifi.radio.mac_address)) |
|
| 4 | +print("My IP address is", wifi.radio.ipv4_address) |
|
| ... | ... | \ No newline at end of file |
Tech-dat/Interface-dat/I2C-dat/I2C-dat.md
| ... | ... | @@ -1,6 +1,10 @@ |
| 1 | 1 | |
| 2 | 2 | # I2C Dat |
| 3 | 3 | |
| 4 | + |
|
| 5 | +## common I2C devices address |
|
| 6 | + |
|
| 7 | + |
|
| 4 | 8 | // I2C device found at address 0x40 ! // INA219, INA226 |
| 5 | 9 | |
| 6 | 10 | for [[IOD1001-dat]] |
| ... | ... | @@ -38,6 +42,20 @@ testing scan I2C |
| 38 | 42 | Wire.begin(4,13); |
| 39 | 43 | Wire.begin(2, 3); |
| 40 | 44 | |
| 45 | +## I2C usage in Micropython |
|
| 46 | + |
|
| 47 | +- [[micropython-dat]] |
|
| 48 | + |
|
| 49 | + from machine import I2C, Pin |
|
| 50 | + |
|
| 51 | + # Define I2C on GPIO 15 (SDA) and GPIO 13 (SCL) |
|
| 52 | + |
|
| 53 | + i2c = I2C(0, scl=Pin(13), sda=Pin(15), freq=400000) |
|
| 54 | + i2c = I2C(0, scl=Pin(13), sda=Pin(15), freq=100000) |
|
| 55 | + |
|
| 56 | + |
|
| 57 | + print("I2C scan:", i2c.scan()) |
|
| 58 | + |
|
| 41 | 59 | ## code library |
| 42 | 60 | |
| 43 | 61 | the most easy to use library for ESP |
Tech-dat/Interface-dat/I2S-dat/I2S-DAC-dat/I2S-DAC-dat.md
| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | + |
|
| 2 | +# I2S-DAC-dat |
|
| 3 | + |
|
| 4 | +I2S DAC Decoder speaker |
|
| 5 | + |
|
| 6 | +- [[PCM5122-dat]] - [[MPC1083-dat]] |
|
| 7 | + |
|
| 8 | +- [[PCM5102-dat]] - [[AMP1006-dat]] |
|
| 9 | + |
|
| 10 | +- [[MAX98357-dat]] |
|
| 11 | + |
|
| 12 | +- [[UDA1334-dat]] - [[AMP1013-dat]] - [[NXP-dat]] |
|
| 13 | + |
|
| 14 | +## Pin |
|
| 15 | + |
|
| 16 | +| Name | default ESP32 | also Name | func | RPI GPIO | RPI pin | |
|
| 17 | +| ---- | ------------- | ------------ | ---------------------------------- | -------- | ------- | |
|
| 18 | +| SCK | 26 | BCLK | Serial Data Clock / Bit clock line | G18 | PIN 12 | |
|
| 19 | +| WS | 25 | LRCK / LRC | Serial Data-Word select line | G19 | PIN 35 | |
|
| 20 | +| SD | 22 | SDIN / SDOUT | At least one multiplexed data line | G21 | PIN 40 | |
|
| 21 | + |
|
| 22 | +I2S Circuit: |
|
| 23 | + |
|
| 24 | +* Arduino/Genuino Zero, MKR family and Nano 33 IoT |
|
| 25 | +* MAX98357: |
|
| 26 | + * GND connected GND |
|
| 27 | + * VIN connected 5V |
|
| 28 | + * LRC connected to pin 0 (Zero) or 3 (MKR), A2 (Nano) or 25 (ESP32) |
|
| 29 | + * BCLK connected to pin 1 (Zero) or 2 (MKR), A3 (Nano) or 5 (ESP32) |
|
| 30 | + * DIN connected to pin 9 (Zero) or A6 (MKR), 4 (Nano) or 26 (ESP32) |
|
| 31 | + |
|
| 32 | + DAC Circuit: |
|
| 33 | + * ESP32 or ESP32-S2 |
|
| 34 | + * Audio amplifier |
|
| 35 | + - Note: |
|
| 36 | + - ESP32 has DAC on GPIO pins 25 and 26. |
|
| 37 | + - ESP32-S2 has DAC on GPIO pins 17 and 18. |
|
| 38 | + - Connect speaker(s) or headphones. |
|
| 39 | + |
|
| 40 | +- [[MAX98357-dat]] |
|
| ... | ... | \ No newline at end of file |
Tech-dat/Interface-dat/I2S-dat/I2S-dat.md
| ... | ... | @@ -11,35 +11,11 @@ One of the key features of I2S interfaces is their ability to support full-duple |
| 11 | 11 | |
| 12 | 12 | This makes I2S a popular choice for high-speed data transfer applications. |
| 13 | 13 | |
| 14 | -- [[I2S-microphone-dat]] - [[I2S-speaker-dat]] |
|
| 14 | +- [[I2S-microphone-dat]] - [[I2S-DAC-dat]] |
|
| 15 | 15 | |
| 16 | 16 | - [[everest-semi-dat]] |
| 17 | 17 | |
| 18 | -## Pin |
|
| 19 | - |
|
| 20 | -| Name | default ESP32 | also Name | func | RPI GPIO | RPI pin | |
|
| 21 | -| ---- | ------------- | ------------ | ---------------------------------- | -------- | ------- | |
|
| 22 | -| SCK | 26 | BCLK | Serial Data Clock / Bit clock line | G18 | PIN 12 | |
|
| 23 | -| WS | 25 | LRCK / LRC | Serial Data-Word select line | G19 | PIN 35 | |
|
| 24 | -| SD | 22 | SDIN / SDOUT | At least one multiplexed data line | G21 | PIN 40 | |
|
| 25 | - |
|
| 26 | -I2S Circuit: |
|
| 27 | - |
|
| 28 | -* Arduino/Genuino Zero, MKR family and Nano 33 IoT |
|
| 29 | -* MAX08357: |
|
| 30 | - * GND connected GND |
|
| 31 | - * VIN connected 5V |
|
| 32 | - * LRC connected to pin 0 (Zero) or 3 (MKR), A2 (Nano) or 25 (ESP32) |
|
| 33 | - * BCLK connected to pin 1 (Zero) or 2 (MKR), A3 (Nano) or 5 (ESP32) |
|
| 34 | - * DIN connected to pin 9 (Zero) or A6 (MKR), 4 (Nano) or 26 (ESP32) |
|
| 35 | - |
|
| 36 | - DAC Circuit: |
|
| 37 | - * ESP32 or ESP32-S2 |
|
| 38 | - * Audio amplifier |
|
| 39 | - - Note: |
|
| 40 | - - ESP32 has DAC on GPIO pins 25 and 26. |
|
| 41 | - - ESP32-S2 has DAC on GPIO pins 17 and 18. |
|
| 42 | - - Connect speaker(s) or headphones. |
|
| 18 | + |
|
| 43 | 19 | |
| 44 | 20 | ## Common Microphone, Speaker Wiring |
| 45 | 21 | |
| ... | ... | @@ -56,44 +32,64 @@ I2S Circuit: |
| 56 | 32 | |
| 57 | 33 | |
| 58 | 34 | |
| 59 | -## Solution - control (slave module) |
|
| 60 | 35 | |
| 61 | -- [[I2S-microphone-dat]] |
|
| 62 | 36 | |
| 63 | -audio amplifer - [[audio-dat]] - [[amplifier-dat]] - [[CS4344-dat]] |
|
| 64 | 37 | |
| 65 | -I2S speaker - [[PCM5122-dat]] - [[MPC1083-dat]] - [[MAX98357-dat]] - [[PCM5102-dat]] - [[AMP1006-dat]] |
|
| 66 | 38 | |
| 67 | -- [[ES9023-dat]] - [[MPC1111-dat]] - [[ES9018-dat]] |
|
| 68 | - |
|
| 69 | -- [[WM8960-dat]] - [[WM8978-dat]] |
|
| 39 | +## demo video |
|
| 70 | 40 | |
| 71 | -- [[UDA1334-dat]] - [[AMP1013-dat]] |
|
| 41 | +- [[MAX98357-dat]] works with [[ESP32-dat]] - https://x.com/electro_phoenix/status/1877255863846465989 |
|
| 72 | 42 | |
| 73 | -- [[bt-audio-dat]] - [[ESP32-DAC-dat]] - [[ADC-dat]] - [[DAC-dat]] - [[ESP32-I2S-dat]] |
|
| 74 | 43 | |
| 75 | -- [[PCM1808-dat]] |
|
| 44 | +## code |
|
| 76 | 45 | |
| 77 | -- [[software-i2s-dat]] |
|
| 46 | +https://github.com/sheaivey/ESP32-AudioInI2S |
|
| 78 | 47 | |
| 48 | +https://github.com/atomic14/esp32_audio == [[platformIO-dat]] |
|
| 79 | 49 | |
| 50 | +https://github.com/schreibfaul1/ESP32-audioI2S == easy |
|
| 80 | 51 | |
| 52 | +https://github.com/earlephilhower/ESP8266Audio |
|
| 81 | 53 | |
| 54 | +## Micropython driver |
|
| 82 | 55 | |
| 83 | -## demo video |
|
| 56 | +- [[Micropython-dat]] |
|
| 84 | 57 | |
| 85 | -- [[MAX98357-dat]] works with [[ESP32-dat]] - https://x.com/electro_phoenix/status/1877255863846465989 |
|
| 58 | +- [[I2S-DAC-dat]] driver |
|
| 86 | 59 | |
| 60 | +https://github.com/miketeachman/micropython-i2s-examples |
|
| 87 | 61 | |
| 88 | -## code |
|
| 62 | +- [[I2S-microphone-dat]] driver |
|
| 89 | 63 | |
| 90 | -https://github.com/sheaivey/ESP32-AudioInI2S |
|
| 64 | +#ESP32 I2S MEMS Microphone Arduino IDE Example This repository holds some samples for connecting a I2S MEMS microphone to an ESP32 board. |
|
| 91 | 65 | |
| 92 | -https://github.com/atomic14/esp32_audio == [[platformIO-dat]] |
|
| 66 | +https://github.com/miketeachman/micropython-i2s-examples |
|
| 67 | + |
|
| 68 | + |
|
| 69 | +## I2S sesnors |
|
| 70 | + |
|
| 71 | +[SPL06-MEMS-barometer-micropython](https://github.com/ChangboBro/SPL06-MEMS-barometer-micropython) |
|
| 72 | + |
|
| 73 | +The SPL06 is a high precision MEMS barometer, its resolution of altitude can up to 5cm! (but I think maybe +-10cm, still very good) |
|
| 74 | + |
|
| 75 | +## ref |
|
| 76 | + |
|
| 77 | +audio amplifer - [[audio-dat]] - [[amplifier-dat]] - [[CS4344-dat]] |
|
| 78 | + |
|
| 79 | + |
|
| 80 | +- [[ES9023-dat]] - [[MPC1111-dat]] - [[ES9018-dat]] |
|
| 81 | + |
|
| 82 | +- [[WM8960-dat]] - [[WM8978-dat]] |
|
| 83 | + |
|
| 84 | + |
|
| 85 | + |
|
| 86 | +- [[bt-audio-dat]] - [[ESP32-DAC-dat]] - [[ADC-dat]] - [[DAC-dat]] - [[ESP32-I2S-dat]] |
|
| 87 | + |
|
| 88 | +- [[PCM1808-dat]] |
|
| 89 | + |
|
| 90 | +- [[software-i2s-dat]] |
|
| 93 | 91 | |
| 94 | -https://github.com/schreibfaul1/ESP32-audioI2S == easy |
|
| 95 | 92 | |
| 96 | -https://github.com/earlephilhower/ESP8266Audio |
|
| 97 | 93 | |
| 98 | 94 | |
| 99 | 95 | ## ref |
Tech-dat/Interface-dat/I2S-dat/I2S-microphone-dat/I2S-microphone-dat.md
| ... | ... | @@ -19,7 +19,16 @@ I2S Output Digital Microphone - [[INMP441-dat]] - [[MSM261S4030H0R-dat]] |
| 19 | 19 | | [[SPH0645-dat]] | yes | yes | yes | yes | |
| 20 | 20 | |
| 21 | 21 | |
| 22 | - |
|
| 22 | +## wiring reference |
|
| 23 | + |
|
| 24 | +| Signal | Connection | |
|
| 25 | +| ------ | ----------------------------------------------- | |
|
| 26 | +| SEL | unconnected (only one channel, apparently left) | |
|
| 27 | +| LRCL | #15 | |
|
| 28 | +| DOUT | #32 | |
|
| 29 | +| BCKL | #14 | |
|
| 30 | +| GND | GND | |
|
| 31 | +| 3V | 3V | |
|
| 23 | 32 | |
| 24 | 33 | |
| 25 | 34 | ## go advance |
Tech-dat/sensor-camera-dat/camera-SDK-dat/OV2640-lemariva-dat/OV2640-lemariva-dat.md
| ... | ... | @@ -14,6 +14,8 @@ https://github.com/lemariva/micropython-camera-driver |
| 14 | 14 | https://github.com/lemariva/upyCam |
| 15 | 15 | https://github.com/lemariva/upyCam/tree/timelapse-camera |
| 16 | 16 | |
| 17 | +- [[MP-ESP32-dat]] |
|
| 18 | + |
|
| 17 | 19 | flash camera driver firmware |
| 18 | 20 | |
| 19 | 21 | esptool --port COM6 --baud 460800 write-flash 0x1000 micropython_camera_feeeb5ea3_esp32_idf4_4.bin |
Tech-dat/sensor-camera-dat/camera-SDK-dat/camera-SDK-dat.md
| ... | ... | @@ -5,11 +5,16 @@ |
| 5 | 5 | |
| 6 | 6 | - [[camera-dat]] |
| 7 | 7 | |
| 8 | -[[micropython-dat]] - [[script-based-SDK]] |
|
| 8 | + |
|
| 9 | 9 | |
| 10 | 10 | |
| 11 | 11 | ## repro |
| 12 | 12 | |
| 13 | +- [[openMV-dat]] |
|
| 14 | + |
|
| 15 | +- [[circuitpython-dat]] - better support for [[ESP32-S3-dat]] not well support for ESP32-CAM == [[SCM1030-dat]] == https://github.com/adafruit/Adafruit_CircuitPython_OV2640/issues/22 |
|
| 16 | + |
|
| 17 | + |
|
| 13 | 18 | - https://github.com/alanesq/esp32cam-demo |
| 14 | 19 | - https://github.com/espressif/esp32-camera |
| 15 | 20 | - https://github.com/yoursunny/esp32cam |
| ... | ... | @@ -19,6 +24,11 @@ |
| 19 | 24 | - https://github.com/donny681/ESP32_CAMERA_QR |
| 20 | 25 | - https://github.com/ArduCAM/Arduino |
| 21 | 26 | |
| 27 | + |
|
| 28 | + |
|
| 29 | + |
|
| 30 | +[[micropython-dat]] - [[script-based-SDK]] |
|
| 31 | + |
|
| 22 | 32 | ## OV2640 |
| 23 | 33 | |
| 24 | 34 | - [[OV2640-lemariva-dat]] |
Tech-dat/sensor-camera-dat/camera-SDK-dat/openMV-dat/openMV-dat.md
| ... | ... | @@ -0,0 +1,6 @@ |
| 1 | + |
|
| 2 | +# openMV-dat |
|
| 3 | + |
|
| 4 | +- https://github.com/openmv/openmv |
|
| 5 | + |
|
| 6 | +The ESP32 is much slower than the H7 or IMX. So, it’s really just a port for the sake of it. Actual performance will be very low. |
|
| ... | ... | \ No newline at end of file |