Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability for boards to provide a custom pixel order in neopixelWrite() #10128

Merged
merged 21 commits into from
Aug 19, 2024

Conversation

sblantipodi
Copy link
Contributor

The hint for the builtin neopixleWrite() function has the wrong information.
It shows
void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val)
but then the color order is swapped to GRB.

Supposed that we want to use RGB color order as default one, function must match this order.

The BlinkRGB.ino example also is incorrect in the color order with the current implementation.

@CLAassistant
Copy link

CLAassistant commented Aug 7, 2024

CLA assistant check
All committers have signed the CLA.

Copy link
Contributor

github-actions bot commented Aug 7, 2024

Warnings
⚠️

Some issues found for the commit messages in this PR:

  • the commit message "Remove const to allow changing the order":
    • summary looks empty
    • type/action looks empty
  • the commit message "fix(rgbled): it lacks GRB case":
    • summary looks too short
  • the commit message "fix(rgbled): suffix":
    • summary looks too short
  • the commit message "fix(rgbled): suffix":
    • summary looks too short

Please fix these commit messages - here are some basic tips:

  • follow Conventional Commits style
  • correct format of commit message should be: <type/action>(<scope/component>): <summary>, for example fix(esp32): Fixed startup timeout issue
  • allowed types are: change,ci,docs,feat,fix,refactor,remove,revert,test
  • sufficiently descriptive message summary should be between 20 to 72 characters and start with upper case letter
  • avoid Jira references in commit messages (unavailable/irrelevant for our customers)

TIP: Install pre-commit hooks and run this check when committing (uses the Conventional Precommit Linter).

⚠️ Please consider squashing your 21 commits (simplifying branch history).

👋 Hello sblantipodi, we appreciate your contribution to this project!


Click to see more instructions ...


This automated output is generated by the PR linter DangerJS, which checks if your Pull Request meets the project's requirements and helps you fix potential issues.

DangerJS is triggered with each push event to a Pull Request and modify the contents of this comment.

Please consider the following:
- Danger mainly focuses on the PR structure and formatting and can't understand the meaning behind your code or changes.
- Danger is not a substitute for human code reviews; it's still important to request a code review from your colleagues.
- Resolve all warnings (⚠️ ) before requesting a review from human reviewers - they will appreciate it.
- To manually retry these Danger checks, please navigate to the Actions tab and re-run last Danger workflow.

Review and merge process you can expect ...


We do welcome contributions in the form of bug reports, feature requests and pull requests.

1. An internal issue has been created for the PR, we assign it to the relevant engineer.
2. They review the PR and either approve it or ask you for changes or clarifications.
3. Once the GitHub PR is approved we do the final review, collect approvals from core owners and make sure all the automated tests are passing.
- At this point we may do some adjustments to the proposed change, or extend it by adding tests or documentation.
4. If the change is approved and passes the tests it is merged into the default branch.

Generated by 🚫 dangerJS against ec3d597

@SuGlider
Copy link
Collaborator

SuGlider commented Aug 7, 2024

@sblantipodi - Have you tested that?
WS2812B protocol order is GRB.

@sblantipodi
Copy link
Contributor Author

sblantipodi commented Aug 7, 2024

@SuGlider sure...
WS2812B protocol does not have a specific color order, color orders depends on the LEDs you are using and how it is connected to the board.

Lolin ESP32-C3 Mini for example uses RGB color order,
Lolin ESP32-S3 Mini uses GRB color order.

Programmers should know what kind of color order to use for the board of their interest and call that function accordingly.

For example:

To light up the LED red on Lolin S3 I need to call
neopixelWrite(LED_BUILTIN, 255, 0, 0);

To light up the LED red on Lolin C3 I need to call
neopixelWrite(LED_BUILTIN, 0, 255, 0);

but this is not really correct because C3 is using RGB color order and S3 is using GRB color order.

Having a double conversion inside the neopixelWrite function is somewhat misleading and not really needed in my opinion.

Please take into consideration that color orders may varies a lot, from my experience there are a lot of leds using those color order:

  • GRB
  • RGB
  • BGR
  • BRG
  • RBG
  • GBR

even though RGB and GRB are the most used ones.

@SuGlider
Copy link
Collaborator

SuGlider commented Aug 7, 2024

@sblantipodi - I see. Thanks for the explanation.
In that case, shall we change this PR to consider that the user may set a color order before using neoPixelWrite()?
Maybe a separated API for it?

@SuGlider
Copy link
Collaborator

SuGlider commented Aug 7, 2024

@sblantipodi - The way the PR is set, it doesn't work for the ESP DevKits that I have here. The order used by their LEDs ir GRB.

@SuGlider SuGlider self-assigned this Aug 7, 2024
@sblantipodi
Copy link
Contributor Author

@sblantipodi - I see. Thanks for the explanation. In that case, shall we change this PR to consider that the user may set a color order before using neoPixelWrite()? Maybe a separated API for it?

