EnRav - Box (TonUINO Remix)


#61

Kurze Frage: Welche VS1053 Library nutzt ihr?


#62

wobei unsere Versionen nicht mehr identisch sind. Aber Basis sollte Mikes GitHub sein. Meine Anpassungen kann er dann bei Bedarf übernehmen.


#63

Ich habe es noch einmal getestet. Bei mir nimmt er die FAT Reihenfolge. Im Zweifel also beliebig.
Schau gerne über das rüber was ich bisher dazu gemacht habe. Einlesen und sortieren klappt soweit. Ich bin aber blutiger Anfänger was Speicheroptimierung angeht. Das geht bestimmt besser oder schlanker.

Ich lade den Schnipsel morgen hier hoch.

EDIT:

/// Read all files in given directory, sort and save m3u to disk
void HELPER::CreatePlaylist(File dir) {
uint8_t mycounter=0;
char *tempPointer;
String MyTempString;

 
//Count files 
while(true) {
  File entry =  dir.openNextFile();
  if (entry && !(entry.isDirectory())) {
    mycounter++;
  } else {
    dir.rewindDirectory();
    break;
  }
} 
  
ESP_LOGD(TAG, "Found %d files in given directory.", mycounter);
    
char *pFileNames[mycounter];
  
  //store filenames to array
  for(uint8_t i = 0; i < mycounter; i++){
    File entry = dir.openNextFile();
    if (!(entry.isDirectory())) {
      MyTempString = entry.name();
      MyTempString = MyTempString.substring(MyTempString.lastIndexOf("/") + 1,MyTempString.length()); //Filename only to save mem
      pFileNames[i] = (char *)malloc(MyTempString.length()+1); // allocate mem 
      MyTempString.toCharArray(pFileNames[i],MyTempString.length()+1); // 
      //pFileNames[i] = strdup(MyTempString);
      entry.close();
      ESP_LOGV(TAG, "-> %s", pFileNames[i]);
    }
  }
  
  //Sort files  -> https://www.stm32duino.com/viewtopic.php?t=4149
  for (uint8_t mainLoop = 1; mainLoop < mycounter - 1; mainLoop++) {
    for (uint8_t innerLoop = 1; innerLoop < mycounter -1; innerLoop++) {
      if (strncmp(pFileNames[innerLoop], pFileNames[innerLoop + 1], 20) > 0) {
        tempPointer = pFileNames[innerLoop];
        pFileNames[innerLoop] = pFileNames[innerLoop + 1];
        pFileNames[innerLoop + 1] = tempPointer;
       }
    }
  }

  for(uint8_t i = 0; i < mycounter; i++){
      
      ESP_LOGV(TAG, " SORT -> %s", pFileNames[i]);
      // Write to disk
      // free pFileNames !!!
  }
  


}

Wie gesagt…ich mache da einige Verrenkungen um Speicher zu sparen. Ist das überhaupt wirksam, notwendig, sinnvoll ?


#64

Hi,

ich habe mir das mal angeschaut. Tolle Arbeit!

Ich habe mit dieser Hardware noch nicht mit Multi-threading gearbeitet. Geht das gut, dass der Kartenleser und ggf. weitere Hardware (Displays?), die per SPI angeklemmt wird, mit dem Mp3Player, der in einem eigenen Thread läuft? Mir ist da keine Semaphore o.Ä. aufgefallen…


#65

Das “fiese” beim ESP32 ist ja auch noch, dass er auch noch 2 Cores hat, also sogar 2 Threads tatsächich parallel arbeiten können.

Die sind im Arduino Framework von Espressif versteckt. Die Threads stören sich nicht, wenn sie auf den SPI Bus zugreifen wollen. Ein Problem gibt es nur dann, wenn mehrere Threads auf das gleiche SPI Device zugreifen. Das ist nicht abgesichert.

Wenn man alles zusammenfügt, wird man also mindestens für die SD Karte noch einen zusätzlichen Mutex spendieren müssen.


#66

So, bis auf die Ladebuchse ist das die erste Version des Gehäuses fertig:

Größe ist 12x12x12 cm, wenn es noch kleiner werden soll, braucht man definitiv eine selbst erstellte Platine.

Aber erstmal passt alles (Platinenstapel, 18650 Batterie Shield, Lautsprecher und Schalter) rein.


#67

Soweit ich das verstanden habe, nutzt der ESP32 defaultmäßig nur einen Core (Core 1). Du kannst ihn aber explizit dazu veranlassen, Core 0 für bestimmte Tasks zu verwenden.
Siehe hier -> https://randomnerdtutorials.com/esp32-dual-core-arduino-ide/ oder sehr schön erklärt hier: https://www.youtube.com/watch?v=k_D_Qu0cgu8

Wenn man Aufgaben, die klar voneinander getrennt sind, auf unterschiedlichen Cores implementiert, muss man sich auch keine großen Gedanken um Semaphore machen. Also alles was auf die SD-Karte oder die NFC-Karte schreibt, sollte sinnigerweise im selben Core ablaufen :slight_smile:


#68

Wenn man ein Programm “nur” mit der Arduino IDE schreibt, dann ist das der Fall ,da es dann ja auch nur einen Thread gibt. Sobald du aber auch selber Threads erzeugst sorgt der Scheduler dafür, dass beide Kerne benutzt werden.
Mit dem gezeigten Code kannst du nur zusätzlich dafür sorgen das ein Thread immer auf einem bestimmten Core ausgeführt wird.

So einfach ist das leider nicht. Denn auch auf einem Core können sich die Tasks gegenseitig unterbrechen. (Das ist ja gerade das Prinzip eines RTOS.)


#69

Hab hier mal mein Projekt vorgestellt:


#70

Ja, ich bin davon ausgegangen, dass die Arduino IDE verwendet wird - natürlich nicht sehr weitsichtig von mir, von seinen eigenen Gewohnheiten/Möglichkeiten auszugehen. :wink:


#71

Ich wollte damit eher sagen, so lange man das “originale” Arduino Framework benutzt :wink:
Da ist die Funktion xTaskCreate() ja nicht bekannt und von daher bleibt man dann auf einem Core :smiley:


#72

Der erste Prototyp ist fertig und wird ab sofort getestet ( auch wenn die Firmware noch eine Beta ist )


#73

Sauber.

Sag mal hast Du auch interessante Geräusche beim Betrieb?

  • Beim booten kommen allerhand Störgeräusche. Obwohl direkt nach dem begin ein SetVol 0 steht.
  • Manchmal habe ich beim Booten eine Rückkopplung mit dem eingebauten Mikrofon. Nur reset hilft.
  • Beim Stoppen eines Tracks geht die Lautstärke für geschätzte 200ms auf max. bevor der Track stoppt (auch hier ist der erste befehl eigentliche ein setvol 0).
  • Beim re-start des Tracks das selbe.
  • Manchmal hängt begin vom VS, nur reset hilft.

Kennst du irgendwas davon?


#74

Das Gehäuse sieht wirklich super aus! Ich stelle es mir gerade in lila vor und kenne hier jemanden, der vor Glück ausrasten wird. :wink:

Hast Du vor, die Gehäuse-Druckdaten zu veröffentlichen oder willst Du das Gehäuse nur zum Kauf anbieten?


#75

Werde ich noch veröffentlichen, ich muss nur noch warten bis meine USB Buchse mit Kabel ankommt. Sobald diese ihren Platz im Gehäuse gefunden hat kann man das auch nachdrucken :slight_smile:


#76

Perfekt! Da sag ich jetzt schon mal ein ganz herzliches Dankeschön :slight_smile:


#77

Welche USB-Buchse wirst Du denn verwenden?

Ich habe diese hier im Einsatz:

Vorteil ist, dass man die auch für Holzprojekte gut verwenden kann (einfach nur ein runder Bohrer und gut ist.

Die hier ein paar mal vorgeschlagene Variante mit einem Apter dieser Bauart, z.B. ->

finde ich nicht ganz so hübsch, da durch die Befestigung mit Schrauben immer ein relativ großer Überstand da ist. Vorteil ist natürlich, dass man damit vorhandene Micro-USB Kabel verwenden kann.

Aber im Endeffekt ist es egal, das kann man dann ja in den Druckdateien ändern. :slight_smile:


#78

Ich hab vor die USB Version zu nehmen

Ich dachte mir einfach, dass das Verkabeln einfacher ist und da die Box von mir eine “Wandstärke” von 1 cm hat sollte sich das auch ohne Überstand einbauen lassen.
Mein Plan war es, die Buchse vielleicht 5mm nach hinten Versetzt zu platzieren so dass dann auch noch ein wenig geschützt ist.

Vielleicht designe ich die Platte auch so, dass man sie von hinten einkleben kann. Dann wäre der Versatz noch geringer, dafür ist das tauschen schwieriger.


#79

Stimmt, daran hatte ich noch nicht gedacht. Eventuell kannst Du sie ja auch ganz versenken und an dieser Stelle die Rückwand um diese Stelle im inneren des Gehäuse dicker machen, damit die Befestigung noch genügend Halt hat. Ich habe mal versucht es aufzuzeichnen.


#80

Hatte ich ganz vergessen: Ich hatte einfach Bock drauf das selbst zu machen und habe es komplett mit String eingebaut, da das keine langlaufende Anwendung ist, mache ich mir da auch um Heapfragmentierung nicht so sehr einen Kopf… Ich hab jetzt nicht gemessen, wie der Speicherverbrauch ist. Aber da es ja immer nur für ein Verzeichnis ist, sollte das nicht signifikant sein. Ich habe den Aufruf für das Erzeugen der M3U direkt in die ConnectToSD eingebaut.
Und wie du schon schriebst muss man es selbst sortieren, ansonsten ist es die FAT Reihenfolge. Quicksort hat mal wieder Spaß gemacht :slight_smile:

Speicher-relevanter ist die Liste möglichen Tracks beim Zuordnen zu den Karten im WebIF. Da habe ich aktuell den ganzen Baum im Speicher, das wird nicht für immer gutgehen. Die HTML Seite musste ich sequenziell als tmp File zusammenbauen und mit Server.StreamFile hochladen, da sich Anzahl Karten mit Anzahl Optionen in der Dropdown Liste multiplizieren…

Viel Spaß hatte ich am Wochenende mit Sonderzeichen “enhanced” ASCII von der Karte vs UTF-8 vs HTML. Aber jetzt ist auch das generierte HTML W3C valide.

Vielleicht merkt man: Meine Hauptmotivation neben der Freude für die Kinder ist das “Projekt” selbst. Hab grad einen Riesenspaß dran.