Merge branch 'mdev' into audio_fastpath

This commit is contained in:
Ewoud
2023-05-16 16:02:47 +02:00
46 changed files with 7552 additions and 5996 deletions

View File

@@ -26,6 +26,15 @@
#endif
#endif
//the default ratio for the voltage divider
#ifndef USERMOD_BATTERY_VOLTAGE_MULTIPLIER
#ifdef ARDUINO_ARCH_ESP32
#define USERMOD_BATTERY_VOLTAGE_MULTIPLIER 2.0f
#else //ESP8266 boards
#define USERMOD_BATTERY_VOLTAGE_MULTIPLIER 4.2f
#endif
#endif
#ifndef USERMOD_BATTERY_MAX_VOLTAGE
#define USERMOD_BATTERY_MAX_VOLTAGE 4.2f
#endif

View File

@@ -29,6 +29,10 @@ class UsermodBattery : public Usermod
float rawValue = 0.0f;
// calculated voltage
float voltage = maxBatteryVoltage;
// between 0 and 1, to control strength of voltage smoothing filter
float alpha = 0.05f;
// multiplier for the voltage divider that is in place between ADC pin and battery, default will be 2 but might be adapted to readout voltages over ~5v ESP32 or ~6.6v ESP8266
float voltageMultiplier = USERMOD_BATTERY_VOLTAGE_MULTIPLIER;
// mapped battery level based on voltage
int8_t batteryLevel = 100;
// offset or calibration value to fine tune the calculated voltage
@@ -110,6 +114,17 @@ class UsermodBattery : public Usermod
}
}
float readVoltage()
{
#ifdef ARDUINO_ARCH_ESP32
// use calibrated millivolts analogread on esp32 (150 mV ~ 2450 mV default attentuation) and divide by 1000 to get from milivolts to volts and multiply by voltage multiplier and apply calibration value
return (analogReadMilliVolts(batteryPin) / 1000.0f) * voltageMultiplier + calibration;
#else
// use analog read on esp8266 ( 0V ~ 1V no attenuation options) and divide by ADC precision 1023 and multiply by voltage multiplier and apply calibration value
return (analogRead(batteryPin) / 1023.0f) * voltageMultiplier + calibration;
#endif
}
public:
//Functions called by WLED
@@ -126,6 +141,7 @@ class UsermodBattery : public Usermod
if (pinManager.allocatePin(batteryPin, false, PinOwner::UM_Battery)) {
DEBUG_PRINTLN(F("Battery pin allocation succeeded."));
success = true;
voltage = readVoltage();
}
if (!success) {
@@ -135,8 +151,8 @@ class UsermodBattery : public Usermod
pinMode(batteryPin, INPUT);
}
#else //ESP8266 boards have only one analog input pin A0
pinMode(batteryPin, INPUT);
voltage = readVoltage();
#endif
nextReadTime = millis() + readingInterval;
@@ -176,22 +192,12 @@ class UsermodBattery : public Usermod
initializing = false;
#ifdef ARDUINO_ARCH_ESP32
// use calibrated millivolts analogread on esp32 (150 mV ~ 2450 mV)
rawValue = analogReadMilliVolts(batteryPin);
// calculate the voltage
voltage = (rawValue / 1000.0f) + calibration;
// usually a voltage divider (50%) is used on ESP32, so we need to multiply by 2
voltage *= 2.0f;
#else
// read battery raw input
rawValue = analogRead(batteryPin);
rawValue = readVoltage();
// filter with exponential smoothing because ADC in esp32 is fluctuating too much for a good single readout
voltage = voltage + alpha * (rawValue - voltage);
// calculate the voltage
voltage = ((rawValue / getAdcPrecision()) * maxBatteryVoltage) + calibration;
#endif
// check if voltage is within specified voltage range, allow 10% over/under voltage
voltage = ((voltage < minBatteryVoltage * 0.85f) || (voltage > maxBatteryVoltage * 1.1f)) ? -1.0f : voltage;
// check if voltage is within specified voltage range, allow 10% over/under voltage - removed cause this just makes it hard for people to troubleshoot as the voltage in the web gui will say invalid instead of displaying a voltage
//voltage = ((voltage < minBatteryVoltage * 0.85f) || (voltage > maxBatteryVoltage * 1.1f)) ? -1.0f : voltage;
// translate battery voltage into percentage
/*
@@ -363,6 +369,7 @@ class UsermodBattery : public Usermod
battery[F("max-voltage")] = maxBatteryVoltage;
battery[F("capacity")] = totalBatteryCapacity;
battery[F("calibration")] = calibration;
battery[F("voltage-multiplier")] = voltageMultiplier;
battery[FPSTR(_readInterval)] = readingInterval;
JsonObject ao = battery.createNestedObject(F("auto-off")); // auto off section
@@ -375,6 +382,9 @@ class UsermodBattery : public Usermod
lp[FPSTR(_threshold)] = lowPowerIndicatorThreshold;
lp[FPSTR(_duration)] = lowPowerIndicatorDuration;
// read voltage in case calibration or voltage multiplier changed to see immediate effect
voltage = readVoltage();
DEBUG_PRINTLN(F("Battery config saved."));
}
@@ -441,6 +451,7 @@ class UsermodBattery : public Usermod
setMaxBatteryVoltage(battery[F("max-voltage")] | maxBatteryVoltage);
setTotalBatteryCapacity(battery[F("capacity")] | totalBatteryCapacity);
setCalibration(battery[F("calibration")] | calibration);
setVoltageMultiplier(battery[F("voltage-multiplier")] | voltageMultiplier);
setReadingInterval(battery[FPSTR(_readInterval)] | readingInterval);
JsonObject ao = battery[F("auto-off")];
@@ -597,21 +608,7 @@ class UsermodBattery : public Usermod
totalBatteryCapacity = capacity;
}
/*
* Get the choosen adc precision
* esp8266 = 10bit resolution = 1024.0f
* esp32 = 12bit resolution = 4095.0f
*/
float getAdcPrecision()
{
#ifdef ARDUINO_ARCH_ESP32
// esp32
return 4096.0f;
#else
// esp8266
return 1024.0f;
#endif
}
/*
* Get the calculated voltage
@@ -649,6 +646,23 @@ class UsermodBattery : public Usermod
calibration = offset;
}
/*
* Set the voltage multiplier value
* A multiplier that may need adjusting for different voltage divider setups
*/
void setVoltageMultiplier(float multiplier)
{
voltageMultiplier = multiplier;
}
/*
* Get the voltage multiplier value
* A multiplier that may need adjusting for different voltage divider setups
*/
float getVoltageMultiplier()
{
return voltageMultiplier;
}
/*
* Get auto-off feature enabled status

View File

@@ -9,33 +9,9 @@ function toggleCEEditor(name, segID) {
d.getElementById('ceEditor').style.transform = (isCEEditor) ? "translateY(0px)":"translateY(100%)";
}
function fetchAndExecute(url, name, callback, callError)
{
fetch
(url+name, {
method: 'get'
})
.then(res => {
if (!res.ok) {
callError("File " + name + " not found");
return "";
}
return res.text();
})
.then(text => {
callback(text);
})
.catch(function (error) {
callError("Error getting " + name);
})
.finally(() => {
// if (callback) setTimeout(callback,99);
});
}
function loadLogFile(name, attempt) {
var ceLogArea = d.getElementById("ceLogArea");
fetchAndExecute((loc?`http://${locip}`:'.') + "/", name , function(logtext)
fetchAndExecute((loc?`http://${locip}`:'.') + "/", name, null, function(parms,logtext)
{
if (logtext == "") {
if (attempt < 10) {
@@ -50,7 +26,7 @@ function loadLogFile(name, attempt) {
}
else
ceLogArea.value = logtext;
}, function(error){
}, function(parms,error){
showToast(error);
console.log(error);
});
@@ -91,7 +67,7 @@ function saveCE(name, segID) {
function populateCEEditor(name, segID)
{
fetchAndExecute((loc?`http://${locip}`:'.') + "/", name + ".wled", function(text)
fetchAndExecute((loc?`http://${locip}`:'.') + "/", name + ".wled", null, function(parms,text)
{
var cn=`ARTI-FX Editor<br>
<i>${name}.wled</i><br>
@@ -117,7 +93,7 @@ function populateCEEditor(name, segID)
ceLogArea.value = ".";
loadLogFile(name + ".log", 1);
}, function(error){
}, function(parms,error){
showToast(error);
console.log(error);
});
@@ -129,7 +105,7 @@ function downloadGHFile(url, name, save=false, warn=false) { //Githubfile
if (url == "HBE") url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/Presets/HB_PresetPack210808_32x32_16seg/Effects%20pack/";
if (url == "LM") url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/Ledmaps/";
fetchAndExecute(url, name, function(text) {
fetchAndExecute(url, name, null, function(parms,text) {
if (save) {
if (warn && !confirm('Are you sure to download/overwrite ' + name + '?'))
return;
@@ -140,7 +116,7 @@ function downloadGHFile(url, name, save=false, warn=false) { //Githubfile
var ceProgramArea = d.getElementById("ceProgramArea");
ceProgramArea.value = text;
}
}, function(error){
}, function(parms,error){
showToast(error);
console.log(url + name,error);
});

View File

@@ -4,7 +4,7 @@ In this usermod file you can find the documentation on how to take advantage of
## Installation
Copy `usermod_v2_fastled.h` to the wled00 directory.
Copy `usermod_v2_animartrix.h` to the wled00 directory.
Uncomment the corresponding lines in `usermods_list.cpp` and compile!
_(You shouldn't need to actually install this, it does nothing useful)_

View File

@@ -20,7 +20,7 @@
//based on: https://gist.github.com/StefanPetrick/9c091d9a28a902af5a7b540e40442c64
class StefanPetrickCore {
class AnimartrixCore {
private:
public:
@@ -60,11 +60,11 @@ class StefanPetrickCore {
float noise_angle_c, noise_angle_d, noise_angle_e, noise_angle_f; // angles based on linear noise travel
float dir_c, dir_d, dir_e, dir_f; // direction multiplicators
StefanPetrickCore() {
USER_PRINTLN("StefanPetrickCore constructor");
AnimartrixCore() {
USER_PRINTLN("AnimartrixCore constructor");
}
~StefanPetrickCore() {
USER_PRINTLN("StefanPetrickCore destructor");
~AnimartrixCore() {
USER_PRINTLN("AnimartrixCore destructor");
}
void init() {
@@ -177,7 +177,7 @@ class StefanPetrickCore {
}
};
class PolarBasics:public StefanPetrickCore {
class PolarBasics:public AnimartrixCore {
private:
public:
@@ -262,7 +262,7 @@ class PolarBasics:public StefanPetrickCore {
void calculate_oscillators() {
StefanPetrickCore::calculate_oscillators();
AnimartrixCore::calculate_oscillators();
uint16_t noi;
noi = inoise16(10000 + linear_c * 100000); // some noise controlled angular offsets
@@ -369,7 +369,7 @@ class PolarBasics:public StefanPetrickCore {
//based on https://gist.github.com/StefanPetrick/35ffd8467df22a77067545cfb889aa4f
//and Fastled podcast nr 3: https://www.youtube.com/watch?v=3tfjP7GJnZo
class CircularBlobs:public StefanPetrickCore {
class CircularBlobs:public AnimartrixCore {
private:
float fade(float t){ return t * t * t * (t * (t * 6 - 15) + 10); }
@@ -498,7 +498,7 @@ class CircularBlobs:public StefanPetrickCore {
void calculate_oscillators() {
StefanPetrickCore::calculate_oscillators();
AnimartrixCore::calculate_oscillators();
float n;
@@ -615,11 +615,11 @@ uint16_t mode_CircularBlobs(void) {
static const char _data_FX_mode_CircularBlobs[] PROGMEM = "💡CircularBlobs ☾@AngleDist,AngleMult;;!;2;sx=51,ix=51,c1=0,c2=0,c3=0";
class FastledUsermod : public Usermod {
class AnimartrixUsermod : public Usermod {
public:
FastledUsermod(const char *name, bool enabled):Usermod(name, enabled) {} //WLEDMM
AnimartrixUsermod(const char *name, bool enabled):Usermod(name, enabled) {} //WLEDMM
void setup() {
strip.addEffect(255, &mode_PolarBasics, _data_FX_mode_PolarBasics);
@@ -640,7 +640,7 @@ class FastledUsermod : public Usermod {
uint16_t getId()
{
return USERMOD_ID_FASTLED;
return USERMOD_ID_ANIMARTRIX;
}
};

View File

@@ -40,39 +40,39 @@ class WordClockUsermod : public Usermod
// Normal wiring
const int maskMinutes[14][maskSizeMinutes] =
{
{107, 108, 109, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // :00
{ 7, 8, 9, 10, 40, 41, 42, 43, -1, -1, -1, -1}, // :05 fünf nach
{ 11, 12, 13, 14, 40, 41, 42, 43, -1, -1, -1, -1}, // :10 zehn nach
{ 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1}, // :15 viertel
{ 15, 16, 17, 18, 19, 20, 21, 40, 41, 42, 43, -1}, // :20 zwanzig nach
{ 7, 8, 9, 10, 33, 34, 35, 44, 45, 46, 47, -1}, // :25 fünf vor halb
{ 44, 45, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1}, // :30 halb
{ 7, 8, 9, 10, 40, 41, 42, 43, 44, 45, 46, 47}, // :35 fünf nach halb
{ 15, 16, 17, 18, 19, 20, 21, 33, 34, 35, -1, -1}, // :40 zwanzig vor
{ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1}, // :45 dreiviertel
{ 11, 12, 13, 14, 33, 34, 35, -1, -1, -1, -1, -1}, // :50 zehn vor
{ 7, 8, 9, 10, 33, 34, 35, -1, -1, -1, -1, -1}, // :55 fünf vor
{ 26, 27, 28, 29, 30, 31, 32, 40, 41, 42, 43, -1}, // :15 alternative viertel nach
{ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1} // :45 alternative viertel vor
{107, 108, 109, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 0 - 00
{ 7, 8, 9, 10, 40, 41, 42, 43, -1, -1, -1, -1}, // 1 - 05 fünf nach
{ 11, 12, 13, 14, 40, 41, 42, 43, -1, -1, -1, -1}, // 2 - 10 zehn nach
{ 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1}, // 3 - 15 viertel
{ 15, 16, 17, 18, 19, 20, 21, 40, 41, 42, 43, -1}, // 4 - 20 zwanzig nach
{ 7, 8, 9, 10, 33, 34, 35, 44, 45, 46, 47, -1}, // 5 - 25 fünf vor halb
{ 44, 45, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1}, // 6 - 30 halb
{ 7, 8, 9, 10, 40, 41, 42, 43, 44, 45, 46, 47}, // 7 - 35 fünf nach halb
{ 15, 16, 17, 18, 19, 20, 21, 33, 34, 35, -1, -1}, // 8 - 40 zwanzig vor
{ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1}, // 9 - 45 dreiviertel
{ 11, 12, 13, 14, 33, 34, 35, -1, -1, -1, -1, -1}, // 10 - 50 zehn vor
{ 7, 8, 9, 10, 33, 34, 35, -1, -1, -1, -1, -1}, // 11 - 55 fünf vor
{ 26, 27, 28, 29, 30, 31, 32, 40, 41, 42, 43, -1}, // 12 - 15 alternative viertel nach
{ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1} // 13 - 45 alternative viertel vor
};
// Meander wiring
const int maskMinutesMea[14][maskSizeMinutesMea] =
{
{ 99, 100, 101, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // :00
{ 7, 8, 9, 10, 33, 34, 35, 36, -1, -1, -1, -1}, // :05 fünf nach
{ 18, 19, 20, 21, 33, 34, 35, 36, -1, -1, -1, -1}, // :10 zehn nach
{ 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1}, // :15 viertel
{ 11, 12, 13, 14, 15, 16, 17, 33, 34, 35, 36, -1}, // :20 zwanzig nach
{ 7, 8, 9, 10, 41, 42, 43, 44, 45, 46, 47, -1}, // :25 fünf vor halb
{ 44, 45, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1}, // :30 halb
{ 7, 8, 9, 10, 33, 34, 35, 36, 44, 45, 46, 47}, // :35 fünf nach halb
{ 11, 12, 13, 14, 15, 16, 17, 41, 42, 43, -1, -1}, // :40 zwanzig vor
{ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1}, // :45 dreiviertel
{ 18, 19, 20, 21, 41, 42, 43, -1, -1, -1, -1, -1}, // :50 zehn vor
{ 7, 8, 9, 10, 41, 42, 43, -1, -1, -1, -1, -1}, // :55 fünf vor
{ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1}, // :15 alternative viertel nach
{ 26, 27, 28, 29, 30, 31, 32, 41, 42, 43, -1, -1} // :45 alternative viertel vor
{ 99, 100, 101, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 0 - 00
{ 7, 8, 9, 10, 33, 34, 35, 36, -1, -1, -1, -1}, // 1 - 05 fünf nach
{ 18, 19, 20, 21, 33, 34, 35, 36, -1, -1, -1, -1}, // 2 - 10 zehn nach
{ 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1}, // 3 - 15 viertel
{ 11, 12, 13, 14, 15, 16, 17, 33, 34, 35, 36, -1}, // 4 - 20 zwanzig nach
{ 7, 8, 9, 10, 41, 42, 43, 44, 45, 46, 47, -1}, // 5 - 25 fünf vor halb
{ 44, 45, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1}, // 6 - 30 halb
{ 7, 8, 9, 10, 33, 34, 35, 36, 44, 45, 46, 47}, // 7 - 35 fünf nach halb
{ 11, 12, 13, 14, 15, 16, 17, 41, 42, 43, -1, -1}, // 8 - 40 zwanzig vor
{ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1}, // 9 - 45 dreiviertel
{ 18, 19, 20, 21, 41, 42, 43, -1, -1, -1, -1, -1}, // 10 - 50 zehn vor
{ 7, 8, 9, 10, 41, 42, 43, -1, -1, -1, -1, -1}, // 11 - 55 fünf vor
{ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1}, // 12 - 15 alternative viertel nach
{ 26, 27, 28, 29, 30, 31, 32, 41, 42, 43, -1, -1} // 13 - 45 alternative viertel vor
};
@@ -284,12 +284,13 @@ class WordClockUsermod : public Usermod
setHours(hours + 1, false);
break;
case 9:
// viertel vor bzw dreiviertel
// viertel vor
if (nord) {
setMinutes(9);
setMinutes(13);
}
// dreiviertel
else {
setMinutes(12);
setMinutes(9);
}
setHours(hours + 1, false);
break;
@@ -422,12 +423,18 @@ class WordClockUsermod : public Usermod
*/
void addToConfig(JsonObject& root)
{
JsonObject top = root.createNestedObject("WordClockUsermod");
top["active"] = usermodActive;
top["displayItIs"] = displayItIs;
top["ledOffset"] = ledOffset;
top["Meander wiring?"] = meander;
top["Norddeutsch"] = nord;
JsonObject top = root.createNestedObject(F("WordClockUsermod"));
top[F("active")] = usermodActive;
top[F("displayItIs")] = displayItIs;
top[F("ledOffset")] = ledOffset;
top[F("Meander wiring?")] = meander;
top[F("Norddeutsch")] = nord;
}
void appendConfigData()
{
oappend(SET_F("addInfo('WordClockUsermod:ledOffset', 1, 'Number of LEDs before the letters');"));
oappend(SET_F("addInfo('WordClockUsermod:Norddeutsch', 1, 'Viertel vor instead of Dreiviertel');"));
}
/*
@@ -450,15 +457,15 @@ class WordClockUsermod : public Usermod
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
// setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
JsonObject top = root["WordClockUsermod"];
JsonObject top = root[F("WordClockUsermod")];
bool configComplete = !top.isNull();
configComplete &= getJsonValue(top["active"], usermodActive);
configComplete &= getJsonValue(top["displayItIs"], displayItIs);
configComplete &= getJsonValue(top["ledOffset"], ledOffset);
configComplete &= getJsonValue(top["Meander wiring?"], meander);
configComplete &= getJsonValue(top["Norddeutsch"], nord);
configComplete &= getJsonValue(top[F("active")], usermodActive);
configComplete &= getJsonValue(top[F("displayItIs")], displayItIs);
configComplete &= getJsonValue(top[F("ledOffset")], ledOffset);
configComplete &= getJsonValue(top[F("Meander wiring?")], meander);
configComplete &= getJsonValue(top[F("Norddeutsch")], nord);
return configComplete;
}