本帖最后由 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安装一些依赖包直接运行即可: 
			
			
			- sudo apt-get update
 - 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源配置到阿里云提升速度。 - pip config set global.index-url <a href="http://mirrors.aliyun.com/pypi/simple" target="_blank">http://mirrors.aliyun.com/pypi/simple</a>
 - pip config set global.trusted-host mirrors.aliyun.com
 
  复制代码
  
 
4.下载仓库运行即可: - mkdir -p ~/esp
 - cd ~/esp
 - git clone <a href="https://gitee.com/EspressifSystems/esp-gitee-tools.git" target="_blank">https://gitee.com/EspressifSystems/esp-gitee-tools.git</a>
 - git clone <a href="https://gitee.com/EspressifSystems/esp-idf.git" target="_blank">https://gitee.com/EspressifSystems/esp-idf.git</a>
 - git clone -b esp32p4 <a href="https://github.com/Vincent1-python/micropython.git" target="_blank">https://github.com/Vincent1-python/micropython.git</a>
 - 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>
 - git clone <a href="https://github.com/cnadler86/mp_jpeg" target="_blank">https://github.com/cnadler86/mp_jpeg</a>
 
  复制代码
  
 
5.切换ESP-IDF的版本 
- cd esp-idf
 - git checkout v5.4.1
 
  复制代码
  
 
6.配置esp-idf官方为了解决国内开发者从github克隆esp相关仓库慢的问题,已将esp-idf和部分重要仓库及其关联的子模块镜像到了jihu。根据官方建议,使用以下命令将仓库的URL替换为jihu的URL,并更新子模块,完成安装。 - cd ~/esp/esp-gitee-tools
 - ./jihu-mirror.sh set
 - ./submodule-update.sh ~/esp/esp-idf/
 - ./install.sh ~/esp/esp-idf/
 
  复制代码
  
可能会提示Python virtual environment未安装成功。按照建议执行以下命令,并重新安装。 - sudo apt install python3.10-venv
 - ./install.sh ~/esp/esp-idf/
 
  复制代码
  
安装一大堆东西后,提示(xx是用户名): - All done! You can now run:
 - . /home/xx/esp/esp-idf/export.sh
 
  复制代码
  
表示安装成功。添加环境变量: - cd ~/esp/esp-idf
 - source export.sh
 
  复制代码
  
提示:idf.py buildinstall.sh步骤只需要执行一次。每次新会话都需要使用export.sh 7.确认esp-idf版本 
复制代码
  
再次确认ESP-IDFv5.4.1。 8.构建固件 
- cd ~/esp/micropython
 - make -C mpy-cross
 - cd ports/esp32
 - make submodules
 - make
 
  复制代码
  
如果顺利的话,就会在~/esp/micropython/ports/esp32/build-FireBeetle_2_ESP32_P4/中生成一个firmware.bin固件。 9.绑定两个驱动在~/esp中新建一个文件micropython.cmake写入以下代码: - include(${CMAKE_CURRENT_LIST_DIR}/micropython_csi_camera/micropython.cmake)
 - include(${CMAKE_CURRENT_LIST_DIR}/mp_jpeg/src/micropython.cmake)
 
  复制代码
  
 
10.最终的编译运行: - make clean
 - make USER_C_MODULES=~/esp/micropython.cmake
 
  复制代码
  
运行完成后,会在~/esp/micropython/ports/esp32/build-FireBeetle_2_ESP32_P4/中生成一个firmware.bin固件。复制到合适的地方开始烧录。 3.烧录网上有很多方式我就不详细写了,注意烧录地址为:0x002000 4.正式体验这里板载外设为主: LED测试: - from machine import Pin
 - import time
 - 
 - led = Pin(3,Pin.OUT)
 - 
 - while True:
 -     led.value(1)
 -     time.sleep(1)
 -     led.value(0)
 -     time.sleep(1)
 
  复制代码
  