@SuGlider yes, that will be the best way to do it IMHO.
I can change this PR according to this...

give me some minutes :)

@me-no-dev
Copy link
Member

please leave arguments order to be red green blue as this is the logical order of colors used everywhere

@sblantipodi
Copy link
Contributor Author

sblantipodi commented Aug 7, 2024

I added a
void neopixelWriteOrdered(uint8_t pin, color_order_t color_order, uint8_t red_val, uint8_t green_val, uint8_t blue_val)
function to allow the user to select the preferred color order without going crazy with inverting the values.

I tested it on S3 from Lolin, Adafruit, UnexpectedMaker
and on a C3 from Lolin.

ESP DevKits will continue to work as before with no breaking changes,
default function neopixelWrite() is still using the RGB arguments as per me-no-dev request.

@sblantipodi sblantipodi changed the title fix(esp32): Fixed the hint for the builtin neopixleWrite() function change(esp32): Added a neopixelWriteOrdered() function Aug 7, 2024
Copy link
Contributor

github-actions bot commented Aug 7, 2024

Test Results

 56 files   -  83   56 suites   - 83   5m 10s ⏱️ - 1h 37m 50s
 21 tests  -   9   21 ✅  -   9  0 💤 ±0  0 ❌ ±0 
135 runs   - 168  135 ✅  - 168  0 💤 ±0  0 ❌ ±0 

Results for commit ec3d597. ± Comparison against base commit def319a.

This pull request removes 9 tests.
performance.coremark.test_coremark ‑ test_coremark
performance.fibonacci.test_fibonacci ‑ test_fibonacci
performance.psramspeed.test_psramspeed ‑ test_psramspeed
performance.ramspeed.test_ramspeed ‑ test_ramspeed
performance.superpi.test_superpi ‑ test_superpi
test_touch_errors
test_touch_interrtupt
test_touch_read
validation.periman.test_periman ‑ test_periman

♻️ This comment has been updated with latest results.

Copy link
Contributor

github-actions bot commented Aug 7, 2024

Memory usage test (comparing PR against master branch)

The table below shows the summary of memory usage change (decrease - increase) in bytes and percentage for each target.

MemoryFLASH [bytes]FLASH [%]RAM [bytes]RAM [%]
TargetDECINCDECINCDECINCDECINC
ESP32S30⚠️ +960.00⚠️ +0.03000.000.00
ESP32S20⚠️ +1000.00⚠️ +0.03000.000.00
ESP32C30⚠️ +800.00⚠️ +0.03000.000.00
ESP32C60⚠️ +780.00⚠️ +0.04000.000.00
ESP32H20⚠️ +800.00⚠️ +0.03000.000.00
ESP320⚠️ +840.00⚠️ +0.03000.000.00
Click to expand the detailed deltas report [usage change in BYTES]
TargetESP32S3ESP32S2ESP32C3ESP32C6ESP32H2ESP32
ExampleFLASHRAMFLASHRAMFLASHRAMFLASHRAMFLASHRAMFLASHRAM
ArduinoOTA/examples/BasicOTA⚠️ +800⚠️ +880⚠️ +760⚠️ +760--00
AsyncUDP/examples/AsyncUDPClient00000000--00
AsyncUDP/examples/AsyncUDPMulticastServer00000000--00
AsyncUDP/examples/AsyncUDPServer00000000--00
BLE/examples/BLE5_extended_scan00--000000--
BLE/examples/BLE5_multi_advertising00--000000--
BLE/examples/BLE5_periodic_advertising00--000000--
BLE/examples/BLE5_periodic_sync00--000000--
BLE/examples/Beacon_Scanner00--00000000
BLE/examples/Client00--00000000
BLE/examples/EddystoneTLM_Beacon00--0000--00
BLE/examples/EddystoneURL_Beacon00--0000--00
BLE/examples/Notify00--00000000
BLE/examples/Scan00--00000000
BLE/examples/Server00--00000000
BLE/examples/Server_multiconnect00--00000000
BLE/examples/UART00--00000000
BLE/examples/Write00--00000000
BLE/examples/iBeacon00--00000000
DNSServer/examples/CaptivePortal00000000--00
EEPROM/examples/eeprom_class000000000000
EEPROM/examples/eeprom_extra000000000000
EEPROM/examples/eeprom_write000000000000
ESP32/examples/AnalogOut/LEDCFade000000000000
ESP32/examples/AnalogOut/LEDCSingleChannel000000000000
ESP32/examples/AnalogOut/LEDCSoftwareFade000000000000
ESP32/examples/AnalogOut/SigmaDelta000000000000
ESP32/examples/AnalogOut/ledcFrequency000000000000
ESP32/examples/AnalogOut/ledcWrite_RGB000000000000
ESP32/examples/AnalogRead000000000000
ESP32/examples/AnalogReadContinuous000000000000
ESP32/examples/ArduinoStackSize000000000000
ESP32/examples/CI/CIBoardsTest⚠️ +800⚠️ +800⚠️ +740⚠️ +740⚠️ +74000
ESP32/examples/Camera/CameraWebServer0000------00
ESP32/examples/ChipID/GetChipID000000000000
ESP32/examples/DeepSleep/ExternalWakeUp0000------00
ESP32/examples/DeepSleep/TimerWakeUp00000000--00
ESP32/examples/DeepSleep/TouchWakeUp0000------00
ESP32/examples/FreeRTOS/BasicMultiThreading⚠️ +800⚠️ +800⚠️ +760⚠️ +760⚠️ +76000
ESP32/examples/FreeRTOS/Mutex000000000000
ESP32/examples/FreeRTOS/Queue000000000000
ESP32/examples/FreeRTOS/Semaphore000000000000
ESP32/examples/GPIO/BlinkRGB⚠️ +800⚠️ +800⚠️ +800⚠️ +780⚠️ +80000
ESP32/examples/GPIO/FunctionalInterrupt000000000000
ESP32/examples/GPIO/FunctionalInterruptStruct000000000000
ESP32/examples/GPIO/GPIOInterrupt000000000000
ESP32/examples/HWCDC_Events00--⚠️ +740⚠️ +740⚠️ +740--
ESP32/examples/MacAddress/GetMacAddress000000000000
ESP32/examples/RMT/Legacy_RMT_Driver_Compatible000000000000
ESP32/examples/RMT/RMTCallback000000000000
ESP32/examples/RMT/RMTLoopback000000000000
ESP32/examples/RMT/RMTReadXJT000000000000
ESP32/examples/RMT/RMTWriteNeoPixel000000000000
ESP32/examples/RMT/RMT_CPUFreq_Test⚠️ +800⚠️ +800⚠️ +720⚠️ +740⚠️ +720⚠️ +840
ESP32/examples/RMT/RMT_EndOfTransmissionState000000000000
ESP32/examples/RMT/RMT_LED_Blink000000000000
ESP32/examples/ResetReason/ResetReason000000000000
ESP32/examples/ResetReason/ResetReason2000000000000
ESP32/examples/Serial/BaudRateDetect_Demo000000000000
ESP32/examples/Serial/OnReceiveError_BREAK_Demo000000000000
ESP32/examples/Serial/OnReceive_Demo000000000000
ESP32/examples/Serial/RS485_Echo_Demo000000000000
ESP32/examples/Serial/RxFIFOFull_Demo000000000000
ESP32/examples/Serial/RxTimeout_Demo000000000000
ESP32/examples/Serial/Serial_All_CPU_Freqs000000000000
ESP32/examples/Serial/Serial_STD_Func_OnReceive000000000000
ESP32/examples/Serial/onReceiveExample000000000000
ESP32/examples/TWAI/TWAIreceive000000000000
ESP32/examples/TWAI/TWAItransmit000000000000
ESP32/examples/Template/ExampleTemplate000000000000
ESP32/examples/Time/SimpleTime00000000--00
ESP32/examples/Timer/RepeatTimer000000000000
ESP32/examples/Timer/WatchdogTimer000000000000
ESP32/examples/Touch/TouchButtonV20000--------
ESP32/examples/Touch/TouchInterrupt0000------00
ESP32/examples/Touch/TouchRead0000------00
ESP32/examples/Utilities/HEXBuilder000000000000
ESP32/examples/Utilities/MD5Builder000000000000
ESP32/examples/Utilities/SHA1Builder000000000000
ESP_I2S/examples/ES8388_loopback⚠️ +800⚠️ +800⚠️ +740⚠️ +740⚠️ +74000
ESP_I2S/examples/Record_to_WAV00--------00
ESP_I2S/examples/Simple_tone000000000000
ESP_NOW/examples/ESP_NOW_Broadcast_Master00000000--00
ESP_NOW/examples/ESP_NOW_Broadcast_Slave00000000--00
ESP_NOW/examples/ESP_NOW_Network00000000--00
ESP_NOW/examples/ESP_NOW_Serial00000000--00
ESP_SR/examples/Basic⚠️ +800----------
ESPmDNS/examples/mDNS-SD_Extended00000000--00
ESPmDNS/examples/mDNS_Web_Server00000000--00
Ethernet/examples/ETH_W5500_Arduino_SPI⚠️ +800⚠️ +800⚠️ +760⚠️ +760⚠️ +76000
Ethernet/examples/ETH_W5500_IDF_SPI⚠️ +840⚠️ +800⚠️ +760⚠️ +760⚠️ +76000
Ethernet/examples/ETH_WIFI_BRIDGE⚠️ +840⚠️ +800⚠️ +760⚠️ +760--00
FFat/examples/FFat_Test000000000000
FFat/examples/FFat_time00000000--00
HTTPClient/examples/Authorization00000000--00
HTTPClient/examples/BasicHttpClient00000000--00
HTTPClient/examples/BasicHttpsClient00000000--00
HTTPClient/examples/HTTPClientEnterprise00000000--00
HTTPClient/examples/ReuseConnection00000000--00
HTTPClient/examples/StreamHttpClient00000000--00
HTTPUpdate/examples/httpUpdate⚠️ +800⚠️ +1000⚠️ +760⚠️ +760--00
HTTPUpdate/examples/httpUpdateSPIFFS⚠️ +800⚠️ +840⚠️ +760⚠️ +760--00
HTTPUpdate/examples/httpUpdateSecure⚠️ +800⚠️ +840⚠️ +760⚠️ +760--00
HTTPUpdateServer/examples/WebUpdater⚠️ +840⚠️ +840⚠️ +760⚠️ +760--00
Insights/examples/DiagnosticsSmokeTest000000----00
Insights/examples/MinimalDiagnostics000000----00
LittleFS/examples/LITTLEFS_test000000000000
LittleFS/examples/LITTLEFS_time00000000--00
NetBIOS/examples/ESP_NBNST00000000--00
NetworkClientSecure/examples/WiFiClientInsecure00000000--00
NetworkClientSecure/examples/WiFiClientPSK00000000--00
NetworkClientSecure/examples/WiFiClientSecure00000000--00
NetworkClientSecure/examples/WiFiClientSecureEnterprise00000000--00
NetworkClientSecure/examples/WiFiClientSecureProtocolUpgrade00000000--00
NetworkClientSecure/examples/WiFiClientShowPeerCredentials00000000--00
NetworkClientSecure/examples/WiFiClientTrustOnFirstUse00000000--00
PPP/examples/PPP_Basic⚠️ +800⚠️ +840⚠️ +760⚠️ +760⚠️ +76000
PPP/examples/PPP_WIFI_BRIDGE⚠️ +800⚠️ +840⚠️ +760⚠️ +760--00
Preferences/examples/Prefs2Struct000000000000
Preferences/examples/StartCounter000000000000
RainMaker/examples/RMakerCustom⚠️ +960⚠️ +760⚠️ +760⚠️ +760--00
RainMaker/examples/RMakerCustomAirCooler⚠️ +800⚠️ +840⚠️ +740⚠️ +740--00
RainMaker/examples/RMakerSonoffDualR3⚠️ +800⚠️ +920⚠️ +740⚠️ +740--00
RainMaker/examples/RMakerSwitch⚠️ +960⚠️ +720⚠️ +760⚠️ +760--00
SD/examples/SD_Test⚠️ +800⚠️ +800⚠️ +760⚠️ +760⚠️ +76000
SD/examples/SD_time⚠️ +800⚠️ +720⚠️ +760⚠️ +760--00
SD_MMC/examples/SD2USBMSC⚠️ +800----------
SD_MMC/examples/SDMMC_Test00--------00
SD_MMC/examples/SDMMC_time00--------00
SPI/examples/SPI_Multiple_Buses⚠️ +800⚠️ +800------00
SPIFFS/examples/SPIFFS_Test000000000000
SPIFFS/examples/SPIFFS_time00000000--00
SimpleBLE/examples/SimpleBleDevice00----000000
TFLiteMicro/examples/hello_world000000000000
Ticker/examples/Blinker⚠️ +800⚠️ +800⚠️ +720⚠️ +720⚠️ +72000
Ticker/examples/TickerBasic⚠️ +800⚠️ +800⚠️ +740⚠️ +720⚠️ +74000
Ticker/examples/TickerParameter⚠️ +800⚠️ +800⚠️ +740⚠️ +740⚠️ +74000
USB/examples/CompositeDevice⚠️ +80000--------
USB/examples/ConsumerControl⚠️ +80000--------
USB/examples/CustomHIDDevice⚠️ +80000--------
USB/examples/FirmwareMSC⚠️ +80000--------
USB/examples/Gamepad⚠️ +80000--------
USB/examples/HIDVendor⚠️ +80000--------
USB/examples/Keyboard/KeyboardLogout⚠️ +80000--------
USB/examples/Keyboard/KeyboardMessage⚠️ +80000--------
USB/examples/Keyboard/KeyboardReprogram⚠️ +80000--------
USB/examples/Keyboard/KeyboardSerial⚠️ +80000--------
USB/examples/KeyboardAndMouseControl⚠️ +80000--------
USB/examples/MIDI/MidiController⚠️ +80000--------
USB/examples/MIDI/MidiInterface⚠️ +80000--------
USB/examples/MIDI/MidiMusicBox⚠️ +80000--------
USB/examples/MIDI/ReceiveMidi⚠️ +80000--------
USB/examples/Mouse/ButtonMouseControl⚠️ +80000--------
USB/examples/SystemControl⚠️ +80000--------
USB/examples/USBMSC⚠️ +80000--------
USB/examples/USBSerial⚠️ +80000--------
USB/examples/USBVendor⚠️ +80000--------
Update/examples/AWS_S3_OTA_Update⚠️ +800⚠️ +800⚠️ +760⚠️ +760--00
Update/examples/HTTPS_OTA_Update00000000--00
Update/examples/HTTP_Client_AES_OTA_Update⚠️ +800⚠️ +760⚠️ +760⚠️ +760--00
Update/examples/HTTP_Server_AES_OTA_Update⚠️ +800⚠️ +840⚠️ +760⚠️ +760--00
Update/examples/OTAWebUpdater⚠️ +800⚠️ +800⚠️ +760⚠️ +760--00
Update/examples/SD_Update⚠️ +800⚠️ +800⚠️ +760⚠️ +760⚠️ +76000
WebServer/examples/AdvancedWebServer⚠️ +840⚠️ +840⚠️ +760⚠️ +760--00
WebServer/examples/FSBrowser00000000--00
WebServer/examples/Filters⚠️ +800⚠️ +800⚠️ +760⚠️ +760--00
WebServer/examples/HelloServer⚠️ +600⚠️ +800⚠️ +760⚠️ +760--00
WebServer/examples/HttpAdvancedAuth⚠️ +800⚠️ +960⚠️ +760⚠️ +760--00
WebServer/examples/HttpAuthCallback⚠️ +800⚠️ +800⚠️ +760⚠️ +760--00
WebServer/examples/HttpAuthCallbackInline⚠️ +840⚠️ +920⚠️ +760⚠️ +760--00
WebServer/examples/HttpBasicAuth⚠️ +840⚠️ +1000⚠️ +760⚠️ +760--00
WebServer/examples/HttpBasicAuthSHA1⚠️ +920⚠️ +800⚠️ +760⚠️ +760--00
WebServer/examples/HttpBasicAuthSHA1orBearerToken⚠️ +800⚠️ +800⚠️ +760⚠️ +760--00
WebServer/examples/MultiHomedServers⚠️ +800⚠️ +800⚠️ +760⚠️ +760--00
WebServer/examples/PathArgServer00000000--00
WebServer/examples/SDWebServer⚠️ +800⚠️ +840⚠️ +760⚠️ +760--00
WebServer/examples/SimpleAuthentification00000000--00
WebServer/examples/UploadHugeFile⚠️ +800⚠️ +920⚠️ +760⚠️ +760--00
WebServer/examples/WebServer00000000--00
WebServer/examples/WebUpdate⚠️ +800⚠️ +800⚠️ +760⚠️ +760--00
WiFi/examples/FTM/FTM_Initiator00000000--00
WiFi/examples/FTM/FTM_Responder00000000--00
WiFi/examples/SimpleWiFiServer⚠️ +800⚠️ +840⚠️ +760⚠️ +760--00
WiFi/examples/WPS00000000--00
WiFi/examples/WiFiAccessPoint⚠️ +760⚠️ +800⚠️ +760⚠️ +760--00
WiFi/examples/WiFiBlueToothSwitch00--0000--00
WiFi/examples/WiFiClient00000000--00
WiFi/examples/WiFiClientBasic00000000--00
WiFi/examples/WiFiClientConnect00000000--00
WiFi/examples/WiFiClientEnterprise00000000--00
WiFi/examples/WiFiClientEvents00000000--00
WiFi/examples/WiFiClientStaticIP00000000--00
WiFi/examples/WiFiExtender00000000--00
WiFi/examples/WiFiIPv600000000--00
WiFi/examples/WiFiMulti00000000--00
WiFi/examples/WiFiMultiAdvanced00000000--00
WiFi/examples/WiFiScan00000000--00
WiFi/examples/WiFiScanAsync00000000--00
WiFi/examples/WiFiScanDualAntenna00000000--00
WiFi/examples/WiFiScanTime00000000--00
WiFi/examples/WiFiSmartConfig00000000--00
WiFi/examples/WiFiTelnetToSerial00000000--00
WiFi/examples/WiFiUDPClient00000000--00
WiFiProv/examples/WiFiProv00000000--00
Wire/examples/WireMaster000000000000
Wire/examples/WireScan000000000000
Wire/examples/WireSlave000000000000
OpenThread/examples/COAP/coap_lamp------⚠️ +740⚠️ +720--
OpenThread/examples/COAP/coap_switch------⚠️ +720⚠️ +720--
OpenThread/examples/SimpleCLI------0000--
OpenThread/examples/SimpleNode------0000--
OpenThread/examples/SimpleThreadNetwork/LeaderNode------0000--
OpenThread/examples/SimpleThreadNetwork/RouterNode------0000--
OpenThread/examples/ThreadScan------0000--
OpenThread/examples/onReceive------0000--
BluetoothSerial/examples/DiscoverConnect----------00
BluetoothSerial/examples/GetLocalMAC----------00
BluetoothSerial/examples/SerialToSerialBT----------00
BluetoothSerial/examples/SerialToSerialBTM----------00
BluetoothSerial/examples/SerialToSerialBT_Legacy----------00
BluetoothSerial/examples/SerialToSerialBT_SSP----------00
BluetoothSerial/examples/bt_classic_device_discovery----------00
BluetoothSerial/examples/bt_remove_paired_devices----------00
ESP32/examples/DeepSleep/SmoothBlink_ULP_Code----------00
ESP32/examples/Touch/TouchButton----------00
Ethernet/examples/ETH_LAN8720----------00
Ethernet/examples/ETH_TLK110----------00

@robertlipe
Copy link

robertlipe commented Aug 8, 2024

Aren't there multiple independent implementations of neopixelwrite? If you're proposing a new API, it should be available in all of them. Isn't neopixelwrite really meant to control the on-board status indicator and not arbitrary strips you might connect?

IMO, you're way better off just calling the constructor with the order you need and not trying to create a new API here. Otherwise, you're on the road to turn this into AdaFruitNeoPixel, FastLED, Makuna NeoPixel, or idf's led_strip . In fact, shouldn't this code really just call the latter?

It's a bit ironic that this very week, we've been working this same issue in two of those projects, such as
espressif/idf-extra-components#344

It's a messy topic. It's quite reasonable to want to use this library's neopixelWrite() to indicate, say, WiFi connection status for the onboard pixel while
using a "real" led library to control multiple strips of different types. Probably best to keep the use cases strongly separated.

@SuGlider
Copy link
Collaborator

SuGlider commented Aug 8, 2024

There is point here: it shall be as simple as possible and address the onboard LED only.
@sblantipodi said that some other boards use a different RGB order than the one set for Espressif onboard neopixel.

In order to simplify it, a suggestion would be to define the RGB order in the pins_arduino.h, which is specific for the board.

The API would continue to be just neopixelWrite(pin, Red, Green, Blue) and the function would use this board setting, if it is defined, to decide how to send the colors to the WS2812B LED. If nothing is defined, it uses the default which would be R-G-B order.

