24浏览
查看: 24|回复: 0

[Micropython] 玩转ESP32P4:开启使用MicroPython

[复制链接]
本帖最后由 PY学习笔记 于 2025-7-29 18:04 编辑

近期,dfrobot出了一款新的开发板——FireBeetle 2 ESP32-P4,板载ESP32P4,虽然没有内置的WIFI和BLE,但是它的性能十分的高,所以很有幸能体验到这款开发板
1.开发板介绍
FireBeetle 2 ESP32-P4有很多种外设:
  • Type-C USB CDC:Type-C USB烧录、调试接口
  • IO3/LED:板载LED引脚
  • Power LED:主板电源指示灯
  • RST:复位按键
  • IO35/BOOT:IO引脚/BOOT按键
  • MIC: MEMS PDM麦克风
  • HIGH-SPEED USB OTG 2.0: Type-C高速USB OTG 2.0
  • ESP32-P4:ESP32-P4芯片
  • MIPI-DSI: 两通道MIPI-DSI屏幕(兼容树莓派4B DSI屏幕线序)
  • MIPI-CSI: 两通道MIPI-DSI屏幕(兼容树莓派4B CSI摄像头线序)
  • TF Card: TF卡插槽
  • 16MB FLASH: 16MB Flash存储
  • ESP32-C6:ESP32-C6-MINI-1模组,通过SDIO与ESP32-P4连接,用于扩展WiFi、蓝牙

2.micropython编译
现在micropython官方还没实现,因为他们的代码很多都是旧版的,要更新得一段时间,这里我使用PR上大佬得半成品改了改实现了除USB、屏幕(DF官方还未实现)外的其它外设,仓库地址:
摄像头这里使用树莓派的摄像头实现,仓库地址:
考虑到后期需要使用jpeg的编码以及解码所以还需要使用cnadler86大佬的库,仓库地址:
接下来就可以开始编译了:
1.安装虚拟机
我用的是虚拟机,也可以用其它的方式安装Linux系统进行编译,建议VMware+Ubuntu,参考:
2.ESP-IDF开发环境安装
Ubuntu安装一些依赖包直接运行即可:
  1. sudo apt-get update
  2. sudo apt-get install git wget libncurses-dev flex bison gperf python3 python3-pip python3-setuptools python3-serial python3-click python3-cryptography python3-future python3-pyparsing python3-pyelftools cmake ninja-build ccache libffi-dev libssl-dev python-is-python3
复制代码

3.pip源配置
ESP-IDF安装过程中会在python virtual environment中使用pip安装所需的包,但默认情况下,pip使用的是国外的官方源,使得安装比较慢。可以使用以下命令将pip源配置到阿里云提升速度。
  1. pip config set global.index-url <a href="http://mirrors.aliyun.com/pypi/simple" target="_blank">http://mirrors.aliyun.com/pypi/simple</a>
  2. pip config set global.trusted-host mirrors.aliyun.com
复制代码


4.下载仓库
运行即可:
  1. mkdir -p ~/esp
  2. cd ~/esp
  3. git clone <a href="https://gitee.com/EspressifSystems/esp-gitee-tools.git" target="_blank">https://gitee.com/EspressifSystems/esp-gitee-tools.git</a>
  4. git clone <a href="https://gitee.com/EspressifSystems/esp-idf.git" target="_blank">https://gitee.com/EspressifSystems/esp-idf.git</a>
  5. git clone -b esp32p4 <a href="https://github.com/Vincent1-python/micropython.git" target="_blank">https://github.com/Vincent1-python/micropython.git</a>
  6. git clone <a href="https://github.com/Vincent1-python/micropython_csi_camera.git" target="_blank">https://github.com/Vincent1-python/micropython_csi_camera.git</a>
  7. git clone <a href="https://github.com/cnadler86/mp_jpeg" target="_blank">https://github.com/cnadler86/mp_jpeg</a>
复制代码


5.切换ESP-IDF的版本
  1. cd esp-idf
  2. git checkout v5.4.1
复制代码


6.配置esp-idf
官方为了解决国内开发者从github克隆esp相关仓库慢的问题,已将esp-idf和部分重要仓库及其关联的子模块镜像到了jihu。根据官方建议,使用以下命令将仓库的URL替换为jihu的URL,并更新子模块,完成安装。
  1. cd ~/esp/esp-gitee-tools
  2. ./jihu-mirror.sh set
  3. ./submodule-update.sh ~/esp/esp-idf/
  4. ./install.sh ~/esp/esp-idf/
复制代码

可能会提示Python virtual environment未安装成功。按照建议执行以下命令,并重新安装。
  1. sudo apt install python3.10-venv
  2. ./install.sh ~/esp/esp-idf/
复制代码

安装一大堆东西后,提示(xx是用户名):
  1. All done! You can now run:
  2. . /home/xx/esp/esp-idf/export.sh
复制代码

表示安装成功。添加环境变量:
  1. cd ~/esp/esp-idf
  2. source export.sh
复制代码

提示:idf.py buildinstall.sh步骤只需要执行一次。每次新会话都需要使用export.sh
7.确认esp-idf版本
  1. idf.py –version
复制代码

再次确认ESP-IDFv5.4.1。
8.构建固件
  1. cd ~/esp/micropython
  2. make -C mpy-cross
  3. cd ports/esp32
  4. make submodules
  5. make
复制代码

如果顺利的话,就会在~/esp/micropython/ports/esp32/build-FireBeetle_2_ESP32_P4/中生成一个firmware.bin固件。
9.绑定两个驱动
在~/esp中新建一个文件micropython.cmake写入以下代码:
  1. include(${CMAKE_CURRENT_LIST_DIR}/micropython_csi_camera/micropython.cmake)
  2. include(${CMAKE_CURRENT_LIST_DIR}/mp_jpeg/src/micropython.cmake)
复制代码


10.最终的编译
运行:
  1. make clean
  2. make USER_C_MODULES=~/esp/micropython.cmake
复制代码

运行完成后,会在~/esp/micropython/ports/esp32/build-FireBeetle_2_ESP32_P4/中生成一个firmware.bin固件。复制到合适的地方开始烧录。
3.烧录
网上有很多方式我就不详细写了,注意烧录地址为:0x002000
4.正式体验
这里板载外设为主:
LED测试:
  1. from machine import Pin
  2. import time
  3. led = Pin(3,Pin.OUT)
  4. while True:
  5.     led.value(1)
  6.     time.sleep(1)
  7.     led.value(0)
  8.     time.sleep(1)
复制代码

麦克风测试:
  1. import os
  2. from machine import Pin
  3. from machine import I2S
  4. SCK_PIN = 12
  5. #WS_PIN = 25
  6. SD_PIN = 9
  7. I2S_ID = 0
  8. BUFFER_LENGTH_IN_BYTES = 40000
  9. # ======= AUDIO CONFIGURATION =======
  10. WAV_FILE = "mic.wav"
  11. RECORD_TIME_IN_SECONDS = 4
  12. WAV_SAMPLE_SIZE_IN_BITS = 16
  13. FORMAT = I2S.MONO
  14. SAMPLE_RATE_IN_HZ = 8000
  15. # ======= AUDIO CONFIGURATION =======
  16. format_to_channels = {I2S.MONO: 1, I2S.STEREO: 2}
  17. NUM_CHANNELS = format_to_channels[FORMAT]
  18. WAV_SAMPLE_SIZE_IN_BYTES = WAV_SAMPLE_SIZE_IN_BITS // 8
  19. RECORDING_SIZE_IN_BYTES = (
  20.     RECORD_TIME_IN_SECONDS * SAMPLE_RATE_IN_HZ * WAV_SAMPLE_SIZE_IN_BYTES * NUM_CHANNELS
  21. )
  22. def create_wav_header(sampleRate, bitsPerSample, num_channels, num_samples):
  23.     datasize = num_samples * num_channels * bitsPerSample // 8
  24.     o = bytes("RIFF", "ascii")  # (4byte) Marks file as RIFF
  25.     o += (datasize + 36).to_bytes(
  26.         4, "little"
  27.     )  # (4byte) File size in bytes excluding this and RIFF marker
  28.     o += bytes("WAVE", "ascii")  # (4byte) File type
  29.     o += bytes("fmt ", "ascii")  # (4byte) Format Chunk Marker
  30.     o += (16).to_bytes(4, "little")  # (4byte) Length of above format data
  31.     o += (1).to_bytes(2, "little")  # (2byte) Format type (1 - PCM)
  32.     o += (num_channels).to_bytes(2, "little")  # (2byte)
  33.     o += (sampleRate).to_bytes(4, "little")  # (4byte)
  34.     o += (sampleRate * num_channels * bitsPerSample // 8).to_bytes(4, "little")  # (4byte)
  35.     o += (num_channels * bitsPerSample // 8).to_bytes(2, "little")  # (2byte)
  36.     o += (bitsPerSample).to_bytes(2, "little")  # (2byte)
  37.     o += bytes("data", "ascii")  # (4byte) Data Chunk Marker
  38.     o += (datasize).to_bytes(4, "little")  # (4byte) Data size in bytes
  39.     return o
  40. audio_in = I2S(
  41.     I2S_ID,
  42.     sck=Pin(SCK_PIN),
  43.     #ws=Pin(WS_PIN),
  44.     sd=Pin(SD_PIN),
  45.     mode=I2S.PDM_RX,
  46.     bits=WAV_SAMPLE_SIZE_IN_BITS,
  47.     format=FORMAT,
  48.     rate=SAMPLE_RATE_IN_HZ * 4,
  49.     ibuf=BUFFER_LENGTH_IN_BYTES,
  50.    
  51.    
  52. )
  53. # allocate sample arrays
  54. # memoryview used to reduce heap allocation in while loop
  55. mic_samples = bytearray(40000)
  56. mic_samples_mv = memoryview(mic_samples)
  57. recording_buffer = bytearray(RECORDING_SIZE_IN_BYTES)
  58. bytes_received = 0
  59. print("Recording size: {} bytes".format(RECORDING_SIZE_IN_BYTES))
  60. print("==========  START RECORDING ==========")
  61. try:
  62.     while bytes_received < RECORDING_SIZE_IN_BYTES:
  63.         # read a block of samples from the I2S microphone
  64.         bytes_read = audio_in.readinto(mic_samples_mv)
  65.         if bytes_read > 0:
  66.             bytes_to_write = min(
  67.                 bytes_read, RECORDING_SIZE_IN_BYTES - bytes_received
  68.             )
  69.             recording_buffer[bytes_received:bytes_received+bytes_to_write] = mic_samples_mv[0:bytes_to_write]
  70.             print('FILL', bytes_received, bytes_to_write)
  71.             bytes_received += bytes_read
  72.     print("==========  DONE RECORDING ==========")
  73. except (KeyboardInterrupt, Exception) as e:
  74.     print("caught exception {} {}".format(type(e).__name__, e))
  75. # Write to WAV
  76. wav = open(WAV_FILE, "wb")
  77. # create header for WAV file and write to SD card
  78. wav_header = create_wav_header(
  79.     SAMPLE_RATE_IN_HZ,
  80.     WAV_SAMPLE_SIZE_IN_BITS,
  81.     NUM_CHANNELS,
  82.     SAMPLE_RATE_IN_HZ * RECORD_TIME_IN_SECONDS,
  83. )
  84. wav.write(wav_header)
  85. # write samples to WAV file
  86. wav.write(recording_buffer)
  87. # cleanup
  88. wav.close()
  89. print("Wrote ", WAV_FILE)
  90. audio_in.deinit()
复制代码

SD卡测试:
  1. from machine import Pin,SDCard
  2. import os
  3. sd = SDCard(slot=0,width=4, sck=43, cmd=44, data=(39, 40, 41, 42), freq=40000000)
  4. os.mount(sd, '/sd')
  5. os.listdir('/sd')
  6. print(os.listdir('/sd'))
  7. os.listdir('/sd')
复制代码

联网测试:
  1. import network,time
  2. def connect():
  3.     wlan = network.WLAN(network.STA_IF)
  4.     wlan.active(True)
  5.     if not wlan.isconnected():
  6.         print('esp32p4正在联网',end="")
  7.         wlan.connect('SSID', 'PWD')
  8.         while not wlan.isconnected():
  9.             print(".",end="")
  10.             time.sleep(1)
  11.     print('\n网络信息为: ', wlan.ifconfig())  
  12. connect()
复制代码

摄像头拍照测试:
  1. import camera,time,jpeg
  2. camera.init()
  3. time.sleep(5)
  4. img = camera.capture()  # bytes
  5. camera.deinit()
  6. with open("capture.jpg", "wb") as f:
  7.     f.write(img)
  8. print("JPEG 编码完成")
复制代码

网页图传测试:
  1. from microdot import Microdot
  2. import time,jpeg,camera,network
  3. def connect():
  4.     wlan = network.WLAN(network.STA_IF)
  5.     wlan.active(True)
  6.     if not wlan.isconnected():
  7.         print('esp32p4正在联网',end="")
  8.         wlan.connect('SSID', 'PWD')
  9.         while not wlan.isconnected():
  10.             print(".",end="")
  11.             time.sleep(1)
  12.     print('\n网络信息为: ', wlan.ifconfig())
  13.     ifconfig = wlan.ifconfig()
  14.     print('请在浏览器打开:{}:5000'.format(ifconfig[0]))
  15. connect()
  16. app = Microdot()
  17. camera.init()
  18.    
  19.    
  20. @app.route('/')
  21. def index(request):
  22.     return '''<!doctype html>
  23. <html>
  24.   <head>
  25.     <title>ESP32P4网页图传</title>
  26.     <meta charset="UTF-8">
  27.   </head>
  28.   <body>
  29.     <h1>ESP32P4网页图传:</h1>
  30.     <img src="/video_feed" width="50%">
  31.   </body>
  32. </html>''', 200, {'Content-Type': 'text/html; charset=utf-8'}
  33. @app.route('/video_feed')
  34. def video_feed(request):
  35.     def stream():
  36.         yield b'--frame\r\n'
  37.         while True:
  38.             frame = camera.capture()
  39.             yield b'Content-Type: image/jpeg\r\n\r\n' + frame + \
  40.                 b'\r\n--frame\r\n'
  41.             gc.collect()
  42.             #time.sleep_ms(50)
  43.     return stream(), 200, {'Content-Type':
  44.                            'multipart/x-mixed-replace; boundary=frame'}
  45. if __name__ == '__main__':
  46.     app.run(debug=True)
  47.     camera.deinit()
复制代码

点灯视频:

网页图传效果视频:



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail