VU-Meter, aber korrekt!

OP #5747587
Lesenswert?

Hallo,

ich möchte gerne ein VU-Meter als korrektes Messgerät bauen.
Insperiert von hier: 
https://www.hackster.io/ericBcreator/stereo-neopixel-ring-vu-meter-b28e78

Da wird der anzuzeigende Wert per

  leftValue = map(leftAnalogValue, minValue, maxValue, 0, maxSegments);
  rightValue = map(rightAnalogValue, minValue, maxValue, 0, 
maxSegments);

map-befehl ausgewertet, was natürlich nur was "fürs Auge" ist, aber 
nicht viel mit echten Messwerten zutun hat.

Um nun jeder LED (WS2812) nun einen bestimmten Wert zuweisen zu können,
müsste ich per

IF(Spannung => 775mV)
{
 LED_0dB = true;
}
else if (Spannung => 690mV)
{
 LED_-1dB = true;
}
else if (Spannung => ....

usw

.. etliche If-Schleifen einbauen mit deren der map Befehl ersetzt wird.

Das Anzeigeband soll von -40 bis +10dB mit 70 LEDs sein.

1) Wäre es trotz der vielen IF Schleifen trotzdem noch flüssig oder 
bräuchte man Assembler Routinen?

2) Wer kennt sich aus mit Assembler Routinen unter der Arduino-IDE?


Gruß,
Wolfram.
#5747596
Lesenswert?

Ich habe soetwas (zwar ohne "Neopixel") bereits gemacht.

Im Prinzip reicht eine For-SCHLEIFE. Die Skalierung kann entweder 
logarithmisch (am besten per LUT) oder linear erfolgen.

Linear sähe das in etwa so aus:
1
for(i = 0; i < NUM_STEPS; i++){
2
      if(adc_value >= (i+1)*STEP_SIZE){
3
         led_cnt++;
4
      } else {
5
          break;
6
      }
7
}
8
LED_Activate(led_cnt);

Bei einer (logarithmischen) LUT müsste man eben anstatt mit "STEP_SIZE" 
eben "LOG_LUT[i]" schreiben.
Gast #5747603
Lesenswert?

Wolfram F. schrieb:

> Das Anzeigeband soll von -40 bis +10dB mit 70 LEDs sein.

Das ist prinzipiell absolut kein Problem füt einen AVR8. Für 
IF-Schleifen-Benutzer/Arduino-Jünger könnte es allerdings etwas zu 
kompliziert werden...

Das sind vermutlich auch die einzigen Leute, die es nicht einfach 
machen, sondern erst die Öffentlichkeit eines Forums mit solchen 
Trivialitäten behelligen müssen...
#5747627
Lesenswert?

Wolfram F. schrieb:
> ich möchte gerne ein VU-Meter als korrektes Messgerät bauen.

Da bist du noch weit von entfernt.

Grundlagen siehe:

http://www.dse-faq.elektronik-kompendium.de/dse-faq.htm#F.30.2

> .. etliche If-Schleifen einbauen

Es gibt keine If-Schleifen.
Beim Programmieren stehst du auch noch ganz am Anfang ?

> Das Anzeigeband soll von -40 bis +10dB mit 70 LEDs sein.

> 1) Wäre es trotz der vielen IF Schleifen trotzdem noch flüssig oder
> bräuchte man Assembler Routinen?

Wolfram F. schrieb:
> 2) Wer kennt sich aus mit Assembler Routinen unter der Arduino-IDE?

Echter Arduino-Code wird zu langsam sein. Aber ein Arduino ist auch in 
richtigem C und in Assembler programmierbar.

http://www.uni-koeln.de/phil-fak/muwi/ag/praktikum/assembler_arduino.pdf

Aber das wird man nur für kleine Stücke machen. Und es gibt schnelle 
Libs für WS2812. https://www.reddit.com/r/FastLED/

Das Mapping wird man sicherlich klüger programmieren. Zudem wird man den 
VU und den Peak-Wert mappen wollen, und das auch noch stereo.

Grundlage wäre: Man braucht 30us pro LED, für einen 70er Strip also 
2.1ms, stereo 4.2ms, macht 230 Hz Update refreshrate. Das reicht. Man 
kann es verkürzen, in dem man kürzere Strips parallel mit Daten 
versorgt.

Wenn deine +10dB so 3.16Vrms also 4.5Vpeak wären, sind -40dB so 10mV, 
das passt in 10 bit A/D und ein Array von 1024 bytes ist nicht zu gross, 
man wird also einfach
1
 einzuschaltende_LED_Position = vorberechnetesArray[Spannung_aus_ADC]
nutzen. Das geht schnell.
OP #5747776
Lesenswert?

c-hater schrieb:
> Wolfram F. schrieb:
>
>> Das Anzeigeband soll von -40 bis +10dB mit 70 LEDs sein.
>
> Das ist prinzipiell absolut kein Problem füt einen AVR8. Für
> IF-Schleifen-Benutzer/Arduino-Jünger könnte es allerdings etwas zu
> kompliziert werden...
>
> Das sind vermutlich auch die einzigen Leute, die es nicht einfach
> machen, sondern erst die Öffentlichkeit eines Forums mit solchen
> Trivialitäten behelligen müssen...

Danke für Deinen sinnlosen Kommentar!
Gerade in diesem Forum gibt es zu hauf immer wieder Leute wie Dich,
weshalb es immer unsympatischer wird..
Lass es!
#5747949
Lesenswert?

Wolfram F. schrieb:
> wieso sollen +10dB 3.16V sein?

Damit der ganze Messbereich des A/D-Wandlers genutzt wird.
Da vor dem Analogeingang eh ein Gleichrichter und Hüllkurvenfilter sein 
muss, z.B. AD636, deine Prohrammierkenntnisse reichen nicht für eine 
Echtzeit-rms-Wandlung, kann man den Spannungspegel gleich passsend 
verstärken.

Je nach Signalquelle läge der 0dB Normpegel bei 1.228V (XLR), 0.775V 
(Cinch), 1.55V (ARD), 0.3162V (Klinke) oder 1uA (Diodenbuchse).
#5748274
Lesenswert?

Apollo M. schrieb:
> c-hater schrieb:
>> Das sind vermutlich auch die einzigen Leute, die es nicht einfach
>> machen, sondern erst die Öffentlichkeit eines Forums mit solchen
>> Trivialitäten behelligen müssen...
>
> ... das wird hier langsam zur seuche und die tu's ziehen das niveau
> weiter und weiter runter, bäh!
>

Dann erweise doch der Menschheit die Gnade und hebe das Niveau dieses 
Forums, indem Du selbst etwas sinnvolles zum Besten gibst. Die größte 
Belästigung hier geht von Leuten wie Dir aus, die völlig sinnfrei das 
Forum zumüllen.

Wenn Wolfram alles wüsste, bräuchte er hier nicht zu fragen.

Wenn Du etwas wüsstest, könntest Du es anderen mitteilen.

Beides scheint nicht zuzutreffen.
Gast #5748329
Lesenswert?

Stefan S. schrieb:
> Linear sähe das in etwa so aus:for(i = 0; i < NUM_STEPS; i++){
>       if(adc_value >= (i+1)*STEP_SIZE){
>          led_cnt++;
>       } else {
>           break;
>       }
> }
> LED_Activate(led_cnt);
>
> Bei einer (logarithmischen) LUT müsste man eben anstatt mit "STEP_SIZE"
> eben "LOG_LUT[i]" schreiben.

Dann kannst du die LUT direkt so aufsetzen, dass LED_Cnt rauskommt. Dann 
brauchst gar keinen Vergleich mehr. Nur ne Exceltabelle und ein bisschen 
Hirnschmalz im Vorraus.
In etwa:
LED_Cnt = LUT[adc_value]
OP #5748570
Lesenswert?

aha, d.h., wenn ich ein Array mit 1024 Werten erstelle, kann für jede
Stufe des AD-Wandlers der Wert für die LED Nr. definiert werden?

etwa so:

byte LUT[1024] = {
  1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1, 
1,   1,
  1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1, 
1,   1,
  1,   2,   2,   2,   2,   2,   2,   2,   2,   3,   3,   3,   3,   3, 
4,   4,
  4,   4,   4,   5,   5,   5,   5,   6,   6,   6,   6,   7,   7,   7, 
7,   8,

...

  69, 70 };

leftValue = LUT[analogRead(leftPin)];
rightValue = LUT[analogRead(rightPin)];

wird ne riesen Tabelle, kann man die nicht noch vereinfachen?
#5748585
Lesenswert?

Moin,

Wolfram F. schrieb:
> kann man die nicht noch vereinfachen?

Was und wieso willst du denn immer noch weiter vereinfachen? Die 
eigentliche Software sind 2 Zeilen C fuer Stereo. Performancemaessig 
auch Anschlag. Klar, die olle Tabelle sind 1024 Eintraege, von denen am 
einen Ende immer ziemlich viele hintereinander gleich sind. So what?
Du musst die Tabelle nicht von Hand mit einem Taschenrechner erstellen, 
sondern darfst die C-sourcen auch per Sprache deiner Wahl erzeugen 
lassen.

Gruss
WK
Gast #5748600
Lesenswert?

Wolfram F. schrieb:
> wird ne riesen Tabelle, kann man die nicht noch vereinfachen?

Ja, durch eine eingange kategorisch verworfene map()-Funktion. Diese 
setzt einen linearen Zusammenhang zwischen Signal und Ausgang voraus. 
Man kann auch quadratisch usw. mittels Formel interpolieren.
1
long map(long x, long in_min, long in_max, long out_min, long out_max)
2
{
3
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
4
}

Es ist wie oft eine Abwaegung zwischen Codegroesse und Geschwindigkeit, 
die man nur fuer die Zielarchitektur messen kann. Bei einer rein 
optischen Anzeige spielt das keine Rolle.

leo
OP #5748613
Lesenswert?

so in etwa ist es jetzt auch, aber ich bezweifel, daß die Ergebnisse
des MAP Befehls so exakt sind wie die LUT-Methode!

  // map values
  float log10MaxDisplaySegments = log10(maxSegments);
  leftValue = map(leftAnalogValue, minValue, maxValue, 0, maxSegments);
  rightValue = map(rightAnalogValue, minValue, maxValue, 0, 
maxSegments);
  leftValue = ((log10(leftValue  + 1) / log10MaxDisplaySegments * 
maxSegments));
  rightValue = ((log10(rightValue  + 1) / log10MaxDisplaySegments * 
maxSegments));
#5748627
Lesenswert?

Wolfram F. schrieb:
> Gerade in diesem Forum gibt es zu hauf immer wieder Leute wie Dich,
> weshalb es immer unsympatischer wird..

Leider gibt es im Forum auch immer mehr Leute wie Dich, durch die es mit 
trivialen Fragen zugemüllt wird.

Nicht dass Fragen ansich etwas Schlechtes wäre, aber wenn so sehr 
deutlich wird, dass sich der Fragende so gar keine Gedanken gemacht 
hat...

leo schrieb:
> return (x - in_min) * (out_max - out_min) / (in_max - in_min) +
> out_min;

Wobei Dir das / auf dem Avr wieder die Performance versaut. Es sei denn 
Du bist so schlau die Werte auf 1024 und 0 zu setzen (was nicht ganz 
korrekt ist, denn in_max wäre ja 1023) und der Compiler kann da ein shr 
10 draus machen.

Wolfram F. schrieb:
> wird ne riesen Tabelle, kann man die nicht noch vereinfachen?

Drehs halt um: Mach eine Tabelle, wo für jede LED der ADC-Schwellwert 
drinsteht, und durchsuche dann die Tabelle bis Eingangswert < 
Schwellwert. Sind 144 statt 1024 Byte.

Wenn Du das linear durchsuchst, ist es immer noch schneller als das div 
mit longs. Wenn Du es verzweigt durchsuchst, bist Du mit 7 Schritten 
fertig.
#5748635
Lesenswert?

Wolfram F. schrieb:
> float log10MaxDisplaySegments = log10(maxSegments);

Oh bitte, beschäftige Dich mal mit den Grundlagen der µC-Programmierung.

float ist hier so ziemlich das Letzte, was Du nehmen solltest, und sowas 
wie log10 ist ganz böse. So ein AVR Controller hat keinen 
Mathe-Coprozessor.

Wolfram F. schrieb:
> ich komme nicht darauf, wie ich das Array richtig füllen kann,

Mit LibreOffice => Calc. Mehr brauchst Du nicht. LEDs 1 bis 72, dazu die 
Schwellwerte berechnen lassen, sinnvoll runden.
OP #5748638
Lesenswert?

Karl K. schrieb:
> Drehs halt um: Mach eine Tabelle, wo für jede LED der ADC-Schwellwert
> drinsteht, und durchsuche dann die Tabelle bis Eingangswert <
> Schwellwert. Sind 144 statt 1024 Byte.

oder 70 Bytes, da ich 2 IOs für 2 Stripes mit je 70 LEDs verwenden will,
die Suche nach den richtigen Schwellwert kann ja einmal für den linken 
und einmal für den rechten Kanal aufgerufen werden.

Der Tip ist super, das werde ich die Tage probieren!
#5748680
Lesenswert?

Karl K. schrieb:
> Drehs halt um: Mach eine Tabelle, wo für jede LED der ADC-Schwellwert
> drinsteht, und durchsuche dann die Tabelle bis Eingangswert <
> Schwellwert. Sind 144 statt 1024 Byte.

Das war auch eher das, worauf ich hinaus wollte; so hatte ich dies für 
"nur" 2 Mal 64 LEDs auch gelöst gehabt.
Bei meinem ursprünglichen Post habe ich dies etwas missverständlich per 
Nachtrag eingefügt gehabt.

Die Liste habe ich mir per Excel berechnen lassen und per Copy/Paste als 
LUT abgelegt.
Gast #5749566
Lesenswert?

Die Arduinos haben doch idr einen Mega328 oder vergleichbares an board. 
Mit 32k Flash würde ich mir nicht die Mühe machen da sparen zu wollen. 
Wir reden hier von 1/32 ~= 3% des verfügbaren Speichers.
#5749712
Lesenswert?

Minimalist schrieb:
> Mit 32k Flash würde ich mir nicht die Mühe machen da sparen zu wollen.

Dann muss man die LUT aber auch richtig im Flash ablegen, und nicht 
einfach als Array definieren, wo sie dann im Ram rumliegt.

Und: Es ist nie falsch sich Gedanken um effizientes Programmieren zu 
machen. Sonst kommt dann der nächste Heulthread: Hilfe, mein Arduino 
reicht nicht für den LED-Blinker, ich brauch dafür einen Raspberry.
OP #5749923
Lesenswert?

Michael B. schrieb:
> Wolfram F. schrieb:
>> kann man die nicht noch vereinfachen?
>
> Man muss die Tabelle nicht eintippen, man kann sie am Programmanfang
> ausrechnen lassen.

das versuche ich gerade, komme aber nicht weiter... blöde Mathematik..

  // --- setup LookUpTable -------------
  Serial.begin(9600);
  for (i = 0; i < 1024; i++)
  {
    LUT[i] = log10(i / 70);
    Serial.println(LUT[i]);
  }
  // -----------------------------------
#5750198
Lesenswert?

Moin,

Minimalist schrieb:
> Das wird mit dem 10 bit ADC nicht gehen.

Und wieso? Ich mein, nachdem hier zwar uldrakorreggd gemessen werden 
soll, aber bislang noch kein Wort ueber die Schaltung am Eingang des 
ADCs verloren wurde, glaub' ich zwar auch nicht so direkt an den 
sofortigen Erfolg, aber - watt solls? :-)
Fuer alle, die besser ihren Namen tanzen koennen als rechnen, hier ein 
Vorschlag fuer so eine 50dB Tabelle fuer 70 LEDs:
1
uint8_t bla[]={
2
 0, 0, 7,11,14,16,18,20,21,22,23,24,25,26,27,27,
3
28,29,29,30,30,31,31,32,32,33,33,33,34,34,34,35,
4
35,35,36,36,36,37,37,37,37,38,38,38,38,39,39,39,
5
39,39,40,40,40,40,40,41,41,41,41,41,41,42,42,42,
6
42,42,42,43,43,43,43,43,43,43,44,44,44,44,44,44,
7
44,45,45,45,45,45,45,45,45,45,46,46,46,46,46,46,
8
46,46,46,47,47,47,47,47,47,47,47,47,47,48,48,48,
9
48,48,48,48,48,48,48,48,49,49,49,49,49,49,49,49,
10
49,49,49,49,49,50,50,50,50,50,50,50,50,50,50,50,
11
50,50,51,51,51,51,51,51,51,51,51,51,51,51,51,51,
12
51,51,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
13
52,52,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
14
53,53,53,53,53,54,54,54,54,54,54,54,54,54,54,54,
15
54,54,54,54,54,54,54,54,54,55,55,55,55,55,55,55,
16
55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,
17
56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
18
56,56,56,56,56,56,56,56,57,57,57,57,57,57,57,57,
19
57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
20
57,57,57,57,58,58,58,58,58,58,58,58,58,58,58,58,
21
58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
22
58,58,59,59,59,59,59,59,59,59,59,59,59,59,59,59,
23
59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,
24
59,59,59,60,60,60,60,60,60,60,60,60,60,60,60,60,
25
60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
26
60,60,60,60,60,60,60,60,61,61,61,61,61,61,61,61,
27
61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
28
61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
29
61,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,
30
62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,
31
62,62,62,62,62,62,62,62,62,62,62,62,62,62,63,63,
32
63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,
33
63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,
34
63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,64,
35
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
36
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
37
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
38
64,64,64,64,64,64,65,65,65,65,65,65,65,65,65,65,
39
65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
40
65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
41
65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
42
65,65,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
43
66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
44
66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
45
66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
46
66,66,66,66,67,67,67,67,67,67,67,67,67,67,67,67,
47
67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,
48
67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,
49
67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,
50
67,67,67,67,67,67,67,67,67,67,67,67,67,67,68,68,
51
68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
52
68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
53
68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
54
68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
55
68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,69,
56
69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
57
69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
58
69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
59
69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
60
69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
61
69,69,69,69,69,69,69,69,70,70,70,70,70,70,70,70,
62
70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,
63
70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,
64
70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,
65
70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70
66
};

Gruss
WK
#5750211
Lesenswert?

Wolfram F. schrieb:
> Das Anzeigeband soll von -40 bis +10dB mit 70 LEDs sein.

Also 0,714 dB pro LED?

Wolfram F. schrieb:
> das versuche ich gerade, komme aber nicht weiter... blöde Mathematik..
>
>   // --- setup LookUpTable -------------
>   Serial.begin(9600);
>   for (i = 0; i < 1024; i++)
>   {
>     LUT[i] = log10(i / 70);

Von welchem Typ ist i? Wenn es ein Integer ist, dann ist i / 70 eine 
Integer-Division, spirch: Nachkommastellen fehlen. Und davon wird dann 
dein Logarithmus gebildet.

>     Serial.println(LUT[i]);
>   }
>   // -----------------------------------
OP #5751001
Lesenswert?

Dergute W. schrieb:
> Vorschlag fuer so eine 50dB Tabelle fuer 70 LEDs:
> uint8_t bla[]={
>  0, 0, 7,11,14,16,18,20,21,22,23,24,25,26,27,27,

hmm, was ist mit den LEDs 1,2,3,4,5 und 6?
die leuchten nach deiner Tabelle nie...

zur eingangsschaltung: ich habe vor, einen NE5532 als Anpassung an den 
AD vorzusetzen. Als gleichrichtung müsste eine Halbwelle doch reichen, 
oder?
Der AD soll eine externe Referenz-Spannungsquelle bekommen, dachte an 
4.096V.

Die Skala sollte +10,+9,+8,+7,+6,+5,+4,+3,+2,+1,0 und im
negativen Bereich -0.1, -0.2, -0,3, -0.4 -0.5, -0.6, -0.7, -0.8, -0.9, 
-1,
-1.5, -2, -2.5, -3, -3.5, -4, -4.5, -5, -5.5, -6, -6.5, -7, -7.5, -8,
-8.5, -9, -9.5, -10, -10.5, -11, -11.5, -12, -12.5, -13, -13.5, -14,
-14.5, -15, -15.5, -16, -16.5, -17, -17.5, -18, -18.5, -19, -19.5, -20,
-20.5, -21, -21.5, -22, -22.5, -23, -23.5, -24, -25, -30, -40
definiert werden.

Dazu ist sicherlich die Methode mit den Schwellwerten in einem Array 
wesentlich besser geeignet.
Der Verstärkungsfaktor des OPs wird dann so eingestellt, daß 4.096V 
+10db bzw. den AD Wert 1023 ergibt.

Wie "sauber" sampled der AD eigentlich? sollte man noch ein Oversampling 
mit einbauen? Und einen Lowpass filter < 25kHz ?
#5751439
Lesenswert?

Dergute W. schrieb:
> Moin,
>
> Minimalist schrieb:
>> Das wird mit dem 10 bit ADC nicht gehen.
>
> Und wieso? Ich mein, nachdem hier zwar uldrakorreggd gemessen werden
> soll, aber bislang noch kein Wort ueber die Schaltung am Eingang des
> ADCs verloren wurde, glaub' ich zwar auch nicht so direkt an den
> sofortigen Erfolg, aber - watt solls? :-)
> Fuer alle, die besser ihren Namen tanzen koennen als rechnen, hier ein
> Vorschlag fuer so eine 50dB Tabelle fuer 70 LEDs:
>
> [c]uint8_t bla[]={
>  0, 0, 7,11,14,16,18,20,21,22,23,24,25,26,27,27,

Und hier reicht es, sich die erste Zeile anzuschauen,
um zu sehen, daß der ADC hierfür zu wenig Auflösung hat.

Denn wo sind die Einträge für die LEDs 1 bis 6, 9, 10, 13, 15, 17, 19?
Nach 0 LEDs gehen hier direkt die ersten 7 an, was natürlich Mist ist, 
denn von einem VU Meter erwartet man zu Recht, daß mit langsam 
steigendem Pegel eine LED nach der anderen angeht und nicht auf einen 
Schlag die ersten sieben.

Daß vor den ADC Input zumindest noch ein RMS-Wandler gehört, damit sowas 
wie ein VU-Meter dabei herauskommt, ist noch eine ganz andere Baustelle.
OP #5752366
Lesenswert?

So, ich habe es nun hinbekommen!

Zuerst habe ich die 70 Spannungswerte in ein Array von Hand eingetragen:
1
// Spannungen in mV entsprechend dB
2
word LUT_U[71] =
3
{
4
  8, 25, 43, 48, 52, 55, 58, 62, 65, 69, // -40.0 -30.0 -25.0 -24.0 -23.5 -23.0 -22.5 -22.0 -21.5 -21.0
5
  73, 77, 82, 86, 92, 97, 103, 109, 116, 123, // -20.5 -20.0 -19.5 -19.0 -18.5 -18.0 -17.5 -17.0 -16.5 -16.0
6
  130, 138, 146, 155, 164, 173, 184, 195, 206, 218, // -15.5 -15.0 -14.5 -14.0 -13.5 -13.0 -12.5 -12.0 -11.5 -11.0
7
  231, 245, 259, 275, 291, 308, 327, 346, 367, 388, // -10.5 -10.0  -9.5  -9.0  -8.5  -8.0  -7.5  -7.0  -6.5  -6.0
8
  411, 436, 461, 489, 518, 548, 581, 615, 652, 690, //  -5.5  -5.0  -4.5  -4.0  -3.5  -3.0  -2.5  -2.0  -1.5  -1.0
9
  698, 706, 715, 723, 731, 740, 748, 757, 766, 775, //  -0.9  -0.8  -0.7  -0.6  -0.5  -0.4  -0.3  -0.2  -0.1   0.0
10
  869, 975, 1095, 1228, 1377, 1549, 1734, 1946, 2183, 2449  //  +1.0  +2.0  +3.0  +4.0  +5.0  +6.0  +7.0  +8.0  +9.0 +10.0
11
};
Dann eine zweite (leere) LUT erstellt,
1
word LUT_ADC[71] =
2
{
3
  // AD-Werte entsprechend dB (werden von der make_adc_value Routine erzeugt)
4
  0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, // -40.0 -30.0 -25.0 -24.0 -23.5 -23.0 -22.5 -22.0 -21.5 -21.0
5
  0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, // -20.5 -20.0 -19.5 -19.0 -18.5 -18.0 -17.5 -17.0 -16.5 -16.0
6
  0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, // -15.5 -15.0 -14.5 -14.0 -13.5 -13.0 -12.5 -12.0 -11.5 -11.0
7
  0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, // -10.5 -10.0  -9.5  -9.0  -8.5  -8.0  -7.5  -7.0  -6.5  -6.0
8
  0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, //  -5.5  -5.0  -4.5  -4.0  -3.5  -3.0  -2.5  -2.0  -1.5  -1.0
9
  0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, //  -0.9  -0.8  -0.7  -0.6  -0.5  -0.4  -0.3  -0.2  -0.1   0.0
10
  0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 1023  //  +1.0  +2.0  +3.0  +4.0  +5.0  +6.0  +7.0  +8.0  +9.0 +10.0
11
};
diese wird entsprechend dem Faktor 1023/Vref (z.z. 2.449V) mit den 
ADC-Werten gefüllt:
1
float faktor = 1023 / 2449.0 ;
2
void make_adc_value()
3
{
4
  for (i = 0; i < 71; i++)
5
  {
6
    LUT_ADC[i] = (int)LUT_U[i] * faktor + 0.5;
7
  }
8
}
Hier die Auswerte-Routine die die Anzahl der LEDs in leftValue bzw. 
rightValue ergibt:
1
void readValues() {
2
  leftAnalogValue = analogRead(leftPin);
3
  rightAnalogValue = analogRead(rightPin);
4

5
  for (i = 0; i < 71; i++)
6
  {
7
    if (leftAnalogValue < LUT_ADC[i])
8
    {
9
      leftValue = i;
10
      break;
11
    }
12
  }
13
  for (i = 0; i < 71; i++)
14
  {
15
    if (rightAnalogValue < LUT_ADC[i])
16
    {
17
      rightValue = i;
18
      break;
19
    }
20
  }
21

22
  Serial.print("LED: ");
23
  Serial.print(leftValue);
24
  Serial.print("      ADC: ");
25
  Serial.print(LUT_ADC[i]);
26
  Serial.print("      mV: ");
27
  Serial.println(LUT_U[i]);
28
}
natürlich dann ohne die Serial.prints...

Ergebnis passt super!
Serial:
1
LED: 43      ADC: 129      mV: 308
2
LED: 42      ADC: 122      mV: 291
3
LED: 42      ADC: 145      mV: 346
4
LED: 42      ADC: 145      mV: 346
5
LED: 42      ADC: 145      mV: 346
6
LED: 42      ADC: 145      mV: 346
7
LED: 41      ADC: 137      mV: 327
8
LED: 41      ADC: 137      mV: 327
9
LED: 41      ADC: 137      mV: 327
10
LED: 41      ADC: 137      mV: 327
11
LED: 41      ADC: 229      mV: 548
12
LED: 40      ADC: 229      mV: 548
13
LED: 40      ADC: 229      mV: 548
14
LED: 40      ADC: 216      mV: 518
15
LED: 40      ADC: 216      mV: 518
16
LED: 40      ADC: 216      mV: 518
17
LED: 39      ADC: 216      mV: 518
18
LED: 39      ADC: 216      mV: 518
19
LED: 39      ADC: 216      mV: 518
20
LED: 39      ADC: 204      mV: 489
21
LED: 39      ADC: 204      mV: 489
22
LED: 38      ADC: 204      mV: 489
23
LED: 38      ADC: 204      mV: 489
24
LED: 38      ADC: 204      mV: 489
25
LED: 38      ADC: 204      mV: 489
26
LED: 37      ADC: 193      mV: 461
27
LED: 37      ADC: 193      mV: 461

Soweit so gut, vielleicht könnte man da noch etwas optimieren?
Danke an alle die mir hier geholfen haben!
Nun gehts an die Referenzspannungsquelle, Gleichrichtung und um den 
OP...
#5753500
Lesenswert?

Moin,

Thorsten S. schrieb:
> Nach 0 LEDs gehen hier direkt die ersten 7 an, was natürlich Mist ist,
> denn von einem VU Meter erwartet man zu Recht, daß mit langsam
> steigendem Pegel eine LED nach der anderen angeht und nicht auf einen
> Schlag die ersten sieben.

Ja Mei. So 'n Logarithmus ist halt ein klassicher Vertreter einer 
nicht linearen Funktion. Da kann sowas schonmal passieren, auch wenns 
einem so ueberhaupt nicht in den Kram passt...

Wolfram F. schrieb:
> vielleicht könnte man da noch etwas optimieren?

Laeuft doch alles. Hoer' doch mal auf, immer alles ums Verrecken 
optimieren zu wollen. Mach' erstmal. Wenns dann irgendwo zu langsam oder 
zu gross oder zu Teppich wird, kannste immernoch mit "optimieren" 
anfangen.

ChrisMicro schrieb:
> Hier bitteschön:
> 
https://github.com/m5stack/M5Stack/blob/master/examples/Fire/M5StackFire_NeoPixelVUmeter/M5StackFire_NeoPixelVUmeter.ino

Ja, jeder Depp hat wohl schonmal sowas zusammengespaxt; das www ist voll 
davon. Ich nehm' mich da mal nicht aus:-)

Beitrag "VU-Meter mit Attiny13a statt LM3916"

Gruss
WK
OP #5753543
Lesenswert?

Dergute W. schrieb:
> Laeuft doch alles. Hoer' doch mal auf, immer alles ums Verrecken
> optimieren zu wollen. Mach' erstmal. Wenns dann irgendwo zu langsam oder
> zu gross oder zu Teppich wird, kannste immernoch mit "optimieren"
> anfangen.

Na ich mag es eben wenns geht, gleich optimal zu programmieren.
Das habe ich mir angewöhnt, seit dem ich mal meine Listings von 1988 
unter 6502 Assembler angeschaut habe :-)

Platine und Gehäuse sind in Arbeit, wird sicher ein schönes Gerät.
Gast #5753648
Lesenswert?

>Beitrag "VU-Meter mit Attiny13a statt LM3916"

Den Effektivwert über die 1000 Samples berechne ich auch. Es hat sich 
auch herausgestellt, dass beim M5Stack den Gleichspannungsoffset am 
besten abzieht.

Ich habe den Logarithmus durch die Umkehrfunktion ersetzt, weil ich den 
Code minimalistisch halten wollte. Das Ergebnis ist gleich. Der Code ist 
nicht zeitoptimiert, muss er meiner Meinung nach auch nicht sein.

Wenn man es genau machen will, ist der Wikipedia-Beitrag nützlich.
Speziell was das Timing angeht:

https://en.wikipedia.org/wiki/VU_meter

Hab's leider auch erst jetzt gesehen.

>Ja, jeder Depp hat wohl schonmal sowas zusammengespaxt; das www ist voll
>davon. Ich nehm' mich da mal nicht aus:-)

Lass diese Ausdrucksweise bleiben.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren