Как сделать программный код потокобезопасным?

Вчера я опубликовал сообщение, в котором столкнулся с проблемой на ESP32, использующем оба ядра на микроконтроллере (с включенным Wi-Fi, если это важно).

Я использую оба ядра для управления двумя полосками Neopixel по отдельности. Я создаю музыкальный визуализатор, и я хочу, чтобы неопиксели реагировали на изменения в музыке как можно быстрее, поэтому я чувствовал, что наличие одного для каждого отдельного ядра было лучшим способом для этого. Проблема, с которой я сталкиваюсь, заключается в том, что при воспроизведении звука функция музыкального визуализатора либо в основном ядре (ядро 1), либо во вторичном ядре (ядро 0) просто полностью зависает. Я попытался устранить неполадки с помощью какого-то серийного номера.Распечатайте инструкции, чтобы понять, где происходит разрыв кода, и, похоже, это происходит вокруг команды setPixelColor. Я думаю, что мой код заблокирован по потоку, и я хотел знать, что я могу сделать, чтобы сделать его потокобезопасным.

void musicVisualizer(void) {
  middle_strip.clear();
  upper_strip.clear();

  middle_strip.show();
  upper_strip.show();

  // 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
      else if (tweeter_adc > MIDDLE_LED_COUNT)
        tweeter_adc = tweeter_prev; // Filter for if there are intermittent spikes in the adc
    }
    tweeter_filter.Filter(tweeter_adc);
    tweeter = tweeter_filter.Current() * 6;  // 6 scaler is for when Alexa is at Volume Level 4

    //    /* Changing LED Number to improve efficency when turning on LED's */
    //    if (tweeter > 43)
    //      LED_COUNT = 65;
    //    else if (tweeter > 21)
    //      LED_COUNT = 43;
    //    else if (tweeter <= 21)
    //      LED_COUNT = 21;

    /* 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, color);
        middle_strip.setPixelColor(x, 0, 0, middle_strip.gamma32(brightness));
        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.show();
      }
    }
  }

  /* 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();
  }
}


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);
        if (sub_adc > LOWER_LED_COUNT)
          sub_adc = LOWER_LED_COUNT-1;
        sub_filter.Filter(sub_adc);
        sub = sub_filter.Current();
        //        if (sub < 0)
        //          sub = 0;
        Serial.println(sub);
        if ((sub > sub_prev) && (sub <= LOWER_LED_COUNT)) {
          for (int x = sub_prev; x < sub; x++) {
            //            lower_strip.setPixelColor(x, color);
            lower_strip.setPixelColor(x, 0, lower_strip.gamma32(brightness), 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.show();
          }
        }
        Blynk.run();
      }
    }
  }
}

, 👍0


1 ответ


1

Я не уверен, что это связано с безопасностью потоков, но вы должны знать , что strip.show ()-это медленная функция, которая блокируется во время отправки данных. setPixelColor(), напротив, работает быстро, так как обновляет только данные в памяти.

Я предлагаю вам изменить musicVisualizer() таким образом, чтобы он только покажите()каждую полосу один раз. Основная часть функции должна быть посвящена вычислению нужных цветов и их настройке с помощью setPixelColor(). Затем, в самом конце функции, покажите() три полоски.

,

Я благодарю вас за это предложение. Я внедрил это в свой код, но это не устранило проблему, с которой я столкнулся, когда одно из ядер замерзло. Я чувствую, что это может быть связано с тем, что они используют один и тот же заголовок библиотеки?, @Jay