Peak hold und decay LED bleibt an

Prinzip Geräuschmonitor (U-Bahn Station) mit peak hold und decay. Die peak LED geht nicht aus. Ein - 1 wie bei den "eigentlichen LEDs" newPeak = constrain(map(audioFiltered, 10, 200, 0, ledCount), 0, ledCount) - 1; geht nicht, da die peak LED dann vorlaufen würde. Was muß ich ändern? Sehe den Wald vor Bäumen nicht.

#include "FastLED.h"

const byte pinData = 6;
const int timeIntervalSampling = 40; // Sample window Breite (50 ms wäre 20Hz)
const int levelShift = 512;

const byte ledCount = 24;
const byte ledBrightness = 255;

struct CRGB ledRing[ledCount];
struct CRGB ledGradient[ledCount];
CHSV gradientHueStart = CHSV(96, 255, 255);
CHSV grandientHueEnd = CHSV(0, 255, 255);

int audioInRaw;
int audioInRectified;
float audioFiltered;

const int intervalPeakHold = 600;
const byte intervalPeakDecay = 20;

int newPeak;
int previousPeak;
unsigned long timeOfPeak; // Zeitstempel
bool peakDecay = false;
byte peakBrightness;
float peakBrightnessDecay;

void setup()
{
  Serial.begin(115200);

  FastLED.addLeds<NEOPIXEL, pinData>(ledRing, ledCount);
  FastLED.setBrightness(ledBrightness);

  fill_gradient(ledGradient, 0, gradientHueStart, ledCount, grandientHueEnd, SHORTEST_HUES);
}

void loop()
{
  unsigned long timeSamplingStart = millis();

  uint16_t audioPeakToPeak = 0;
  uint16_t audioMin = 1023;
  uint16_t audioMax = 0;

  while (millis() - timeSamplingStart < timeIntervalSampling)
  {
    audioInRaw = analogRead(0);
    audioInRectified = abs(audioInRaw - levelShift);

    audioMin = min(audioInRectified, audioMin);
    audioMax = max(audioInRectified, audioMax);
  }

  audioPeakToPeak = audioMax - audioMin;
  if (audioPeakToPeak <= 5) // Kann später weg
    audioPeakToPeak = 0;

  audioFiltered = 0.8 * audioFiltered + (1 - 0.8) * audioPeakToPeak; // Leaky integrator, schnelles attack, langsameres decay

  // 10 und 200 sind magic numbers, muß später mit auto-range weg
  newPeak = constrain(map(audioFiltered, 10, 200, 0, ledCount), 0, ledCount) - 1;

  if (newPeak >= previousPeak)
  {
    previousPeak = newPeak;
    timeOfPeak = millis();
    peakDecay = false;
    peakBrightness = 255;
  }

  else if (!peakDecay && (millis() - timeOfPeak > intervalPeakHold))
  {
    peakDecay = true;
    timeOfPeak += intervalPeakHold - intervalPeakDecay;
  }

  else if (peakDecay && (millis() - timeOfPeak > intervalPeakDecay))
  {
    if (previousPeak > 0)
    {
      previousPeak--;
      timeOfPeak += intervalPeakDecay;
    }
  }

  FastLED.clear();
  
  for ( byte i = 0; i <= newPeak; i++)
  {
    ledRing[i] = ledGradient[i];
  }

  ledRing[previousPeak] = CHSV(0, 255, peakBrightness);

  FastLED.show();
}

Den Wald funktioniert im Simulator. Etwa eine Sekunde Pause, bevor die Spitzen-LED erlischt.

Fügen Sie diesen Code in WOKWI.COM ein.

Original code
#include "FastLED.h"

const byte pinData = 6;
const int timeIntervalSampling = 40; // Sample window Breite (50 ms wäre 20Hz)
const int levelShift = 512;

const byte ledCount = 24;
const byte ledBrightness = 255;

