mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-25 01:05:27 +03:00
Merge pull request #10762 from g3gg0/add_SK6812_RGBW
add SK6812 RGBW 4-channel LEDs
This commit is contained in:
commit
ac7774cc73
4 changed files with 33 additions and 10 deletions
|
@ -89,6 +89,8 @@ It could be possible to be able to specify the timings required via CLI if users
|
||||||
* Fits well under motors on mini 250 quads.
|
* Fits well under motors on mini 250 quads.
|
||||||
* [Adafruit NeoPixel Stick](https://www.adafruit.com/products/1426) (works well)
|
* [Adafruit NeoPixel Stick](https://www.adafruit.com/products/1426) (works well)
|
||||||
* Measured current consumption in all white mode ~ 350 mA.
|
* Measured current consumption in all white mode ~ 350 mA.
|
||||||
|
* [Aliexpress SK6812 RBGWW strip](https://www.aliexpress.com/wholesale?SearchText=rgbw+sk6812) (works well)
|
||||||
|
* Alternative [Adafruit NeoPixel Stick RGBW](https://www.adafruit.com/product/2869)
|
||||||
|
|
||||||
|
|
||||||
### WS2811 vs WS2812
|
### WS2811 vs WS2812
|
||||||
|
@ -97,6 +99,8 @@ The [WS2811](https://cdn-shop.adafruit.com/datasheets/WS2811.pdf) is a LED drive
|
||||||
|
|
||||||
The [WS2812](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) is integrated into the package of a 50:50 LED rather than as a separate device. It accepts data in the form of 8 bits each of Green-Red-Blue.
|
The [WS2812](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) is integrated into the package of a 50:50 LED rather than as a separate device. It accepts data in the form of 8 bits each of Green-Red-Blue.
|
||||||
|
|
||||||
|
With the [SK6812](https://cdn-shop.adafruit.com/product-files/1138/SK6812+LED+datasheet+.pdf) also GRBW variants are supported, which have a fourth (white) channel and such provide a much cleaner white color.
|
||||||
|
|
||||||
It is thus possible, depending on the LED board/strip being used that either Red-Green-Blue or Green-Red-Blue encoding may be required. This may be controlled by setting the following.
|
It is thus possible, depending on the LED board/strip being used that either Red-Green-Blue or Green-Red-Blue encoding may be required. This may be controlled by setting the following.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -107,8 +111,14 @@ or
|
||||||
```
|
```
|
||||||
set ledstrip_grb_rgb = GRB
|
set ledstrip_grb_rgb = GRB
|
||||||
```
|
```
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
set ledstrip_grb_rgb = GRBW
|
||||||
|
```
|
||||||
|
|
||||||
Then confirm the required setting by simply setting an LED to be green. If it lights up red, you have the wrong setting.
|
Then confirm the required setting by simply setting an LED to be green. If it lights up red, you have the wrong setting.
|
||||||
|
Afterwards check if the second LED also lights up red - if not, you might have 4-color SK6812 LEDs and would have to select GRBW.
|
||||||
|
|
||||||
## Connections
|
## Connections
|
||||||
|
|
||||||
|
|
|
@ -366,7 +366,7 @@ static const char * const lookupOverclock[] = {
|
||||||
|
|
||||||
#ifdef USE_LED_STRIP
|
#ifdef USE_LED_STRIP
|
||||||
static const char * const lookupLedStripFormatRGB[] = {
|
static const char * const lookupLedStripFormatRGB[] = {
|
||||||
"GRB", "RGB"
|
"GRB", "RGB", "GRBW"
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
#include "common/maths.h"
|
||||||
|
|
||||||
#ifdef USE_LED_STRIP
|
#ifdef USE_LED_STRIP
|
||||||
|
|
||||||
|
@ -139,8 +140,8 @@ void ws2811LedStripEnable(void)
|
||||||
|
|
||||||
const hsvColor_t hsv_black = { 0, 0, 0 };
|
const hsvColor_t hsv_black = { 0, 0, 0 };
|
||||||
setStripColor(&hsv_black);
|
setStripColor(&hsv_black);
|
||||||
// RGB or GRB ordering doesn't matter for black
|
// RGB or GRB ordering doesn't matter for black, use 4-channel LED configuraton to make sure all channels are zero
|
||||||
ws2811UpdateStrip(LED_RGB, 100);
|
ws2811UpdateStrip(LED_GRBW, 100);
|
||||||
|
|
||||||
ws2811Initialised = true;
|
ws2811Initialised = true;
|
||||||
}
|
}
|
||||||
|
@ -153,23 +154,34 @@ bool isWS2811LedStripReady(void)
|
||||||
|
|
||||||
STATIC_UNIT_TESTED void updateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbColor24bpp_t *color, unsigned ledIndex)
|
STATIC_UNIT_TESTED void updateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbColor24bpp_t *color, unsigned ledIndex)
|
||||||
{
|
{
|
||||||
|
uint32_t bits_per_led;
|
||||||
uint32_t packed_colour;
|
uint32_t packed_colour;
|
||||||
|
|
||||||
switch (ledFormat) {
|
switch (ledFormat) {
|
||||||
case LED_RGB: // WS2811 drivers use RGB format
|
case LED_RGB: // WS2811 drivers use RGB format
|
||||||
packed_colour = (color->rgb.r << 16) | (color->rgb.g << 8) | (color->rgb.b);
|
packed_colour = (color->rgb.r << 16) | (color->rgb.g << 8) | (color->rgb.b);
|
||||||
|
bits_per_led = 24;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LED_GRBW: // SK6812 drivers use this
|
||||||
|
{
|
||||||
|
/* reconstruct white channel from RGB, making the intensity a bit nonlinear, but thats fine for this use case */
|
||||||
|
uint8_t white = MIN(MIN(color->rgb.r, color->rgb.g), color->rgb.b);
|
||||||
|
packed_colour = (color->rgb.g << 24) | (color->rgb.r << 16) | (color->rgb.b << 8) | (white);
|
||||||
|
bits_per_led = 32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case LED_GRB: // WS2812 drivers use GRB format
|
case LED_GRB: // WS2812 drivers use GRB format
|
||||||
default:
|
default:
|
||||||
packed_colour = (color->rgb.g << 16) | (color->rgb.r << 8) | (color->rgb.b);
|
packed_colour = (color->rgb.g << 16) | (color->rgb.r << 8) | (color->rgb.b);
|
||||||
|
bits_per_led = 24;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned dmaBufferOffset = 0;
|
unsigned dmaBufferOffset = 0;
|
||||||
for (int index = 23; index >= 0; index--) {
|
for (int index = bits_per_led-1; index >= 0; index--) {
|
||||||
ledStripDMABuffer[ledIndex * WS2811_BITS_PER_LED + dmaBufferOffset++] = (packed_colour & (1 << index)) ? BIT_COMPARE_1 : BIT_COMPARE_0;
|
ledStripDMABuffer[ledIndex * bits_per_led + dmaBufferOffset++] = (packed_colour & (1 << index)) ? BIT_COMPARE_1 : BIT_COMPARE_0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,11 @@
|
||||||
|
|
||||||
#define WS2811_LED_STRIP_LENGTH 32
|
#define WS2811_LED_STRIP_LENGTH 32
|
||||||
|
|
||||||
#define WS2811_BITS_PER_LED 24
|
#define WS2811_BITS_PER_LED_MAX 32
|
||||||
|
|
||||||
#if defined(USE_WS2811_SINGLE_COLOUR)
|
#if defined(USE_WS2811_SINGLE_COLOUR)
|
||||||
#define WS2811_DATA_BUFFER_SIZE 1
|
#define WS2811_DATA_BUFFER_SIZE 1
|
||||||
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE * WS2811_BITS_PER_LED)
|
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE * WS2811_BITS_PER_LED_MAX)
|
||||||
// Do 2 extra iterations of the DMA transfer with the output set to low to generate the > 50us delay.
|
// Do 2 extra iterations of the DMA transfer with the output set to low to generate the > 50us delay.
|
||||||
#define WS2811_DELAY_ITERATIONS 2
|
#define WS2811_DELAY_ITERATIONS 2
|
||||||
#else
|
#else
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
// for 50us delay
|
// for 50us delay
|
||||||
#define WS2811_DELAY_BUFFER_LENGTH 42
|
#define WS2811_DELAY_BUFFER_LENGTH 42
|
||||||
// number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes)
|
// number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes)
|
||||||
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE * WS2811_BITS_PER_LED + WS2811_DELAY_BUFFER_LENGTH)
|
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE * WS2811_BITS_PER_LED_MAX + WS2811_DELAY_BUFFER_LENGTH)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LEDSTRIP_CACHE_MGMT
|
#ifdef USE_LEDSTRIP_CACHE_MGMT
|
||||||
|
@ -64,7 +64,8 @@ extern uint32_t ledStripDMABuffer[WS2811_DMA_BUFFER_SIZE];
|
||||||
// Enumeration to match the string options defined in lookupLedStripFormatRGB in settings.c
|
// Enumeration to match the string options defined in lookupLedStripFormatRGB in settings.c
|
||||||
typedef enum {
|
typedef enum {
|
||||||
LED_GRB,
|
LED_GRB,
|
||||||
LED_RGB
|
LED_RGB,
|
||||||
|
LED_GRBW
|
||||||
} ledStripFormatRGB_e;
|
} ledStripFormatRGB_e;
|
||||||
|
|
||||||
void ws2811LedStripInit(ioTag_t ioTag);
|
void ws2811LedStripInit(ioTag_t ioTag);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue