more accurate FPS forESP32

the standard millis() code is very inaccurate in the "high FPS" ranges. This replaces it with the esp32 high resolution timer.
This commit is contained in:
Frank
2023-04-21 17:34:01 +02:00
parent 9130e4be54
commit 8e9db0adde
3 changed files with 27 additions and 2 deletions

View File

@@ -2809,7 +2809,7 @@ uint16_t mode_bouncing_balls(void) {
// number of balls based on intensity setting to max of 7 (cycles colors)
// non-chosen color is a random color
uint16_t numBalls = (SEGMENT.intensity * (maxNumBalls - 1)) / 255 + 1; // minimum 1 ball
const float gravity = -9.81; // standard value of gravity
constexpr float gravity = -9.81; // standard value of gravity
const bool hasCol2 = SEGCOLOR(2);
const unsigned long time = millis();

View File

@@ -689,6 +689,10 @@ class WS2812FX { // 96 bytes
_targetFps(WLED_FPS),
_frametime(FRAMETIME_FIXED),
_cumulativeFps(2),
#ifdef ARDUINO_ARCH_ESP32
_cumulativeFps500(2*500), // WLEDMM more accurate FPS measurement for ESP32
_lastShow500(0),
#endif
_isServicing(false),
_isOffRefreshRequired(false),
_hasWhiteChannel(false),
@@ -907,6 +911,10 @@ class WS2812FX { // 96 bytes
uint8_t _targetFps;
uint16_t _frametime;
uint16_t _cumulativeFps;
#ifdef ARDUINO_ARCH_ESP32
uint64_t _cumulativeFps500; // WLEDMM more accurate FPS measurement for ESP32
uint64_t _lastShow500;
#endif
// will require only 1 byte
struct {

View File

@@ -26,6 +26,9 @@
#include "wled.h"
#include "FX.h"
#include "palettes.h"
#ifdef ARDUINO_ARCH_ESP32
#include <esp_timer.h> // WLEDMM to get esp_timer_get_time()
#endif
/*
Custom per-LED mapping has moved!
@@ -206,7 +209,7 @@ void Segment::setUpLeds() {
else if (!leds) {
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
if (psramFound())
leds = (CRGB*)ps_malloc(sizeof(CRGB)*length());
leds = (CRGB*)ps_malloc(sizeof(CRGB)*length()); // WLEDMM: stupid - PSRAM is too slow for this !!!
else
#endif
leds = (CRGB*)malloc(sizeof(CRGB)*length());
@@ -1631,6 +1634,16 @@ void WS2812FX::show(void) {
if (diff > 0) fpsCurr = 1000 / diff;
_cumulativeFps = (3 * _cumulativeFps + fpsCurr) >> 2;
_lastShow = now;
#ifdef ARDUINO_ARCH_ESP32 // WLEDMM more accurate FPS measurement for ESP32
uint64_t now500 = esp_timer_get_time() / 2; // native timer; micros /2 -> millis * 500
int64_t diff500 = now500 - _lastShow500;
if ((diff500 > 300) && (diff500 < 800000)) { // exclude stupid values (timer rollover, major hickups)
float fpcCurr500 = 500000.0f / float(diff500);
if (fpcCurr500 > 2)
_cumulativeFps500 = (3 * _cumulativeFps500 + (500.0 * fpcCurr500)) / 4; // average for some smoothing
}
_lastShow500 = now500;
#endif
}
/**
@@ -1647,7 +1660,11 @@ bool WS2812FX::isUpdating() {
*/
uint16_t WS2812FX::getFps() {
if (millis() - _lastShow > 2000) return 0;
#ifdef ARDUINO_ARCH_ESP32
return ((_cumulativeFps500 + 250) / 500); // +250 for proper rounding
#else
return _cumulativeFps +1;
#endif
}
void WS2812FX::setTargetFps(uint8_t fps) {