Example:
variants/esp32c3/pins_arduino.h would define

#define RGB_BUILTIN_ORDER      LED_COLOR_ORDER_RGB

cores/esp32/esp32-hal-rgb-led.h would just declare the list:

typedef enum {
  LED_COLOR_ORDER_RGB,
  LED_COLOR_ORDER_BGR,
  LED_COLOR_ORDER_BRG,
  LED_COLOR_ORDER_RBG,
  LED_COLOR_ORDER_GBR,
  LED_COLOR_ORDER_GRB
} rgb_led_color_order_t;

cores/esp32/esp32-hal-rgb-led.c would do something like:

rgb_led_color_order_t rgb_led_color_order = LED_COLOR_ORDER_RGB;
#ifdef RGB_BUILTIN_ORDER
rgb_led_color_order = RGB_BUILTIN_ORDER;
#endif

// + the switch() and so on as proposed in the PR ....

For instance, the Lolin ESP32-S3 Mini that uses GRB color order, would declare in its own pins_arduino.h file the correct order for its neopixel:

#define RGB_BUILTIN_ORDER LED_COLOR_ORDER_GRB


Would it be better @robertlipe, @sblantipodi and @me-no-dev?
Let's talk and implement it.

@robertlipe
Copy link

I agree with the goal of simplicity here.

