ESP32 内核在控制两个 LED 灯串时冻结

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

上周,我一直在处理 ESP32 的问题。有关背景信息,我正在开发一个 Music Meter 项目。我的目标是让 ESP32 采样两个音频信号,并让两组 LED 灯串对两个相应的音频信号做出反应。当我同时使用两个内核(使用 Arduino IDE)时遇到的问题是,当我采样音频时,其中一个内核经常冻结。我知道核心已冻结,并且不会卡在循环中,因为我设置了一个条件,如果长时间没有任何活动,其中一个 LED 将改变颜色,并且它从未改变颜色.

同样奇怪的是,作为基线测试,我想看看我是否可以控制 LED,但有一个简单的 for 循环打开和关闭每个灯条,效果很好。只有当我开始在多个核心上采样音频并且 LED 做出反应时,问题才会出现。如果我单独执行每个核心,那么核心永远不会冻结,并且它会按照我想要的方式工作。

/* This is in Core 1 */
for (int i = 0; i < MIDDLE_LED_COUNT; i++) {
    middle_strip.setPixelColor(i, color);
    middle_strip.show();
}
for (int i = (MIDDLE_LED_COUNT - 1); i >= 0 ; i--) {
    middle_strip.setPixelColor(i, 0, 0, 0, 0);
    middle_strip.show();
}
/* This is in Core 0 */
for (int i = 0; i < LOWER_LED_COUNT; i++) {
    lower_strip.setPixelColor(i, color);
    lower_strip.show();
}
for (int i = (LOWER_LED_COUNT - 1); i >= 0 ; i--) {
    lower_strip.setPixelColor(i, 0, 0, 0, 0);
    lower_strip.show();
}

其他需要注意的事项:当 ESP 通过 WiFi.mode( WIFI_MODE_NULL ) 处于“Music Visualizer”模式时,WiFi 已断开。 我已将所有可能会更改的变量设置为易失性,只是为了看看这是否会使其变得更好。它略有改善,但没有解决问题。

此时,我已经没有绳子了,我不知道如何解决这个问题。我当前的代码如下:

    /* Core 1 */
void musicVisualizer(void) {
  middle_strip.clear();
  upper_strip.clear();

  middle_strip.show();
  upper_strip.show();
  WiFi.mode( WIFI_MODE_NULL );
  delay(100);
  // Add code to tell Core 0 to wait until LED's are cleared.
  while (vu_meter) {
    tweeter_prev = tweeter;
    if (analogRead(tweeter_sample) <= 490)
      tweeter_adc = 0;
    else {
      tweeter_adc = (analogRead(tweeter_sample) - 490);
      if (tweeter_adc < 0)
        tweeter_adc = 0; // Filter for changing reference voltage
    }
    tweeter_filter.Filter(tweeter_adc);
    tweeter = tweeter_filter.Current() * 4;  // 6 scaler is for when Alexa is at Volume Level 4

    /* LED's turning on and off in response to audio */
    if ((tweeter > tweeter_prev) && (tweeter < MIDDLE_LED_COUNT)) {
      for (int x = tweeter_prev; x <= tweeter; x++) {
        middle_strip.setPixelColor(x, 0, 0, middle_strip.gamma32(BRIGHTNESS));
      }
      middle_strip.setPixelColor(0, 0, 0, middle_strip.gamma32(BRIGHTNESS));  // Removes status LED if active
      tweeter_count = 0;
      middle_strip.show();
    }
    else if (tweeter_prev > tweeter) {
      for (int x = tweeter_prev; x >= tweeter; x--) {
        middle_strip.setPixelColor(x, 0, 0, 0);
      }
      middle_strip.setPixelColor(0, 0, 0, middle_strip.gamma32(BRIGHTNESS));  // Removes status LED if active
      tweeter_count = 0;
      middle_strip.show();
    }
    else {
      tweeter_count += 1;
      if (tweeter_count < 1000)
        middle_strip.setPixelColor(0, middle_strip.gamma32(BRIGHTNESS), 0, 0, 0);
      else
        middle_strip.setPixelColor(0, 0, 0, 0, middle_strip.gamma32(BRIGHTNESS));
      middle_strip.show();
    }
    //        Blynk.run();
  }

  /* Leaving VU Meter, returning to current lamp color set */
  if (led_on) {
    if (!color_white) {
      for (int i = 0; i < LOWER_LED_COUNT; i++) {
        lower_strip.setPixelColor(i, color);
        lower_strip.show();
      }
      for (int i = 0; i < MIDDLE_LED_COUNT; i++) {
        middle_strip.setPixelColor(i, color);
        middle_strip.show();
      }
      for (int i = 0; i < UPPER_LED_COUNT; i++) {
        upper_strip.setPixelColor(i, color);
        upper_strip.show();
      }
    }
    else {
      for (int i = 0; i < LOWER_LED_COUNT; i++) {
        lower_strip.setPixelColor(i, 0, 0, 0, lower_strip.gamma32(BRIGHTNESS));
        lower_strip.show();
      }
      for (int i = 0; i < MIDDLE_LED_COUNT; i++) {
        middle_strip.setPixelColor(i, 0, 0, 0, middle_strip.gamma32(BRIGHTNESS));
        middle_strip.show();
      }
      for (int i = 0; i < UPPER_LED_COUNT; i++) {
        upper_strip.setPixelColor(i, 0, 0, 0, upper_strip.gamma32(BRIGHTNESS));
        upper_strip.show();
      }
    }
  }
  else {
    upper_strip.clear();
    middle_strip.clear();
    lower_strip.clear();

    upper_strip.show();
    middle_strip.show();
    lower_strip.show();
  }
}


/* Core 0 */
void vu_meter_sub(void * parameter) {
  while (true) {
    esp_task_wdt_init(30, false);

    if (vu_meter) {
      lower_strip.clear();
      lower_strip.show();
      while (vu_meter) {
        sub_prev = sub;
        sub_adc = analogRead(sub_sample);
        sub_filter.Filter(sub_adc);
        sub = sub_filter.Current();
        if ((sub > sub_prev) && (sub < LOWER_LED_COUNT)) {
          for (int x = sub_prev; x <= sub; x++) {
            lower_strip.setPixelColor(x, 0, lower_strip.gamma32(BRIGHTNESS), 0);
          }
          lower_strip.setPixelColor(0, 0, lower_strip.gamma32(BRIGHTNESS), 0);
          sub_count = 0;
          lower_strip.show();
        }
        else if (sub_prev > sub) {
          for (int x = sub_prev; x >= sub; x--) {
            lower_strip.setPixelColor(x, 0, 0, 0);
          }
          lower_strip.setPixelColor(0, 0, lower_strip.gamma32(BRIGHTNESS), 0);
          sub_count = 0;
          lower_strip.show();
        }
        else {
          sub_count += 1;
          if (sub_count < 1000)
            lower_strip.setPixelColor(0, lower_strip.gamma32(BRIGHTNESS), 0, 0, 0);
          else
            lower_strip.setPixelColor(0, 0, 0, 0, lower_strip.gamma32(BRIGHTNESS));
          lower_strip.show();
        }
      }
    }
  }
}
arduino esp32 led cpu-cores neopixel
1个回答
0
投票

排除故障后,我想我找到了问题,我想将其发布给将来可能遇到这篇文章的任何人。

在我的程序中,我需要为两个内核中的两个 music_visualizer 函数添加 1 毫秒的延迟,以防止 CPU 运行时间不足(我相信这就是正在发生的情况)。这样做大大提高了固件的成功率。我注意到,如果 Blynk(控制灯的应用程序)未注释,并且可以自由运行多次,则其中一个 CPU 饥饿的机会就会增加。为了解决这个问题,我所做的就是使用 millis() 计时器来跟踪调用 Blynk 之前经过的时间。 1000ms后,Blynk函数将被调用一次,并会再等待1000ms。因为我证明这可以工作,所以不需要 WIFI_MODE_NULL,因为不需要禁用 WiFi。

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