Анимация светодиодной ленты с ESP32 не работает при использовании WiFi
Я использую ESP32 для простого проекта. Я знаю, как анимировать светодиодную ленту, используя atmega328p с Arduino, но когда я анимирую ее на ESP32, это не работает так хорошо. Было бы неплохо, если бы я мог использовать один и тот же ESP32 для запуска всего моего проекта без необходимости включать еще один MCU. Удалось ли кому-нибудь анимировать светодиодную ленту, используя Wi-Fi на ESP32?
Это код, который я использую для анимации светодиодной ленты при использовании Wi-Fi. Я сам написал этот код, поэтому, возможно, я делаю что-то не так. Он работает лучше, чем любая из библиотек, которые я нашел в Интернете. Лучше всего работает библиотека esp32WS2811-master. Но все равно в моем случае этот код работает лучше, чем эта библиотека.
#include <Arduino.h>
#include "WiFi.h"
#include <Adafruit_NeoPixel.h>
// запускаем задачу, которая анимирует светодиодную ленту на отдельном ядре ардуино
TaskHandle_t Task1;
// куда подключен светодиод и количество светодиодов для анимации
#define PIN 32
#define NUM_LEDS 80
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
// мьютекс, который помогает войти в критические секции, пока мы анимируем светодиодную ленту
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
// он будет работать на ядре 0 esp32. Отвечает за анимацию светодиодной ленты.
void loop2(void *parameter)
{
uint32_t _color = strip.Color(0, 0, 0);
for (;;) // бесконечный цикл
{
_color = strip.Color(0, 0, 255);
// анимация 1
for (uint16_t i = 0; i < strip.numPixels(); i++)
{
strip.setPixelColor(i, _color);
//портОТКЛЮЧИТЬ_ПРЕРЫВАНИЕ(); // альтернатива портуENTER_CRITICAL
portENTER_CRITICAL(&mux); /* start critical section */
strip.show();
//portENABLE_INTERRUPTS(); // альтернатива портуEXIT_CRITICAL
portEXIT_CRITICAL(&mux); /* end critical section */
vTaskDelay(15); // задержка в один тик (15 мс) между чтениями для стабильности
}
// анимация 2
_color = strip.Color(0, 255, 0);
for (uint16_t i = 0; i < strip.numPixels(); i++)
{
strip.setPixelColor(i, _color);
//портОТКЛЮЧИТЬ_ПРЕРЫВАНИЕ(); // альтернатива портуENTER_CRITICAL
portENTER_CRITICAL(&mux); /* start critical section */
strip.show();
//portENABLE_INTERRUPTS(); // альтернатива портуEXIT_CRITICAL
portEXIT_CRITICAL(&mux); /* end critical section */
vTaskDelay(15); // задержка в один тик (15 мс) между чтениями для стабильности
}
}
}
void setup()
{
Serial.begin(115200);
// отключение Wi-Fi помогает, но нам это нужно
// WiFi.режим(WIFI_OFF);
// инициализируем светодиодную ленту
strip.begin();
strip.setBrightness(4);
strip.show(); // Инициализируем все пиксели выключенными
// создаем задачу, которая работает на ядре 0 esp32
xTaskCreatePinnedToCore(
loop2,
"Task_1",
1000,
NULL,
2, // приоритет 0 — самый низкий.
&Task1,
0 // использовать ядро 0. Ядро 1 является ядром по умолчанию
);
// продолжить выполнение кода на ядре 1 по умолчанию esp32
// Установить WiFi в режим станции и отключиться от точки доступа, если она ранее была подключена
WiFi.mode(WIFI_STA);
WiFi.disconnect();
Serial.println("Setup done");
}
// в сети сканирования основного цикла просто для того, чтобы показать, как светодиодная лента не работает, когда используется Wi-Fi
// Этот код я скопировал и вставил из примеров WiFi esp32
void loop()
{
Serial.println("scan start");
// WiFi.scanNetworks вернет количество найденных сетей
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n == 0)
{
Serial.println("no networks found");
}
else
{
Serial.print(n);
Serial.println(" networks found");
for (int i = 0; i < n; ++i)
{
// Печатаем SSID и RSSI для каждой найденной сети
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
delay(10);
}
}
Serial.println("");
// ждем 5 секунд до следующего сканирования сети
auto end = millis() + (unsigned long)5000;
while(millis() < end) {
vTaskDelay(1);
}
}
Когда я запускаю этот код, первый светодиод мигает. Другие светодиоды отлично анимируют 99,99% времени. Когда я отключаю WiFi, этот код отлично работает. Мне по-прежнему нужен portENTER_CRITICAL(&mux);
или portDISABLE_INTERRUPTS();
, чтобы он работал, даже если я отключу WiFi. Кому-нибудь удалось успешно анимировать светодиодную ленту с помощью ESP-32, используя Wi-Fi?
Если мне нужно использовать отдельный микроконтроллер, какой из них вы порекомендуете? ATtiny85?
@Tono Nam, 👍0
Обсуждение1 ответ
Лучший ответ:
Я использовал библиотеку FastLed, и теперь она работает. По какой-то причине библиотека adafruit работает только тогда, когда я не использую WiFi. Этот код работает:
#include "Arduino.h"
#include <FastLED.h>
#include "WiFi.h"
// запускаем задачу, которая анимирует светодиодную ленту на отдельном ядре ардуино
TaskHandle_t Task1;
#define LED_PIN 32
#define NUM_LEDS 108
#define BRIGHTNESS 10
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
#define UPDATES_PER_SECOND 100
// сканируем сеть каждые 5 секунд
void loop2(void *parameter)
{
for (;;)
{
Serial.println("scan start");
// WiFi.scanNetworks вернет количество найденных сетей
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n == 0)
{
Serial.println("no networks found");
}
else
{
Serial.print(n);
Serial.println(" networks found");
for (int i = 0; i < n; ++i)
{
// Печатаем SSID и RSSI для каждой найденной сети
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
delay(10);
}
}
Serial.println("");
vTaskDelay(5000);
}
}
void setup()
{
Serial.begin(115200);
delay(1000); // задержка безопасности при включении питания
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
// Установить WiFi в режим станции и отключиться от точки доступа, если она ранее была подключена
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// создаем задачу, которая работает на ядре 0 esp32
xTaskCreatePinnedToCore(
loop2,
"Task_1",
1000,
NULL,
2, // приоритет 0 — самый низкий.
&Task1,
1 // использовать ядро 0. Ядро 1 — ядро по умолчанию
);
Serial.println("Setup done");
}
void loop()
{
// красный
for (int i = 0; i < NUM_LEDS; i++)
{
leds[i] = 0xFF0000;
FastLED.show();
FastLED.delay(25);
}
// зеленый
for (int i = 0; i < NUM_LEDS; i++)
{
leds[i] = 0x00FF00;
FastLED.show();
FastLED.delay(25);
}
// синий
for (int i = 0; i < NUM_LEDS; i++)
{
leds[i] = 0x0000FF;
FastLED.show();
FastLED.delay(25);
}
// rgb красный зеленый синий
//Периодически менять палитру();
//FillLEDsFromPaletteColors(startIndex);
}
Пожалуйста, примите свой собственный ответ, чтобы он не появлялся снова и снова., @Sim Son
- Почему необходимо использовать ключевое слово volatile для глобальных переменных при обработке прерываний в ардуино?
- esp32 Stack canary watchpoint срабатывает
- Постоянная частота дискретизации АЦП на ESP8266 или ESP32
- Почему функция server.on() из "ESPAsyncWebServer.h" выполняется на стороне setup(), а не на стороне loop()?
- Какие Arduino поддерживают ATOMIC_BLOCK?
- Как избежать электромагнитных помех на входе ESP32
- ESP32 отправляет данные на другой ESP32 без установления соединения Wi-Fi
- ESP32 + Фастлед + WS2801
это не Wi-Fi, это ваши звонки с задержкой и заявления во время, которые останавливают шоу., @dandavis
Задержка является частью анимации. Если я отключу Wi-Fi, анимация будет отлично работать @dandavis. Мне нужно анимировать один светодиод каждые 15 миллисекунд., @Tono Nam
ну, я знаю, что могу передавать значения RGB через Wi-Fi на esp32 со скоростью 30 кадров в секунду на полосе 64 пикселя. Если бы Wi-Fi заблокировался, это выглядело бы очень рывками, но это не так, за исключением случайных сбоев, которые устраняются сами собой. Я даже не возился с прерываниями или явным управлением потоком. Сделайте свою анимацию асинхронной (например, мигание без задержки), чтобы одновременно происходило более одного действия. Для меня это потребовало перезаписи библиотеки adafruit, чтобы переместить циклы в автономные вызываемые функции, которые выполняли работу за одну итерацию в нужное время, как это определено логикой loop() и millis()., @dandavis
Разве все программное обеспечение для управления WiFi не работает на ядре 0? Если вы работаете на ядре 1, это улучшается?, @Majenko
@danvis, вы используете адресную светодиодную ленту? Вы анимируете свой светодиод, меняя цвет одного светодиода за раз? Если я использую не адресную светодиодную ленту, она работает., @Tono Nam
@Majenko, если я использую ядро 1, оно работает лучше. У меня просто мигает раз в 5 секунд. Но светодиоды отлично анимируются, это просто мерцание, которое я должен как-то решить, как решить., @Tono Nam