Waveshare Pico-Audio mit Pico

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Ich möchte für ein Projekt verschiedene Rauscharten über den Raspberry Pi Pico erzeugen und anschließend über Lautsprecher ausgeben.

    Habe einen Pico von 2020 und ein Erweiterungsmodul von Waveshare, den Pico-Audio Rev. 2.1. Waveshare - Pico-Audio

    Der Pico und das Modul sind bereits miteinander verbunden und bin soweit es mir möglich war der Anleitung auf dem Wiki von Waveshare -> Link gefolgt.

    Ich bin ein totaler Anfänger was Python, MicroPython und Raspberry Pi angeht, daher verwirren mich viele Beschreibungen sehr.

    Bis auf das Wiki finde ich auch keine einzige Anleitung oder Erklärung zu der Nutzung des Pico-Audio und mittlerweile bin ich sehr frustriert.


    Laut dem Wiki muss man sich eine zip Datei herunterladen, link ist da auch auf der Seite. Wenn ich diese entpacke habe ich einen Ordner mit drei Unterordnern, in jedem befindet sich eine .uf2 Datei. Ab hier bin ich relativ ratlos was ich genau machen muss. :conf:

    Wenn ich die rp2-pico-20220618-v1.19.1.uf2 aus dem Python Ordner auf den Pico flashe funktioniert alles normal über thonny und ich kann das Audio_V2_PIO.py abspielen, was mir einen Ton erzeugt.
    Den Code in dem Programm kann ich halt überhaupt nicht nachvollziehen, daher weiß ich nicht wie ich jetzt irgend etwas anderes abspielen kann außer diesen Ton. Außerdem wird im Wiki erwähnt, dass man die anderen .uf2 Dateien auf den Pico kopieren soll. Ich weiß aber nicht wo hin und wenn ich nur eine der anderen drauf flashe, dann kann ich gar nichts mehr Programmieren.

    Ziel wäre es über die Lautsprecher eine kurze .wav Datei abzuspielen. ich stecke aber gerade in meiner Unwissenheit fest. :helpnew:

    Vielleicht weiß einer von euch wie ich weiter komme.

  • T_V_N_A Die *.uf2-Dateien sind Firmware-Dateien. Da kann immer nur eine von installiert werden. Die drei Varianten in dem Archiv sind für a) MicroPython, b) C/C++, und c) eine Firmware die den Pico für den Rechner wie eine USB-Soundkarte aussehen lässt.

    Falls Du in MicroPython programmieren möchtest, wäre also die MicroPython-Firmware die richtige für Dich. Wobei ich sehr stark vermute, das man auch einfach das aktuelle offizielle MicroPython und sehr wahrscheinlich auch CircuitPython installieren kann um die *.py-Datei in dem Ordner ausführen zu können.

    Um zu verstehen was in dem Code passiert, wird es schlicht keine Erklärung geben im Sinne von hier ist *ein* Text der das *alles* erklärt. Da wird MicroPython benutzt, das ist halbwegs gut dokumentiert. Auf einem Pico, der ist gut dokumentiert. Das Programm benutzt PIO, also eine Art spezialisierter Maschinensprache um Pins schnell und präzise anzusteuern. So ein kleines PIO-Programm ist in der Python-Datei und das sorgt dafür, das die Daten an den Pins für den Audio-Chip im richtigen Takt anliegen. Auf der Wikiseite direkt ist ein Zeitdiagramm der Kommunikation und wie's aussieht, gibt es eine Leitung die wählt ob die Daten gerade für den rechten oder den linken Kanal sind, eine Clock Leitung, die die einzelnen Bits abgrenzt, und eine Datenleitung wo die Werte für die einzelnen Bits anliegen müssen.

    Die Audiodaten in `sine_wave_table` sehen nach 16-Bit, unsigned aus, und die werden vor dem Abspielen in signed umgewandelt und jedes Sample wird zweimal in einen 32-Bit-Wert gesteckt, der dann an das PIO-Programm übergeben wird. Zweimal das gleiche Sample weil die Ausgabe Stereo ist und das Beispiel nur ein Mono-Signal darstellt. Wenn man links und rechts unterschiedliche Daten abspielen möchte, wäre das die Stelle wo man zwei unterschiedliche Samples zu einem 32-Bit-Wert zusammen packen muss.

    Das ist auch eine Stelle an der Du ein wenig experimentieren kannst ob Du verstanden hast was da passiert. Du könntest Beispielsweise überlegen was Du am Beispiel ändern müsstest, damit nur links oder nur rechts der Ton ausgegeben wird und diese Vermutung dann mal überprüfen. Oder wie man den Code ändern müsste damit auf einer Seite der Ton halb so laut ist. Oder wie man es wohl hinbekommt das der Ton zwischen beiden Seiten hin und her wandert.

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • __blackjack__
    Das Hilft mir schonmal weiter indem ich das Sinussignal besser interpretieren kann. Die 16 Bit erkennst du an den 16*16 Werten in der sine_wave_table nehme ich an?
    Habe tatsächlich noch nie mit dem Hexadezimalsystem gearbeitet, aber durch deinen Hinweis konnte ich zumindest durch plotten erkennen wo der erzeugte Sinus hergenommen wird.

    Die Frequenz konnte ich auch schon ändern zumindest in einem bestimmten Bereich. Ab 230 Hz knistert es aus den Lautsprechern, selbst über Kopfhörer kommt da dann nichts mehr raus.

    Rechter und Linker Kanal hab ich noch nicht herausgefunden. Aber jetzt weiß ich zumindest nach was man suchen kann. Vielen Dank dafür schonmal!

    @DeaD_EyE danke für den Link! Es ist als Amateur nicht so einfach etwas zu finden wenn man nicht einmal weiß was man sucht :lol:

  • Die 16 Bit habe ich am Wertebereich erkannt. Eine Hexadezimalziffer beschreibt 4 Bits und wir haben da jeweils 4 Ziffern pro Wert, und der Höchstwert 0xFFFF wird auch fast erreicht:

    Python
    In [169]: max(sine_wave_table)
    Out[169]: 65534
    
    In [170]: hex(max(sine_wave_table))
    Out[170]: '0xfffe'
    
    In [171]: max(sine_wave_table).bit_length()
    Out[171]: 16

    Wie hast Du die Frequenz denn geändert? Das macht man eher nicht über die Abspielfrequenz, sondern über die Daten.

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • Ah alles klar, das ist auf jeden fall mal gut zu wissen, mit den 4 Bit pro Ziffer, danke!

    Ich hab es beim ersten mal tatsächlich über die Abspielfrequenz geändert, bin mir nicht sicher warum in Zeile 70 die Abtastfrequenz mal 128 genommen wird.
    Habe im Internet einen Generator gefunden der mit einen Sinus in Hexadezimal ausgibt. -> Link

    Je weniger werte ich nehme desto höher ist der Ton. Macht für mich auch Sinn, da die Frequenz ja mit 1/s definiert ist und immer eine Schwingung mit den Werten gebildet wird. Ich bin mir aber noch nicht sicher welcher Zeitbereich gilt, was ich ja für die Frequenzbestimmung benötige.

    habe mich auch mal daran versucht selber einen Code zu schreiben für einen Sinus.

    Damit kann ich jetzt die werte für die Frequenz genau bestimmen. Scheint auch zu funktionieren.

    Wenn ich es jetzt noch wüsste wie ich eine .wav Datei im Pico auslesen kann wäre ich schonmal einen großen Schritt weiter am Endziel.

  • Hallo,

    Ich bin mir aber noch nicht sicher welcher Zeitbereich gilt, was ich ja für die Frequenzbestimmung benötige.

    wie meinst du das mit dem Zeitbereich? Ich verstehe nicht was dir unklar ist.

    Ich habe deinem Code mal ein paar Namen verpasst, damit man deutlicher sieht, was da berechnet wird:

    Ich hoffe ich habe das richtig interpretiert?


    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • T_V_N_A Die Daten werden seriell übertragen, also Bit für Bit müssen die 32 Bits für die beiden Samples für Stereo übertragen werden, und das muss natürlich schneller laufen als die Abtastrate. Darum wird die Frequenz mit der das PIO-Programm zum übertragen läuft, mit einem Wert multipliziert, der zu der Zeit passt, die diese Übertragung dauert. In der MicroPython-Dokumentation ist ein PIO-Beispiel um eine LED mit 1 kHz blinken zu lassen — das PIO-Programm dafür läuft mit 2 kHz und da hat der Programmierer dann Taktzyklen der Befehle gezählt und Verzögerungen eingebaut, damit das hin kommt. Taktzyklen zählen – das ist so schön Retro. ?

    Zum WAV-Datei auslesen gibt es ja eigentlich ein Modul in der Python-Standardbibliothek Das gibt es aber (noch) nicht in der (einzeln, Modul für Modul) nach-installierbaren micropython-lib:

    This is a dummy implementation of a module for MicroPython standard library. It contains zero or very little functionality, and primarily intended to avoid import errors (using idea that even if an application imports a module, it may be not using it onevery code path, so may work at least partially). It is expected that more complete implementation of the module will be provided later. Please help with the development if you are interested in this module.

    Bleibt also tatsächlich dieses Modul zumindest teilweise zu implementieren — da würden sich sicher auch andere drüber freuen. Oder sich was eigenes, anderes überlegen.

    Da das Programm ja wahrscheinlich einen festen Satz an Audiodaten haben wird, der nicht dynamisch auf das Gerät kommt, könnte man einfach rohe Sampledaten verwenden, von denen man weiss wie die aussehen. Also im Grunde wie jetzt, nur dass die aus einer Datei kommen statt im Quelltext zu stehen. Den Schritt von unsigned nach signed und Mono nach Stereo könnte man dann auch schon beim erstellen der Dateien machen, und muss das dann nicht mehr auf dem Pico umrechnen.

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • Es gibt numpy (ulab) für micropython:

    Das ist nur ein Beispiel mit einem Kanal.

    Bei zwei Kanälen kann man den Buffer einmal kopieren und ggf. die Form ändern.

    Code
    stereo = np.array([sinus_440, sinus_440])
    print(stereo.shape)

    Das Problem an der Sache ist, dass du dann Micropython selbst mit ulab kompilieren musst.

    Den Buffer kannst du dann z.B. wiederholt via I2S an den Lautsprecher senden.

    Eine FFT kann man damit auch machen.

  • Dennis89 Bei dem Generator den ich im Internet gefunden habe ->Link, wird eine Sinusschwingung erzeugt, egal ob ich bei Number of points einen hohen oder einen niedrigen Wert auswähle.
    Um eine Frequenz zu bestimmen benötige ich soweit ich das beurteilen kann eine Angabe im Zeitbereich, das heißt in welcher zeit wird die Schwingung vollzogen, die sogenannte Periodendauer T.
    Mit der Formen Frequenz = 1/Periodendauer also f = 1/T kann ich dann darauf schließen welchen Ton ich abspiele.
    Dieser Zeitbereich ist aber wie gesagt bei dem Generator nicht da, also ist es für mich umständlicher gewesen einen bestimmten Ton zu erzeugen. Daher auch mein eigener Code.

    War jetzt aber auch eher zum Verständnis für mich selbst gedacht um mal was anderes rauszubekommen als den Standardton aus dem Test File des Waveshare.

    Danke auf jeden fall für das umschreiben, ich hab die für mich bekannten Formelzeichen und Abkürzungen verwendet, so ist es aber allgemeiner Verständlich.

    __blackjack__ Die .wav Datei ist ein weißes Rauschen, bzw. am ende sollen auch mehrere Rauscharten über den Pico abgespielt werden können und zwar in einer Endlosschleife. Was das Beispielprogramm ja auch eigentlich schon macht nur mit Tönen.
    Das mit den Sampledaten hatte ich, nachdem ich andere Töne rausbekommen habe, auch schon versucht.
    Ich bekomme auch ein Rauschen über die Lautsprecher bzw. über den AUX Anschluss raus, jedoch hört es sich an als wäre das Rauschen moduliert und schwankt in der Lautstärke.
    Ich weiß nicht was ich daran ändern könnte.

    Code
    import numpy as np
    
    volume = 0.5     # range [0.0, 1.0]
    sampling_rate = 44100.0     # sampling rate, Hz
    duration = 1   # in seconds
    
    # generate samples
    samples = np.random.normal(1,volume,int(fs*duration))

    Die Samples bringe ich dann genauso wie beim Sinuston mit *0x7FFF in Form und kopiere sie in thonny in die sine_wave_table.

    Das Rauschen hört sich dann aber nicht mehr gleichmäßig an. Vor dem *0x7FFFF hat es sich in Python wie ganz normales weißes Rauschen angehört.

    Das Prinzip müsste aber doch eigentlich das gleiche sein wie beim Sinus oder ?

    @DeaD_EyE ich hab das mit IS2 noch nicht so wirklich verstanden, habe damit auch noch nichts zum laufen gebracht. Das mit numpy ist aber auf jeden fall schonmal gold wert, weil ich das in micropython echt vermisse.

  • T_V_N_A Die Werte sind schon mal nicht im richtigen Wertebereich:

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!