ESP32-WROOM-32 开发模块启动后短时间内崩溃

问题描述 投票:0回答:1

我正在使用 [https://github.com/pschatzmann/ESP32-A2DP/tree/main](ESP32-A2DP) 库和 Arduino IDE 制作 A2DP Sink 蓝牙音频接收器。当我启动程序时,连接到音频源(电脑或手机)并播放音乐,在播放的前几秒钟后,我的程序崩溃并出现此错误:

E (24574) task_wdt:  - IDLE0 (CPU 0)
E (24574) task_wdt: Tasks currently running:
E (24574) task_wdt: CPU 0: BTC_TASK
E (24574) task_wdt: CPU 1: IDLE1
E (24574) task_wdt: Aborting.
E (24574) task_wdt: Print CPU 0 (current core) backtrace

Backtrace: 0x4000bfed:0x3ffd2940 0x40097f28:0x3ffd2950 0x4009596f:0x3ffd2970 0x400dacd5:0x3ffd29b0 0x400d334e:0x3ffd29f0 0x400d336f:0x3ffd2a20 0x401a0233:0x3ffd2a50 0x4019f9bd:0x3ffd2a70 0x401a01d9:0x3ffd2a90 0x400d3fd5:0x3ffd2ab0 0x4019fff9:0x3ffd2ad0 0x400d36df:0x3ffd2af0 0x40120071:0x3ffd2b10 0x4011873d:0x3ffd2b50 0x401186d9:0x3ffd2b70 0x40097caa:0x3ffd2ba0

此回溯解码为:

0x40097f28: vPortExitCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos\portmacro.h:568
0x4009596f: xQueueGenericSend at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/FreeRTOS-Kernel\queue.c:998
0x400dacd5: i2s_channel_write at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/i2s\i2s_common.c:1145
0x400d334e:  is in I2SClass::write(unsigned char*, unsigned int) (C:\Users\20vik\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.0.7\libraries\ESP_I2S\src\ESP_I2S.cpp:831).
0x400d336f:  is in I2SClass::write(unsigned char) (C:\Users\20vik\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.0.7\libraries\ESP_I2S\src\ESP_I2S.cpp:889).
0x401a0233:  is in Print::write(unsigned char const*, unsigned int) (C:\Users\20vik\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.0.7\cores\esp32\Print.cpp:41).
0x4019f9bd:  is in BluetoothA2DPOutputPrint::write(unsigned char const*, unsigned int) (c:\Users\20vik\Documents\Arduino\libraries\ESP32-A2DP\src/BluetoothA2DPOutput.h:132).
0x401a01d9:  is in BluetoothA2DPSink::i2s_write_data(unsigned char const*, unsigned int) (c:\Users\20vik\Documents\Arduino\libraries\ESP32-A2DP\src\BluetoothA2DPSink.cpp:1242).
0x400d3fd5:  is in BluetoothA2DPSink::write_audio(unsigned char const*, unsigned int) (c:\Users\20vik\Documents\Arduino\libraries\ESP32-A2DP\src/BluetoothA2DPSink.h:533).
0x4019fff9:  is in BluetoothA2DPSink::audio_data_callback(unsigned char const*, unsigned long) (c:\Users\20vik\Documents\Arduino\libraries\ESP32-A2DP\src\BluetoothA2DPSink.cpp:1049).
0x400d36df:  is in ccall_audio_data_callback(uint8_t const*, uint32_t) (c:\Users\20vik\Documents\Arduino\libraries\ESP32-A2DP\src\BluetoothA2DPSink.cpp:1183).
0x40097caa: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa\port.c:162

这是我的代码:

#include <Wire.h>
#include <ESP_I2S.h>
#include <BluetoothA2DPSink.h>
#include <LiquidCrystal_I2C.h>
#include "DebugTools.h"


#define I2C_SCL 17
#define I2C_SDA 16

#define I2S_SCK 22
#define I2S_WS 25
#define I2S_SD 26

#define LCD_I2C_ADDRESS 0x27

I2SClass i2s;
BluetoothA2DPSink a2dp_sink(i2s);
//BluetoothA2DPSink a2dp_sink; //debug
LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, 20, 4);

String currentSongTitle;
String currentSongArtist;
String currentSongAlbum;

// FOR OPTIMISATION (FUTURE)
/*
struct AVRCP_MetadataEvent 
{
  uint8_t id;
  String value;
};
*/
//QueueHandle_t songMetadataQueue;

struct ScrollState 
{
  int scrollIndex = 0;
  unsigned long previousMillis = 0;
};


void setup() 
{
  Serial.begin(115200);

  Wire.setPins(I2C_SDA, I2C_SCL);
  lcd.init();                      
  lcd.backlight();

  a2dp_sink.set_avrc_metadata_attribute_mask(ESP_AVRC_MD_ATTR_TITLE | ESP_AVRC_MD_ATTR_ARTIST 
  | ESP_AVRC_MD_ATTR_ALBUM);
  //a2dp_sink.set_avrc_rn_track_change_callback([](uint8_t *id){
  //  currentSongTitle = "";
  //  currentSongArtist = "";
  //  currentSongAlbum = "";
  //  lcd.clear();
  //});
  a2dp_sink.set_avrc_metadata_callback([](uint8_t metadata_id, const uint8_t *metadata_value){
    dt::cb::print_avrc_metadata(metadata_id, metadata_value); 
    switch (metadata_id) 
    {
      case ESP_AVRC_MD_ATTR_TITLE:
        currentSongTitle = (const char*)metadata_value;
        break;
      case ESP_AVRC_MD_ATTR_ARTIST:
        currentSongArtist = (const char*)metadata_value;
        break;
      case ESP_AVRC_MD_ATTR_ALBUM:
        currentSongAlbum = (const char*)metadata_value;
        break;
      default:
        break;
    }
  });
  //a2dp_sink.set_stream_reader(dt::cb::read_data_stream, false); //debug
  i2s.setPins(I2S_SCK, I2S_WS, I2S_SD);
  i2s.begin(I2S_MODE_STD, 44100, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, I2S_STD_SLOT_BOTH);
  a2dp_sink.start("AurioSystem");
}

ScrollState titleScrollState;
ScrollState artistScrollState;
ScrollState albumScrollState;

void loop() 
{
  if (a2dp_sink.is_connected())
  {
    printFormattedSongData();
  }
  else
  { 
    lcd.setCursor(0, 0);
    lcd.print("Not Connected");
  }
}

String repeatString(String text, int times) 
{
  String result = "";
  for (int i = 0; i < times; i++)
    result += text;
  return result;
}

void displayStaticAndScrollData(String dataText, int row, int displayWidth, int interval, ScrollState &state) 
{
  if (dataText.length() > displayWidth) 
  {
    dataText += "  ";
    unsigned long currentMillis = millis();
    if (currentMillis - state.previousMillis >= interval) 
    {
      state.previousMillis = currentMillis;

      lcd.setCursor(0, row);
      lcd.print(repeatString(" ", displayWidth));

      String displayText;
      if (state.scrollIndex + displayWidth <= dataText.length())
        displayText = dataText.substring(state.scrollIndex, state.scrollIndex + displayWidth);
      else
        displayText = dataText.substring(state.scrollIndex) + dataText.substring(0, (state.scrollIndex + displayWidth) % dataText.length());

      lcd.setCursor(0, row);
      lcd.print(displayText);

      state.scrollIndex = (state.scrollIndex + 1) % dataText.length();
    }
  } 
  else 
  {
    lcd.setCursor(0, row);
    lcd.print(dataText);
  }
}

void printFormattedSongData()
{
  displayStaticAndScrollData(currentSongTitle, 0, 20, 250, titleScrollState);
  displayStaticAndScrollData(currentSongArtist, 1, 20, 250, artistScrollState);
  displayStaticAndScrollData(currentSongAlbum, 2, 20, 250, albumScrollState);
}

我尝试删除 i2s 输出功能,并且该程序不会刷新歌曲更改时的 AVRCP 元数据,只有当我暂停它时。

c++ bluetooth esp32 a2dp avrcp
1个回答
0
投票

除了增加看门狗定时器的长度之外,另一个解决方案是使用状态机来分割任务并让

loop
迭代得更快。

void printFormattedSongData()
{
  static unsigned char state = 0;
  switch (state % 3) {
  case 0:
    displayStaticAndScrollData(currentSongTitle, 0, 20, 250, titleScrollState);
    break;
  case 1:
    displayStaticAndScrollData(currentSongArtist, 1, 20, 250, artistScrollState);
    break;
  case 2:
    displayStaticAndScrollData(currentSongAlbum, 2, 20, 250, albumScrollState);
    break;
  }
  
  state += 1;
}

这是嵌入式世界中一种非常的常见做法,可以让主循环运行得更快。 主循环越快,您可以在主循环中放入的内容就越多,并且在中断中“不必”发生的事情就越多。需要的中断越多,并发带来的复杂性就越高。

© www.soinside.com 2019 - 2024. All rights reserved.