Skip to content

Commit 570993a

Browse files
authored
Multi-threading and multi-segment support (#10)
1 parent ca6997c commit 570993a

16 files changed

Lines changed: 2574 additions & 597 deletions

File tree

.github/workflows/push-master.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: HyperSerialEsp8266 CI Build
1+
name: HyperSerialESP32 CI Build
22

33
on: [push]
44

.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"files.associations": {
3+
"algorithm": "cpp"
4+
}
5+
}

README.md

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,37 +24,82 @@ Why the data integrity check was introduced which causes incompatibility with ot
2424

2525
Recommend to use [esphome-flasher](https://github.com/esphome/esphome-flasher/releases)
2626

27-
For **RGBW LED strip** like RGBW SK6812 NEUTRAL white choose: *firmware_SK6812_RGBW_NEUTRAL.bin*
27+
ESP32-S2 lolin mini requires special firmware version (also provided)
28+
29+
Generic ESP32:
30+
31+
For **RGBW LED strip** like RGBW SK6812 NEUTRAL white choose: *firmware_esp32_SK6812_RGBW_NEUTRAL.bin*
2832

29-
For **RGBW LED strip** like RGBW SK6812 COLD white choose: *firmware_SK6812_RGBW_COLD.bin*
33+
For **RGBW LED strip** like RGBW SK6812 COLD white choose: *firmware_esp32_SK6812_RGBW_COLD.bin*
3034

31-
For **RGB LED strip** like WS8212b or RGB SK6812 variant choose: *firmware_WS281x_RGB.bin*
35+
For **RGB LED strip** like WS8212b or RGB SK6812 variant choose: *firmware_esp32_WS281x_RGB.bin*
3236

33-
For **SPI driven RGB LED strip** APA102: *firmware_SPI_APA102_SK9822_HD107.bin*, WS8201: *firmware_SPI_WS2801.bin*
37+
For **SPI driven RGB LED strip** APA102: *firmware_esp32_SPI_APA102_SK9822_HD107.bin*, WS8201: *firmware_esp32_SPI_WS2801.bin*
3438

3539
If you want to disable your first LED because it's used as a sacrificial level shifter, please use [HyperHDR v19](https://github.com/awawa-dev/HyperHDR/pull/379)
3640

3741
For the RGBW firmware the white channel is automatically calculated and R,G,B channels are corrected.
3842

3943
# Usage in HyperHDR
4044

41-
Make sure you set "Refresh time" to zero, "Baudrate" to 2000000 and enabled HyperHDR's AWA protocol.
42-
Enabling "White channel calibration" is optional, if you want to fine tune the white channel balance of your sk6812 RGBW LED strip.
45+
Make sure you are using HyperHDR v19beta2 or above.
46+
Set `Refresh time` to zero, `Baudrate` to 2000000 and you enabled `HyperHDR's AWA protocol`.
47+
Enabling `White channel calibration` is optional, if you want to fine tune the white channel balance of your sk6812 RGBW LED strip.
48+
`ESP8266/ESP32 handshake` could help you to properly initialize the ESP device and enables statistics available in the logs (you must stop the LED device first to get them).
49+
50+
![obraz](https://user-images.githubusercontent.com/69086569/207109594-0493fe58-3530-46bb-a0a3-31a110475ed6.png)
4351

44-
![obraz](https://user-images.githubusercontent.com/69086569/192893595-324cfcf8-e247-438c-88ce-e52a29463121.png)
4552

4653
# Compiling
4754

4855
Currently we use PlatformIO to compile the project. Install [Visual Studio Code](https://code.visualstudio.com/) and add [PlatformIO plugin](https://platformio.org/).
4956
This environment will take care of everything and compile the firmware for you.
5057

51-
But there is also an alternative and an easier way. Just fork the project and enable its Github Action. Use the online editor to make changes to the ```platformio.ini``` file, for example change default pin-outs, and save it. Github Action will compile new firmware automatically in the Artifacts archive. It has never been so easy!
58+
But there is also an alternative and an easier way. Just fork the project and enable its Github Action. Use the online editor to make changes to the ```platformio.ini``` file, for example change default pin-outs/speed or enable multi-segments support, and save it. Github Action will compile new firmware automatically in the Artifacts archive. It has never been so easy!
59+
60+
Tutorial: https://github.com/awawa-dev/HyperSerialESP32/wiki
5261

5362
# Pinout
5463

5564
**ESP32:**
5665
**LED output (non-SPI):** GPIO 2
57-
**LED output (SPI):** GPIO 0 for Clock, GPIO 2 for Data
66+
**LED output (SPI):** GPIO 4 for Clock, GPIO 2 for Data
67+
68+
# Some benchmark results
69+
70+
ESP32 MH-ET LIVE mini is capable of 4Mb serial port speed and ESP32-S2 lolin mini is capable of 5Mb. But to give equal chances all models were tested using the default speed of 2Mb.
71+
72+
## Multi-segments can double your large sk6812/ws2812b setup refresh rate for free. All you need is to properly project & construct the LED strip and use HyperSerialESP32 v8.
73+
74+
| LED strip / Device | ESP32<br>MH-ET LIVE mini |
75+
|----------------------------------------------------------------------------------|--------------------------|
76+
| 300LEDs<br>Refresh rate/continues output=100Hz<br>SECOND_SEGMENT_START_INDEX=150 | 93-97 |
77+
| 600LEDs<br>Refresh rate/continues output=100Hz<br>SECOND_SEGMENT_START_INDEX=300 | 78-79 |
78+
| 900LEDs<br>Refresh rate/continues output=100Hz<br>SECOND_SEGMENT_START_INDEX=450 | 55-56 |
79+
80+
## Comparing v6.1 and v8 version (single segment) refresh rate using MH-ET LIVE mini
81+
82+
| LED strip / Device | ESP32<br>MH-ET LIVE mini<br>HyperSerialESP32 v6.1 | ESP32<br>MH-ET LIVE mini<br>HyperSerialESP32 v8 |
83+
|------------------------------------------------|---------------------------------------------------|-------------------------------------------------|
84+
| 300LEDs<br>Refresh rate/continues output=100Hz | 81-83 | 80-83 |
85+
| 600LEDs<br>Refresh rate/continues output=60Hz | 39-40 | 41-42 |
86+
| 900LEDs<br>Refresh rate/continues output=40Hz | 21-26 | 26-28 |
87+
88+
## Comparing v6.1 and v8 version (single segment) refresh rate using generic ESP32 with CH340C
89+
90+
| LED strip / Device | ESP32 (CH340C)<br>HyperSerialESP32 v6.1 | ESP32 (CH340C)<br>HyperSerialESP32 v8 |
91+
|------------------------------------------------|-----------------------------------------|---------------------------------------|
92+
| 300LEDs<br>Refresh rate/continues output=100Hz | 72-78 | 81-83 |
93+
| 600LEDs<br>Refresh rate/continues output=60Hz | 33-38 | 39-42 |
94+
| 900LEDs<br>Refresh rate/continues output=40Hz | 21-25 | 26-28 |
95+
96+
## ESP32-S2 lolin mini performance
97+
98+
| LED strip / Device | ESP32-S2 lolin mini<br>HyperSerialESP32 v8 |
99+
|------------------------------------------------|--------------------------------------------|
100+
| 300LEDs<br>Refresh rate/continues output=100Hz | 80-84 |
101+
| 600LEDs<br>Refresh rate/continues output=60Hz | 42 |
102+
| 900LEDs<br>Refresh rate/continues output=40Hz | 27-28 |
58103

59104
# Disclaimer
60105

include/README

Lines changed: 0 additions & 39 deletions
This file was deleted.

include/base.h

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/* base.h
2+
*
3+
* MIT License
4+
*
5+
* Copyright (c) 2022 awawa-dev
6+
*
7+
* https://github.com/awawa-dev/HyperSerialESP32
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in all
17+
* copies or substantial portions of the Software.
18+
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
* SOFTWARE.
26+
*/
27+
28+
#ifndef BASE_H
29+
#define BASE_H
30+
31+
#if defined(SECOND_SEGMENT_START_INDEX)
32+
#if !defined(SECOND_SEGMENT_DATA_PIN)
33+
#error "Please define SECOND_SEGMENT_DATA_PIN for second segment"
34+
#elif !defined(SECOND_SEGMENT_CLOCK_PIN) && !defined(NEOPIXEL_RGBW) && !defined(NEOPIXEL_RGB)
35+
#error "Please define SECOND_SEGMENT_CLOCK_PIN and SECOND_SEGMENT_DATA_PIN for second segment"
36+
#endif
37+
#endif
38+
39+
class Base
40+
{
41+
// LED strip number
42+
int ledsNumber = 0;
43+
// NeoPixelBusLibrary primary object
44+
LED_DRIVER* ledStrip1 = nullptr;
45+
// NeoPixelBusLibrary second object
46+
LED_DRIVER2* ledStrip2 = nullptr;
47+
// frame is set and ready to render
48+
bool readyToRender = false;
49+
50+
public:
51+
// static data buffer for the loop
52+
uint8_t buffer[MAX_BUFFER];
53+
// handle to tasks
54+
TaskHandle_t processTaskHandle;
55+
// current queue position
56+
uint16_t queueCurrent = 0;
57+
// queue end position
58+
volatile uint16_t queueEnd = 0;
59+
60+
inline int getLedsNumber()
61+
{
62+
return ledsNumber;
63+
}
64+
65+
inline LED_DRIVER* getLedStrip1()
66+
{
67+
return ledStrip1;
68+
}
69+
70+
inline LED_DRIVER2* getLedStrip2()
71+
{
72+
return ledStrip2;
73+
}
74+
75+
void initLedStrip(int count)
76+
{
77+
if (ledStrip1 != nullptr)
78+
{
79+
delete ledStrip1;
80+
ledStrip1 = nullptr;
81+
}
82+
83+
if (ledStrip2 != nullptr)
84+
{
85+
delete ledStrip2;
86+
ledStrip2 = nullptr;
87+
}
88+
89+
ledsNumber = count;
90+
91+
#if defined(SECOND_SEGMENT_START_INDEX)
92+
if (ledsNumber > SECOND_SEGMENT_START_INDEX)
93+
{
94+
#if defined(NEOPIXEL_RGBW) || defined(NEOPIXEL_RGB)
95+
ledStrip1 = new LED_DRIVER(SECOND_SEGMENT_START_INDEX, DATA_PIN);
96+
ledStrip1->Begin();
97+
ledStrip2 = new LED_DRIVER2(ledsNumber - SECOND_SEGMENT_START_INDEX, SECOND_SEGMENT_DATA_PIN);
98+
ledStrip2->Begin();
99+
#else
100+
ledStrip1 = new LED_DRIVER(SECOND_SEGMENT_START_INDEX);
101+
ledStrip1->Begin(CLOCK_PIN, 12, DATA_PIN, 15);
102+
ledStrip2 = new LED_DRIVER2(ledsNumber - SECOND_SEGMENT_START_INDEX);
103+
ledStrip2->Begin(SECOND_SEGMENT_CLOCK_PIN, 12, SECOND_SEGMENT_DATA_PIN, 15);
104+
#endif
105+
}
106+
#endif
107+
108+
if (ledStrip1 == nullptr)
109+
{
110+
#if defined(NEOPIXEL_RGBW) || defined(NEOPIXEL_RGB)
111+
ledStrip1 = new LED_DRIVER(ledsNumber, DATA_PIN);
112+
ledStrip1->Begin();
113+
#else
114+
ledStrip1 = new LED_DRIVER(ledsNumber);
115+
ledStrip1->Begin(CLOCK_PIN, 12, DATA_PIN, 15);
116+
#endif
117+
}
118+
}
119+
120+
/**
121+
* @brief Check if there is already prepared frame to display
122+
*
123+
* @return true
124+
* @return false
125+
*/
126+
inline bool hasLateFrameToRender()
127+
{
128+
return readyToRender;
129+
}
130+
131+
inline void renderLeds(bool newFrame)
132+
{
133+
if (newFrame)
134+
readyToRender = true;
135+
136+
if (readyToRender &&
137+
(ledStrip1 != nullptr && ledStrip1->CanShow()) &&
138+
!(ledStrip2 != nullptr && !ledStrip2->CanShow()))
139+
{
140+
statistics.increaseShow();
141+
readyToRender = false;
142+
143+
// display segments
144+
ledStrip1->Show(false);
145+
if (ledStrip2 != nullptr)
146+
ledStrip2->Show(false);
147+
}
148+
}
149+
150+
inline bool setStripPixel(uint16_t pix, ColorDefinition &inputColor)
151+
{
152+
if (pix < ledsNumber)
153+
{
154+
#if defined(SECOND_SEGMENT_START_INDEX)
155+
if (pix < SECOND_SEGMENT_START_INDEX)
156+
ledStrip1->SetPixelColor(pix, inputColor);
157+
else
158+
{
159+
#if defined(SECOND_SEGMENT_REVERSED)
160+
ledStrip2->SetPixelColor(ledsNumber - pix - 1, inputColor);
161+
#else
162+
ledStrip2->SetPixelColor(pix - SECOND_SEGMENT_START_INDEX, inputColor);
163+
#endif
164+
}
165+
#else
166+
ledStrip1->SetPixelColor(pix, inputColor);
167+
#endif
168+
}
169+
170+
return (pix + 1 < ledsNumber);
171+
}
172+
} base;
173+
174+
#endif

0 commit comments

Comments
 (0)