struct CRGB ledRing[ledCount];
struct CRGB ledGradient[ledCount];
CHSV gradientHueStart = CHSV(96, 255, 255);
CHSV grandientHueEnd = CHSV(0, 255, 255);

int audioInRaw;
int audioInRectified;
float audioFiltered;

const int intervalPeakHold = 600;
const byte intervalPeakDecay = 20;

int newPeak;
int previousPeak;
unsigned long timeOfPeak; // Zeitstempel
bool peakDecay = false;
byte peakBrightness;
float peakBrightnessDecay;

void setup() {
  Serial.begin(115200);
  FastLED.addLeds<NEOPIXEL, pinData>(ledRing, ledCount);
  FastLED.setBrightness(ledBrightness);
  fill_gradient(ledGradient, 0, gradientHueStart, ledCount, grandientHueEnd, SHORTEST_HUES);
}

void loop() {
  unsigned long timeSamplingStart = millis();
  uint16_t audioPeakToPeak = 0;
  uint16_t audioMin = 1023;
  uint16_t audioMax = 0;

  while (millis() - timeSamplingStart < timeIntervalSampling) {
    audioInRaw = analogRead(0);
    audioInRectified = abs(audioInRaw - levelShift);
    audioMin = min(audioInRectified, audioMin);
    audioMax = max(audioInRectified, audioMax);
  }

  audioPeakToPeak = audioMax - audioMin;
  if (audioPeakToPeak <= 5) // Kann später weg
    audioPeakToPeak = 0;
  audioFiltered = 0.8 * audioFiltered + (1 - 0.8) * audioPeakToPeak; // Leaky integrator, schnelles attack, langsameres decay

  // 10 und 200 sind magic numbers, muß später mit auto-range weg
  newPeak = constrain(map(audioFiltered, 10, 200, 0, ledCount), 0, ledCount) - 1;

  if (newPeak >= previousPeak) {
    previousPeak = newPeak;
    timeOfPeak = millis();
    peakDecay = false;
    peakBrightness = 255;
  }

  else if (!peakDecay && (millis() - timeOfPeak > intervalPeakHold)) {
    peakDecay = true;
    timeOfPeak += intervalPeakHold - intervalPeakDecay;
  }

  else if (peakDecay && (millis() - timeOfPeak > intervalPeakDecay)) {
    if (previousPeak > 0) {
      previousPeak--;
      timeOfPeak += intervalPeakDecay;
    }
  }

  FastLED.clear();
 
  for ( byte i = 0; i <= newPeak; i++) {
    ledRing[i] = ledGradient[i];
  }

  ledRing[previousPeak] = CHSV(0, 255, peakBrightness);

  FastLED.show();
}
diagram.json
{
  "version": 1,
  "author": "Anonymous maker",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-nano", "id": "nano", "top": -4.8, "left": -0.5, "attrs": {} },
    {
      "type": "wokwi-neopixel-matrix",
      "id": "ring2",
      "top": -50.6,
      "left": -322.78,
      "rotate": 270,
      "attrs": { "pixleate": "1", "rows": "1", "cols": "24" }
    },
    { "type": "wokwi-vcc", "id": "vcc1", "top": -95.24, "left": 163.2, "attrs": {} }
  ],
  "connections": [
    [ "nano:GND.2", "ring2:GND", "black", [ "v-28.8", "h-144" ] ],
    [ "vcc1:VCC", "ring2:VCC", "red", [ "v28.8", "h-192" ] ],
    [ "nano:6", "ring2:DIN", "green", [ "v-48", "h-96" ] ]
  ],
  "dependencies": {}
}

Ich habe peakHoldAndRelease - Wokwi ESP32, STM32, Arduino Simulator ausprobiert, aber dort sind alle LEDs incl. peak LED an, flimmern am Anschlag (23).

Aber ich habe herausbekommen, wo der Fehler war. Nun funktioniert es.

WOKWI json

{
{
  "version": 1,
  "author": "Anonymous maker",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-uno", "id": "uno", "top": 0.6, "left": 37.8, "attrs": {} },
    { "type": "wokwi-microphone", "id": "mic", "top": 127.02, "left": 350.19, "attrs": {} },
    {
      "type": "wokwi-neopixel-canvas",
      "id": "strip",
      "top": -61.4,
      "left": -95.7,
      "attrs": { "rows": "1", "cols": "24", "pixelate": "circle", "_temp_gamma": "0.45" }
    }
  ],
  "connections": [
    [ "mic:1", "uno:A0", "green", [ "v38.4", "h-119" ] ],
    [ "mic:2", "uno:GND.3", "black", [ "v48", "h-157.61" ] ],
    [ "strip:DIN", "uno:6", "yellow", [ "v19.2", "h52.2" ] ],
    [ "strip:VSS", "uno:GND.1", "black", [ "v28.8", "h-29.5" ] ],
    [ "strip:VDD", "uno:5V", "red", [ "v19.2", "h-149", "v240", "h169" ] ]
  ],
  "dependencies": {}
}

WOKWI code

#include "FastLED.h"

const byte pinData = 6;
const int timeIntervalSampling = 40;
const int levelShift = 512;

const byte ledCount = 24;
const byte ledBrightness = 255;

struct CRGB ledRing[ledCount];
struct CRGB ledGradient[ledCount];
CHSV gradientHueStart = CHSV(96, 255, 255);
CHSV grandientHueEnd = CHSV(0, 255, 255);

int audioInRaw;
int audioInRectified;
float audioFiltered;

const int intervalPeakHold = 600;
const byte intervalPeakDecay = 20;

int newPeak;
int previousPeak;
unsigned long timeOfPeak;
bool peakDecay = false;
byte peakBrightness;

void setup()
{
  Serial.begin(115200);

  FastLED.addLeds<NEOPIXEL, pinData>(ledRing, ledCount);
  FastLED.setBrightness(ledBrightness);

  fill_gradient(ledGradient, 0, gradientHueStart, ledCount, grandientHueEnd, SHORTEST_HUES);
}

void loop()
{
  unsigned long timeSamplingStart = millis();

  uint16_t audioPeakToPeak = 0;
  uint16_t audioMin = 1023;
  uint16_t audioMax = 0;

  while (millis() - timeSamplingStart < timeIntervalSampling)
  {
    audioInRaw = analogRead(0);
    audioInRectified = abs(audioInRaw - levelShift);

    audioMin = min(audioInRectified, audioMin);
    audioMax = max(audioInRectified, audioMax);
  }

  audioPeakToPeak = audioMax - audioMin;

  if (audioPeakToPeak <= 5)
    audioPeakToPeak = 0;

  audioFiltered = 0.8 * audioFiltered + (1 - 0.8) * audioPeakToPeak;

  newPeak = constrain(map(audioFiltered, 10, 150, 0, ledCount), 0, ledCount) - 1;

  if (newPeak >= previousPeak)
  {
    previousPeak = newPeak;
    timeOfPeak = millis();
    peakDecay = false;
  }

  else if (!peakDecay && (millis() - timeOfPeak > intervalPeakHold))
  {
    peakDecay = true;
    timeOfPeak += intervalPeakHold - intervalPeakDecay;
    peakBrightness = 255;
  }

  else if (peakDecay && (millis() - timeOfPeak > intervalPeakDecay))
  {
    if (previousPeak >= 0)
    {
      previousPeak--;
      timeOfPeak += intervalPeakDecay;
    }
  }

  FastLED.clear();

  for ( byte i = 0; i <= newPeak; i++)
  {
    ledRing[i] = ledGradient[i];
  }

  ledRing[previousPeak] = CHSV(0, 255, peakBrightness);

  FastLED.show();
}

Prosit!

Na ja, allerdings ist WOKWI erheblich langsamer als ein physischer Microcontroller - peak hold ist ok, aber decay ist zu langsam, selbst wenn const byte intervalPeakDecay = 0; ist. Oder der 40ms while-loop zum Datensammeln kommt in die Quere.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.