But first, a diversion into yak-shaving, so we can get all our parlance consistent. World Semi brand 2811's (the chips often on strips, commonly in 12 and 24v applications so you can attach multiple bulbs per pixel) often have bulbs in crazy orders despite the pins having labels like "green". The WS2812 is a package that integrates (the equivalent of) that 2811 chip into a package with three LEDs of different colors. Those LED appear in the packet order as GRB in the data packet. From this, we should derive that a WS2811 (which allows crazy color orders and voltages > 5 because the LEDs are separate from the TTL) should be UNcommon on a dev board and a real WS2812 (which allows only GRB) would be far more likely to appear on a dev board.

Based on this, I'm going to ask and confirm if everyone is really really sure that they A) have a dev board (where cost and size rule) that is either taking the cost and size hit of a WS2811 and wiring them in a crazy order, B) have some kind of mutant device that isn't really a World Semi part (WS2812's are always GRB), or C) are actually talking external strips.

There might have been a short time some 15 years ago (?) where WS2811 + 3 5V LEDs on a dev board made sense to save two GPIOs (At least to someone that never learned about Charlieplexing...) , but I just can't imagine we have a lot of A in the world of dev boards. There might be some kind of clone chips that do their own thing in color order, but that seems an awfully brave move to break compatiblity in such an important way. (Yes, I DO know what companies will do to save a sixteenth of a cent somewhere :-) ) SuGlider and I are agreeing this file/function isn't about C) at all.