麦克风测试: - import os
 - from machine import Pin
 - from machine import I2S
 - 
 - SCK_PIN = 12
 - #WS_PIN = 25
 - SD_PIN = 9
 - I2S_ID = 0
 - BUFFER_LENGTH_IN_BYTES = 40000
 - 
 - # ======= AUDIO CONFIGURATION =======
 - WAV_FILE = "mic.wav"
 - RECORD_TIME_IN_SECONDS = 4
 - WAV_SAMPLE_SIZE_IN_BITS = 16
 - FORMAT = I2S.MONO
 - SAMPLE_RATE_IN_HZ = 8000
 - # ======= AUDIO CONFIGURATION =======
 - 
 - format_to_channels = {I2S.MONO: 1, I2S.STEREO: 2}
 - NUM_CHANNELS = format_to_channels[FORMAT]
 - WAV_SAMPLE_SIZE_IN_BYTES = WAV_SAMPLE_SIZE_IN_BITS // 8
 - RECORDING_SIZE_IN_BYTES = (
 -     RECORD_TIME_IN_SECONDS * SAMPLE_RATE_IN_HZ * WAV_SAMPLE_SIZE_IN_BYTES * NUM_CHANNELS
 - )
 - 
 - 
 - def create_wav_header(sampleRate, bitsPerSample, num_channels, num_samples):
 -     datasize = num_samples * num_channels * bitsPerSample // 8
 -     o = bytes("RIFF", "ascii")  # (4byte) Marks file as RIFF
 -     o += (datasize + 36).to_bytes(
 -         4, "little"
 -     )  # (4byte) File size in bytes excluding this and RIFF marker
 -     o += bytes("WAVE", "ascii")  # (4byte) File type
 -     o += bytes("fmt ", "ascii")  # (4byte) Format Chunk Marker
 -     o += (16).to_bytes(4, "little")  # (4byte) Length of above format data
 -     o += (1).to_bytes(2, "little")  # (2byte) Format type (1 - PCM)
 -     o += (num_channels).to_bytes(2, "little")  # (2byte)
 -     o += (sampleRate).to_bytes(4, "little")  # (4byte)
 -     o += (sampleRate * num_channels * bitsPerSample // 8).to_bytes(4, "little")  # (4byte)
 -     o += (num_channels * bitsPerSample // 8).to_bytes(2, "little")  # (2byte)
 -     o += (bitsPerSample).to_bytes(2, "little")  # (2byte)
 -     o += bytes("data", "ascii")  # (4byte) Data Chunk Marker
 -     o += (datasize).to_bytes(4, "little")  # (4byte) Data size in bytes
 -     return o
 - 
 - 
 - audio_in = I2S(
 -     I2S_ID,
 -     sck=Pin(SCK_PIN),
 -     #ws=Pin(WS_PIN),
 -     sd=Pin(SD_PIN),
 -     mode=I2S.PDM_RX,
 -     bits=WAV_SAMPLE_SIZE_IN_BITS,
 -     format=FORMAT,
 -     rate=SAMPLE_RATE_IN_HZ * 4,
 -     ibuf=BUFFER_LENGTH_IN_BYTES,
 -     
 -     
 - )
 - 
 - # allocate sample arrays
 - # memoryview used to reduce heap allocation in while loop
 - mic_samples = bytearray(40000)
 - mic_samples_mv = memoryview(mic_samples)
 - 
 - 
 - recording_buffer = bytearray(RECORDING_SIZE_IN_BYTES)
 - bytes_received = 0
 - 
 - print("Recording size: {} bytes".format(RECORDING_SIZE_IN_BYTES))
 - print("==========  START RECORDING ==========")
 - try:
 -     while bytes_received < RECORDING_SIZE_IN_BYTES:
 -         # read a block of samples from the I2S microphone
 -         bytes_read = audio_in.readinto(mic_samples_mv)
 -         if bytes_read > 0:
 -             bytes_to_write = min(
 -                 bytes_read, RECORDING_SIZE_IN_BYTES - bytes_received
 -             )
 -             recording_buffer[bytes_received:bytes_received+bytes_to_write] = mic_samples_mv[0:bytes_to_write]
 -             print('FILL', bytes_received, bytes_to_write)
 -             bytes_received += bytes_read
 - 
 -     print("==========  DONE RECORDING ==========")
 - except (KeyboardInterrupt, Exception) as e:
 -     print("caught exception {} {}".format(type(e).__name__, e))
 - 
 - 
 - # Write to WAV
 - wav = open(WAV_FILE, "wb")
 - 
 - # create header for WAV file and write to SD card
 - wav_header = create_wav_header(
 -     SAMPLE_RATE_IN_HZ,
 -     WAV_SAMPLE_SIZE_IN_BITS,
 -     NUM_CHANNELS,
 -     SAMPLE_RATE_IN_HZ * RECORD_TIME_IN_SECONDS,
 - )
 - wav.write(wav_header)
 - 
 - # write samples to WAV file
 - wav.write(recording_buffer)
 - 
 - # cleanup
 - wav.close()
 - print("Wrote ", WAV_FILE)
 - audio_in.deinit()
 
  复制代码
  
SD卡测试: - from machine import Pin,SDCard
 - import os
 - 
 - 
 - sd = SDCard(slot=0,width=4, sck=43, cmd=44, data=(39, 40, 41, 42), freq=40000000)
 - 
 - os.mount(sd, '/sd')
 - os.listdir('/sd')
 - print(os.listdir('/sd'))
 - os.listdir('/sd')
 
  复制代码
  
联网测试: - import network,time
 - def connect():
 -     wlan = network.WLAN(network.STA_IF)
 -     wlan.active(True)
 -     if not wlan.isconnected():
 -         print('esp32p4正在联网',end="")
 -         wlan.connect('SSID', 'PWD') 
 -         while not wlan.isconnected():
 -             print(".",end="")
 -             time.sleep(1)
 -     print('\n网络信息为: ', wlan.ifconfig())  
 - 
 - connect()
 
  复制代码
  
摄像头拍照测试: - import camera,time,jpeg
 - camera.init()
 - time.sleep(5)
 - img = camera.capture()  # bytes
 - camera.deinit()
 - with open("capture.jpg", "wb") as f:
 -     f.write(img)
 - 
 - print("JPEG 编码完成")
 
  复制代码
  
网页图传测试: - from microdot import Microdot
 - import time,jpeg,camera,network
 - 
 - def connect():
 -     wlan = network.WLAN(network.STA_IF)
 -     wlan.active(True)
 -     if not wlan.isconnected():
 -         print('esp32p4正在联网',end="")
 -         wlan.connect('SSID', 'PWD') 
 -         while not wlan.isconnected():
 -             print(".",end="")
 -             time.sleep(1)
 -     print('\n网络信息为: ', wlan.ifconfig())
 -     ifconfig = wlan.ifconfig()
 -     print('请在浏览器打开:{}:5000'.format(ifconfig[0]))
 - 
 - connect()
 - app = Microdot()
 - camera.init()
 -     
 -     
 - @app.route('/')
 - def index(request):
 -     return '''<!doctype html>
 - <html>
 -   <head>
 -     <title>ESP32P4网页图传</title>
 -     <meta charset="UTF-8">
 -   </head>
 -   <body>
 -     <h1>ESP32P4网页图传:</h1>
 -     <img src="/video_feed" width="50%">
 -   </body>
 - </html>''', 200, {'Content-Type': 'text/html; charset=utf-8'}
 - 
 - @app.route('/video_feed')
 - def video_feed(request):
 -     def stream():
 -         yield b'--frame\r\n'
 -         while True:
 -             frame = camera.capture()
 -             yield b'Content-Type: image/jpeg\r\n\r\n' + frame + \
 -                 b'\r\n--frame\r\n'
 -             gc.collect()
 -             #time.sleep_ms(50)
 - 
 -     return stream(), 200, {'Content-Type':
 -                            'multipart/x-mixed-replace; boundary=frame'}
 - 
 - 
 - if __name__ == '__main__':
 -     app.run(debug=True)
 -     camera.deinit()
 
  复制代码
  
点灯视频: 
 
网页图传效果视频: 
 
 
 
 |