Bon j'ai pris un ESP32-S3 avec un écran ISP.
Mon code fonctionne mais j'ai besoin de votre aide pour le code.
Je sais que c'est un ESP32 mais le code est kif kif et j'aurai peut être une réponse ici.
Globalement j'ai une interface et ça lit les mp3 mais j'ai un problème de son qui craque quelque soit le type de haut parleur que j'utilise.
Peut être avez vous un conseil pour optimiser le code. Je sais qu'il y a du code inutilisé que je vais supprimer mais à part ça, est-ce possible d'améliorer pour libérer un peu de puissance?
#include "Arduino.h"
#include "Audio.h"
#include "FS.h"
#include "SPI.h"
#include "SD.h"
#include <Wire.h>
#include <vector>
#include <lvgl.h>
#include <ui.h>
#include <Arduino_GFX_Library.h>
#define TFT_BL 2
#define SD_SCK 12 // CLK
#define SD_MISO 13 // D0
#define SD_MOSI 11 // CMD
#define SD_CS 10 // CLK
#define I2S_DOUT 17
#define I2S_BCLK 0
#define I2S_LRC 18
#define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin
#if defined(DISPLAY_DEV_KIT)
Arduino_GFX *gfx = create_default_Arduino_GFX();
#else /* !defined(DISPLAY_DEV_KIT) */
Arduino_ESP32RGBPanel *bus = new Arduino_ESP32RGBPanel(
GFX_NOT_DEFINED /* CS */, GFX_NOT_DEFINED /* SCK */, GFX_NOT_DEFINED /* SDA */,
40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 42 /* PCLK */,
45 /* R0 */, 48 /* R1 */, 47 /* R2 */, 21 /* R3 */, 14 /* R4 */,
5 /* G0 */, 6 /* G1 */, 7 /* G2 */, 15 /* G3 */, 16 /* G4 */, 4 /* G5 */,
8 /* B0 */, 3 /* B1 */, 46 /* B2 */, 9 /* B3 */, 1 /* B4 */
);
// option 1:
// ST7262 IPS LCD 800x480
Arduino_RPi_DPI_RGBPanel *gfx = new Arduino_RPi_DPI_RGBPanel(
bus,
800 /* width */, 0 /* hsync_polarity */, 8 /* hsync_front_porch */, 4 /* hsync_pulse_width */, 8 /* hsync_back_porch */,
480 /* height */, 0 /* vsync_polarity */, 8 /* vsync_front_porch */, 4 /* vsync_pulse_width */, 8 /* vsync_back_porch */,
1 /* pclk_active_neg */, 12000000 /* prefer_speed */, true /* auto_flush */);
#endif /* !defined(DISPLAY_DEV_KIT) */
/*******************************************************************************
* End of Arduino_GFX setting
******************************************************************************/
/*******************************************************************************
* Please config the touch panel in touch.h
******************************************************************************/
#include "touch.h"
Audio audio;
File musical;
std::vector<String> mp3Files;
int currentSongIndex = -1;
bool isPlaying = false;
bool playbackFinished = false; // Flag to detect playback completion
struct Music_info
{
String name;
int length;
int runtime;
int volume;
int status;
int mute_volume;
} music_info = {"", 0, 0, 0, 0, 0};
// Structure for storing file information
struct FileInfo
{
String parentFolder;
String currentFolder;
String shortFileName;
String fullPath;
};
std::vector<FileInfo> fileInfoList; // Store file information
// Structure for storing folder information
struct FolderInfo
{
String parentFolder;
String currentFolder;
std::vector<FileInfo> files;
};
std::vector<FolderInfo> folderInfoList; // Store folder information
/* Change to your screen resolution */
static uint32_t screenWidth;
static uint32_t screenHeight;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t *disp_draw_buf;
static lv_disp_drv_t disp_drv;
// Add a variable to keep track of the current folder
String currentFolder = "/m"; // Start with the root folder
void setup()
{
// Hardware initialization
pin_init();
sd_init();
// Init Display
gfx->begin();
gfx->fillScreen(RED);
delay(500);
gfx->fillScreen(GREEN);
delay(500);
gfx->fillScreen(BLUE);
delay(500);
gfx->fillScreen(BLACK);
delay(500);
lv_init();
delay(10);
touch_init();
screenWidth = gfx->width();
screenHeight = gfx->height();
#ifdef ESP32
disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 4, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
#else
disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 4);
#endif
if (!disp_draw_buf)
{
Serial.println("LVGL disp_draw_buf allocate failed!");
}
else
{
lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * screenHeight / 4);
/* Initialize the display */
lv_disp_drv_init(&disp_drv);
/* Change the following line to your display resolution */
disp_drv.hor_res = screenWidth;
disp_drv.ver_res = screenHeight;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);
/* Initialize the (dummy) input device driver */
static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register(&indev_drv);
// Loading interface
ui_init();
lv_obj_add_event_cb(ui_btPrevious, playPreviousSong, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(ui_btPlay, playNextSong, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(ui_btPause, tooglePlayPause, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(ui_btNext, playNextSong, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(ui_btStop, stopSong, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(ui_btHome, ui_event_btHome, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(ui_btUp, goToPreviousFolder, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(ui_btDown, goToNextFolder, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(ui_btHistory, ui_event_btHistory, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(ui_btMusical, setMusicalMode, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(ui_sliderVolume, changeVolume, LV_EVENT_VALUE_CHANGED, NULL);
// Setup MP3
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(7); // Adjust the initial volume as needed
// Set the root directory to "/m"
//setRootDirectory(currentFolder); // Set the root directory to the current folder
//printFolderInfoList();
// Add more debugging statements
//Serial.print("After setRootDirectory: ");
//Serial.println(fileInfoList.size());
// Play the first MP3 file if available
//playFirstMP3IfAvailable();
// Add a delay to ensure serial output is visible before the loop starts
//delay(1000); // You can adjust the delay time as needed
}
}
void loop()
{
// Your other main loop code can go here
audio.loop();
lv_event_t lv_event;
checkAndPlayNextSong(&lv_event);
// Check if playback is finished
if (playbackFinished && isPlaying)
{
isPlaying = false;
playbackFinished = false; // Reset the flag
}
lv_timer_handler(); /* let the GUI do its work */
delay(2);
}
// Functions
/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
uint32_t w = (area->x2 - area->x1 + 1);
uint32_t h = (area->y2 - area->y1 + 1);
#if (LV_COLOR_16_SWAP != 0)
gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#else
gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#endif
lv_disp_flush_ready(disp);
}
void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
if (touch_has_signal())
{
if (touch_touched())
{
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = touch_last_x;
data->point.y = touch_last_y;
}
else if (touch_released())
{
data->state = LV_INDEV_STATE_REL;
}
}
else
{
data->state = LV_INDEV_STATE_REL;
}
}
// Function to play an MP3 file
void setMusicalMode(lv_event_t *e)
{
currentFolder = "/m"; // Set the current folder to /m
setRootDirectory(currentFolder); // Set the root directory to /m
playFirstMP3IfAvailable(); // Play the first MP3 file in the new folder if available
}
void playFirstMP3IfAvailable()
{
if (!fileInfoList.empty())
{
currentSongIndex = 0; // Start with the first MP3 file
const String &firstMP3 = fileInfoList[currentSongIndex].fullPath;
currentFolder = fileInfoList[currentSongIndex].currentFolder; // Update currentFolder
playMP3(firstMP3);
}
}
void playMP3(const String &mp3FilePath)
{
const char *mp3Path = mp3FilePath.c_str();
audio.connecttoSD(mp3Path);
updateTitleLabel();
isPlaying = true;
playbackFinished = false; // Reset the flag
}
void checkAndPlayNextSong(lv_event_t *event)
{
if (isPlaying && !audio.isRunning())
{
// Current MP3 file has finished playing, play the next one if available
currentSongIndex++;
if (currentSongIndex < fileInfoList.size())
{
const String &nextMP3 = fileInfoList[currentSongIndex].fullPath;
playMP3(nextMP3);
}
else
{
// All MP3 files in the folder have been played
isPlaying = false;
}
}
}
void playNextSong(lv_event_t *event)
{
if (currentSongIndex >= 0 && currentSongIndex < fileInfoList.size() - 1)
{
currentSongIndex++;
const String &nextMP3 = fileInfoList[currentSongIndex].fullPath;
playMP3(nextMP3);
}
else if (!fileInfoList.empty())
{
// At the last song, play the first song of the folder
currentSongIndex = 0;
const String &firstMP3 = fileInfoList[currentSongIndex].fullPath;
playMP3(firstMP3);
}
}
void playPreviousSong(lv_event_t *event)
{
if (currentSongIndex > 0)
{
currentSongIndex--;
const String &prevMP3 = fileInfoList[currentSongIndex].fullPath;
playMP3(prevMP3);
}
else
{
// Already at the first song, play it again or handle as needed
const String &firstMP3 = fileInfoList[0].fullPath;
playMP3(firstMP3);
}
}
void replayCurrentSong()
{
if (currentSongIndex >= 0 && currentSongIndex < fileInfoList.size())
{
const String ¤tMP3 = fileInfoList[currentSongIndex].fullPath;
playMP3(currentMP3);
isPlaying = true;
}
else
{
// No song is currently playing, so start playing the first one
playFirstMP3IfAvailable();
}
}
void stopSong(lv_event_t *event) {
audio.stopSong();
isPlaying = false;
}
void tooglePlayPause(lv_event_t *event) {
audio.pauseResume();
if (isPlaying) {
isPlaying = false;
} else {
isPlaying = true;
}
}
void updateTitleLabel() {
if (currentSongIndex >= 0 && currentSongIndex < fileInfoList.size()) {
String album = currentFolder; // Use the current folder as the album name
int lastSlashIndex = album.lastIndexOf('/');
if (lastSlashIndex != -1) {
album = album.substring(lastSlashIndex + 1);
}
String title = fileInfoList[currentSongIndex].shortFileName;
lv_label_set_text(ui_labelAlbum, album.c_str());
lv_label_set_text(ui_labelTitle, title.c_str());
} else {
lv_label_set_text(ui_labelAlbum, "");
lv_label_set_text(ui_labelTitle, "");
}
}
void changeVolume(lv_event_t *event) {
lv_event_code_t code = lv_event_get_code(event);
if (code == LV_EVENT_VALUE_CHANGED) {
int volume = lv_slider_get_value(ui_sliderVolume);
audio.setVolume(volume);
char volumeText[8];
snprintf(volumeText, sizeof(volumeText), "%d", volume);
lv_label_set_text(ui_labelVolume, volumeText);
}
}
void goToPreviousFolder(lv_event_t *event)
{
if (folderInfoList.empty()) {
return;
}
int currentFolderIndex = -1;
for (int i = 0; i < folderInfoList.size(); i++) {
if (folderInfoList[i].currentFolder == currentFolder) {
currentFolderIndex = i;
break;
}
}
if (currentFolderIndex <= 0) {
currentFolderIndex = folderInfoList.size() - 1;
} else {
currentFolderIndex--;
}
currentFolder = folderInfoList[currentFolderIndex].currentFolder;
fileInfoList = folderInfoList[currentFolderIndex].files;
currentSongIndex = -1;
playFirstMP3IfAvailable();
}
void goToNextFolder(lv_event_t *event)
{
if (folderInfoList.empty()) {
return;
}
int currentFolderIndex = -1;
for (int i = 0; i < folderInfoList.size(); i++) {
if (folderInfoList[i].currentFolder == currentFolder) {
currentFolderIndex = i;
break;
}
}
if (currentFolderIndex == -1) {
return;
}
if (currentFolderIndex == folderInfoList.size() - 1) {
currentFolderIndex = 0;
currentFolder = folderInfoList[currentFolderIndex].currentFolder;
fileInfoList = folderInfoList[currentFolderIndex].files;
} else {
currentFolderIndex++;
currentFolder = folderInfoList[currentFolderIndex].currentFolder;
fileInfoList = folderInfoList[currentFolderIndex].files;
}
updateTitleLabel();
currentSongIndex = -1;
playFirstMP3IfAvailable();
int currentIndex = currentFolderIndex;
}
void printFolderInfoList() {
Serial.println("Folder Information List:");
for (int i = 0; i < folderInfoList.size(); i++) {
Serial.println("Folder Index: " + String(i));
Serial.println("Parent Folder: " + folderInfoList[i].parentFolder);
Serial.println("Current Folder: " + folderInfoList[i].currentFolder);
}
}
void setRootDirectory(const String &rootDir)
{
folderInfoList.clear();
fileInfoList.clear();
File root = SD.open(rootDir);
if (!root)
{
Serial.println("Failed to open root directory.");
return;
}
collectFolderInfo(root, "", rootDir);
fileInfoList = folderInfoList[0].files; // Set fileInfoList based on the root folder
root.close();
}
void collectFolderInfo(fs::File dir, String parentFolder, String currentFolder)
{
FolderInfo folderInfo;
folderInfo.parentFolder = parentFolder;
folderInfo.currentFolder = currentFolder;
while (File entry = dir.openNextFile())
{
String entryName = entry.name();
if (entry.isDirectory())
{
String subfolder = currentFolder + "/" + entryName;
Serial.print("Entering folder: ");
Serial.println(subfolder);
collectFolderInfo(entry, currentFolder, subfolder);
}
else
{
String fileExtension = entryName.substring(entryName.lastIndexOf('.') + 1);
// Check if the file has an MP3 extension (you can add other audio file extensions if needed)
if (fileExtension.equalsIgnoreCase("mp3"))
{
FileInfo fileInfo;
fileInfo.parentFolder = parentFolder;
fileInfo.currentFolder = currentFolder;
fileInfo.shortFileName = entryName;
fileInfo.fullPath = currentFolder + "/" + entryName;
fileInfoList.push_back(fileInfo);
}
}
entry.close();
}
if (currentFolder != "/m" && currentFolder != "/h") {
folderInfo.files = fileInfoList;
folderInfoList.push_back(folderInfo);
}
fileInfoList.clear();
Serial.print("File count in ");
Serial.print(currentFolder);
Serial.print(": ");
Serial.println(folderInfo.files.size());
}
void pin_init()
{
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH);
}
void sd_init()
{
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
SPI.begin(SD_SCK, SD_MISO, SD_MOSI);
SPI.setFrequency(1000000);
if (!SD.begin(SD_CS, SPI))
{
Serial.println("Card Mount Failed");
while (1)
;
}
else
{
Serial.println("SD OK");
}
}