I am creating a device to use a bluetooth app to control the effects in the ws2812fx library on a esp32 thing from Sparkfun. It works great using the arduino serial monitor to update. But whenever I add the BLE code the led signal becomes unstable and starts to make the leds flicker and change colors.
I get the same result with multithreading or not.
I have tried running this with the leds being powered from the chip and on their own power supply.
I have tried the following wiring configurations with a 16led ws2812 ring (I have also tried these with different led fixtures including a ws2811 string):
1. esp32.usb > led.5v, esp32.gnd > led.gnd, esp32.gpio16(I have tried on other gpio's) > led.din
a. esp32.gpio > 470ohm resistor > led.din
2. I also tried this configuration with a 3.3v-5v logic level converter in between. Placing the resistor before and after the logic level converter.
I have tried this with 2 different Sparkfun esp32 thing's. I also tried this on an Adafruit esp32 Feather. All with the same results.
Here is the code:
main.cpp
#include <Arduino.h>
#include <Streaming.h>
#include <comm.h>
#include <led.h>
TaskHandle_t taskComm, taskLED;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(500);
xTaskCreatePinnedToCore(
TaskComm, /* pvTaskCode */
"Communication", /* pcName */
2048, /* usStackDepth */
NULL, /* pvParameters */
1, /* uxPriority */
&taskComm, /* pxCreatedTask */
0); /* xCoreID */
Serial.println("Start Comm process on Core 0");
xTaskCreatePinnedToCore(
TaskLED, /* pvTaskCode */
"LED", /* pcName */
1024, /* usStackDepth */
NULL, /* pvParameters */
1, /* uxPriority */
&taskLED, /* pxCreatedTask */
1); /* xCoreID */
Serial.println("Start LED process on Core 1");
}
void loop() {
// put your main code here, to run repeatedly:
if(cmd_complete) { //from comm.h
ProcessCommand(); //from led.h
}
}
comm.h
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "71ae1439-4160-4532-b952-74fa9ccbd337"
#define CHARACTERISTIC_UUID "0fffbd21-d7ca-4869-88d3-53005b6192a7"
#define MAX_NUM_CHARS 16 // maximum number of characters read from the Serial Monitor
char cmd[MAX_NUM_CHARS]; // char[] to store incoming serial commands
boolean cmd_complete = false; // whether the command string is complete
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
int index;
if (value.length() > 0) {
for (int i = 0; i < value.length(); i++) {
cmd[i] = value[i];
index = i + 1;
}
cmd[index] = '\0'; // terminate the string
Serial << "BLE received '" << cmd << "'" << endl;
cmd_complete = true;
}
}
};
void recvChar(void) {
static byte index = 0;
while (Serial.available() > 0 && cmd_complete == false) {
char rc = Serial.read();
if (rc != '\n') {
if(index < MAX_NUM_CHARS) cmd[index++] = rc;
} else {
cmd[index] = '\0'; // terminate the string
index = 0;
Serial << "received '" << cmd << "'" << endl;
cmd_complete = true;
}
}
}
void TaskComm( void * parameter ) {
//Setup
//Bluetooth Setup
char chipName[20];
uint64_t chipid=ESP.getEfuseMac();
snprintf(chipName, 20, "board-%04X%08X", (uint16_t)(chipid >> 32), (uint32_t)chipid);
Serial << "Chip Name: " << chipName << endl;
BLEDevice::init(chipName);
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Isomia LED Controller");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
for (;;) {
//Loop
recvChar(); // read serial comm
delay(10);
}
}
led.h
#include <WS2812FX.h>
#define LED_COUNT 16
#define LED_PIN 16
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void ProcessCommand() {
if (strncmp(cmd,"b ",2) == 0) {
uint8_t b = (uint8_t)atoi(cmd + 2);
ws2812fx.setBrightness(b);
Serial << "Set brightness to: " << ws2812fx.getBrightness() << endl;
}
if (strncmp(cmd,"s ",2) == 0) {
uint16_t s = (uint16_t)atoi(cmd + 2);
ws2812fx.setSpeed(s);
Serial << "Set speed to: " << ws2812fx.getSpeed() << endl;
}
if (strncmp(cmd,"m ",2) == 0) {
uint8_t m = (uint8_t)atoi(cmd + 2);
ws2812fx.setMode(m);
Serial << "Set mode to: " << ws2812fx.getMode() << " - " << ws2812fx.getModeName(ws2812fx.getMode()) << endl;
}
if (strncmp(cmd,"c ",2) == 0) {
uint32_t c = (uint32_t)strtoul(cmd + 2, NULL, 16);
ws2812fx.setColor(c);
Serial << "Set color to: 0x" << String(ws2812fx.getColor(), HEX) << endl;
}
cmd[0] = '\0'; // reset the commandstring
cmd_complete = false; // reset command complete
}
void TaskLED( void * parameter ) {
//Setup
ws2812fx.init();
ws2812fx.setBrightness(1);
ws2812fx.setSpeed(1000);
ws2812fx.setColor(0x007BFF);
ws2812fx.setMode(1);
ws2812fx.start();
for (;;) {
//Loop
ws2812fx.service();
}
}
```
Best Answer
Using RMT on the esp32 chip solved my problem. I even tested on a board without a 470ohm resistor or logic level converter. I took out the multithreading as well. Here is the source code. You need to add the ESP32_RMT_Driver.h from the ws2812fx_esp32 example