The number of places we can introduce inconsistencies here is large and if we start trying to fix software to reflect that one vendor is using some kind of hardware that isn't really a WS2812 at all, we open the door to battling later. The number of times I've had to dig into this to find the effects layer is coded for one order but the API is coded for a second, the driver layer is coded for a third, and the the strips are soldered in a wacky fourth order but it doesn't all QUITE cancel out (sometimes it does!) is ridiculous.

The schematic for the non-compliant board you cite says they're using World Semi 2812B's in a 35x35mm package. There is no way to miswire that part to give different color orders.

On to SuGlider's proposal: if you're not worried about binary compat or supporting multiple pilot lights or whatever, just "fix" it at compile time when you unpack the values into the the teensy little buffer that you're handing off to the RMT here. No runtime switch per pixel needed.

But first, let's figure out what problem is REALLY trying to be solved here.

TL;DR: I'm highly skeptical there is an RGB WS2812b. Stick your scope on the data pin and if they're real WS2812b's or even WS2812c, they're GRB at the packet level.

P.S. May name may not be well known here, but I help heavily with a couple of Blinky LED projects.

@robertlipe
Copy link

uses the default which would be R-G-B order.

Not to over-correct my superiour (logical "elder" if not necessarily physically so :-) ) here in our first meeting, but the default is, and should remain, G R B.

int color[] = {green_val, red_val, blue_val}; // Color coding is in order GREEN, RED, BLUE

The incoming arguments in $a1, $a2, $a3 (sweeten calling convention to taste) are copied into a three byte buffer here:

int color[] = {green_val, red_val, blue_val};

The bytes in color are then unpacked into the bits of the WS281x protocol and shoved into RMT format before being handed off to the RMT's DMAc to be shoved off the edge of the chip.

So: The function argument order (which was changed above and then, thankfully, reverted) remain R G B , but the orders on the wire (the RMT output and the GPIO output and the LED's data input) are G R B.

We all call it "RGB" because that's what it's been called everywhere forever, but the bits on the wire for these specific blinkies are ordered G R B.

As a mnemonic, I remember it like the icky little potato worms or the Linux bootloader. The fact that I associate those two items is telling...

And all of this is why this function should also not care about cold white or warm white, either.

@sblantipodi
Copy link
Contributor Author

sblantipodi commented Aug 9, 2024

TL;DR: I'm highly skeptical there is an RGB WS2812b. Stick your scope on the data pin and if they're real WS2812b's or even WS2812c, they're GRB at the packet level.

@robertlipe I double checked some of my ESPs and the Lolin ESP32-S3 is using RGB and not GRB, same thing for the TinyS3 from Unexpected Maker.

As per WS2812B in general my firmware has lots of users using WS2812B RGB strips leave alone the more popular WLED, this just to tell you that the chip used on the LED does not have a specific color order.

@robertlipe
Copy link

robertlipe commented Aug 9, 2024 via email

@SuGlider
Copy link
Collaborator

SuGlider commented Aug 9, 2024

@sblantipodi @robertlipe - Let's be practical.

@sblantipodi says that he has a couple boards that have an RGB LED that works with a different color order. This can be tested using ESP32 Arduino neopixelWrite(pin, 255, 0, 0);. If the LED color is set to RED, the order is GRB. But if the color is set to GREEN, the color order would be RGB (given that the code sends always GRB order). @sblantipodi - please confirm it.

Considering that it happens, some users may have some trouble with the onboard RGB LED.
@UnexpectedMaker - Can you please give us a hand here? You certainly have the answer in this case.

For this PR, I still suggest the approach described in #10128 (comment)

@robertlipe
Copy link

Please consider solutions that don't insert RGB_BUILTIN_ORDER, rgb_led_color_order_t, and and rgb_led_color_order into the user's namespace. Those symbols are likely to collide for someone.

You can do with this without introducing any extra CPU overhead (not an issue for an on-board status light; big issue for 10,000 pixels) that populates the struct in #10128 (comment) in the intended error.

But, yes, if someone out there is mislabeling WS2812B's, then let's find a way to special case it in those board header, provide a sensible default, and as little runtime special casing (I'm leaning toward "zero") as possible.

@SuGlider
Copy link
Collaborator

You can do with this without introducing any extra CPU overhead

Something like this is not the most elegant way, but it for sure efficient.
No extracode, just define the builtin RGB LED bit order, directly in the code, for any board that needs it.

variants/esp32c3/pins_arduino.h would define

//  neopixelWrite() RMT will use G, R, B bits order
#define RGB_BUILTIN_COLOR_ORDER_STRUCT {green_val, red_val, blue_val} 

cores/esp32/esp32-hal-rgb-led.c would do something like:

#ifdef RGB_BUILTIN_COLOR_ORDER_STRUCT
int color[] = RGB_BUILTIN_COLOR_ORDER_STRUCT;
#else
// WS2812B color bit order is G, R, B
int color[] = {green_val, red_val, blue_val};
#endif

For instance, the Lolin ESP32-S3 Mini that uses GRB color order, would declare in its own pins_arduino.h file the correct order for its neopixel:

// neopixelWrite() RMT will use R, G, B bits order
#define RGB_BUILTIN_COLOR_ORDER_STRUCT {red_val, green_val, blue_val}

@robertlipe, @sblantipodi @me-no-dev
Let me know.

@sblantipodi
Copy link
Contributor Author

You can do with this without introducing any extra CPU overhead

Something like this is not the most elegant way, but it for sure efficient.
No extracode, just define the builtin RGB LED bit order, directly in the code, for any board that needs it.

variants/esp32c3/pins_arduino.h would define

//  neopixelWrite() RMT will use G, R, B bits order
#define RGB_BUILTIN_COLOR_ORDER_STRUCT {green_val, red_val, blue_val} 

cores/esp32/esp32-hal-rgb-led.c would do something like:

#ifdef RGB_BUILTIN_COLOR_ORDER_STRUCT
int color[] = RGB_BUILTIN_COLOR_ORDER_STRUCT;
#else
// WS2812B color bit order is G, R, B
int color[] = {green_val, red_val, blue_val};
#endif

For instance, the Lolin ESP32-S3 Mini that uses GRB color order, would declare in its own pins_arduino.h file the correct order for its neopixel:

// neopixelWrite() RMT will use R, G, B bits order
#define RGB_BUILTIN_COLOR_ORDER_STRUCT {red_val, green_val, blue_val}

@robertlipe, @sblantipodi @me-no-dev
Let me know.

I like this approach, I will not have access to my PC for some days, if no one will do it before me, I'll commit this idea as soon as I return home.

@sblantipodi
Copy link
Contributor Author

@sblantipodi @robertlipe - Let's be practical.

@sblantipodi says that he has a couple boards that have an RGB LED that works with a different color order. This can be tested using ESP32 Arduino neopixelWrite(pin, 255, 0, 0);. If the LED color is set to RED, the order is GRB. But if the color is set to GREEN, the color order would be RGB (given that the code sends always GRB order). @sblantipodi - please confirm it.

Considering that it happens, some users may have some trouble with the onboard RGB LED.
@UnexpectedMaker - Can you please give us a hand here? You certainly have the answer in this case.

For this PR, I still suggest the approach described in #10128 (comment)

I confirm my Lolin S3 Mini has different color order than my Lolin C3 mini. Don't remember who is RGB and who is GRB currently but using the same code, on one board the led is red and on another board is green.

@SuGlider
Copy link
Collaborator

SuGlider commented Aug 14, 2024

@sblantipodi - I'll modify it as requested by @me-no-dev, mixing some ideas we have discussed before.
@robertlipe - the proposed code mixes some of the points we discussed and opens space for @me-no-dev request.
@me-no-dev - please review it and let me know.

PR main goals:

  • Allow users and board makers to change the RGB LED color order sent using RMT.
  • Addresses only 1 LED per pin such as the onboard LED.
  • When the board uses standard WS2812b LED, no firmware/memory/flash changes will happen/be necessary.
  • Only affects boards that require such change. It can be defined in "pins_arduino.h" specific board file.

@SuGlider
Copy link
Collaborator

@sblantipodi - please test using your LolinS3 Mini board ... CI won't test it at all.

@SuGlider
Copy link
Collaborator

given that the switch() takes a constant value, it is very possible that the compiler will optimize the code and ignore it, by just setting the color order directly as specified.

@me-no-dev me-no-dev added the Status: Pending Merge Pull Request is ready to be merged label Aug 14, 2024
@sblantipodi
Copy link
Contributor Author

@SuGlider it works as expected

Made GRB default + switch/case exceptions.
If RGB_BUILTIN_LED_COLOR_ORDER is not defined, the type rgb_led_color_order_t won't be declared.
cores/esp32/esp32-hal-rgb-led.h Outdated Show resolved Hide resolved
cores/esp32/esp32-hal-rgb-led.c Outdated Show resolved Hide resolved
@me-no-dev
Copy link
Member

@sblantipodi @robertlipe @SuGlider PTAL at the latest changes

void rgbLedWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val);

// Backward compatibility
#define neopixelWrite(p, r, g, b) rgbLedWrite(p, r, g, b)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attribute ((deprecated));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is something that we will deal with separately for other reasons.

Copy link
Collaborator

@SuGlider SuGlider left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ready for Merging @me-no-dev

@me-no-dev me-no-dev merged commit 66c9c0b into espressif:master Aug 19, 2024
57 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Pending Merge Pull Request is ready to be merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants