Old Fidelity - HiFi Klassiker Forum

Normale Version: Digitales VU-Meter (Mikrocontroller, Display, LED) reVox A700
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.

DIYLAB

(21.06.2020, 11:27)gogosch schrieb: [ -> ]Das EVOR04 verwendet sogar 4 Images, je nachem welcher Over-Point aufleuchten soll, gleichzeitig und die völlig flackerfrei.  Dash1

Man müsste sich mit der ILI9341_t3n Lib ernsthaft beschäftigen und speziell mit DMA und FrameBuffer, aber unser Wasserschaden hat bei mir heute auch einen Dachschaden im Kopp hinterlassen - ich fühle mich derzeit völlig bekloppt Jester

Guck mal, was flackerfrei funktioniert (aus diesem Thread):


Selbstverständlich alles ohne Code, aus dem man lernen könnte!
Die Genies halten alles geheim, denn sie werden ganz sicher mal sehr berühmt und stinkreich Lol1

LG

gogosch

Ich glaube für echtes DMA haben wir das falsche Display. SPI ist ein serielles Protokoll. Und da liegt der Flaschenhals

DIYLAB

(21.06.2020, 12:51)gogosch schrieb: [ -> ]Ich glaube für echtes DMA haben wir das falsche Display. SPI ist ein serielles Protokoll. Und da liegt der Flaschenhals

Moin,

sehe ich nicht so eng, SPI ist schon sehr schnell und den Bus takte ich mit 40MHz.
Ich nehme nur noch die ILI9341_t3n Lib, die hat ein paar nette Funktionen, die uns das Leben erleichtern.
Nun funktioniert auch der Framebuffer und dank Clipping können Bereiche upgedatet werden.
Beides zusammen bewirkt flackerfreie Zeiger.
Code kommt morgen, ich muss noch etwas glattziehen.

LG

DIYLAB

Moin,

ok Leute, zum Teamwork gehört es manchmal dazu, sich zu outen  Undecided .
Mathe gehört nun mal zu diesem Projekt dazu und ich habe mit der 9. Klasse Trigonometrie so meine Probleme.

Ich habe dazu ein nicht maßstabsgetreues Bild gemalt und auch nur die linke Seite des analogen Displays.
Der Zeiger beginnt bei Koordinaten, die außerhalb des Displays liegen und das ist ja auch so richtig.
Die Skala wird durch den roten Kreis angedeutet.
Das orange Dreieck ergibt sich aus dem gezeichneten Zeiger (dick rot).
Alle Parameter des orangen Dreiecks sind dementsprechend bekannt.

Gesucht wird der Schnittpunkt, bei dem der Zeiger in das Display eintritt (grüner Pfeil).
Oder die Höhe 'h' (im Bild der dicke blaue Strich).
*Bei Winkeln wird in 'c' der Radiant statt Grad benutzt.

Ich habe versucht, mittels der Tangensgleichung die Höhe zu errechnen und bin scheinbar zu doof.
Wer ist denn hier mathematisch besser aufgestellt?

[Bild: qc4sTxU.png]

Liebe Grüße
Bruno

DIYLAB

Hmm ...
Im Prinzip ist das Bild im letzten Beitrag falsch  Denker .
Ich zeige es noch mal am lebenden Objekt ...

Ihr seht die linke Displayseite und wo der Zeiger ins Display eintritt.
Ich habe an Hand des bekannten Dreiecks im sichtbaren Bereich ein blaues Rechteck gezeichnet.
Das bekannte Dreieck befindet sich bei dieser Zeigerposition unterhalb des roten Zeigers!
Diese Höhe ist bekannt.

Gesucht wird der Schnittpunkt des Zeigers zum Display oder die Höhe, die mit 'h?' beschriftet ist.

Hilfeeeeee  Jester .

[Bild: jMhrEZG.png]

Liebe Grüße
Bruno

DIYLAB

Ich habe es nochmals deutlicher dargestellt:

[Bild: schnittpunkt.png]

Liebe Grüße
Bruno
Ich würde hier den Tangens verwenden. Über den Winkel kannst du dann die Höhe bestimmen. So kommst du auf den Schnittpunkt.

DIYLAB

(26.06.2020, 10:02)norman0 schrieb: [ -> ]Ich würde hier den Tangens verwenden. 

Ja, das hab ich versucht, nur bei der Umsetzung bin ich zu doof  Lipsrsealed2 .

Ich habe hier mal ein auf das wirklich notwendigste gekürztes Stück Code (damit man keinen Overhead hat), welches die Nadel und das blaue Rechteck (zum Test) zeichnet und den Sinus- und Cosinussatz verwendet, wie es auch schon Gogosch gemacht hat.
Kannst Du mir bitte ein bisschen behilflich sein beim Tangens?
Auch den Strahlensatz kann ich nicht umsetzen - hätte damals besser aufpassen sollen  Lipsrsealed2 .

Das Display ist vertikal ausgerichtet mit 240Px Breite und 320Px Höhe.
Der Startpunkt der Nadel liegt bei -115 und der Hälfte des Displays, also 160.

Code:
#define DEG2RAD 0.0174532925

void drawNeedle(uint8_t percent) {
        double scale = map(percent, 0, 100, 57, 123);
        double arc = scale * DEG2RAD;
        int16_t x1 = -115 + 193 * sin(arc);
        int16_t y1 = 160 + 193 * cos(arc);

        // blaues Rechteck zum Test
        tft.drawRect(0, min(160, y1), x1, max(160, y1) - min(160, y1), ILI9341_BLUE);

        // Nadel
        tft.drawLine(-115, 160, x1, y1, ILI9341_RED);
}

 LG
[Bild: C118-CD06-662-C-4-B01-87-ED-E216338653-E3.jpg]

[Bild: 1301717-B-8-BA7-44-E8-9-EFF-9-F719-B780-A18.jpg]

Vielleicht hilft ein Strahlensatz Wink3 gesucht: Strecke |BX|, bekannt: |ZA|, |ZA'|, |A'B'|.

Im Rechteck A-A'-B-X sind die senkrechten Strecken gleich lang: |A'B'| = |AB| + |BX|.
Das Verhältnis der Senkrechten ist gleich dem Verhältnis der Abschnitte auf einem Strahl:
|AB| : |A'B'| = |ZA| : |ZA'|

Nun die erste Gleichung nach dem gesuchten |BX| umstellen und die zweite nach |AB|,
letztere dann in die erste einsetzen.

DIYLAB

King1
Strahlensatz geht nicht, da sich der Punkt B' nicht auf einer Gerade bewegt, sondern auf einer Kreisbahn...

Wegen Tangens muss ich noch mal hirnen...
Ist eigentlich ganz einfach. Du brauchst nur die Strecke a und den Winkel

[Bild: 85f411f4bca38ab38637a2dfc262c480.jpg]

gogosch

Ähhm! Schaue erst jezt rein. Mit Tangens hab ich auch die Position der x-Koordnate errechnet. a= 115 px. x=Endkordinate der Zeigerspitze, apha=Winkel
somit müsste es sein: x-a*tan(alpha).

DIYLAB

(26.06.2020, 12:53)gogosch schrieb: [ -> ]Ähhm! Schaue erst jezt rein. Mit Tangens hab ich auch die Position der x-Koordnate errechnet.  a= 115 px. x=Endkordinate der Zeigerspitze, apha=Winkel
somit müsste es sein: x-a*tan(alpha).

Moin,

nanü?
Hatte in Deinem Code keinen Tangens gefunden und Du zeichnest links fest ab -115  Denker .

Liebe Grüße

gogosch

(26.06.2020, 15:57)DIYLAB schrieb: [ -> ]
(26.06.2020, 12:53)gogosch schrieb: [ -> ]Ähhm! Schaue erst jezt rein. Mit Tangens hab ich auch die Position der x-Koordnate errechnet.  a= 115 px. x=Endkordinate der Zeigerspitze, apha=Winkel
somit müsste es sein: x-a*tan(alpha).

Moin,

nanü?
Hatte in Deinem Code keinen Tangens gefunden und Du zeichnest links fest ab -115  Denker .

Liebe Grüße
Das war der Test, mit dem Zeichnen ab der y=0 bzw y=240 Achse um zu sehen ob es jetzt nicht mehr flackert. Siehe Posting #201. Hab es wieder rausgelöscht, da es nichts gebracht hat.

gogosch

Nimm das:
Code:
tft.drawLine(Rx + 115 * tanf((Rdeg + 90) * 0.0174532925f), 0, Rx, Ry, ILI9341_RED);
für den rechten Kanal!

gogosch

Hier der komplette Code:
Code:
void plotNeedle(int Lvalue, int Rvalue, byte ms_delay)
{
    tft.writeRect(0, 0, vu.width, vu.height, (uint16_t*)(vu.pixel_data));
   
    float Rdeg = map(Rvalue, 0, 220, 57, 123); // Netto 220px avaiable for display graph x axis
    int Rx =  160 + 193 * cosf(Rdeg * 0.0174532925f);
    int Ry = -115 + 193 * sinf(Rdeg * 0.0174532925f);
//    tft.drawLine(160, -115, Rx-1, Ry, ILI9341_RED);
//    tft.drawLine(160, -115, Rx,  Ry, ILI9341_MAGENTA);
//    tft.drawLine(160, -115, Rx+1, Ry, ILI9341_RED);

    tft.drawLine(Rx + 115 * tanf((Rdeg + 90) * 0.0174532925f), 0, Rx-1, Ry, ILI9341_RED);
    tft.drawLine(Rx + 115 * tanf((Rdeg + 90) * 0.0174532925f), 0, Rx,   Ry, ILI9341_MAGENTA);
    tft.drawLine(Rx + 115 * tanf((Rdeg + 90) * 0.0174532925f), 0, Rx+1, Ry, ILI9341_RED);

   
    float Ldeg = map(Lvalue, 0, 220, 303, 235); // Netto 220px avaiable for display graph x axis
    int Lx = 160 +      193 * cosf(Ldeg * 0.0174532925f);
    int Ly = 115 + 240 + 193 * sinf(Ldeg * 0.0174532925f);
//    tft.drawLine(160, 240 + 115, Lx-1, Ly, ILI9341_RED);
//    tft.drawLine(160, 240 + 115, Lx,  Ly, ILI9341_MAGENTA);
//    tft.drawLine(160, 240 + 115, Lx+1, Ly, ILI9341_RED);

    tft.drawLine(Lx - 115 * tanf((Ldeg - 90) * 0.0174532925f), 240, Lx-1, Ly, ILI9341_RED);
    tft.drawLine(Lx - 115 * tanf((Ldeg - 90) * 0.0174532925f), 240, Lx,   Ly, ILI9341_MAGENTA);
    tft.drawLine(Lx - 115 * tanf((Ldeg - 90) * 0.0174532925f), 240, Lx+1, Ly, ILI9341_RED);
   
    if (Rvalue > 174) tft.fillCircle(160, 22,7,ILI9341_RED);
    if (Lvalue > 174) tft.fillCircle(160,218,7,ILI9341_RED);
}
(26.06.2020, 12:53)gogosch schrieb: [ -> ]Ähhm! Schaue erst jezt rein. Mit Tangens hab ich auch die Position der x-Koordnate errechnet.  a= 115 px. x=Endkordinate der Zeigerspitze, apha=Winkel
somit müsste es sein: x-a*tan(alpha).

Super, dass es so einfach weiter geht. Thumbsup

- - -

Kleiner Styleguide: man sollte die Magic Numbers
Code:
tft.drawLine(Rx + 115 * tanf((Rdeg + 90) * 0.0174532925f), 0, Rx, Ry, ILI9341_RED);
projektweit (oder im Scope der Funktion) einheitlich als Makro  (-> sprechende Namen) etablieren.
Die Bibliothek des LCD-Panels macht es vor: ILI9341_RED

DIYLAB

Moin,

vielleicht können wir aus den jeweils gemachten Erfahrungen ein neues Paket schnüren ...
Hier zumindest mal mein Ansatz mit Framebuffer und Clipping zum Download.
Momentan ist der Zeiger nur 1px breit, da konnte ich besser das Clipping beobachten.

Funktionsweise:
  • So lange kein updateScreen() erfolgt, wird im Framebuffer gezeichnet.
  • Das Hintergrundbild ist aus zwei Halbbildern zusammengesetzt (bis zur Displaymitte), da muss der Controller nicht immer das ganze Bild refreshen.
  • Zuerst wird der Clippingbereich für den Hintergrund festgelegt und das Bild reingeladen.
  • Danach neuer Clippingbereich für die PeaK-LED und LED zeichnen, falls der Wert erreicht ist.
  • Dann neuer Clippingbereich für die Nadel, Nadel zeichnen.
Die Nadel wird nur im sichtbaren Bereich gezeichnet (yEdge).
Das Clippingrechteck der Nadel passt sich dem Bereich an und umschließt nur im sichtbaren Bereich die Nadel, so bleibt die Fläche klein, die upgedatet werden muss.

Hier sieht man zum Test die Rechtecke um die Nadeln, sie entsprechen dem Clippingbereich zum Update des Displays.

[Bild: 87f0T0r.jpg]

Die Nadel sieht im Video "nervös" aus, liegt aber an den Interferenzen des Displays. In "echt" läuft sie besser.
Jetzt müsste man den Code optimieren, aber ich werde mich erst mal mit den echten Audiodaten beschäftigen.



Download: RevoxA700.zip

LG

PS: die digitale Anzeige ist viel einfacher und deutlich schneller  Thumbsup .

(26.06.2020, 20:30)winix schrieb: [ -> ]man sollte die Magic Numbers projektweit (oder im Scope der Funktion) einheitlich als Makro  (-> sprechende Namen) etablieren.

Yepp, hab ich drin in der Version, die ich gerade veröffentlicht habe.

LG

DIYLAB

Ich konnte die Geschwindigkeit noch um ca. 25% steigern, in dem ich für den Hintergrund nicht die beiden 120x320px Bilder nehme, sondern nur die Skalen ausgeschnitten habe und an die richtige Stelle setze. Das sind auch zwei Bilder mit nun 96x224px.
Das reduziert das jedesmal nötige Update und daher steigen die FPS.
96 und 224 lassen sich auch glatt durch 8 teilen, damit kann der Controller besser rechnen.
Aber da geht noch mehr.
Nicht das wir das unbedingt brauchen, aber haben schadet auch nicht.
Die Beschriftung oben und unten Mitte erzeuge ich dann selbst.
Das spart auch Speicherplatz im Controller, wenn nicht immer ganze Bilder benutzt werden.

Aktuellen Code dann am Wochenende.

LG

DIYLAB

Moin,

hier der Download der neuesten Version: RevoxA700.zip

Geschwindigkeitssteigerung zu gestern knapp 300% Raucher  .
Der Zeiger ist nun so schnell, dass das Auge nicht folgen kann.
Aber (!), das sind natürlich nur Tests, wenn die 'richtigen' Audiodaten verarbeitet werden, dann sieht das normal aus.
Nur man hat dann halt viel Reserve für schnelle Wechsel.

Änderungen:
  • SPI Bus testweise auf 50MHz angehoben und über Nacht laufen lassen - stabil (kann jederzeit im Programm geändert werden, vorher 40Mhz).
  • Die beiden Bilder für links und rechts sind nicht mehr 120x320px, sondern 96x224px, spart Zeit beim Refresh.
  • Aus den Bilddateien 'PROGMEM' rausgenommen! Das bringt echt Schub. Bei PROGMEM nimmt er bei jdem Refresh die Bilder aus dem Programmspeicher (langsam) - ohne 'PPROGMEM' werden sie in den RAM geladen und dort vorgehalten (schnell).
  • '+DB-' und 'VU' werden nun direkt ins Display gezeichnet.
  • Auf dem Display werden unten Debug-Daten angezeigt, also die Millisekunden für den gesamten Loop rechts und links, das sind 400 Aufrufe der Paintmethoden, passiert in 247ms.
Die meiste Zeit ist die CPU damit beschäftigt, die beiden Bilder zu malen.
Das sind immerhin 24Bit Echtfarben, wäre nicht nötig!
Wenn es Hans-Volker schaffen würde, die Farben auf 16 zu reduzieren, ohne das das Aussehen leidet, dann gibt es in der Lib extra dafür eine Methode, diese 16 Farb-Bilder in Hyperspeed anzeigen zu lassen. Das wäre sozusagen der Megaturbo Thumbsup .

Viel Spaß beim Basteln und ein schönes Wochenende Drinks .
Hallo Bruno,
auf 16 Farben zu reduzieren geht bestimmt, aber ich muss schauen, welches Format dann geht. Bin mir nicht sicher, ob es mit png geht.
Um an dem Spaß teihaben zu können... wird denn nun außer dem Teensy 4.0 auch das AudioModul benötigt oder nicht? Vielleicht/Wahrscheinlich habe ich irgendwas übersehen aber das ist mir nicht ganz klar. 

schönes Wochenende
Andreas

DIYLAB

(27.06.2020, 09:42)akguzzi schrieb: [ -> ]Um an dem Spaß teihaben zu können... wird denn nun außer dem Teensy 4.0 auch das AudioModul benötigt oder nicht? Vielleicht/Wahrscheinlich habe ich irgendwas übersehen aber das ist mir nicht ganz klar.

Moin Andreas,

auf dem Shield sitzt ein Chip drauf, der einfach nur genial ist.
Man könnte das Projekt auch ohne das Audioshield durchziehen und die AD-Wandler nehmen, aber ich zumindest mache das ganz sicher nicht, weil das absoluter Quatsch wäre. Da hätte man dann auch gleich einen ESP32 Controller nehmen können.
Also Audioshield JA (egal ob Teensy 4.0 oder 4.1 - passen beide drauf).

LG
Danke, Bruno!
Ich hab hier eine "einäugige" A77 stehen... da werde ich mir gar keine Mühe geben ein zweites VU-Meter zu bekommen sondern das eine vorhandene dann an einen Leidenden abgeben  LOL

schönes Wochenende
Andreas