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.
Wolfram F. schrieb: > map-befehl ausgewertet, was natürlich nur was "fürs Auge" ist, aber > nicht viel mit echten Messwerten zutun hat. Kommt auf die Linearität an. > etliche If-Schleifen Es gibt keine "If-Schleifen". Nein, für 70 Vergleiche braucht man keinen Assembler.
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.
:
Bearbeitet durch User
Moin, Man braucht auch nichtmal 70 Vergleiche. log(70)/log(2) = 6.firlefanz. Also reichen pro Messung 7 Vergleiche. Gruss WK
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...
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.
wieso sollen +10dB 3.16V sein? Dachte das wären 2,449V! Siehe http://www.sengpielaudio.com/dB-Tabelle.htm Ok, ich werds mit ner Tabelle versuchen, Pointer auf diese..
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!
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).
:
Bearbeitet durch User
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! mt
Wolfram F. schrieb: > 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! sinnlos ist hier nur das gequake. für blinde und talentfreie war dieses forum nie gedacht! mt
Wolfram F. schrieb: > ich möchte gerne ein VU-Meter als korrektes Messgerät bauen. Aber natürlich. Nur Effektivwerte lassen sich nicht so leicht korrekt messen. mfg Klaus
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.
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]
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?
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
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
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));
Dergute W. schrieb: > 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 Sorry, ich komme nicht darauf, wie ich das Array richtig füllen kann, zeigst Du mir bitte, wie?
Wolfram F. schrieb: > so in etwa ist es jetzt auch, aber ich bezweifel, daß die Ergebnisse > des MAP Befehls so exakt sind wie die LUT-Methode! Das ist keine Meinungsfrage. Es geht um linear oder nicht. leo
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.
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.
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!
Karl K. schrieb: >> float log10MaxDisplaySegments = log10(maxSegments); > > Oh bitte, beschäftige Dich mal mit den Grundlagen der µC-Programmierung. :-) ich weiss, dieser Code stammt nicht von mir sonder aus dem o.g. Link...
Wolfram F. schrieb: > oder 70 Bytes Words, da Du dann natürlich den Wertebereich des AD-Wandlers abbilden musst.
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.
Wolfram F. schrieb: > kann man die nicht noch vereinfachen? Man muss die Tabelle nicht eintippen, man kann sie am Programmanfang ausrechnen lassen.
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.
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.
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]); } // -----------------------------------
:
Bearbeitet durch User
Mir fällt jetzt erst auf, das -40db bis +10db Dynamik gewünscht wird. Das wird mit dem 10 bit ADC nicht gehen. Wahrscheinlich werden es mehr so -30db bis +5db werden.
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
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]); > } > // -----------------------------------
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 ?
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
Hier bitteschön: https://github.com/m5stack/M5Stack/blob/master/examples/Fire/M5StackFire_NeoPixelVUmeter/M5StackFire_NeoPixelVUmeter.ino Den Logarithmus kann man sich sparen, weil die Tresholds über die Exponentialfunktione ( btw. Schrittweise Multiplikation ) berechnet werden können.
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...
:
Bearbeitet durch User
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
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.
>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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.