Besoin de conseils : Boite à histoires / musiques

Besoin de conseils : Boite à histoires / musiques - Nano-ordinateur, microcontrôleurs, FPGA - Electronique, domotique, DIY

Marsh Posté le 15-09-2023 à 09:09:33    

Bonjour,
 
J'ai pour projet de faire une boite à histoires type Lunii.
Mon projet comprendra :
 
une batterie
un écran tactile
un ou deux HPs (à voir)
une carte SD
un bouton ON/OFF physique
un bouton volume
(en tactile)
 
Fonctions :
 
Lire des fichiers MP3 soit simplement comme une musique, soit avec des choix interactifs (par exemple choisir un personnage, un lieu etc) [ cette seconde partie est optionnelle pour l'instant]
Afficher un menu stop/play
Afficher un menu de sélection (probablement pour commencer, sous la forme de deux boutons précédent/suivant + un bouton "Home" ) sur l'écran tactile
Avoir un menu paramètre pour désactiver si besoin certaines fonctionnalités si présentes sur la carte (comme le wifi/BT)
pouvoir éteindre l'appareil
pouvoir régler le volume.
La taille : ça sera un peu plus grand/large que la boite à histoire de lunii j'imagine l'écran devant faire dans les 3/5 pouces idéalement (par ex 4.3).
Concernant le boitier, j'ai un ami qui dispose d'un laser de découpe donc ça sera sur du bois.
 
 
Ce que je recherche sur ce forum ce sont des conseils de matériels à choisir pour réaliser ce projet et surtout qui fonctionnent. Je pense qu'en tant que connaisseurs ou habitués, ça sera plus rapide de vous demander.
 
Merci d'avance !
 
EDIT :
 
Suite à pas mal de recherches on m'a conseillé de passer sur de l'ESP32. En cherchant un peu quoi acheter, je me suis perdu dans ces recherches.
 
Donc j'ai surtout besoin de conseils sur la liste du matos afin que ça puisse fonctionner ensemble. Le code je vais gérer.
 
 
 
J'ai repéré quelques trucs :
- ESP32-WT32-SC01 PLUS (https://fr.aliexpress.com/item/1005004267336768.html) -> à voir si je peux y mettre un HP et une batterie (si oui lesquels)
- ESP32-S3-LCD-EV-Board-2 (introuvable)
- ESP32-S3 HMI (IPS 4.3) (https://fr.aliexpress.com/item/1005005633096413.html) -> à voir si je peux y mettre un HP et une batterie (si oui lesquels)
- monter avec un ensemble de pièces (c'est là que je bloque aussi, je ne sais pas trop quoi acheter), mais à base d'ESP-S3 je  pense
 
Merci !


Message édité par headquaker le 15-09-2023 à 14:32:19

---------------
Helldivers 2, une petite composition : https://www.youtube.com/watch?v=JGW [...] nnel=HeadQ - Soundcloud : https://soundcloud.com/headquaker/tracks
Reply

Marsh Posté le 15-09-2023 à 09:09:33   

Reply

Marsh Posté le 15-09-2023 à 14:23:54    

Tu pars de loin visiblement... Tu as un peu d'expérience/des connaissances en électronique? Un fer à souder (même si tu prend des modules faudra peut-être rajouter un câble ou ...), un multi même basique?
 
Plusieurs points en vrac:
 
-Déjà merci de nettoyer les liens Ali, TOUT ce qui vient après le point d'interrogation c'est du tracking.
 
-Les boutons tactiles sont plus complexes car il faut un contrôleur ou un CI dédié qui gère ça tout en limitant la consommation de courant.
 
-Justement parlant d'énergie, un conseil, ne prend pas de batteries Li* chez Ali. Perso je suis pas convaincu de la qualiteuh et c'est pas sans danger ces bestioles... Aussi il faudrait faire au moins un calcul rapide pour voir ce que ça donne avec le ESP, il a des modes "sleep" ou similaire? Et un écran, enfin surtout l'éclairage, ça bouffe...
 
-Pour du MP3 depuis carte SD faut de la puissance de calcul, donc ESP obligatoire et à voir si c'est suffisant / si on trouve des lib (tu veux partir sur du code Arduino je suppose?). Un proc' 8 bits genre les Arduino "classiques" ne va pas le faire.

Reply

Marsh Posté le 15-09-2023 à 14:35:48    

je sais qu'arduino ne serait pas suffisant.
En électronique, un peu, j'ai du matos et un ami qui maitrise bien aussi les soudures.
 
Ca ne me dérange pas de partir sur du bouton physique.
Je voulais même prendre un écran type E-paper comme les liseuses.
Pour l'énergie, je ne sais pas encore où je vais acheter. S'il existe des bonnes marques de batterie, je prends. Je veux une belle autonomie comme l'actuelle Lunii que nous avons. (donc plusieurs jours)


Message édité par headquaker le 15-09-2023 à 14:38:37

---------------
Helldivers 2, une petite composition : https://www.youtube.com/watch?v=JGW [...] nnel=HeadQ - Soundcloud : https://soundcloud.com/headquaker/tracks
Reply

Marsh Posté le 16-09-2023 à 12:26:22    

J'ai pris un kit ESP32 S3 pour déjà voir si mon concept tient la route. avec un petit écran et pour m'entrainer aussi.


---------------
Helldivers 2, une petite composition : https://www.youtube.com/watch?v=JGW [...] nnel=HeadQ - Soundcloud : https://soundcloud.com/headquaker/tracks
Reply

Marsh Posté le 23-09-2023 à 22:55:22    

mon concept marche bien pour l'instant.
Pause/Play : OK
Volume Down/UP : OK
Titre précédent / suivant : OK
Désactivation du Wifi & BT : OK
 
Petite vidéo :
https://www.youtube.com/shorts/AbkSwMBzGEQ
 
Prochaine étape : gestion des albums.
 
Ensuite : portage du concept sur un ESP32-S3 IHM avec écran tactile.
A prévoir en plus :
- Gestion des images sur les albums
- Menu settings protégé par mot de passe
- Gestion de la batterie
- Gestion de la luminosité de l'écran
- Le design de l'interface (basique car pour enfant)
- Le boitier + protection de l'écran


Message édité par headquaker le 24-09-2023 à 01:02:58

---------------
Helldivers 2, une petite composition : https://www.youtube.com/watch?v=JGW [...] nnel=HeadQ - Soundcloud : https://soundcloud.com/headquaker/tracks
Reply

Marsh Posté le 02-10-2023 à 13:39:04    

J'ai besoin d'aide sur le code, ne maitrisant pas du coup cpp.
 
Je suis capable de lire un fichier MP3, et j'ai déjà beaucoup de code qui fonctionne bien pour effectuer des opérations telles que suivant, pause, etc.
 
Le problème est que ce code fonctionnait avec une structure SD où tous les fichiers MP3 se trouvaient à la racine.
 
Ce que je souhaite, c'est être en mesure de passer d'un dossier à un autre et de lire des fichiers MP3 à l'intérieur de ces dossiers.
 
Pourriez-vous m'aider ?
 
Je suis au courant de connecttoSD et connecttoFS, mais je n'arrive pas à les faire fonctionner avec FS, et je ne veux pas utiliser de chemins statiques comme ici.

Code :
  1. String filePath = "/m/RandomFolder1/" + filename;
  2.   audio.connecttoSD(filePath.c_str());


SD Card structure

Code :
  1. root
  2. root/h
  3. root/m
  4.  root/m/RandomFolder1
  5.   root/m/RandomFolder1-1.mp3
  6.   root/m/RandomFolder1-2.mp3
  7.   root/m/RandomFolder1-3.mp3
  8.   ...
  9.  root/m/RandomFolder2
  10.   root/m/RandomFolder2-1.mp3
  11.   root/m/RandomFolder2-2.mp3
  12.   root/m/RandomFolder2-3.mp3
  13.   ...
  14.  root/m/RandomFolderX
  15.   root/m/RandomFolderX-1.mp3
  16.   root/m/RandomFolderX-2.mp3
  17.   root/m/RandomFolderX-3.mp3
  18.   ...


 

Code :
  1. #include "Arduino.h"
  2. #include "Audio.h"
  3. #include "FS.h"
  4. #include "SPI.h"
  5. #include "SD.h"
  6. #include <Wire.h>
  7. #include <vector>
  8. #define TFT_BL 2
  9. #define SD_SCK 12 // CLK
  10. #define SD_MISO 13 // D0
  11. #define SD_MOSI 11 // CMD
  12. #define SD_CS 10 // CLK
  13. #define I2S_DOUT 17
  14. #define I2S_BCLK 0
  15. #define I2S_LRC 18
  16. const unsigned long VOL_CHANGE_DELAY = 500; // Delay between volume changes
  17. const unsigned long DISPLAY_VOLUME_DURATION = 3000; // Display volume for 3 seconds
  18. struct Music_info
  19. {
  20.   String name;
  21.   int length;
  22.   int runtime;
  23.   int volume;
  24.   int status;
  25.   int mute_volume;
  26. } music_info = {"", 0, 0, 0, 0, 0};
  27. Audio audio;
  28. File musical;
  29. std::vector<String> mp3Files;
  30. int currentSongIndex = -1;
  31. bool isPlaying = false;
  32. void setup()
  33. {
  34.   Serial.begin(115200);
  35.   pin_init();
  36.   sd_init();
  37.   musical = SD.open("/m" );
  38.   if (!musical || !musical.isDirectory())
  39.   {
  40.     Serial.println("Failed to open /M directory" );
  41.     return;
  42.   }
  43.   // Load the list of MP3 files in the first album (subdirectory) under /M/
  44.   loadMP3Files();
  45.   // Check if there are MP3 files in the album
  46.   if (mp3Files.size() > 0)
  47.   {
  48.     // Start playing the first MP3 file
  49.     currentSongIndex = 0;
  50.       audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  51.   audio.setVolume(15); // Adjust the initial volume as needed
  52.     playMP3File(mp3Files[currentSongIndex]);
  53.   }
  54.   else
  55.   {
  56.     Serial.println("No MP3 files found in the first album" );
  57.   }
  58. }
  59. void loop()
  60. {
  61.   //handleAudio();
  62.   // Your other main loop code can go here
  63.   audio.loop();
  64. }
  65. //---- Device init --------------------------------------------------
  66. void pin_init()
  67. {
  68.   pinMode(TFT_BL, OUTPUT);
  69.   digitalWrite(TFT_BL, HIGH);
  70. }
  71. void sd_init()
  72. {
  73.   pinMode(SD_CS, OUTPUT);
  74.   digitalWrite(SD_CS, HIGH);
  75.   SPI.begin(SD_SCK, SD_MISO, SD_MOSI);
  76.   SPI.setFrequency(400000);
  77.   if (!SD.begin(SD_CS, SPI))
  78.   {
  79.     Serial.println("Card Mount Failed" );
  80.     while (1)
  81.       ;
  82.   }
  83.   else
  84.   {
  85.     Serial.println("SD OK" );
  86.   }
  87. }
  88. void loadMP3Files()
  89. {
  90.   mp3Files.clear();
  91.   File entry;
  92.   // Open the first album (subdirectory) in /M/
  93.   File album = musical.openNextFile();
  94.   if (!album || !album.isDirectory())
  95.   {
  96.     Serial.println("No albums found in /M directory" );
  97.     return;
  98.   }
  99.   // Load the list of MP3 files in the first album
  100.   while (File entry = album.openNextFile())
  101.   {
  102.     if (!entry.isDirectory() && String(entry.name()).endsWith(".mp3" ))
  103.     {
  104.       mp3Files.push_back(String(entry.name()));
  105.     }
  106.   }
  107.   album.rewindDirectory();
  108. }
  109. void playMP3File(const String &filename)
  110. {
  111.   Serial.println("Playing: " + filename);
  112.   //Serial.println("Folder: " + SD.name());
  113.   // Extract the name of the MP3 file without the extension
  114.   int dotIndex = filename.lastIndexOf("." );
  115.   if (dotIndex != -1)
  116.   {
  117.     String nameWithoutExtension = filename.substring(0, dotIndex);
  118.     // Assuming 'music_info' is a struct or object with a 'name' member variable
  119.     music_info.name = nameWithoutExtension;
  120.   String filePath = "/m/RandomFolder1/" + filename;
  121.   audio.connecttoSD(filePath.c_str());
  122.     isPlaying = true;
  123.   }
  124.   else
  125.   {
  126.     Serial.println("Invalid filename" );
  127.   }
  128. }
  129. void handleAudio()
  130. {
  131.   if (isPlaying)
  132.   {
  133.     if (!audio.isRunning())
  134.     {
  135.       // Audio playback has finished
  136.       Serial.println("Playback finished" );
  137.       isPlaying = false;
  138.       // Add logic here to advance to the next MP3 file or perform other actions
  139.       // For example, you can increment currentSongIndex and call playMP3File again
  140.       if (currentSongIndex < mp3Files.size() - 1)
  141.       {
  142.         currentSongIndex++;
  143.         playMP3File(mp3Files[currentSongIndex]);
  144.       }
  145.       else
  146.       {
  147.         Serial.println("No more MP3 files to play" );
  148.       }
  149.     }
  150.   }
  151. }


---------------
Helldivers 2, une petite composition : https://www.youtube.com/watch?v=JGW [...] nnel=HeadQ - Soundcloud : https://soundcloud.com/headquaker/tracks
Reply

Marsh Posté le 08-10-2023 à 11:27:24    

Bonjour j'ai un code qui marche, je sais qu'il y a pleins de conneries, faut que je l'optimise maintenant
 

Code :
  1. #include "Arduino.h"
  2. #include "Audio.h"
  3. #include "FS.h"
  4. #include "SPI.h"
  5. #include "SD.h"
  6. #include <Wire.h>
  7. #include <vector>
  8. #include <lvgl.h>
  9. #include <ui.h>
  10. #include <Arduino_GFX_Library.h>
  11. #define TFT_BL 2
  12. #define SD_SCK 12 // CLK
  13. #define SD_MISO 13 // D0
  14. #define SD_MOSI 11 // CMD
  15. #define SD_CS 10 // CLK
  16. #define I2S_DOUT 17
  17. #define I2S_BCLK 0
  18. #define I2S_LRC 18
  19. #define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin
  20. #if defined(DISPLAY_DEV_KIT)
  21. Arduino_GFX *gfx = create_default_Arduino_GFX();
  22. #else /* !defined(DISPLAY_DEV_KIT) */
  23. Arduino_ESP32RGBPanel *bus = new Arduino_ESP32RGBPanel(
  24.     GFX_NOT_DEFINED /* CS */, GFX_NOT_DEFINED /* SCK */, GFX_NOT_DEFINED /* SDA */,
  25.     40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 42 /* PCLK */,
  26.     45 /* R0 */, 48 /* R1 */, 47 /* R2 */, 21 /* R3 */, 14 /* R4 */,
  27.     5 /* G0 */, 6 /* G1 */, 7 /* G2 */, 15 /* G3 */, 16 /* G4 */, 4 /* G5 */,
  28.     8 /* B0 */, 3 /* B1 */, 46 /* B2 */, 9 /* B3 */, 1 /* B4 */
  29. );
  30. // option 1:
  31. // ST7262 IPS LCD 800x480
  32. Arduino_RPi_DPI_RGBPanel *gfx = new Arduino_RPi_DPI_RGBPanel(
  33.     bus,
  34.     800 /* width */, 0 /* hsync_polarity */, 8 /* hsync_front_porch */, 4 /* hsync_pulse_width */, 8 /* hsync_back_porch */,
  35.     480 /* height */, 0 /* vsync_polarity */, 8 /* vsync_front_porch */, 4 /* vsync_pulse_width */, 8 /* vsync_back_porch */,
  36.     1 /* pclk_active_neg */, 12000000 /* prefer_speed */, true /* auto_flush */);
  37. #endif /* !defined(DISPLAY_DEV_KIT) */
  38. /*******************************************************************************
  39. * End of Arduino_GFX setting
  40. ******************************************************************************/
  41. /*******************************************************************************
  42. * Please config the touch panel in touch.h
  43. ******************************************************************************/
  44. #include "touch.h"
  45. Audio audio;
  46. File musical;
  47. std::vector<String> mp3Files;
  48. int currentSongIndex = -1;
  49. bool isPlaying = false;
  50. bool playbackFinished = false; // Flag to detect playback completion
  51. struct Music_info
  52. {
  53.     String name;
  54.     int length;
  55.     int runtime;
  56.     int volume;
  57.     int status;
  58.     int mute_volume;
  59. } music_info = {"", 0, 0, 0, 0, 0};
  60. // Structure for storing file information
  61. struct FileInfo
  62. {
  63.     String parentFolder;
  64.     String currentFolder;
  65.     String shortFileName;
  66.     String fullPath;
  67. };
  68. std::vector<FileInfo> fileInfoList; // Store file information
  69. // Structure for storing folder information
  70. struct FolderInfo
  71. {
  72.     String parentFolder;
  73.     String currentFolder;
  74.     std::vector<FileInfo> files;
  75. };
  76. std::vector<FolderInfo> folderInfoList; // Store folder information
  77. /* Change to your screen resolution */
  78. static uint32_t screenWidth;
  79. static uint32_t screenHeight;
  80. static lv_disp_draw_buf_t draw_buf;
  81. static lv_color_t *disp_draw_buf;
  82. static lv_disp_drv_t disp_drv;
  83. // Add a variable to keep track of the current folder
  84. String currentFolder = "/m"; // Start with the root folder
  85. void setup()
  86. {
  87.     // Hardware initialization
  88.     pin_init();
  89.     sd_init();
  90.     // Init Display
  91.     gfx->begin();
  92.     gfx->fillScreen(RED);
  93.     delay(500);
  94.     gfx->fillScreen(GREEN);
  95.     delay(500);
  96.     gfx->fillScreen(BLUE);
  97.     delay(500);
  98.     gfx->fillScreen(BLACK);
  99.     delay(500);
  100.     lv_init();
  101.     delay(10);
  102.     touch_init();
  103.     screenWidth = gfx->width();
  104.     screenHeight = gfx->height();
  105. #ifdef ESP32
  106.     disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 4, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
  107. #else
  108.     disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 4);
  109. #endif
  110.     if (!disp_draw_buf)
  111.     {
  112.         Serial.println("LVGL disp_draw_buf allocate failed!" );
  113.     }
  114.     else
  115.     {
  116.         lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * screenHeight / 4);
  117.         /* Initialize the display */
  118.         lv_disp_drv_init(&disp_drv);
  119.         /* Change the following line to your display resolution */
  120.         disp_drv.hor_res = screenWidth;
  121.         disp_drv.ver_res = screenHeight;
  122.         disp_drv.flush_cb = my_disp_flush;
  123.         disp_drv.draw_buf = &draw_buf;
  124.         lv_disp_drv_register(&disp_drv);
  125.         /* Initialize the (dummy) input device driver */
  126.         static lv_indev_drv_t indev_drv;
  127.         lv_indev_drv_init(&indev_drv);
  128.         indev_drv.type = LV_INDEV_TYPE_POINTER;
  129.         indev_drv.read_cb = my_touchpad_read;
  130.         lv_indev_drv_register(&indev_drv);
  131.         // Loading interface
  132.         ui_init();
  133.         lv_obj_add_event_cb(ui_btPrevious, playPreviousSong, LV_EVENT_PRESSED, NULL);
  134.         lv_obj_add_event_cb(ui_btPlay, playNextSong, LV_EVENT_PRESSED, NULL);
  135.         lv_obj_add_event_cb(ui_btPause, tooglePlayPause, LV_EVENT_PRESSED, NULL);       
  136.         lv_obj_add_event_cb(ui_btNext, playNextSong, LV_EVENT_PRESSED, NULL);
  137.         lv_obj_add_event_cb(ui_btStop, stopSong, LV_EVENT_PRESSED, NULL);
  138.         lv_obj_add_event_cb(ui_btHome, ui_event_btHome, LV_EVENT_PRESSED, NULL);
  139.         lv_obj_add_event_cb(ui_btUp, goToPreviousFolder, LV_EVENT_PRESSED, NULL);
  140.         lv_obj_add_event_cb(ui_btDown, goToNextFolder, LV_EVENT_PRESSED, NULL);
  141.         lv_obj_add_event_cb(ui_btHistory, ui_event_btHistory, LV_EVENT_PRESSED, NULL);
  142.         lv_obj_add_event_cb(ui_btMusical, setMusicalMode, LV_EVENT_PRESSED, NULL);
  143.         lv_obj_add_event_cb(ui_sliderVolume, changeVolume, LV_EVENT_VALUE_CHANGED, NULL);
  144.         // Setup MP3
  145.         audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  146.         audio.setVolume(7); // Adjust the initial volume as needed
  147.     // Set the root directory to "/m"
  148.     //setRootDirectory(currentFolder); // Set the root directory to the current folder
  149.     //printFolderInfoList();
  150.     // Add more debugging statements
  151.     //Serial.print("After setRootDirectory: " );
  152.     //Serial.println(fileInfoList.size());
  153.     // Play the first MP3 file if available
  154.     //playFirstMP3IfAvailable();
  155.     // Add a delay to ensure serial output is visible before the loop starts
  156.     //delay(1000); // You can adjust the delay time as needed
  157.     }
  158. }
  159. void loop()
  160. {
  161.     // Your other main loop code can go here
  162.     audio.loop();
  163.     lv_event_t lv_event;
  164.     checkAndPlayNextSong(&lv_event);
  165.     // Check if playback is finished
  166.     if (playbackFinished && isPlaying)
  167.     {
  168.         isPlaying = false;
  169.         playbackFinished = false; // Reset the flag
  170.     }
  171.     lv_timer_handler(); /* let the GUI do its work */
  172.     delay(2);
  173. }
  174. // Functions
  175. /* Display flushing */
  176. void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
  177. {
  178.     uint32_t w = (area->x2 - area->x1 + 1);
  179.     uint32_t h = (area->y2 - area->y1 + 1);
  180. #if (LV_COLOR_16_SWAP != 0)
  181.     gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
  182. #else
  183.     gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
  184. #endif
  185.     lv_disp_flush_ready(disp);
  186. }
  187. void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
  188. {
  189.     if (touch_has_signal())
  190.     {
  191.         if (touch_touched())
  192.         {
  193.             data->state = LV_INDEV_STATE_PR;
  194.             /*Set the coordinates*/
  195.             data->point.x = touch_last_x;
  196.             data->point.y = touch_last_y;
  197.         }
  198.         else if (touch_released())
  199.         {
  200.             data->state = LV_INDEV_STATE_REL;
  201.         }
  202.     }
  203.     else
  204.     {
  205.         data->state = LV_INDEV_STATE_REL;
  206.     }
  207. }
  208. // Function to play an MP3 file
  209. void setMusicalMode(lv_event_t *e)
  210. {
  211.     currentFolder = "/m"; // Set the current folder to /m
  212.     setRootDirectory(currentFolder); // Set the root directory to /m
  213.     playFirstMP3IfAvailable(); // Play the first MP3 file in the new folder if available
  214. }
  215. void playFirstMP3IfAvailable()
  216. {
  217.     if (!fileInfoList.empty())
  218.     {
  219.         currentSongIndex = 0; // Start with the first MP3 file
  220.         const String &firstMP3 = fileInfoList[currentSongIndex].fullPath;
  221.         currentFolder = fileInfoList[currentSongIndex].currentFolder; // Update currentFolder
  222.         playMP3(firstMP3);
  223.     }
  224. }
  225. void playMP3(const String &mp3FilePath)
  226. {
  227.     const char *mp3Path = mp3FilePath.c_str();
  228.     audio.connecttoSD(mp3Path);
  229.     updateTitleLabel();
  230.     isPlaying = true;
  231.     playbackFinished = false; // Reset the flag
  232. }
  233. void checkAndPlayNextSong(lv_event_t *event)
  234. {
  235.     if (isPlaying && !audio.isRunning())
  236.     {
  237.         // Current MP3 file has finished playing, play the next one if available
  238.         currentSongIndex++;
  239.         if (currentSongIndex < fileInfoList.size())
  240.         {
  241.             const String &nextMP3 = fileInfoList[currentSongIndex].fullPath;
  242.             playMP3(nextMP3);
  243.         }
  244.         else
  245.         {
  246.             // All MP3 files in the folder have been played
  247.             isPlaying = false;
  248.         }
  249.     }
  250. }
  251. void playNextSong(lv_event_t *event)
  252. {
  253.     if (currentSongIndex >= 0 && currentSongIndex < fileInfoList.size() - 1)
  254.     {
  255.         currentSongIndex++;
  256.         const String &nextMP3 = fileInfoList[currentSongIndex].fullPath;
  257.         playMP3(nextMP3);
  258.     }
  259.     else if (!fileInfoList.empty())
  260.     {
  261.         // At the last song, play the first song of the folder
  262.         currentSongIndex = 0;
  263.         const String &firstMP3 = fileInfoList[currentSongIndex].fullPath;
  264.         playMP3(firstMP3);
  265.     }
  266. }
  267. void playPreviousSong(lv_event_t *event)
  268. {
  269.     if (currentSongIndex > 0)
  270.     {
  271.         currentSongIndex--;
  272.         const String &prevMP3 = fileInfoList[currentSongIndex].fullPath;
  273.         playMP3(prevMP3);
  274.     }
  275.     else
  276.     {
  277.         // Already at the first song, play it again or handle as needed
  278.         const String &firstMP3 = fileInfoList[0].fullPath;
  279.         playMP3(firstMP3);
  280.     }
  281. }
  282. void replayCurrentSong()
  283. {
  284.     if (currentSongIndex >= 0 && currentSongIndex < fileInfoList.size())
  285.     {
  286.         const String &currentMP3 = fileInfoList[currentSongIndex].fullPath;
  287.         playMP3(currentMP3);
  288.         isPlaying = true;
  289.     }
  290.     else
  291.     {
  292.         // No song is currently playing, so start playing the first one
  293.         playFirstMP3IfAvailable();
  294.     }
  295. }
  296. void stopSong(lv_event_t *event) {
  297.   audio.stopSong();
  298.   isPlaying = false;
  299. }
  300. void tooglePlayPause(lv_event_t *event) {
  301.     audio.pauseResume();
  302.     if (isPlaying) {
  303.       isPlaying = false;
  304.     } else {
  305.       isPlaying = true;
  306.     }
  307. }
  308. void updateTitleLabel() {
  309.     if (currentSongIndex >= 0 && currentSongIndex < fileInfoList.size()) {
  310.         String album = currentFolder; // Use the current folder as the album name
  311.         int lastSlashIndex = album.lastIndexOf('/');
  312.         if (lastSlashIndex != -1) {
  313.             album = album.substring(lastSlashIndex + 1);
  314.         }
  315.         String title = fileInfoList[currentSongIndex].shortFileName;
  316.         lv_label_set_text(ui_labelAlbum, album.c_str());
  317.         lv_label_set_text(ui_labelTitle, title.c_str());
  318.     } else {
  319.         lv_label_set_text(ui_labelAlbum, "" );
  320.         lv_label_set_text(ui_labelTitle, "" );
  321.     }
  322. }
  323. void changeVolume(lv_event_t *event) {
  324.     lv_event_code_t code = lv_event_get_code(event);
  325.    
  326.     if (code == LV_EVENT_VALUE_CHANGED) {
  327.         int volume = lv_slider_get_value(ui_sliderVolume);
  328.         audio.setVolume(volume);
  329.         char volumeText[8];
  330.         snprintf(volumeText, sizeof(volumeText), "%d", volume);
  331.         lv_label_set_text(ui_labelVolume, volumeText);
  332.     }
  333. }
  334. void goToPreviousFolder(lv_event_t *event)
  335. {
  336.     if (folderInfoList.empty()) {
  337.         return;
  338.     }
  339.     int currentFolderIndex = -1;
  340.     for (int i = 0; i < folderInfoList.size(); i++) {
  341.         if (folderInfoList[i].currentFolder == currentFolder) {
  342.             currentFolderIndex = i;
  343.             break;
  344.         }
  345.     }
  346.     if (currentFolderIndex <= 0) {
  347.         currentFolderIndex = folderInfoList.size() - 1;
  348.     } else {
  349.         currentFolderIndex--;
  350.     }
  351.     currentFolder = folderInfoList[currentFolderIndex].currentFolder;
  352.     fileInfoList = folderInfoList[currentFolderIndex].files;
  353.     currentSongIndex = -1;
  354.     playFirstMP3IfAvailable();
  355. }
  356. void goToNextFolder(lv_event_t *event)
  357. {
  358.     if (folderInfoList.empty()) {
  359.         return;
  360.     }
  361.     int currentFolderIndex = -1;
  362.     for (int i = 0; i < folderInfoList.size(); i++) {
  363.         if (folderInfoList[i].currentFolder == currentFolder) {
  364.             currentFolderIndex = i;
  365.             break;
  366.         }
  367.     }
  368.     if (currentFolderIndex == -1) {
  369.         return;
  370.     }
  371.     if (currentFolderIndex == folderInfoList.size() - 1) {
  372.         currentFolderIndex = 0;
  373.         currentFolder = folderInfoList[currentFolderIndex].currentFolder;
  374.         fileInfoList = folderInfoList[currentFolderIndex].files;
  375.     } else {
  376.         currentFolderIndex++;
  377.         currentFolder = folderInfoList[currentFolderIndex].currentFolder;
  378.         fileInfoList = folderInfoList[currentFolderIndex].files;
  379.     }
  380.     updateTitleLabel();
  381.     currentSongIndex = -1;
  382.     playFirstMP3IfAvailable();
  383.     int currentIndex = currentFolderIndex;
  384. }
  385. void printFolderInfoList() {
  386.     Serial.println("Folder Information List:" );
  387.     for (int i = 0; i < folderInfoList.size(); i++) {
  388.         Serial.println("Folder Index: " + String(i));
  389.         Serial.println("Parent Folder: " + folderInfoList[i].parentFolder);
  390.         Serial.println("Current Folder: " + folderInfoList[i].currentFolder);
  391.     }
  392. }
  393. void setRootDirectory(const String &rootDir)
  394. {
  395.     folderInfoList.clear();
  396.     fileInfoList.clear();
  397.     File root = SD.open(rootDir);
  398.     if (!root)
  399.     {
  400.         Serial.println("Failed to open root directory." );
  401.         return;
  402.     }
  403.     collectFolderInfo(root, "", rootDir);
  404.     fileInfoList = folderInfoList[0].files; // Set fileInfoList based on the root folder
  405.     root.close();
  406. }
  407. void collectFolderInfo(fs::File dir, String parentFolder, String currentFolder)
  408. {
  409.     FolderInfo folderInfo;
  410.     folderInfo.parentFolder = parentFolder;
  411.     folderInfo.currentFolder = currentFolder;
  412.     while (File entry = dir.openNextFile())
  413.     {
  414.         String entryName = entry.name();
  415.         if (entry.isDirectory())
  416.         {
  417.             String subfolder = currentFolder + "/" + entryName;
  418.             Serial.print("Entering folder: " );
  419.             Serial.println(subfolder);
  420.             collectFolderInfo(entry, currentFolder, subfolder);
  421.         }
  422.         else
  423.         {
  424.             String fileExtension = entryName.substring(entryName.lastIndexOf('.') + 1);
  425.             // Check if the file has an MP3 extension (you can add other audio file extensions if needed)
  426.             if (fileExtension.equalsIgnoreCase("mp3" ))
  427.             {
  428.                 FileInfo fileInfo;
  429.                 fileInfo.parentFolder = parentFolder;
  430.                 fileInfo.currentFolder = currentFolder;
  431.                 fileInfo.shortFileName = entryName;
  432.                 fileInfo.fullPath = currentFolder + "/" + entryName;
  433.                 fileInfoList.push_back(fileInfo);
  434.             }
  435.         }
  436.         entry.close();
  437.     }
  438.     if (currentFolder != "/m" && currentFolder != "/h" ) {
  439.         folderInfo.files = fileInfoList;
  440.         folderInfoList.push_back(folderInfo);
  441.     }
  442.     fileInfoList.clear();
  443.     Serial.print("File count in " );
  444.     Serial.print(currentFolder);
  445.     Serial.print(": " );
  446.     Serial.println(folderInfo.files.size());
  447. }
  448. void pin_init()
  449. {
  450.     pinMode(TFT_BL, OUTPUT);
  451.     digitalWrite(TFT_BL, HIGH);
  452. }
  453. void sd_init()
  454. {
  455.     pinMode(SD_CS, OUTPUT);
  456.     digitalWrite(SD_CS, HIGH);
  457.     SPI.begin(SD_SCK, SD_MISO, SD_MOSI);
  458.     SPI.setFrequency(400000);
  459.     if (!SD.begin(SD_CS, SPI))
  460.     {
  461.         Serial.println("Card Mount Failed" );
  462.         while (1)
  463.             ;
  464.     }
  465.     else
  466.     {
  467.         Serial.println("SD OK" );
  468.     }
  469. }


---------------
Helldivers 2, une petite composition : https://www.youtube.com/watch?v=JGW [...] nnel=HeadQ - Soundcloud : https://soundcloud.com/headquaker/tracks
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed