first commit

This commit is contained in:
Clément SAILLANT
2025-08-01 17:22:17 +02:00
commit 1698c4d375
21 changed files with 6093 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
# PlatformIO
.pio/
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch/
# Compilation
*.o
*.a
*.so
*.exe
# IDE
.DS_Store
Thumbs.db
# Logs
*.log
# Backup files
*.bak
*.tmp
*~
# Configuration sensible (décommentez si nécessaire)
# src/config.h
# include/secrets.h
# Documentation générée
docs/html/
docs/latex/
# Archives
*.zip
*.tar.gz
*.rar
# Fichiers de développement
test_*
debug_*
temp_*
+10
View File
@@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}
+21
View File
@@ -0,0 +1,21 @@
{
"files.associations": {
"*.ino": "cpp",
"platformio.ini": "ini"
},
"C_Cpp.default.configurationProvider": "ms-vscode.vscode-json",
"editor.tabSize": 2,
"editor.insertSpaces": true,
"files.autoSave": "afterDelay",
"files.autoSaveDelay": 1000,
"terminal.integrated.defaultProfile.osx": "zsh",
"platformio-ide.forceUploadAndMonitor": false,
"platformio-ide.autoPreloadEnvTasks": true,
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.patterns": {
"platformio.ini": ".vscode/*, lib/*, test/*, .pio/*, .gitignore",
"README.md": "*.md"
},
"stm32-for-vscode.openOCDPath": false,
"stm32-for-vscode.armToolchainPath": false
}
+200
View File
@@ -0,0 +1,200 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "PlatformIO: Build Main Project",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "main"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Upload Main Project",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "main", "--target", "upload"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Test RTC Module",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "rtc_test", "--target", "upload"],
"group": "test",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Test P10 Matrix",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "p10_test", "--target", "upload"],
"group": "test",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Erase NVS Memory",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "nvs_erase", "--target", "upload"],
"group": "test",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Test Cascade (2 panels)",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "test_cascade", "--target", "upload"],
"group": "test",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Cascade 2x1 (64x16)",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "cascade_2x1", "--target", "upload"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Cascade 3x1 (96x16)",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "cascade_3x1", "--target", "upload"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Cascade 4x1 (128x16)",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "cascade_4x1", "--target", "upload"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Cascade 2x2 (64x32)",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "cascade_2x2", "--target", "upload"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Cascade 6x1 (192x16)",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "cascade_6x1", "--target", "upload"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Cascade 8x1 (256x16)",
"type": "shell",
"command": "pio",
"args": ["run", "-e", "cascade_8x1", "--target", "upload"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": "$gcc"
},
{
"label": "PlatformIO: Monitor Serial",
"type": "shell",
"command": "pio",
"args": ["device", "monitor"],
"group": "test",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"isBackground": true
},
{
"label": "PlatformIO: Clean Project",
"type": "shell",
"command": "pio",
"args": ["run", "--target", "clean"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
}
}
]
}
+226
View File
@@ -0,0 +1,226 @@
# Guide des Panneaux P10 en Cascade
## 🔗 Vue d'ensemble
Ce projet supporte maintenant plusieurs panneaux P10 connectés en cascade pour créer des affichages plus larges ou plus hauts.
## 📐 Configurations Supportées
### Configurations Horizontales (recommandées)
- **1x1** : 32x16 pixels (1 panneau) - Configuration standard
- **2x1** : 64x16 pixels (2 panneaux) - Ideal pour texte plus long
- **3x1** : 96x16 pixels (3 panneaux) - Texte défilant étendu
- **4x1** : 128x16 pixels (4 panneaux) - Affichage type bandeau
- **6x1** : 192x16 pixels (6 panneaux) - Grand bandeau
- **8x1** : 256x16 pixels (8 panneaux) - Très grand bandeau
### Configurations Verticales/Mixtes
- **2x2** : 64x32 pixels (4 panneaux) - Affichage carré
- **1x2** : 32x32 pixels (2 panneaux) - Plus de hauteur
- **4x2** : 128x32 pixels (8 panneaux) - Grand affichage
## 🛠️ Connexion Physique
### Connexion en Cascade (Chaînage)
```
ESP32 ──── Panneau 1 ──── Panneau 2 ──── Panneau 3 ──── ...
(Premier) (Deuxième) (Troisième)
```
### Détails de Connexion
1. **Premier panneau** : Connecté directement à l'ESP32 (voir WIRING.md)
2. **Panneaux suivants** : Connectés via les ports de sortie du panneau précédent
3. **Alimentation** : Chaque panneau doit être alimenté en 5V individuellement
### Important - Alimentation
```
⚠️ ATTENTION ALIMENTATION !
Chaque panneau P10 consomme environ 1-2A sous 5V
- 2 panneaux : 5V/4A minimum
- 4 panneaux : 5V/8A minimum
- 6 panneaux : 5V/12A minimum
Utilisez une alimentation adaptée !
```
## 🎯 Compilation pour Cascade
### Commandes PlatformIO
```bash
# 2 panneaux horizontaux (64x16)
pio run -e cascade_2x1 --target upload
# 3 panneaux horizontaux (96x16)
pio run -e cascade_3x1 --target upload
# 4 panneaux horizontaux (128x16)
pio run -e cascade_4x1 --target upload
# 2x2 panneaux (64x32)
pio run -e cascade_2x2 --target upload
# 6 panneaux horizontaux (192x16)
pio run -e cascade_6x1 --target upload
# 8 panneaux horizontaux (256x16)
pio run -e cascade_8x1 --target upload
# Test de cascade (2 panneaux)
pio run -e test_cascade --target upload
```
### Configuration Personnalisée
Pour une configuration non-standard, modifiez `platformio.ini` :
```ini
[env:custom_cascade]
extends = env:main
build_flags =
${env.build_flags}
-DMATRIX_WIDTH=32 ; Largeur d'un panneau
-DMATRIX_HEIGHT=16 ; Hauteur d'un panneau
-DMATRIX_PANELS_X=5 ; Nombre panneaux horizontaux
-DMATRIX_PANELS_Y=1 ; Nombre panneaux verticaux
-DCASCADE_MODE=1
```
## 🧪 Test des Panneaux
### Test d'Alignement
```bash
pio run -e test_cascade --target upload
```
Ce test affiche :
1. **Bordures** : Contour de chaque panneau
2. **Numérotation** : P1, P2, P3... sur chaque panneau
3. **Couleurs** : Test de toutes les couleurs
4. **Texte défilant** : Test sur toute la largeur
### Vérifications Visuelles
- ✅ Tous les panneaux s'allument
- ✅ Bordures alignées correctement
- ✅ Numérotation séquentielle (P1, P2, P3...)
- ✅ Couleurs uniformes sur tous les panneaux
- ✅ Texte défile sans coupure
## ⚙️ Ajustements Automatiques
### Luminosité Auto-Adaptée
```cpp
// Le code ajuste automatiquement la luminosité :
1-2 panneaux : 125/255 (luminosité normale)
3-4 panneaux : 100/255 (réduite)
5-6 panneaux : 80/255 (plus réduite)
7+ panneaux : 60/255 (très réduite)
```
### Centrage Automatique
- **Horloge** : Centrée automatiquement sur la largeur totale
- **Texte défilant** : Utilise toute la largeur disponible
- **Interface web** : Fonctionne normalement
## 🌐 Interface Web Adaptée
L'interface web fonctionne normalement avec les cascades :
- Configuration identique
- Texte défilant adapté à la largeur
- Couleurs appliquées sur tous les panneaux
- Luminosité globale
## 🔧 Dépannage Cascade
### Problème : Un panneau ne s'allume pas
1. ✅ Vérifiez l'alimentation 5V de chaque panneau
2. ✅ Vérifiez les connexions en cascade
3. ✅ Testez avec moins de panneaux
### Problème : Affichage décalé
1. ✅ Vérifiez l'ordre des panneaux (P1, P2, P3...)
2. ✅ Utilisez le test d'alignement
3. ✅ Vérifiez les paramètres PANELS_X et PANELS_Y
### Problème : Scintillement
1. ✅ Réduisez la luminosité
2. ✅ Vérifiez l'alimentation (suffisamment puissante ?)
3. ✅ Réduisez `PxMATRIX_SPI_FREQUENCY`
### Problème : Texte coupé
1. ✅ Vérifiez que TOTAL_WIDTH est correct
2. ✅ Utilisez le test de texte défilant
3. ✅ Vérifiez la configuration PANELS_X
## 📋 Checklist Installation Cascade
### Étape 1 : Préparation
- [ ] Alimentation suffisante calculée (2A × nombre de panneaux)
- [ ] Panneaux P10 testés individuellement
- [ ] Câbles de connexion préparés
### Étape 2 : Connexion Physique
- [ ] Premier panneau connecté à l'ESP32
- [ ] Panneaux en cascade connectés
- [ ] Alimentation 5V sur chaque panneau
- [ ] Masse commune vérifiée
### Étape 3 : Configuration Logicielle
- [ ] Environnement cascade choisi (ex: cascade_2x1)
- [ ] Code compilé et téléversé
- [ ] Test d'alignement réussi
### Étape 4 : Test Final
- [ ] Tous les panneaux s'allument
- [ ] Numérotation correcte visible
- [ ] Horloge centrée correctement
- [ ] Texte défile sur toute la largeur
- [ ] Interface web accessible
## 💡 Conseils Optimisation
### Performance
- Plus de panneaux = plus de données à traiter
- Réduisez la luminosité si nécessaire
- Utilisez une alimentation stable
### Esthétique
- Alignez physiquement les panneaux parfaitement
- Utilisez des supports adaptés
- Protégez les connexions
### Fiabilité
- Alimentation dimensionnée correctement
- Connexions bien fixées
- Test avant installation finale
## 🎨 Exemples d'Utilisation
### Bandeau d'Information (4x1)
```
┌─────────────────────────────┐
│ 12:34 ESP32 CLOCK │
│ Aujourd'hui 15°C - Beau... │
└─────────────────────────────┘
```
### Affichage Carré (2x2)
```
┌─────────────────┐
│ 12:34 │
│ ESP32 CLOCK │
│ │
│ Message long... │
└─────────────────┘
```
### Grand Bandeau (8x1)
```
┌───────────────────────────────────────────────────────────┐
│ 12:34 - ESP32 DIGITAL CLOCK │
│ Très long message défilant avec beaucoup d'informations... │
└───────────────────────────────────────────────────────────┘
```
La cascade de panneaux P10 permet de créer des affichages personnalisés adaptés à vos besoins !
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

+20
View File
@@ -0,0 +1,20 @@
1. Please enter the "Key" that matches the "Key" in the Arduino code.
2. The "Apply Time and Date" button is to set the time and date on the DS3231 RTC module based on the time and date on your device.
3. "Display Mode" is the setting for display mode.
> Display Mode = 1 is a display mode in which the color of the clock, the color of the scrolling text to display the date
(including the name of the day) and the color of the message in
the scrolling text can be set manually.
> Display Mode = 2 is a display mode in which the color of the clock, the color of the scrolling text to display the date
(including the name of the day) and the color of the message in the scrolling text will change sequentially based on the color code
list in the Arduino code.
4. "Brightness" is the setting to adjust the brightness on the P10 RGB 32x16 panel.
5. "Clock Color" is a setting to adjust the color of the clock display (can only be set if display mode = 1).
6. "Date Color" is a setting to set the scrolling text display color to display the name of the day and date
(can only be set if display mode = 1).
7. "Scrolling Text" is a setting to set the message displayed on the scrolling text (after scrolling the text containing the name of
the day and date).
8. "Text Color" is a setting to set the text color for displaying messages in scrolling text (does not include scrolling text for names of days
and dates and can only be set if display mode = 1).
9. "Scrolling Speed" is a setting to set the speed of scrolling text (scrolling text for names of days and dates and scrolling text for
displaying messages).
10. The "Get Settings" button is to get the settings stored in the ESP32 flash memory.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 516 KiB

+4
View File
@@ -0,0 +1,4 @@
- Adafruit BusIO (V1.16.1) by Adafruit : Install via "Manage Libraries" or "Library Manager" in the Arduino IDE with the search keyword "Adafruit BusIO".
- RTClib by Adafruit (V2.1.4) : Install via "Manage Libraries" or "Library Manager" in the Arduino IDE with the search keyword "RTClib".
- Adafruit GFX Library by Adafruit (V1.11.9) : Install via "Manage Libraries" or "Library Manager" in the Arduino IDE with the search keyword "Adafruit GFX Library".
- PxMatrix Library by 2dom (Dominic Buchstaller) (V1.8.2) : https://github.com/2dom/PxMatrix/tree/master
+527
View File
@@ -0,0 +1,527 @@
const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<title>Digital Clcok & Scrolling Text with ESP32 and P10 RGB 32x16</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html {font-family: Helvetica, sans-serif;}
h1 {font-size: 1.1rem; color:#1976D2;}
label {font-size: 14px;}
.div_Form {
margin: auto;
width: 90%;
border:1px solid #D8D8D8;
border-radius: 10px;
background-color: #f2f2f2;
padding: 9px 9px;
}
.myButton {
display: inline-block;
padding: 3px 25px;
font-size: 13px;
cursor: pointer;
text-align: center;
text-decoration: none;
outline: none;
color: #fff;
background-color: #1976D2;
border: none;
border-radius: 8px;
box-shadow: 0 2px #999;
}
.myButton:hover {background-color: #104d89}
.myButton:active {background-color: #104d89; box-shadow: 0 1px #666; transform: translateY(2px);}
.myButton:disabled {background-color: #666; box-shadow: 0 1px #666; transform: translateY(2px);}
.myButtonX {background-color: #ff0000}
.myButtonX:hover {background-color: #7a0101}
.div_Form_Input {display: table; margin: 0px; padding: 0px; box-sizing: border-box;}
.div_Input_Text {display: table-cell; width: 100%;}
.div_Input_Text > input {width:99.5%; margin-left: 0px; padding-left: 2px; box-sizing: border-box;}
table, th, td {
border: 0px solid black;
border-collapse: collapse;
font-size: 14px;
}
tr {height: 30px;}
textarea {
resize: none;
height:50px;
}
</style>
<body>
<div style="text-align: center;">
<h1>Digital Clcok & Scrolling Text with ESP32 and P10 RGB 32x16</h1>
</div>
<div class="div_Form">
<form>
<!-- Input Key -->
<label for="keys_TXT">Key :</label>
<input type="password" style="width: 170px;" id="input_Keys_TXT" name="input_Keys_TXT" maxlength="20" placeholder="Enter key here..." />
<!-- -->
<hr style="border: 1px solid #e6e6e6;">
<!-- Displays and applies time and date. -->
<label id="show_Date_Time">Please wait...</label>
<br>
<button type="button" class="myButton" style="font-size: 12px; padding: 3px 10px; margin-top: 5px;" id="btn_Apply_TimeDate" onclick="btn_Apply_TimeDate_Click()">Apply Time and Date</button>
<!-- -->
<hr style="border: 1px solid #e6e6e6;">
<table style="width:280px; margin-left: -1px;">
<!-- Set display mode. -->
<tr>
<td>Display Mode</td>
<td>:</td>
<td>
<select name="input_Display_Mode" id="input_Display_Mode">
<option value="1">1</option>
<option value="2">2</option>
</select>
</td>
<td align="right">
<button type="button" class="myButton" style="font-size: 12px; padding: 3px 10px;" id="btn_Apply_Display_Mode" onclick="btn_Apply_Display_Mode_Click()">Apply</button>
</td>
</tr>
<!-- -->
<!-- Set Brightness. -->
<tr>
<td>Brightness</td>
<td>:</td>
<td>
<input type="text" value="50" id="input_Brightness" maxlength="3" size="3" oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*?)\..*/g, '$1');" /> (0 - 255)
</td>
<td align="right">
<button type="button" class="myButton" style="font-size: 12px; padding: 3px 10px;" id="btn_Apply_Input_Brightness" onclick="btn_Apply_Input_Brightness_Click()">Apply</button>
</td>
</tr>
<!-- -->
<!-- Set Clock Color. -->
<tr>
<td>Clock Color</td>
<td>:</td>
<td>
<input type="color" id="input_Color_Clock" name="input_Color_Clock" value="#0000ff">
</td>
<td align="right">
<button type="button" class="myButton" style="font-size: 12px; padding: 3px 10px;" id="btn_Apply_Input_Color_Clock" onclick="btn_Apply_Input_Color_Clock_Click()">Apply</button>
</td>
</tr>
<!-- -->
<!-- Set Date Color. -->
<tr>
<td>Date Color</td>
<td>:</td>
<td>
<input type="color" id="input_Color_Date" name="input_Color_Date" value="#0000ff">
</td>
<td align="right">
<button type="button" class="myButton" style="font-size: 12px; padding: 3px 10px;" id="btn_Apply_Input_Color_Date" onclick="btn_Apply_Input_Color_Date_Click()">Apply</button>
</td>
</tr>
<!-- -->
</table>
<hr style="border: 1px solid #e6e6e6;">
<label for="Keys_TXT">Scrolling Text :</label>
<br>
<table style="width:100%; margin-left: -1px;">
<tr>
<!-- Set Scrolling Text. -->
<td>
<textarea id="input_Scrolling_Text" name="input_Scrolling_Text" style="width: 100%; margin: 0px; padding: 0px;" maxlength="150" placeholder="Enter text here...(Max 150 characters)"></textarea>
</td>
<td style="width: 5px;"></td>
<td style="width: 30px; vertical-align: top;" align="center">
<button type="button" class="myButton myButtonX" style="font-size: 12px; padding: 3px 10px;" id="btn_Clear_Input_Scrolling_Text" onclick="btn_Clear_Input_Scrolling_Text_Click()">X</button>
</td>
<td style="width: 50px; vertical-align: top;" align="right">
<button type="button" class="myButton" style="font-size: 12px; padding: 3px 10px;" id="btn_Apply_Input_Scrolling_Text" onclick="btn_Apply_Input_Scrolling_Text_Click()">Apply</button>
</td>
</tr>
<!-- -->
</table>
<br>
<table style="width:280px; margin-left: -1px;">
<!-- Set Text Color. -->
<tr>
<td>Text Color</td>
<td>:</td>
<td>
<input type="color" id="input_Text_Color" name="input_Text_Color" value="#0000ff">
</td>
<td align="right">
<button type="button" class="myButton" style="font-size: 12px; padding: 3px 10px;" id="btn_Apply_Input_Text_Color" onclick="btn_Apply_Input_Text_Color_Click()">Apply</button>
</td>
</tr>
<!-- -->
<!-- Set Scrolling Speed. -->
<tr>
<td>Scrolling Speed</td>
<td>:</td>
<td>
<select name="input_Scrolling_Speed" id="input_Scrolling_Speed">
<option value="20">20</option>
<option value="25">25</option>
<option value="30">30</option>
<option value="35">35</option>
<option value="40">40</option>
<option value="45">45</option>
<option value="50">50</option>
<option value="55">55</option>
<option value="60">60</option>
<option value="65">65</option>
<option value="70">70</option>
<option value="75">75</option>
</select>
</td>
<td align="right">
<button type="button" class="myButton" style="font-size: 12px; padding: 3px 10px;" id="btn_Apply_Input_Scrolling_Speed" onclick="btn_Apply_Input_Scrolling_Speed_Click()">Apply</button>
</td>
</tr>
<!-- -->
</table>
<hr style="border: 1px solid #e6e6e6;">
<button type="button" class="myButton" id="btn_Get_Settings" onclick="btn_Get_Settings_Click()">Get Settings</button>
</form>
</div>
<script>
setInterval(myTimer, 1000);
var t_Hour;
var t_Minute;
var t_Second;
const d_DaysOfTheWeek_Array = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var d_DaysOfTheWeek_Now;
var d_Day;
var d_Month;
var d_Year;
var full_DateTime;
//________________________________________________________________________________ myTimer()
function myTimer() {
getDateTime();
document.getElementById("show_Date_Time").innerHTML = full_DateTime;
}
//________________________________________________________________________________
//________________________________________________________________________________ getDateTime()
function getDateTime() {
const dt = new Date();
t_Hour = dt.getHours();
t_Minute = dt.getMinutes();;
t_Second = dt.getSeconds();
d_DaysOfTheWeek_Now = dt.getDay();
d_Day = dt.getDate();
d_Month = dt.getMonth() + 1;
d_Year = dt.getFullYear();
full_DateTime = "Date : <b>";
full_DateTime += d_DaysOfTheWeek_Array[d_DaysOfTheWeek_Now];
full_DateTime += ", ";
full_DateTime += d_Day.toString().padStart(2, '0') + "-" + d_Month.toString().padStart(2, '0') + "-" + d_Year;
full_DateTime += "</b> | Time : <b>" + t_Hour.toString().padStart(2, '0') + ":" + t_Minute.toString().padStart(2, '0') + ":" + t_Second.toString().padStart(2, '0') + "</b>";
}
//________________________________________________________________________________
//________________________________________________________________________________ check_Key_TXT()
function check_Key_TXT() {
var key_TXT = document.getElementById("input_Keys_TXT").value;
if (key_TXT == "") {
alert("Error ! \rThe key cannot be empty.");
return false;
} else {
return true;
}
}
//________________________________________________________________________________
//________________________________________________________________________________ function btn_Apply_TimeDate_Click()
// Function to send settings to the server.
function btn_Apply_TimeDate_Click() {
if (check_Key_TXT() == false) return;
var key_TXT = document.getElementById("input_Keys_TXT").value;
getDateTime();
var msg;
msg = "key=" + key_TXT;
msg += "&sta=setTimeDate";
msg += "&d_Year=" + d_Year;
msg += "&d_Month=" + d_Month;
msg += "&d_Day=" + d_Day;
msg += "&t_Hour=" + t_Hour;
msg += "&t_Minute=" + t_Minute;
msg += "&t_Second=" + t_Second;
Send("set", msg);
}
//________________________________________________________________________________
//________________________________________________________________________________ function btn_Apply_Display_Mode_Click()
// Function to send settings to the server.
function btn_Apply_Display_Mode_Click() {
if (check_Key_TXT() == false) return;
var key_TXT = document.getElementById("input_Keys_TXT").value;
var input_Display_Mode = document.getElementById("input_Display_Mode").value;
var msg;
msg = "key=" + key_TXT;
msg += "&sta=setDisplayMode";
msg += "&input_Display_Mode=" + input_Display_Mode;
Send("set", msg);
}
//________________________________________________________________________________
//________________________________________________________________________________ function btn_Apply_Input_Brightness_Click()
// Function to send settings to the server.
function btn_Apply_Input_Brightness_Click() {
if (check_Key_TXT() == false) return;
var key_TXT = document.getElementById("input_Keys_TXT").value;
var input_Brightness = document.getElementById("input_Brightness").value;
var msg;
msg = "key=" + key_TXT;
msg += "&sta=setBrightness";
msg += "&input_Brightness=" + input_Brightness;
Send("set", msg);
}
//________________________________________________________________________________
//________________________________________________________________________________ function btn_Apply_Input_Color_Clock_Click()
// Function to send settings to the server.
function btn_Apply_Input_Color_Clock_Click() {
if (check_Key_TXT() == false) return;
var key_TXT = document.getElementById("input_Keys_TXT").value;
var input_Color_Clock = hexToRgb(document.getElementById("input_Color_Clock").value);
var Color_Clock_R = input_Color_Clock[0];
var Color_Clock_G = input_Color_Clock[1];
var Color_Clock_B = input_Color_Clock[2];
var msg;
msg = "key=" + key_TXT;
msg += "&sta=setColorClock";
msg += "&Color_Clock_R=" + Color_Clock_R + "&Color_Clock_G=" + Color_Clock_G + "&Color_Clock_B=" + Color_Clock_B;
Send("set", msg);
}
//________________________________________________________________________________
//________________________________________________________________________________ function btn_Apply_Input_Color_Date_Click()
// Function to send settings to the server.
function btn_Apply_Input_Color_Date_Click() {
if (check_Key_TXT() == false) return;
var key_TXT = document.getElementById("input_Keys_TXT").value;
var input_Color_Date = hexToRgb(document.getElementById("input_Color_Date").value);
var Color_Date_R = input_Color_Date[0];
var Color_Date_G = input_Color_Date[1];
var Color_Date_B = input_Color_Date[2];
var msg;
msg = "key=" + key_TXT;
msg += "&sta=setColorDate";
msg += "&Color_Date_R=" + Color_Date_R + "&Color_Date_G=" + Color_Date_G + "&Color_Date_B=" + Color_Date_B;
Send("set", msg);
}
//________________________________________________________________________________
//________________________________________________________________________________ btn_Clear_Input_Scrolling_Text_Click()
function btn_Clear_Input_Scrolling_Text_Click() {
document.getElementById("input_Scrolling_Text").value = "";
}
//________________________________________________________________________________
//________________________________________________________________________________ function btn_Apply_Input_Scrolling_Text_Click()
// Function to send settings to the server.
function btn_Apply_Input_Scrolling_Text_Click() {
if (check_Key_TXT() == false) return;
var key_TXT = document.getElementById("input_Keys_TXT").value;
var input_Scrolling_Text = document.getElementById("input_Scrolling_Text").value;
var msg;
msg = "key=" + key_TXT;
msg += "&sta=setScrollingText";
msg += "&input_Scrolling_Text=" + input_Scrolling_Text;
Send("set", msg);
}
//________________________________________________________________________________
//________________________________________________________________________________ function btn_Apply_Input_Text_Color_Click()
// Function to send settings to the server.
function btn_Apply_Input_Text_Color_Click() {
if (check_Key_TXT() == false) return;
var key_TXT = document.getElementById("input_Keys_TXT").value;
var input_Text_Color = hexToRgb(document.getElementById("input_Text_Color").value);
var Color_Text_R = input_Text_Color[0];
var Color_Text_G = input_Text_Color[1];
var Color_Text_B = input_Text_Color[2];
var msg;
msg = "key=" + key_TXT;
msg += "&sta=setTextColor";
msg += "&Color_Text_R=" + Color_Text_R + "&Color_Text_G=" + Color_Text_G + "&Color_Text_B=" + Color_Text_B;
Send("set", msg);
}
//________________________________________________________________________________
//________________________________________________________________________________ function btn_Apply_Input_Scrolling_Speed_Click()
// Function to send settings to the server.
function btn_Apply_Input_Scrolling_Speed_Click() {
if (check_Key_TXT() == false) return;
var key_TXT = document.getElementById("input_Keys_TXT").value;
var input_Scrolling_Speed = document.getElementById("input_Scrolling_Speed").value;
var msg;
msg = "key=" + key_TXT;
msg += "&sta=setScrollingSpeed";
msg += "&input_Scrolling_Speed=" + input_Scrolling_Speed;
Send("set", msg);
}
//________________________________________________________________________________
//________________________________________________________________________________ btn_Get_Settings_Click()
function btn_Get_Settings_Click() {
if (check_Key_TXT() == false) return;
var key_TXT = document.getElementById("input_Keys_TXT").value;
var send_Request;
send_Request = "key=" + key_TXT;
send_Request += "&sta=getSettings";
Send("get", send_Request);
}
//________________________________________________________________________________
//________________________________________________________________________________ function hexToRgb(hex)
function hexToRgb(hex) {
const normal = hex.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);
if (normal) return normal.slice(1).map(e => parseInt(e, 16));
const shorthand = hex.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i);
if (shorthand) return shorthand.slice(1).map(e => 0x11 * parseInt(e, 16));
return null;
}
//________________________________________________________________________________
//________________________________________________________________________________ rgbToHex(red, green, blue)
function rgbToHex(red, green, blue) {
const rgb = (red << 16) | (green << 8) | (blue << 0);
return '#' + (0x1000000 + rgb).toString(16).slice(1);
}
//________________________________________________________________________________
//________________________________________________________________________________ function apply_the_Received_Settings(texts)
// Function to apply settings received from the server.
function apply_the_Received_Settings(texts) {
const myArray_Getting_Settings = texts.split("|");
var input_Display_Mode = myArray_Getting_Settings[0];
var input_Brightness = myArray_Getting_Settings[1];
var Color_Clock_R = myArray_Getting_Settings[2];
var Color_Clock_G = myArray_Getting_Settings[3];
var Color_Clock_B = myArray_Getting_Settings[4];
var input_Color_Clock = rgbToHex(Color_Clock_R, Color_Clock_G, Color_Clock_B);
var Color_Date_R = myArray_Getting_Settings[5];
var Color_Date_G = myArray_Getting_Settings[6];
var Color_Date_B = myArray_Getting_Settings[7];
var input_Color_Date = rgbToHex(Color_Date_R, Color_Date_G, Color_Date_B);
var input_Scrolling_Text = myArray_Getting_Settings[8];
var Color_Text_R = myArray_Getting_Settings[9];
var Color_Text_G = myArray_Getting_Settings[10];
var Color_Text_B = myArray_Getting_Settings[11];
var input_Text_Color = rgbToHex(Color_Text_R, Color_Text_G, Color_Text_B);
var input_Scrolling_Speed = myArray_Getting_Settings[12];
document.getElementById("input_Display_Mode").value = input_Display_Mode;
document.getElementById("input_Brightness").value = input_Brightness;
document.getElementById("input_Color_Clock").value = input_Color_Clock;
document.getElementById("input_Color_Date").value = input_Color_Date;
document.getElementById("input_Scrolling_Text").value = input_Scrolling_Text;
document.getElementById("input_Text_Color").value = input_Text_Color;
document.getElementById("input_Scrolling_Speed").value = input_Scrolling_Speed;
}
//________________________________________________________________________________
//________________________________________________________________________________ function Send(sta, msg)
function Send(sta, msg) {
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
if (this.responseText == "+ERR") {
alert("Error !\rWrong Key !\rPlease enter the correct key.");
return;
}
if (this.responseText == "+ERR_DM") {
alert("Error !\rThis setting is only for Display Mode : 1. \rPlease change the Display Mode to apply this setting.");
return;
}
if (sta == "get") {
apply_the_Received_Settings(this.responseText);
}
}
}
xmlhttp.open("GET", "settings?" + msg, true);
xmlhttp.send();
}
//________________________________________________________________________________
</script>
</body>
</html>
)=====";
+159
View File
@@ -0,0 +1,159 @@
# Guide de Démarrage Rapide - ESP32 P10 Digital Clock
## 🚀 Démarrage en 5 minutes
### Étape 1 : Préparation
1. **Installez PlatformIO** dans VS Code
2. **Ouvrez ce dossier** dans VS Code
3. **Connectez votre ESP32** en USB
### Étape 2 : Configuration WiFi
Modifiez dans `src/main.cpp` lignes ~100 :
```cpp
const char* ssid = "VOTRE_WIFI";
const char* password = "VOTRE_MOT_DE_PASSE";
```
### Étape 3 : Câblage (IMPORTANT !)
#### Panneau P10 → ESP32
```
HUB75 → ESP32
R1 → GPIO2
G1 → GPIO15
B1 → GPIO4
R2 → GPIO16
G2 → GPIO17
B2 → GPIO5
A → GPIO19
B → GPIO23
C → GPIO18
CLK → GPIO14
STB → GPIO32
OE → GPIO33
GND → GND (plusieurs connexions)
```
#### RTC DS3231 → ESP32
```
VCC → 3.3V
GND → GND
SDA → GPIO21
SCL → GPIO22
```
### Étape 4 : Test rapide
1. **Test du panneau P10** :
```bash
pio run -e p10_test --target upload
```
2. **Test du RTC** :
```bash
pio run -e rtc_test --target upload
```
### Étape 5 : Projet principal
```bash
pio run -e main --target upload
pio device monitor
```
## 🌐 Configuration Web
1. **Trouvez l'IP** dans le moniteur série
2. **Ouvrez votre navigateur** → http://IP_AFFICHEE
3. **Utilisez la clé** : `p10rgbesp32ws`
4. **Configurez** date, heure, couleurs, texte
## 🔧 Commandes Utiles
```bash
# Compilation principale
pio run -e main
# Upload et monitoring
pio run -e main -t upload && pio device monitor
# Test des composants
pio run -e rtc_test -t upload # Test RTC
pio run -e p10_test -t upload # Test P10
pio run -e nvs_erase -t upload # Reset mémoire
# Nettoyage
pio run -t clean
```
## ⚡ Commandes VS Code
- **Ctrl+Shift+P** → "Tasks: Run Task"
- Choisissez parmi :
- PlatformIO: Build Main Project
- PlatformIO: Upload Main Project
- PlatformIO: Test RTC Module
- PlatformIO: Test P10 Matrix
- PlatformIO: Monitor Serial
## 🚨 Problèmes Courants
### L'affichage ne fonctionne pas
- ✅ Vérifiez l'**alimentation 5V** (crucial !)
- ✅ Vérifiez **toutes les connexions**
- ✅ Testez avec `pio run -e p10_test -t upload`
### WiFi ne se connecte pas
- ✅ Vérifiez SSID/mot de passe
- ✅ L'ESP32 créera un point d'accès "ESP32_Clock"
### RTC ne fonctionne pas
- ✅ Vérifiez connexions I2C (SDA/SCL)
- ✅ Testez avec `pio run -e rtc_test -t upload`
### Paramètres perdus
- ✅ Effacez la mémoire : `pio run -e nvs_erase -t upload`
## 📱 Interface Web - Fonctionnalités
- **Date/Heure** : Configuration complète
- **Mode 1** : Couleurs manuelles (RGB)
- **Mode 2** : Changement automatique de couleurs
- **Luminosité** : 0-255
- **Texte défilant** : Message personnalisé
- **Vitesse** : Réglage du défilement
## 💡 Configuration Avancée
### Changement des pins
Modifiez dans `src/main.cpp` :
```cpp
#define P_LAT 5 // Pin Latch
#define P_A 19 // Pin A
#define P_B 23 // Pin B
#define P_C 18 // Pin C
#define P_OE 4 // Pin Output Enable
```
### Réduction du bruit d'affichage
```cpp
#define PxMATRIX_SPI_FREQUENCY 8000000 // Réduire si bruit
```
## 📋 Checklist de Test
- [ ] ESP32 se connecte au WiFi
- [ ] Interface web accessible
- [ ] Heure s'affiche correctement
- [ ] Date défile en bas
- [ ] Texte personnalisé fonctionne
- [ ] Changement de couleurs (mode 2)
- [ ] Réglage luminosité
- [ ] Sauvegarde des paramètres
## 🎯 Prêt à utiliser !
Une fois tout testé, votre horloge affichera :
- **Heure** en haut (HH:MM avec : clignotant)
- **Date et texte** défilant en bas
- **Couleurs** selon le mode choisi
- **Configuration** via navigateur web
Clé d'accès web : **p10rgbesp32ws**
+245
View File
@@ -0,0 +1,245 @@
# ESP32 P10 RGB 32x16 Digital Clock - PlatformIO Version
## Description
Horloge numérique utilisant un panneau P10 RGB 32x16 avec ESP32, module RTC DS3231 et interface web de configuration.
Version adaptée pour PlatformIO à partir du code Arduino IDE original.
## Matériel Requis
- **ESP32 DEVKIT V1**
- **Panneau P10 RGB 32x16 HUB75** (Scan 1/8)
- Référence utilisée : P10-2727-8S-32X16-A
- ICs : RUC7258D, DP5125D, 74HC245KA
- **Module RTC DS3231**
- **Alimentation 5V** (importante pour le panneau P10)
## Brochage
### Connexions P10 HUB75
```
HUB75 Pin | ESP32 Pin
----------|----------
R1 | GPIO 2
G1 | GPIO 15
B1 | GPIO 4
GND | GND
R2 | GPIO 16
G2 | GPIO 17
B2 | GPIO 5
GND | GND
A | GPIO 19
B | GPIO 23
C | GPIO 18
GND | GND
CLK | GPIO 14
STB | GPIO 32
OE | GPIO 33
GND | GND
```
**Note :** Ces connexions peuvent varier selon votre panneau P10. Consultez le code et ajustez si nécessaire.
### Connexions RTC DS3231
```
DS3231 | ESP32
-------|-------
VCC | 3.3V
GND | GND
SDA | GPIO 21
SCL | GPIO 22
```
## Installation et Configuration
### 1. Installation PlatformIO
Si vous n'avez pas encore PlatformIO :
```bash
# Via VS Code
# Installez l'extension PlatformIO IDE
# Via ligne de commande
pip install platformio
```
### 2. Configuration du projet
1. **Clonez ou téléchargez** ce projet
2. **Ouvrez le dossier** dans VS Code avec PlatformIO
3. **Modifiez les paramètres WiFi** dans `src/main.cpp` :
```cpp
// Configuration WiFi - Modifiez selon vos besoins
const char* ssid = "VOTRE_WIFI_SSID";
const char* password = "VOTRE_MOT_DE_PASSE_WIFI";
```
### 3. Compilation et téléversement
```bash
# Compilation
pio run
# Téléversement
pio run --target upload
# Monitoring série
pio device monitor
```
Ou utilisez les boutons PlatformIO dans VS Code.
## Structure du Projet
```
├── platformio.ini # Configuration PlatformIO
├── src/
│ └── main.cpp # Code principal de l'horloge
├── include/
│ └── PageIndex.h # Interface web HTML
├── examples/
│ ├── rtc_test.cpp # Test du module RTC
│ ├── p10_test.cpp # Test du panneau P10
│ └── nvs_erase.cpp # Effacement mémoire NVS
└── README.md # Ce fichier
```
## Utilisation
### Premier démarrage
1. **Téléversez le code** sur l'ESP32
2. **Ouvrez le moniteur série** (115200 baud)
3. L'ESP32 va essayer de se connecter à votre WiFi
4. Si la connexion échoue, il créera un point d'accès WiFi
### Configuration via interface web
1. **Connectez-vous au réseau WiFi** :
- Si connecté à votre WiFi : utilisez l'IP affichée dans le moniteur série
- Sinon connectez-vous au point d'accès "ESP32_Clock" (mot de passe : "esp32clock")
2. **Ouvrez votre navigateur** et allez à l'adresse IP
3. **Utilisez la clé** : `p10rgbesp32ws`
4. **Configurez** :
- Date et heure
- Mode d'affichage (1 = couleurs manuelles, 2 = couleurs automatiques)
- Luminosité (0-255)
- Couleurs (en mode 1)
- Texte défilant
- Vitesse de défilement
### Configuration de l'heure RTC
Vous pouvez aussi configurer l'heure directement via le moniteur série :
```
SET,2024,8,1,14,30,0
```
Format : `SET,année,mois,jour,heure,minute,seconde`
## Programmes d'exemple
### Test du module RTC
```bash
# Modifiez src/main.cpp pour inclure examples/rtc_test.cpp
# Ou créez un nouveau projet avec ce fichier
```
### Test du panneau P10
```bash
# Modifiez src/main.cpp pour inclure examples/p10_test.cpp
# Utile pour vérifier les connexions
```
### Effacement mémoire NVS
```bash
# Utilisez examples/nvs_erase.cpp si vous voulez
# réinitialiser toutes les préférences sauvegardées
```
## Modes d'affichage
### Mode 1 - Couleurs manuelles
- Couleurs fixes définissables via l'interface web
- Couleur de l'horloge personnalisable
- Couleur de la date personnalisable
- Couleur du texte personnalisable
### Mode 2 - Couleurs automatiques
- Changement automatique des couleurs
- Cycle entre : Rouge, Vert, Bleu, Jaune, Cyan, Magenta, Blanc
## Paramètres configurables
- **Date et heure** : via interface web ou moniteur série
- **Luminosité** : 0-255
- **Mode d'affichage** : 1 ou 2
- **Couleurs RGB** : 0-255 pour chaque composante (mode 1)
- **Texte défilant** : jusqu'à 150 caractères
- **Vitesse de défilement** : 10-100 (plus bas = plus rapide)
## Dépannage
### Problèmes d'affichage
- Vérifiez l'alimentation 5V (importante !)
- Vérifiez les connexions HUB75
- Ajustez `PxMATRIX_SPI_FREQUENCY` si vous voyez du bruit
### Problèmes WiFi
- Vérifiez le SSID et le mot de passe
- L'ESP32 basculera en mode point d'accès si la connexion échoue
### Problèmes RTC
- Vérifiez les connexions I2C (SDA/SCL)
- Testez avec le programme `examples/rtc_test.cpp`
### Réinitialisation
- Utilisez `examples/nvs_erase.cpp` pour effacer toutes les préférences
## Configuration avancée
### Modification de la fréquence SPI
```cpp
// Dans src/main.cpp, modifiez si vous avez du bruit sur l'affichage
#define PxMATRIX_SPI_FREQUENCY 10000000 // Valeurs possibles: 20000000, 15000000, 10000000, 8000000
```
### Modification des pins
```cpp
// Modifiez ces valeurs dans src/main.cpp si votre câblage est différent
#define P_LAT 5
#define P_A 19
#define P_B 23
#define P_C 18
#define P_OE 4
```
## Bibliothèques utilisées
- **PxMatrix** : Contrôle du panneau P10 RGB
- **RTClib** : Interface avec le module DS3231
- **Preferences** : Sauvegarde des paramètres dans la flash
- **WiFi** : Connectivité réseau
- **WebServer** : Interface web de configuration
## Support
Pour obtenir de l'aide :
1. Vérifiez ce README
2. Consultez les programmes d'exemple
3. Vérifiez les connexions et l'alimentation
4. Consultez la documentation des bibliothèques utilisées
## Crédit
Projet original adapté pour PlatformIO. Code source basé sur les exemples et tutoriels de la communauté ESP32/Arduino.
Bibliothèques utilisées :
- PxMatrix par 2dom (Dominic Buchstaller)
- RTClib par Adafruit
- Adafruit GFX Library
- Adafruit BusIO
+214
View File
@@ -0,0 +1,214 @@
# Schémas de Connexion - ESP32 P10 Digital Clock
## Vue d'ensemble du système
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Alimentation │ │ ESP32 │ │ Panneau P10 │
│ 5V │ │ DEVKIT V1 │ │ RGB 32x16 │
├─────────────────┤ ├─────────────────┤ ├─────────────────┤
│ + ────────────────────│ VIN │ │ │
│ - ────────────────────│ GND │ │ │
└─────────────────┘ │ │ │ │
│ │ │ │
┌─────────────────┐ │ │ │ │
│ RTC DS3231 │ │ │ │ │
├─────────────────┤ │ │ │ │
│ VCC ──────────────────│ 3.3V │ │ │
│ GND ──────────────────│ GND │ │ │
│ SDA ──────────────────│ GPIO21 │ │ │
│ SCL ──────────────────│ GPIO22 │ │ │
└─────────────────┘ │ │ │ │
│ GPIO2 ─────────────────│ R1 │
│ GPIO15 ─────────────────│ G1 │
│ GPIO4 ─────────────────│ B1 │
│ GPIO16 ─────────────────│ R2 │
│ GPIO17 ─────────────────│ G2 │
│ GPIO5 ─────────────────│ B2 │
│ GPIO19 ─────────────────│ A │
│ GPIO23 ─────────────────│ B │
│ GPIO18 ─────────────────│ C │
│ GPIO14 ─────────────────│ CLK │
│ GPIO32 ─────────────────│ STB (LAT) │
│ GPIO33 ─────────────────│ OE │
│ GND ─────────────────│ GND (multiple) │
└─────────────────┘ └─────────────────┘
```
## Connecteur HUB75 - Vue détaillée
```
HUB75 Connector (Vue de face)
┌─────────────────────────┐
│ 1 2 3 4 5 6 7 8 │
│ ┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐│
│ │R││G││B││ ││R││G││B││ ││
│ │1││1││1││G││2││2││2││G││
│ └─┘└─┘└─┘│N│└─┘└─┘└─┘│N││
│ │D│ │D││
│ └─┘ └─┘│
├─────────────────────────┤
│ 9 10 11 12 13 14 15 16 │
│ ┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐│
│ │A││B││C││G││C││S││O││G││
│ │ ││ ││ ││N││L││T││E││N││
│ │ ││ ││ ││D││K││B││ ││D││
│ └─┘└─┘└─┘└─┘└─┘└─┘└─┘└─┘│
└─────────────────────────┘
Pin 1 (R1) → ESP32 GPIO2 Pin 9 (A) → ESP32 GPIO19
Pin 2 (G1) → ESP32 GPIO15 Pin 10 (B) → ESP32 GPIO23
Pin 3 (B1) → ESP32 GPIO4 Pin 11 (C) → ESP32 GPIO18
Pin 4 (GND) → ESP32 GND Pin 12 (GND) → ESP32 GND
Pin 5 (R2) → ESP32 GPIO16 Pin 13 (CLK) → ESP32 GPIO14
Pin 6 (G2) → ESP32 GPIO17 Pin 14 (STB) → ESP32 GPIO32
Pin 7 (B2) → ESP32 GPIO5 Pin 15 (OE) → ESP32 GPIO33
Pin 8 (GND) → ESP32 GND Pin 16 (GND) → ESP32 GND
```
## ESP32 DEVKIT V1 - Pinout
```
ESP32 DEVKIT V1
┌─────────────────────────┐
│ │
│ ● ● │
3.3V │ [ ] [ ] │ VIN ──── Alimentation 5V+
GND │ [ ] [ ] │ GND ──── Alimentation 5V-
Touch │ [ ] [ ] │ GPIO13
Touch │ [ ] [ ] │ GPIO12
Touch │ [ ] [ ] │ GPIO14 ──── CLK (P10)
Touch │ [ ] [ ] │ GPIO27
│ [ ] [ ] │ GPIO26
│ [ ] [ ] │ GPIO25
│ [ ] [ ] │ GPIO33 ──── OE (P10)
│ [ ] [ ] │ GPIO32 ──── STB (P10)
│ [ ] [ ] │ GPIO35
│ [ ] [ ] │ GPIO34
│ [ ] [ ] │ GPIO39
│ [ ] [ ] │ GPIO36
EN │ [ ] [ ] │ GPIO23 ──── B (P10)
│ [ ] [ ] │ GPIO22 ──── SCL (RTC)
GPIO2 ──│ [ ] [ ] │ GPIO21 ──── SDA (RTC)
GPIO4 ──│ [ ] [ ] │ GPIO19 ──── A (P10)
GPIO16 ──│ [ ] [ ] │ GPIO18 ──── C (P10)
GPIO17 ──│ [ ] [ ] │ GPIO5 ──── B2 (P10)
GPIO5 ──│ [ ] [ ] │ TX
GPIO15 ──│ [ ] [ ] │ RX
│ │
│ ┌─────────────┐ │
│ │ ESP32 │ │
│ │ WiFi │ │
│ │ Bluetooth │ │
│ └─────────────┘ │
│ │
│ USB ┌─────────────┐ │
│ ──── │ │ │
└──────┴─────────────┴───┘
Connexions P10:
GPIO2 → R1 GPIO19 → A
GPIO15 → G1 GPIO23 → B
GPIO4 → B1 GPIO18 → C
GPIO16 → R2 GPIO14 → CLK
GPIO17 → G2 GPIO32 → STB
GPIO5 → B2 GPIO33 → OE
Connexions RTC:
GPIO21 → SDA 3.3V → VCC
GPIO22 → SCL GND → GND
```
## Module RTC DS3231
```
┌─────────────────┐
│ RTC DS3231 │
├─────────────────┤
│ VCC ── 3.3V │ ──── ESP32 3.3V
│ GND ── GND │ ──── ESP32 GND
│ SCL ── Clock │ ──── ESP32 GPIO22
│ SDA ── Data │ ──── ESP32 GPIO21
└─────────────────┘
Note: Certains modules ont aussi:
- 32K (sortie 32kHz) - Non utilisé
- SQW (signal carré) - Non utilisé
- RST (reset) - Non utilisé
```
## Alimentation - IMPORTANT !
```
┌─────────────────┐ ┌─────────────────┐
│ Alimentation │ │ ESP32 │
│ 5V/3A │ │ (via USB ou │
│ │ │ pin VIN) │
├─────────────────┤ ├─────────────────┤
│ +5V ────────────┼─┬───┼── VIN │
│ GND ────────────┼─┼───┼── GND │
└─────────────────┘ │ └─────────────────┘
│ ┌─────────────────┐
│ │ Panneau P10 │
│ │ RGB 32x16 │
│ ├─────────────────┤
└───┼── +5V │
│ (via HUB75) │
└─────────────────┘
ATTENTION:
- Le panneau P10 nécessite du 5V avec suffisamment de courant
- Utilisez une alimentation 5V/3A minimum
- L'ESP32 peut être alimenté via USB pour les tests
- Pour un fonctionnement permanent, alimentez l'ESP32 via VIN avec du 5V
```
## Câblage recommandé
```
Étape 1: Connexions d'alimentation
ESP32 VIN ← 5V+
ESP32 GND ← 5V-
P10 +5V ← 5V+ (via HUB75)
P10 GND ← 5V- (via HUB75, plusieurs pins)
Étape 2: Connexions I2C (RTC)
ESP32 GPIO21 ← RTC SDA
ESP32 GPIO22 ← RTC SCL
ESP32 3.3V ← RTC VCC
ESP32 GND ← RTC GND
Étape 3: Connexions HUB75 (P10)
ESP32 GPIO2 ← P10 R1
ESP32 GPIO15 ← P10 G1
ESP32 GPIO4 ← P10 B1
ESP32 GPIO16 ← P10 R2
ESP32 GPIO17 ← P10 G2
ESP32 GPIO5 ← P10 B2
ESP32 GPIO19 ← P10 A
ESP32 GPIO23 ← P10 B
ESP32 GPIO18 ← P10 C
ESP32 GPIO14 ← P10 CLK
ESP32 GPIO32 ← P10 STB/LAT
ESP32 GPIO33 ← P10 OE
ESP32 GND ← P10 GND (plusieurs connexions)
```
## Vérification des connexions
Utilisez un multimètre pour vérifier :
1. **Continuité** entre ESP32 et P10 pour chaque signal
2. **Absence de court-circuit** entre VCC et GND
3. **Tension 5V** sur les pins d'alimentation du P10
4. **Tension 3.3V** sur le module RTC
## Troubleshooting connexions
| Problème | Vérification |
|----------|-------------|
| Affichage noir | Alimentation 5V, connexion OE |
| Couleurs incorrectes | Connexions R1,G1,B1,R2,G2,B2 |
| Affichage instable | Connexions CLK, STB, GND |
| Position incorrecte | Connexions A, B, C |
| RTC ne fonctionne pas | Connexions SDA, SCL, alimentation 3.3V |
+293
View File
@@ -0,0 +1,293 @@
/**
* ESP32 P10 RGB Cascade Test
* Test pour vérifier le bon fonctionnement des panneaux P10 en cascade
*
* Ce test affiche :
* - Des bordures pour vérifier l'alignement des panneaux
* - La numérotation de chaque panneau
* - Des tests de couleurs
* - Un texte défilant sur toute la largeur
*
* Compatible avec toutes les configurations de cascade définies dans platformio.ini
*/
#define PxMATRIX_SPI_FREQUENCY 10000000
#include <Arduino.h>
#include <PxMatrix.h>
// Pins pour la matrice LED
#define P_LAT 5
#define P_A 19
#define P_B 23
#define P_C 18
#define P_OE 4
// Configuration des panneaux - définie par les build flags
#ifndef MATRIX_WIDTH
#define MATRIX_WIDTH 32
#endif
#ifndef MATRIX_HEIGHT
#define MATRIX_HEIGHT 16
#endif
#ifndef MATRIX_PANELS_X
#define MATRIX_PANELS_X 1
#endif
#ifndef MATRIX_PANELS_Y
#define MATRIX_PANELS_Y 1
#endif
// Calcul des dimensions totales
#define TOTAL_WIDTH (MATRIX_WIDTH * MATRIX_PANELS_X)
#define TOTAL_HEIGHT (MATRIX_HEIGHT * MATRIX_PANELS_Y)
// Configuration du timer
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
// Temps d'affichage ajusté selon le nombre de panneaux
uint8_t display_draw_time = (MATRIX_PANELS_X * MATRIX_PANELS_Y > 4) ? 20 : 30;
// Objet matrice
PxMATRIX display(TOTAL_WIDTH, TOTAL_HEIGHT, P_LAT, P_OE, P_A, P_B, P_C);
// Couleurs prédéfinies
uint16_t myRED = display.color565(255, 0, 0);
uint16_t myGREEN = display.color565(0, 255, 0);
uint16_t myBLUE = display.color565(0, 0, 255);
uint16_t myYELLOW = display.color565(255, 255, 0);
uint16_t myCYAN = display.color565(0, 255, 255);
uint16_t myMAGENTA = display.color565(255, 0, 255);
uint16_t myWHITE = display.color565(255, 255, 255);
uint16_t myBLACK = display.color565(0, 0, 0);
uint16_t myORANGE = display.color565(255, 165, 0);
uint16_t colors[] = {myRED, myGREEN, myBLUE, myYELLOW, myCYAN, myMAGENTA, myWHITE, myORANGE};
int numColors = sizeof(colors) / sizeof(colors[0]);
// Variables pour le texte défilant
long scrollX = TOTAL_WIDTH;
unsigned long lastScrollTime = 0;
int scrollSpeed = 50;
const char* scrollText = "=== CASCADE TEST - ESP32 P10 RGB PANELS ===";
// Gestionnaire d'interruption pour l'affichage
void IRAM_ATTR display_updater() {
portENTER_CRITICAL_ISR(&timerMux);
display.display(display_draw_time);
portEXIT_CRITICAL_ISR(&timerMux);
}
// Activation du timer d'affichage
void display_update_enable() {
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &display_updater, true);
timerAlarmWrite(timer, 1500, true);
timerAlarmEnable(timer);
}
// Test des bordures et alignement des panneaux
void testPanelAlignment() {
Serial.println("Testing panel alignment...");
display.clearDisplay();
// Bordure extérieure
display.drawRect(0, 0, TOTAL_WIDTH, TOTAL_HEIGHT, myWHITE);
// Lignes de séparation entre panneaux horizontaux
for (int i = 1; i < MATRIX_PANELS_X; i++) {
int x = i * MATRIX_WIDTH;
display.drawLine(x, 0, x, TOTAL_HEIGHT - 1, myRED);
}
// Lignes de séparation entre panneaux verticaux
for (int i = 1; i < MATRIX_PANELS_Y; i++) {
int y = i * MATRIX_HEIGHT;
display.drawLine(0, y, TOTAL_WIDTH - 1, y, myGREEN);
}
delay(3000);
}
// Test de numérotation des panneaux
void testPanelNumbering() {
Serial.println("Testing panel numbering...");
display.clearDisplay();
display.setTextSize(1);
for (int py = 0; py < MATRIX_PANELS_Y; py++) {
for (int px = 0; px < MATRIX_PANELS_X; px++) {
int panelNum = py * MATRIX_PANELS_X + px + 1;
uint16_t color = colors[panelNum % numColors];
// Position au centre de chaque panneau
int centerX = px * MATRIX_WIDTH + 2;
int centerY = py * MATRIX_HEIGHT + 2;
// Fond coloré pour le panneau
display.fillRect(px * MATRIX_WIDTH + 1, py * MATRIX_HEIGHT + 1,
MATRIX_WIDTH - 2, MATRIX_HEIGHT - 2, color);
// Numéro du panneau en noir
display.setTextColor(myBLACK);
display.setCursor(centerX, centerY);
display.print("P");
display.setCursor(centerX, centerY + 8);
display.print(panelNum);
delay(800);
}
}
delay(3000);
}
// Test des couleurs sur tous les panneaux
void testColors() {
Serial.println("Testing colors...");
for (int i = 0; i < numColors; i++) {
display.fillScreen(colors[i]);
delay(800);
}
display.clearDisplay();
delay(500);
}
// Test du texte défilant
void testScrollingText() {
Serial.println("Testing scrolling text...");
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(myWHITE);
// Calculer la largeur approximative du texte
int textWidth = strlen(scrollText) * 6;
// Faire défiler le texte 2 fois
for (int cycle = 0; cycle < 2; cycle++) {
scrollX = TOTAL_WIDTH;
while (scrollX > -textWidth) {
unsigned long currentTime = millis();
if (currentTime - lastScrollTime >= scrollSpeed) {
lastScrollTime = currentTime;
// Effacer la ligne de texte
display.fillRect(0, 8, TOTAL_WIDTH, 8, myBLACK);
// Afficher le texte à la nouvelle position
display.setCursor(scrollX, 8);
display.print(scrollText);
scrollX--;
}
delay(5);
}
}
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n=== ESP32 P10 RGB CASCADE TEST ===");
Serial.printf("Configuration: %dx%d panels (%dx%d total resolution)\n",
MATRIX_PANELS_X, MATRIX_PANELS_Y, TOTAL_WIDTH, TOTAL_HEIGHT);
Serial.printf("Draw time: %d\n", display_draw_time);
// Initialisation de l'affichage
display.begin(8);
display_update_enable();
display.clearDisplay();
// Luminosité adaptée au nombre de panneaux
int brightness = 150;
if (MATRIX_PANELS_X > 2) brightness = 100;
if (MATRIX_PANELS_X > 4) brightness = 80;
if (MATRIX_PANELS_X > 6) brightness = 60;
display.setBrightness(brightness);
Serial.printf("Brightness set to: %d\n", brightness);
display.setTextWrap(false);
display.setRotation(0);
// Message de démarrage
display.setTextSize(1);
display.setTextColor(myWHITE);
// Calculer position centrée
String startMsg = "CASCADE TEST";
int msgWidth = startMsg.length() * 6;
int startX = (TOTAL_WIDTH - msgWidth) / 2;
if (startX < 0) startX = 0;
display.setCursor(startX, 0);
display.print(startMsg);
if (TOTAL_HEIGHT > 8) {
String configMsg = String(MATRIX_PANELS_X) + "x" + String(MATRIX_PANELS_Y) + " PANELS";
int configWidth = configMsg.length() * 6;
int configX = (TOTAL_WIDTH - configWidth) / 2;
if (configX < 0) configX = 0;
display.setCursor(configX, 8);
display.print(configMsg);
}
delay(3000);
Serial.println("Starting cascade tests...");
}
void loop() {
// Séquence de tests
Serial.println("\n--- Test Cycle Starting ---");
// 1. Test d'alignement des panneaux
testPanelAlignment();
// 2. Test de numérotation des panneaux
testPanelNumbering();
// 3. Test des couleurs
testColors();
// 4. Test du texte défilant
testScrollingText();
// Message de fin de cycle
display.clearDisplay();
display.setTextColor(myGREEN);
String okMsg = "TESTS OK";
int okWidth = okMsg.length() * 6;
int okX = (TOTAL_WIDTH - okWidth) / 2;
if (okX < 0) okX = 0;
display.setCursor(okX, 0);
display.print(okMsg);
if (TOTAL_HEIGHT > 8) {
String restartMsg = "RESTARTING...";
int restartWidth = restartMsg.length() * 6;
int restartX = (TOTAL_WIDTH - restartWidth) / 2;
if (restartX < 0) restartX = 0;
display.setCursor(restartX, 8);
display.print(restartMsg);
}
Serial.println("--- Test Cycle Completed ---");
Serial.println("Restarting in 5 seconds...\n");
delay(5000);
}
+27
View File
@@ -0,0 +1,27 @@
/**
* Effacement et reformatage de la mémoire NVS
* Utilisez ce programme si vous voulez réinitialiser la mémoire de préférences
*/
#include <Arduino.h>
#include <nvs_flash.h>
void setup() {
Serial.begin(115200);
Serial.println();
delay(1000);
Serial.println("=== NVS Memory Erase Tool ===");
Serial.println("Erasing the NVS partition...");
nvs_flash_erase(); // Effacer la partition NVS
Serial.println("Initializing the NVS partition...");
nvs_flash_init(); // Initialiser la partition NVS
Serial.println("NVS Memory erase completed successfully.");
Serial.println("You can now upload your main program.");
}
void loop() {
delay(10);
}
+156
View File
@@ -0,0 +1,156 @@
/**
* Test de la matrice P10 RGB 32x16
* Ce programme permet de tester l'affichage sur la matrice P10
*/
#include <Arduino.h>
#include <PxMatrix.h>
// Configuration SPI
#define PxMATRIX_SPI_FREQUENCY 10000000
// Pins pour la matrice LED
#define P_LAT 5
#define P_A 19
#define P_B 23
#define P_C 18
#define P_OE 4
// Dimensions de la matrice
#define MATRIX_WIDTH 32
#define MATRIX_HEIGHT 16
// Configuration du timer
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
// Temps d'affichage
uint8_t display_draw_time = 30;
// Objet matrice
PxMATRIX display(MATRIX_WIDTH, MATRIX_HEIGHT, P_LAT, P_OE, P_A, P_B, P_C);
// Couleurs
uint16_t myRED = display.color565(255, 0, 0);
uint16_t myGREEN = display.color565(0, 255, 0);
uint16_t myBLUE = display.color565(0, 0, 255);
uint16_t myYELLOW = display.color565(255, 255, 0);
uint16_t myCYAN = display.color565(0, 255, 255);
uint16_t myFUCHSIA = display.color565(255, 0, 255);
uint16_t myWHITE = display.color565(255, 255, 255);
uint16_t myBLACK = display.color565(0, 0, 0);
uint16_t myCOLOR_ARRAY[4] = {myRED, myGREEN, myBLUE, myWHITE};
// Gestionnaire d'interruption pour l'affichage
void IRAM_ATTR display_updater() {
portENTER_CRITICAL_ISR(&timerMux);
display.display(display_draw_time);
portEXIT_CRITICAL_ISR(&timerMux);
}
// Activation/désactivation du timer d'affichage
void display_update_enable(bool is_enable) {
if (is_enable) {
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &display_updater, true);
timerAlarmWrite(timer, 1500, true);
timerAlarmEnable(timer);
} else {
timerDetachInterrupt(timer);
timerAlarmDisable(timer);
}
}
void setup() {
delay(2000);
Serial.begin(115200);
Serial.println();
Serial.println("=== Test P10 RGB 32x16 Matrix ===");
// Initialisation de l'affichage
display.begin(8); // Valeur 8 pour un panneau 1/8 scan
delay(100);
// Activation des interruptions timer
display_update_enable(true);
delay(100);
display.clearDisplay();
delay(1000);
display.setBrightness(125); // 0-255
delay(100);
// Test des couleurs pleines
Serial.println("Testing full screen colors...");
display.fillScreen(myRED);
delay(1000);
display.fillScreen(myGREEN);
delay(1000);
display.fillScreen(myBLUE);
delay(1000);
display.fillScreen(myWHITE);
delay(1000);
display.clearDisplay();
delay(1000);
display.setTextWrap(false);
display.setTextSize(1);
display.setRotation(0);
delay(100);
// Test d'affichage de texte
Serial.println("Testing text display...");
display.fillScreen(myRED);
display.setTextColor(myWHITE);
display.setCursor(0, 0);
display.print("TEST");
display.setCursor(15, 9);
display.print("P10");
delay(2500);
display.clearDisplay();
delay(1000);
Serial.println("Setup completed. Starting color loop...");
}
void loop() {
int myCOLOR_ARRAY_Length = sizeof(myCOLOR_ARRAY) / sizeof(myCOLOR_ARRAY[0]);
for (byte i = 0; i < myCOLOR_ARRAY_Length; i++) {
// Test position 1
display.setTextColor(myCOLOR_ARRAY[i]);
display.setCursor(0, 0);
display.print("1234");
display.setCursor(0, 9);
display.print("ABCD");
delay(2500);
display.clearDisplay();
delay(1000);
// Test position 2
display.setTextColor(myCOLOR_ARRAY[i]);
display.setCursor(4, 0);
display.print("1234");
display.setCursor(4, 9);
display.print("ABCD");
delay(2500);
display.clearDisplay();
delay(1000);
// Test position 3
display.setCursor(9, 0);
display.print("1234");
display.setCursor(9, 9);
display.print("ABCD");
delay(2500);
display.clearDisplay();
delay(1000);
}
}
+160
View File
@@ -0,0 +1,160 @@
/**
* Test du module RTC DS3231
* Ce programme permet de tester et configurer le module RTC
*/
#include <Arduino.h>
#include <RTClib.h>
RTC_DS3231 rtc;
char daysOfTheWeek[8][10] = {"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "ERROR"};
String inputString = "";
bool stringComplete = false;
int d_year;
byte d_month, d_day, daysOfTheWeek_Val;
byte t_hour, t_minute, t_second;
unsigned long prevMill_Update_DateTime = 0;
const long interval_Update_DateTime = 1000;
// Fonction pour traiter les données reçues
String getValue(String data, char separator, int index) {
int found = 0;
int strIndex[] = { 0, -1 };
int maxIndex = data.length() - 1;
for (int i = 0; i <= maxIndex && found <= index; i++) {
if (data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
// Gestion des événements série
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
if (inChar == '\n') {
stringComplete = true;
return;
}
inputString += inChar;
}
}
// Récupération date/heure
void get_DateTime() {
DateTime now = rtc.now();
d_year = now.year();
d_month = now.month();
d_day = now.day();
daysOfTheWeek_Val = now.dayOfTheWeek();
if (daysOfTheWeek_Val > 7 || daysOfTheWeek_Val < 0) daysOfTheWeek_Val = 7;
t_hour = now.hour();
t_minute = now.minute();
t_second = now.second();
char full_DateTime[60];
sprintf(full_DateTime, "%s | %02d-%02d-%d | %02d:%02d:%02d",
daysOfTheWeek[daysOfTheWeek_Val], d_day, d_month, d_year, t_hour, t_minute, t_second);
Serial.print("Date Time : ");
Serial.println(full_DateTime);
}
void setup() {
delay(2000);
Serial.begin(115200);
inputString.reserve(200);
Serial.println();
Serial.println("------------");
Serial.println("Starting the DS3231 RTC module.");
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
Serial.println("Successfully started the DS3231 RTC module.");
Serial.println("------------");
Serial.println();
Serial.println();
Serial.println("------------");
Serial.println("Serial monitor settings :");
Serial.println("- End Char : Newline");
Serial.println("- Baud Rate : 115200");
Serial.println("------------");
Serial.println();
Serial.println();
Serial.println("------------");
Serial.println("Example command to set the time and date on the RTC module : ");
Serial.println("SET,2024,8,1,12,30,0");
Serial.println();
Serial.println("SET = command to set.");
Serial.println("2024 = Year.");
Serial.println("8 = Month.");
Serial.println("1 = Day.");
Serial.println("12 = Hour.");
Serial.println("30 = Minute.");
Serial.println("0 = Second.");
Serial.println("------------");
Serial.println();
delay(3000);
}
void loop() {
serialEvent();
unsigned long currentMillis_Update_DateTime = millis();
if (currentMillis_Update_DateTime - prevMill_Update_DateTime >= interval_Update_DateTime) {
prevMill_Update_DateTime = currentMillis_Update_DateTime;
get_DateTime();
}
if (stringComplete) {
Serial.print("Input String : ");
Serial.println(inputString);
String command = getValue(inputString, ',', 0);
if (command == "SET") {
Serial.println();
Serial.println("------------");
Serial.println("Set the Time and Date of the DS3231 RTC Module.");
Serial.println("Incoming settings data : ");
d_year = getValue(inputString, ',', 1).toInt();
d_month = getValue(inputString, ',', 2).toInt();
d_day = getValue(inputString, ',', 3).toInt();
t_hour = getValue(inputString, ',', 4).toInt();
t_minute = getValue(inputString, ',',5).toInt();
t_second = getValue(inputString, ',', 6).toInt();
Serial.print("- Year : ");Serial.println(d_year);
Serial.print("- Month : ");Serial.println(d_month);
Serial.print("- Day : ");Serial.println(d_day);
Serial.print("- Hour : ");Serial.println(t_hour);
Serial.print("- Minute : ");Serial.println(t_minute);
Serial.print("- Second : ");Serial.println(t_second);
Serial.println("Set Time and Date...");
rtc.adjust(DateTime(d_year, d_month, d_day, t_hour, t_minute, t_second));
Serial.println("Setting the Time and Date has been completed.");
Serial.println("------------");
Serial.println();
}
inputString = "";
stringComplete = false;
}
}
+522
View File
@@ -0,0 +1,522 @@
#ifndef PAGE_INDEX_H
#define PAGE_INDEX_H
#include <Arduino.h>
const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<title>Digital Clcok & Scrolling Text with ESP32 and P10 RGB 32x16</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html {font-family: Helvetica, sans-serif;}
h1 {font-size: 1.1rem; color:#1976D2;}
label {font-size: 14px;}
.div_Form {
margin: auto;
width: 90%;
border:1px solid #D8D8D8;
border-radius: 10px;
background-color: #f2f2f2;
padding: 9px 9px;
}
.myButton {
display: inline-block;
padding: 3px 25px;
font-size: 13px;
cursor: pointer;
text-align: center;
text-decoration: none;
outline: none;
color: #fff;
background-color: #1976D2;
border: none;
border-radius: 8px;
box-shadow: 0 2px #999;
}
.myButton:hover {background-color: #104d89}
.myButton:active {background-color: #104d89; box-shadow: 0 1px #666; transform: translateY(2px);}
.myButton:disabled {background-color: #666; box-shadow: 0 1px #666; transform: translateY(2px);}
.myButtonX {background-color: #ff0000}
.myButtonX:hover {background-color: #7a0101}
.div_Form_Input {display: table; margin: 0px; padding: 0px; box-sizing: border-box;}
.div_Input_Text {display: table-cell; width: 100%;}
.div_Input_Text > input {width:99.5%; margin-left: 0px; padding-left: 2px; box-sizing: border-box;}
table, th, td {
border: 0px solid black;
border-collapse: collapse;
font-size: 14px;
}
.div_Logs {
width: 100%;
height: 150px;
border: 1px solid #D8D8D8;
border-radius: 5px;
background-color: #ffffff;
overflow-y: scroll;
font-family: 'Courier New', monospace;
font-size: 12px;
padding: 5px;
box-sizing: border-box;
}
</style>
<body>
<div style="margin: 10px">
<h1>Digital Clock & Scrolling Text with ESP32 and P10 RGB 32x16</h1>
<div class="div_Form">
<div style="margin-bottom: 10px;">
<label>Key : </label>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="text" id="key" maxlength="20" placeholder="Enter key">
</div>
</div>
</div>
<div style="margin-bottom: 10px;">
<button class="myButton" onclick="getSettings()">Get Settings</button>
</div>
</div>
<br>
<div class="div_Form">
<h3>Set Date & Time</h3>
<table style="width:100%">
<tr>
<td style="width:25%"><label>Year : </label></td>
<td style="width:75%">
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="d_Year" min="2020" max="2099" value="2024">
</div>
</div>
</td>
</tr>
<tr>
<td><label>Month : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="d_Month" min="1" max="12" value="1">
</div>
</div>
</td>
</tr>
<tr>
<td><label>Day : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="d_Day" min="1" max="31" value="1">
</div>
</div>
</td>
</tr>
<tr>
<td><label>Hour : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="t_Hour" min="0" max="23" value="12">
</div>
</div>
</td>
</tr>
<tr>
<td><label>Minute : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="t_Minute" min="0" max="59" value="0">
</div>
</div>
</td>
</tr>
<tr>
<td><label>Second : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="t_Second" min="0" max="59" value="0">
</div>
</div>
</td>
</tr>
</table>
<div style="margin-top: 10px;">
<button class="myButton" onclick="setTimeDate()">Set Date & Time</button>
</div>
</div>
<br>
<div class="div_Form">
<h3>Display Settings</h3>
<table style="width:100%">
<tr>
<td style="width:25%"><label>Display Mode : </label></td>
<td style="width:75%">
<select id="input_Display_Mode" style="width:100%">
<option value="1">Mode 1 (Manual Colors)</option>
<option value="2">Mode 2 (Auto Color Change)</option>
</select>
</td>
</tr>
<tr>
<td><label>Brightness : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="input_Brightness" min="0" max="255" value="125">
</div>
</div>
</td>
</tr>
<tr>
<td><label>Scroll Speed : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="input_Scrolling_Speed" min="10" max="100" value="45">
</div>
</div>
</td>
</tr>
</table>
<div style="margin-top: 10px;">
<button class="myButton" onclick="setDisplayMode()">Set Display Mode</button>
<button class="myButton" onclick="setBrightness()">Set Brightness</button>
<button class="myButton" onclick="setScrollingSpeed()">Set Scroll Speed</button>
</div>
</div>
<br>
<div class="div_Form">
<h3>Color Settings (Mode 1 Only)</h3>
<table style="width:100%">
<tr>
<td colspan="2"><label><strong>Clock Color (RGB)</strong></label></td>
</tr>
<tr>
<td style="width:10%"><label>R : </label></td>
<td style="width:90%">
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="Color_Clock_R" min="0" max="255" value="255">
</div>
</div>
</td>
</tr>
<tr>
<td><label>G : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="Color_Clock_G" min="0" max="255" value="0">
</div>
</div>
</td>
</tr>
<tr>
<td><label>B : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="Color_Clock_B" min="0" max="255" value="0">
</div>
</div>
</td>
</tr>
</table>
<div style="margin-top: 10px;">
<button class="myButton" onclick="setColorClock()">Set Clock Color</button>
</div>
<br>
<table style="width:100%">
<tr>
<td colspan="2"><label><strong>Date Color (RGB)</strong></label></td>
</tr>
<tr>
<td style="width:10%"><label>R : </label></td>
<td style="width:90%">
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="Color_Date_R" min="0" max="255" value="0">
</div>
</div>
</td>
</tr>
<tr>
<td><label>G : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="Color_Date_G" min="0" max="255" value="255">
</div>
</div>
</td>
</tr>
<tr>
<td><label>B : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="Color_Date_B" min="0" max="255" value="0">
</div>
</div>
</td>
</tr>
</table>
<div style="margin-top: 10px;">
<button class="myButton" onclick="setColorDate()">Set Date Color</button>
</div>
<br>
<table style="width:100%">
<tr>
<td colspan="2"><label><strong>Text Color (RGB)</strong></label></td>
</tr>
<tr>
<td style="width:10%"><label>R : </label></td>
<td style="width:90%">
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="Color_Text_R" min="0" max="255" value="0">
</div>
</div>
</td>
</tr>
<tr>
<td><label>G : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="Color_Text_G" min="0" max="255" value="0">
</div>
</div>
</td>
</tr>
<tr>
<td><label>B : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="number" id="Color_Text_B" min="0" max="255" value="255">
</div>
</div>
</td>
</tr>
</table>
<div style="margin-top: 10px;">
<button class="myButton" onclick="setColorText()">Set Text Color</button>
</div>
</div>
<br>
<div class="div_Form">
<h3>Scrolling Text</h3>
<table style="width:100%">
<tr>
<td><label>Text : </label></td>
<td>
<div class="div_Form_Input">
<div class="div_Input_Text">
<input type="text" id="input_Scrolling_Text" maxlength="150" placeholder="Enter scrolling text">
</div>
</div>
</td>
</tr>
</table>
<div style="margin-top: 10px;">
<button class="myButton" onclick="setScrollingText()">Set Scrolling Text</button>
</div>
</div>
<br>
<div class="div_Form">
<h3>System</h3>
<button class="myButton myButtonX" onclick="resetSystem()">Reset System</button>
</div>
</div>
<script>
//________________________________________________________________________________ sendCommandToESP32()
function sendCommandToESP32(sta, msg) {
var xmlhttp;
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
if (this.responseText == "+ERR") {
alert("Error !\\rWrong Key !\\rPlease enter the correct key.");
return;
}
if (this.responseText == "+ERR_DM") {
alert("Error !\\rThis setting is only for Display Mode : 1. \\rPlease change the Display Mode to apply this setting.");
return;
}
if (sta == "get") {
apply_the_Received_Settings(this.responseText);
} else {
alert("Settings applied successfully!");
}
}
}
xmlhttp.open("GET", "settings?" + msg, true);
xmlhttp.send();
}
//________________________________________________________________________________
function getSettings() {
var key = document.getElementById("key").value;
if (key == "") {
alert("Please enter the key!");
return;
}
sendCommandToESP32("get", "key=" + key + "&sta=get");
}
function setTimeDate() {
var key = document.getElementById("key").value;
if (key == "") {
alert("Please enter the key!");
return;
}
var msg = "key=" + key + "&sta=setTimeDate";
msg += "&d_Year=" + document.getElementById("d_Year").value;
msg += "&d_Month=" + document.getElementById("d_Month").value;
msg += "&d_Day=" + document.getElementById("d_Day").value;
msg += "&t_Hour=" + document.getElementById("t_Hour").value;
msg += "&t_Minute=" + document.getElementById("t_Minute").value;
msg += "&t_Second=" + document.getElementById("t_Second").value;
sendCommandToESP32("set", msg);
}
function setDisplayMode() {
var key = document.getElementById("key").value;
if (key == "") {
alert("Please enter the key!");
return;
}
var msg = "key=" + key + "&sta=setDisplayMode";
msg += "&input_Display_Mode=" + document.getElementById("input_Display_Mode").value;
sendCommandToESP32("set", msg);
}
function setBrightness() {
var key = document.getElementById("key").value;
if (key == "") {
alert("Please enter the key!");
return;
}
var msg = "key=" + key + "&sta=setBrightness";
msg += "&input_Brightness=" + document.getElementById("input_Brightness").value;
sendCommandToESP32("set", msg);
}
function setScrollingSpeed() {
var key = document.getElementById("key").value;
if (key == "") {
alert("Please enter the key!");
return;
}
var msg = "key=" + key + "&sta=setScrollingSpeed";
msg += "&input_Scrolling_Speed=" + document.getElementById("input_Scrolling_Speed").value;
sendCommandToESP32("set", msg);
}
function setColorClock() {
var key = document.getElementById("key").value;
if (key == "") {
alert("Please enter the key!");
return;
}
var msg = "key=" + key + "&sta=setColorClock";
msg += "&Color_Clock_R=" + document.getElementById("Color_Clock_R").value;
msg += "&Color_Clock_G=" + document.getElementById("Color_Clock_G").value;
msg += "&Color_Clock_B=" + document.getElementById("Color_Clock_B").value;
sendCommandToESP32("set", msg);
}
function setColorDate() {
var key = document.getElementById("key").value;
if (key == "") {
alert("Please enter the key!");
return;
}
var msg = "key=" + key + "&sta=setColorDate";
msg += "&Color_Date_R=" + document.getElementById("Color_Date_R").value;
msg += "&Color_Date_G=" + document.getElementById("Color_Date_G").value;
msg += "&Color_Date_B=" + document.getElementById("Color_Date_B").value;
sendCommandToESP32("set", msg);
}
function setColorText() {
var key = document.getElementById("key").value;
if (key == "") {
alert("Please enter the key!");
return;
}
var msg = "key=" + key + "&sta=setColorText";
msg += "&Color_Text_R=" + document.getElementById("Color_Text_R").value;
msg += "&Color_Text_G=" + document.getElementById("Color_Text_G").value;
msg += "&Color_Text_B=" + document.getElementById("Color_Text_B").value;
sendCommandToESP32("set", msg);
}
function setScrollingText() {
var key = document.getElementById("key").value;
if (key == "") {
alert("Please enter the key!");
return;
}
var msg = "key=" + key + "&sta=setScrollingText";
msg += "&input_Scrolling_Text=" + encodeURIComponent(document.getElementById("input_Scrolling_Text").value);
sendCommandToESP32("set", msg);
}
function resetSystem() {
var key = document.getElementById("key").value;
if (key == "") {
alert("Please enter the key!");
return;
}
if (confirm("Are you sure you want to reset the system?")) {
var msg = "key=" + key + "&sta=resetSystem";
sendCommandToESP32("set", msg);
}
}
function apply_the_Received_Settings(receivedSettings) {
// Fonction pour appliquer les paramètres reçus
console.log("Settings received:", receivedSettings);
// Ici vous pouvez analyser la réponse et remplir les champs du formulaire
}
</script>
</body>
</html>
)=====";
#endif // PAGE_INDEX_H
+160
View File
@@ -0,0 +1,160 @@
; Configuration commune
[env]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
upload_speed = 921600
board_build.f_cpu = 240000000L
board_build.f_flash = 80000000L
board_build.partitions = default.csv
build_flags =
-DCORE_DEBUG_LEVEL=0
-DARDUINO_USB_CDC_ON_BOOT=0
; Configuration par défaut pour un seul panneau 32x16
-DMATRIX_WIDTH=32
-DMATRIX_HEIGHT=16
-DMATRIX_PANELS_X=1
-DMATRIX_PANELS_Y=1
; ==========================================
; ENVIRONNEMENT PRINCIPAL - Horloge complète
; ==========================================
[env:main]
src_filter = +<main.cpp>
lib_deps =
adafruit/Adafruit BusIO@^1.16.1
adafruit/Adafruit GFX Library@^1.11.9
adafruit/RTClib@^2.1.4
https://github.com/2dom/PxMatrix.git
; ==========================================
; ENVIRONNEMENTS DE TEST
; ==========================================
; Test du module RTC DS3231
[env:rtc_test]
src_filter = +<../examples/rtc_test.cpp>
lib_deps =
adafruit/RTClib@^2.1.4
; Test du panneau P10 RGB
[env:p10_test]
src_filter = +<../examples/p10_test.cpp>
lib_deps =
adafruit/Adafruit BusIO@^1.16.1
adafruit/Adafruit GFX Library@^1.11.9
https://github.com/2dom/PxMatrix.git
; Effacement de la mémoire NVS
[env:nvs_erase]
src_filter = +<../examples/nvs_erase.cpp>
; ==========================================
; ENVIRONNEMENT DE DÉVELOPPEMENT
; ==========================================
[env:debug]
src_filter = +<main.cpp>
lib_deps =
adafruit/Adafruit BusIO@^1.16.1
adafruit/Adafruit GFX Library@^1.11.9
adafruit/RTClib@^2.1.4
https://github.com/2dom/PxMatrix.git
build_flags =
${env.build_flags}
-DCORE_DEBUG_LEVEL=5
-DDEBUG_ESP_PORT=Serial
; Configuration pour OTA (optionnel)
; Décommentez et configurez selon vos besoins
;[env:ota]
;extends = env:main
;upload_protocol = espota
;upload_port = 192.168.1.100
;upload_flags = --auth=your_ota_password
; ==========================================
; CONFIGURATIONS PANNEAUX MULTIPLES
; ==========================================
; Configuration 2 panneaux horizontaux (64x16)
[env:cascade_2x1]
extends = env:main
build_flags =
${env.build_flags}
-DMATRIX_WIDTH=32
-DMATRIX_HEIGHT=16
-DMATRIX_PANELS_X=2
-DMATRIX_PANELS_Y=1
-DCASCADE_MODE=1
; Configuration 3 panneaux horizontaux (96x16)
[env:cascade_3x1]
extends = env:main
build_flags =
${env.build_flags}
-DMATRIX_WIDTH=32
-DMATRIX_HEIGHT=16
-DMATRIX_PANELS_X=3
-DMATRIX_PANELS_Y=1
-DCASCADE_MODE=1
; Configuration 4 panneaux horizontaux (128x16)
[env:cascade_4x1]
extends = env:main
build_flags =
${env.build_flags}
-DMATRIX_WIDTH=32
-DMATRIX_HEIGHT=16
-DMATRIX_PANELS_X=4
-DMATRIX_PANELS_Y=1
-DCASCADE_MODE=1
; Configuration 2x2 panneaux (64x32)
[env:cascade_2x2]
extends = env:main
build_flags =
${env.build_flags}
-DMATRIX_WIDTH=32
-DMATRIX_HEIGHT=16
-DMATRIX_PANELS_X=2
-DMATRIX_PANELS_Y=2
-DCASCADE_MODE=1
; Configuration 6 panneaux horizontaux (192x16)
[env:cascade_6x1]
extends = env:main
build_flags =
${env.build_flags}
-DMATRIX_WIDTH=32
-DMATRIX_HEIGHT=16
-DMATRIX_PANELS_X=6
-DMATRIX_PANELS_Y=1
-DCASCADE_MODE=1
; Configuration 8 panneaux horizontaux (256x16)
[env:cascade_8x1]
extends = env:main
build_flags =
${env.build_flags}
-DMATRIX_WIDTH=32
-DMATRIX_HEIGHT=16
-DMATRIX_PANELS_X=8
-DMATRIX_PANELS_Y=1
-DCASCADE_MODE=1
; Test pour panneaux multiples
[env:test_cascade]
src_filter = +<../examples/cascade_test.cpp>
lib_deps =
adafruit/Adafruit BusIO@^1.16.1
adafruit/Adafruit GFX Library@^1.11.9
https://github.com/2dom/PxMatrix.git
build_flags =
${env.build_flags}
-DMATRIX_WIDTH=32
-DMATRIX_HEIGHT=16
-DMATRIX_PANELS_X=2
-DMATRIX_PANELS_Y=1
-DCASCADE_MODE=1
+822
View File
@@ -0,0 +1,822 @@
/**
* ESP32 P10 RGB 32x16 Digital Clock with Web Server
* Compatible with PlatformIO
*
* Hardware Requirements:
* - ESP32 DEVKIT V1
* - P10 RGB 32x16 HUB75 Panel
* - DS3231 RTC Module
* - 5V Power Supply
*
* Libraries:
* - Adafruit BusIO
* - Adafruit GFX Library
* - PxMatrix Library
* - RTClib
*/
// Defines pour la fréquence SPI (réduire si du bruit apparaît sur l'affichage)
#define PxMATRIX_SPI_FREQUENCY 10000000
// Inclusion des bibliothèques
#include <Arduino.h>
#include <PxMatrix.h>
#include <RTClib.h>
#include <Preferences.h>
#include <WiFi.h>
#include <WebServer.h>
#include <nvs_flash.h>
#include "PageIndex.h"
// Pins pour la matrice LED
#define P_LAT 5
#define P_A 19
#define P_B 23
#define P_C 18
#define P_OE 4
// Configuration des panneaux - définie par les build flags ou valeurs par défaut
#ifndef MATRIX_WIDTH
#define MATRIX_WIDTH 32
#endif
#ifndef MATRIX_HEIGHT
#define MATRIX_HEIGHT 16
#endif
#ifndef MATRIX_PANELS_X
#define MATRIX_PANELS_X 1
#endif
#ifndef MATRIX_PANELS_Y
#define MATRIX_PANELS_Y 1
#endif
// Calcul des dimensions totales
#define TOTAL_WIDTH (MATRIX_WIDTH * MATRIX_PANELS_X)
#define TOTAL_HEIGHT (MATRIX_HEIGHT * MATRIX_PANELS_Y)
// Configuration du timer
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
// Temps d'affichage (plus élevé = plus lumineux, mais attention aux crashs)
uint8_t display_draw_time = 30; // 30-70 est généralement correct
// Objet matrice avec dimensions totales calculées
PxMATRIX display(TOTAL_WIDTH, TOTAL_HEIGHT, P_LAT, P_OE, P_A, P_B, P_C);
// Couleurs prédéfinies
uint16_t myRED = display.color565(255, 0, 0);
uint16_t myGREEN = display.color565(0, 255, 0);
uint16_t myBLUE = display.color565(0, 0, 255);
uint16_t myYELLOW = display.color565(255, 255, 0);
uint16_t myCYAN = display.color565(0, 255, 255);
uint16_t myFUCHSIA = display.color565(255, 0, 255);
uint16_t myWHITE = display.color565(255, 255, 255);
uint16_t myBLACK = display.color565(0, 0, 0);
uint16_t myCOLOR_ARRAY[7] = {myRED, myGREEN, myBLUE, myYELLOW, myCYAN, myFUCHSIA, myWHITE};
int cnt_Color = 0;
int myCOLOR_ARRAY_Length = sizeof(myCOLOR_ARRAY) / sizeof(myCOLOR_ARRAY[0]);
// Variables pour le texte défilant
unsigned long prevMill_Scroll_Text = 0;
int scrolling_Y_Pos = 0;
long scrolling_X_Pos;
long scrolling_X_Pos_CT;
uint16_t scrolling_Text_Color;
uint16_t text_Color;
char text_Scrolling_Text[151];
uint16_t text_Length_In_Pixel;
bool set_up_Scrolling_Text_Length = true;
bool start_Scroll_Text = false;
byte scrolling_text_Display_Order = 0;
bool reset_Scrolling_Text = false;
// Variables de temps
unsigned long prevMill_Update_Time = 0;
const long interval_Update_Time = 1000;
unsigned long prevMill_Show_Clock = 0;
const long interval_Show_Clock = 500;
// Variables pour la date et l'heure
char daysOfTheWeek[7][10] = {"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY"};
char chr_t_Minute[3];
byte minute_Val, last_minute_Val;
char chr_t_Hour[3];
char day_and_date_Text[25];
bool blink_Colon = false;
uint16_t clock_Color;
uint16_t day_and_date_Text_Color;
// Variables de configuration
int d_Year;
byte d_Month, d_Day;
byte t_Hour, t_Minute, t_Second;
byte input_Display_Mode = 1;
byte input_Brightness = 125;
byte input_Scrolling_Speed = 45;
int Color_Clock_R = 255, Color_Clock_G = 0, Color_Clock_B = 0;
int Color_Date_R = 0, Color_Date_G = 255, Color_Date_B = 0;
int Color_Text_R = 0, Color_Text_G = 0, Color_Text_B = 255;
char input_Scrolling_Text[151] = "ESP32 P10 RGB Digital Clock with PlatformIO";
// Configuration WiFi - Modifiez selon vos besoins
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
// Configuration Point d'accès (si pas de WiFi)
const char* ap_ssid = "ESP32_Clock";
const char* ap_password = "esp32clock";
// Clé de sécurité pour l'interface web
#define KEY_TXT "p10rgbesp32ws"
// Mode de fonctionnement WiFi
bool useStationMode = true; // true = se connecter au WiFi, false = créer un point d'accès
// Objets RTC et Preferences
RTC_DS3231 rtc;
Preferences preferences;
// Serveur web
WebServer server(80);
// Gestionnaire d'interruption pour l'affichage
void IRAM_ATTR display_updater() {
portENTER_CRITICAL_ISR(&timerMux);
display.display(display_draw_time);
portEXIT_CRITICAL_ISR(&timerMux);
}
// Activation/désactivation du timer d'affichage
void display_update_enable(bool is_enable) {
if (is_enable) {
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &display_updater, true);
timerAlarmWrite(timer, 1500, true);
timerAlarmEnable(timer);
} else {
timerDetachInterrupt(timer);
timerAlarmDisable(timer);
}
}
// Connexion WiFi
void connecting_To_WiFi() {
Serial.println("\n-------------WIFI mode");
Serial.println("WIFI mode : STA");
WiFi.mode(WIFI_STA);
Serial.println("-------------");
delay(1000);
Serial.println("\n-------------Connection");
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
int connecting_process_timed_out = 40; // 20 secondes timeout
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
if(connecting_process_timed_out > 0) connecting_process_timed_out--;
if(connecting_process_timed_out == 0) {
Serial.println("\nFailed to connect to WiFi. Switching to AP mode.");
useStationMode = false;
break;
}
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi connected");
Serial.print("Successfully connected to : ");
Serial.println(ssid);
Serial.print("IP address : ");
Serial.println(WiFi.localIP());
}
Serial.println("-------------");
}
// Configuration du point d'accès
void set_ESP32_Access_Point() {
Serial.println("\n-------------");
Serial.println("WIFI mode : AP");
WiFi.mode(WIFI_AP);
Serial.println("-------------");
delay(1000);
Serial.println("\n-------------");
Serial.println("Setting up ESP32 to be an Access Point.");
WiFi.softAP(ap_ssid, ap_password);
delay(1000);
IPAddress local_ip(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
WiFi.softAPConfig(local_ip, gateway, subnet);
Serial.println("-------------");
Serial.print("SSID name : ");
Serial.println(ap_ssid);
Serial.print("IP address : ");
Serial.println(WiFi.softAPIP());
delay(1000);
}
// Fonction pour obtenir la largeur du texte en pixels
uint16_t getTextWidth(const char* text) {
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
return w;
}
// Fonction pour dessiner les deux points de l'heure
void drawColon(int16_t x, int16_t y, uint16_t colonColor) {
display.drawPixel(x, y, colonColor);
display.drawPixel(x+1, y, colonColor);
display.drawPixel(x, y+1, colonColor);
display.drawPixel(x+1, y+1, colonColor);
display.drawPixel(x, y+3, colonColor);
display.drawPixel(x+1, y+3, colonColor);
display.drawPixel(x, y+4, colonColor);
display.drawPixel(x+1, y+4, colonColor);
}
// Fonction de texte défilant adaptée aux panneaux multiples
void run_Scrolling_Text(uint8_t st_Y_Pos, byte st_Speed, char * st_Text, uint16_t st_Color) {
if (start_Scroll_Text == true && set_up_Scrolling_Text_Length == true) {
if (strlen(st_Text) > 0) {
text_Length_In_Pixel = getTextWidth(st_Text);
scrolling_X_Pos = TOTAL_WIDTH; // Utiliser la largeur totale
set_up_Scrolling_Text_Length = false;
} else {
start_Scroll_Text = false;
return;
}
}
unsigned long currentMillis_Scroll_Text = millis();
if (currentMillis_Scroll_Text - prevMill_Scroll_Text >= st_Speed) {
prevMill_Scroll_Text = currentMillis_Scroll_Text;
scrolling_X_Pos--;
if (scrolling_X_Pos < -(TOTAL_WIDTH + text_Length_In_Pixel)) { // Utiliser la largeur totale
set_up_Scrolling_Text_Length = true;
start_Scroll_Text = false;
return;
}
scrolling_X_Pos_CT = scrolling_X_Pos + 1;
display.setTextColor(myBLACK);
display.setCursor(scrolling_X_Pos_CT, st_Y_Pos);
display.print(st_Text);
display.setTextColor(st_Color);
display.setCursor(scrolling_X_Pos, st_Y_Pos);
display.print(st_Text);
}
}
// Récupération de l'heure
void get_Time() {
DateTime now = rtc.now();
minute_Val = now.minute();
sprintf(chr_t_Hour, "%02d", now.hour());
sprintf(chr_t_Minute, "%02d", now.minute());
}
// Récupération de la date
void get_Date() {
DateTime now = rtc.now();
sprintf(day_and_date_Text, "%s, %02d-%02d-%d",
daysOfTheWeek[now.dayOfTheWeek()],
now.day(), now.month(), now.year());
}
// Chargement des paramètres depuis la mémoire flash
void loadSettings() {
preferences.begin("mySettings", true);
input_Display_Mode = preferences.getInt("input_DM", 1);
input_Brightness = preferences.getInt("input_BRT", 125);
input_Scrolling_Speed = preferences.getInt("input_SS", 45);
Color_Clock_R = preferences.getInt("CC_R", 255);
Color_Clock_G = preferences.getInt("CC_G", 0);
Color_Clock_B = preferences.getInt("CC_B", 0);
Color_Date_R = preferences.getInt("DC_R", 0);
Color_Date_G = preferences.getInt("DC_G", 255);
Color_Date_B = preferences.getInt("DC_B", 0);
Color_Text_R = preferences.getInt("CT_R", 0);
Color_Text_G = preferences.getInt("CT_G", 0);
Color_Text_B = preferences.getInt("CT_B", 255);
String savedText = preferences.getString("scrollText", "ESP32 P10 RGB Digital Clock with PlatformIO");
strcpy(input_Scrolling_Text, savedText.c_str());
preferences.end();
// Application des paramètres
display.setBrightness(input_Brightness);
if (input_Display_Mode == 1) {
clock_Color = display.color565(Color_Clock_R, Color_Clock_G, Color_Clock_B);
day_and_date_Text_Color = display.color565(Color_Date_R, Color_Date_G, Color_Date_B);
text_Color = display.color565(Color_Text_R, Color_Text_G, Color_Text_B);
}
}
// Gestionnaire de la page principale
void handleRoot() {
server.send(200, "text/html", MAIN_page);
}
// Gestionnaire des paramètres
void handleSettings() {
String incoming_Settings = server.arg("key");
Serial.println("\n-------------Settings");
Serial.print("Key : ");
Serial.println(incoming_Settings);
if (incoming_Settings != KEY_TXT) {
server.send(200, "text/plain", "+ERR");
Serial.println("Wrong key!");
Serial.println("-------------");
return;
}
incoming_Settings = server.arg("sta");
// Définir la date et l'heure
if (incoming_Settings == "setTimeDate") {
d_Year = server.arg("d_Year").toInt();
d_Month = server.arg("d_Month").toInt();
d_Day = server.arg("d_Day").toInt();
t_Hour = server.arg("t_Hour").toInt();
t_Minute = server.arg("t_Minute").toInt();
t_Second = server.arg("t_Second").toInt();
Serial.println("Set Time and Date.");
Serial.printf("DateTime : %02d-%02d-%d %02d:%02d:%02d\n", d_Day, d_Month, d_Year, t_Hour, t_Minute, t_Second);
rtc.adjust(DateTime(d_Year, d_Month, d_Day, t_Hour, t_Minute, t_Second));
Serial.println("Setting completed.");
}
// Définir le mode d'affichage
else if (incoming_Settings == "setDisplayMode") {
input_Display_Mode = server.arg("input_Display_Mode").toInt();
Serial.print("Set Display Mode : ");
Serial.println(input_Display_Mode);
display_update_enable(false);
delay(100);
preferences.begin("mySettings", false);
preferences.putInt("input_DM", input_Display_Mode);
preferences.end();
display_update_enable(true);
if (input_Display_Mode == 1) {
clock_Color = display.color565(Color_Clock_R, Color_Clock_G, Color_Clock_B);
day_and_date_Text_Color = display.color565(Color_Date_R, Color_Date_G, Color_Date_B);
text_Color = display.color565(Color_Text_R, Color_Text_G, Color_Text_B);
}
display.clearDisplay();
reset_Scrolling_Text = true;
scrolling_text_Display_Order = 0;
}
// Définir la luminosité
else if (incoming_Settings == "setBrightness") {
input_Brightness = server.arg("input_Brightness").toInt();
if (input_Brightness > 255) input_Brightness = 255;
if (input_Brightness < 0) input_Brightness = 0;
Serial.print("Set Brightness : ");
Serial.println(input_Brightness);
display_update_enable(false);
delay(100);
preferences.begin("mySettings", false);
preferences.putInt("input_BRT", input_Brightness);
preferences.end();
display_update_enable(true);
display.setBrightness(input_Brightness);
}
// Définir la vitesse de défilement
else if (incoming_Settings == "setScrollingSpeed") {
input_Scrolling_Speed = server.arg("input_Scrolling_Speed").toInt();
if (input_Scrolling_Speed > 100) input_Scrolling_Speed = 100;
if (input_Scrolling_Speed < 10) input_Scrolling_Speed = 10;
Serial.print("Set Scrolling Speed : ");
Serial.println(input_Scrolling_Speed);
preferences.begin("mySettings", false);
preferences.putInt("input_SS", input_Scrolling_Speed);
preferences.end();
}
// Définir la couleur de l'horloge
else if (incoming_Settings == "setColorClock") {
if (input_Display_Mode == 2) {
server.send(200, "text/plain", "+ERR_DM");
Serial.println("-------------");
return;
}
Color_Clock_R = server.arg("Color_Clock_R").toInt();
Color_Clock_G = server.arg("Color_Clock_G").toInt();
Color_Clock_B = server.arg("Color_Clock_B").toInt();
Serial.printf("Set Clock Color (RGB) : %d,%d,%d\n", Color_Clock_R, Color_Clock_G, Color_Clock_B);
display_update_enable(false);
delay(100);
preferences.begin("mySettings", false);
preferences.putInt("CC_R", Color_Clock_R);
preferences.putInt("CC_G", Color_Clock_G);
preferences.putInt("CC_B", Color_Clock_B);
preferences.end();
display_update_enable(true);
clock_Color = display.color565(Color_Clock_R, Color_Clock_G, Color_Clock_B);
}
// Définir la couleur de la date
else if (incoming_Settings == "setColorDate") {
if (input_Display_Mode == 2) {
server.send(200, "text/plain", "+ERR_DM");
Serial.println("-------------");
return;
}
Color_Date_R = server.arg("Color_Date_R").toInt();
Color_Date_G = server.arg("Color_Date_G").toInt();
Color_Date_B = server.arg("Color_Date_B").toInt();
Serial.printf("Set Date Color (RGB) : %d,%d,%d\n", Color_Date_R, Color_Date_G, Color_Date_B);
display_update_enable(false);
delay(100);
preferences.begin("mySettings", false);
preferences.putInt("DC_R", Color_Date_R);
preferences.putInt("DC_G", Color_Date_G);
preferences.putInt("DC_B", Color_Date_B);
preferences.end();
display_update_enable(true);
day_and_date_Text_Color = display.color565(Color_Date_R, Color_Date_G, Color_Date_B);
}
// Définir la couleur du texte
else if (incoming_Settings == "setColorText") {
if (input_Display_Mode == 2) {
server.send(200, "text/plain", "+ERR_DM");
Serial.println("-------------");
return;
}
Color_Text_R = server.arg("Color_Text_R").toInt();
Color_Text_G = server.arg("Color_Text_G").toInt();
Color_Text_B = server.arg("Color_Text_B").toInt();
Serial.printf("Set Text Color (RGB) : %d,%d,%d\n", Color_Text_R, Color_Text_G, Color_Text_B);
display_update_enable(false);
delay(100);
preferences.begin("mySettings", false);
preferences.putInt("CT_R", Color_Text_R);
preferences.putInt("CT_G", Color_Text_G);
preferences.putInt("CT_B", Color_Text_B);
preferences.end();
display_update_enable(true);
text_Color = display.color565(Color_Text_R, Color_Text_G, Color_Text_B);
}
// Définir le texte défilant
else if (incoming_Settings == "setScrollingText") {
String scrollText = server.arg("input_Scrolling_Text");
if (scrollText.length() > 150) scrollText = scrollText.substring(0, 150);
strcpy(input_Scrolling_Text, scrollText.c_str());
Serial.print("Set Scrolling Text : ");
Serial.println(input_Scrolling_Text);
preferences.begin("mySettings", false);
preferences.putString("scrollText", scrollText);
preferences.end();
reset_Scrolling_Text = true;
scrolling_text_Display_Order = 0;
}
// Reset du système
else if (incoming_Settings == "resetSystem") {
Serial.println("System Reset requested");
server.send(200, "text/plain", "+OK");
delay(1000);
ESP.restart();
}
server.send(200, "text/plain", "+OK");
Serial.println("-------------");
}
// Configuration et démarrage du serveur
void prepare_and_start_The_Server() {
server.on("/", handleRoot);
server.on("/settings", handleSettings);
delay(500);
server.begin();
Serial.println("\nHTTP server started");
if (useStationMode) {
Serial.print("Open http://");
Serial.print(WiFi.localIP());
Serial.println(" in your browser");
} else {
Serial.print("Connect to WiFi network: ");
Serial.println(ap_ssid);
Serial.print("Then open http://");
Serial.print(WiFi.softAPIP());
Serial.println(" in your browser");
}
Serial.println("Use key: " KEY_TXT);
delay(500);
}
void setup() {
delay(1000);
Serial.begin(115200);
Serial.println("\n=== ESP32 P10 RGB Digital Clock ===");
Serial.println("Version: PlatformIO Compatible with Cascade Support");
// Affichage de la configuration des panneaux
Serial.println("\n--- Configuration Panneaux ---");
Serial.printf("Panneaux X: %d\n", MATRIX_PANELS_X);
Serial.printf("Panneaux Y: %d\n", MATRIX_PANELS_Y);
Serial.printf("Taille panneau: %dx%d pixels\n", MATRIX_WIDTH, MATRIX_HEIGHT);
Serial.printf("Taille totale: %dx%d pixels\n", TOTAL_WIDTH, TOTAL_HEIGHT);
Serial.printf("Nombre total panneaux: %d\n", MATRIX_PANELS_X * MATRIX_PANELS_Y);
// Ajustement automatique de la luminosité selon le nombre de panneaux
int auto_brightness = 125;
if (MATRIX_PANELS_X > 2) auto_brightness = 100;
if (MATRIX_PANELS_X > 4) auto_brightness = 80;
if (MATRIX_PANELS_X > 6) auto_brightness = 60;
input_Brightness = auto_brightness;
Serial.printf("Luminosité auto-ajustée: %d\n", auto_brightness);
Serial.println("------------------------------");
// Initialisation du RTC
Serial.println("\n------------");
Serial.println("Starting DS3231 RTC module...");
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1) delay(10);
}
Serial.println("DS3231 RTC module started successfully");
Serial.println("------------");
// Initialisation de l'affichage
display.begin(8); // Valeur 8 pour un panneau 1/8 scan
delay(100);
// Activation des interruptions timer
display_update_enable(true);
delay(100);
display.clearDisplay();
delay(500);
// Chargement des paramètres
loadSettings();
// Appliquer la luminosité ajustée si pas de sauvegarde
display.setBrightness(input_Brightness);
// Test d'affichage des couleurs avec message adapté
Serial.println("Testing display colors...");
// Test de bordures pour vérifier l'alignement (panneaux multiples)
if (MATRIX_PANELS_X > 1 || MATRIX_PANELS_Y > 1) {
Serial.println("Testing panel alignment...");
// Bordure extérieure
display.drawRect(0, 0, TOTAL_WIDTH, TOTAL_HEIGHT, myWHITE);
delay(1000);
// Lignes de séparation entre panneaux
for (int i = 1; i < MATRIX_PANELS_X; i++) {
int x = i * MATRIX_WIDTH;
display.drawLine(x, 0, x, TOTAL_HEIGHT - 1, myRED);
}
for (int i = 1; i < MATRIX_PANELS_Y; i++) {
int y = i * MATRIX_HEIGHT;
display.drawLine(0, y, TOTAL_WIDTH - 1, y, myGREEN);
}
delay(2000);
display.clearDisplay();
}
// Test des couleurs
display.fillScreen(myRED);
delay(1000);
display.fillScreen(myGREEN);
delay(1000);
display.fillScreen(myBLUE);
delay(1000);
display.fillScreen(myWHITE);
delay(1000);
display.clearDisplay();
delay(500);
display.setTextWrap(false);
display.setTextSize(1);
display.setRotation(0);
// Affichage du message de démarrage adapté
display.setTextColor(myWHITE);
// Calculer la position centrée pour le texte
String startMsg = "ESP32 CLOCK";
if (MATRIX_PANELS_X > 1) {
startMsg = String(MATRIX_PANELS_X) + "x" + String(MATRIX_PANELS_Y) + " P10 CLOCK";
}
int textWidth = startMsg.length() * 6; // Approximation
int startX = (TOTAL_WIDTH - textWidth) / 2;
if (startX < 0) startX = 0;
display.setCursor(startX, 0);
display.print(startMsg);
if (TOTAL_HEIGHT > 16) {
display.setCursor(startX, 16);
display.print("CASCADE MODE");
} else {
display.setCursor(startX, 8);
display.print("READY");
}
delay(3000);
display.clearDisplay();
// Configuration WiFi
if (useStationMode) {
connecting_To_WiFi();
if (!useStationMode) {
set_ESP32_Access_Point();
}
} else {
set_ESP32_Access_Point();
}
// Démarrage du serveur web
prepare_and_start_The_Server();
Serial.println("\nSetup completed. System ready!");
// Message de fin adapté à la configuration
if (MATRIX_PANELS_X > 1) {
Serial.printf("Running with %dx%d panels cascade (%dx%d total resolution)\n",
MATRIX_PANELS_X, MATRIX_PANELS_Y, TOTAL_WIDTH, TOTAL_HEIGHT);
}
}
void loop() {
// Gestion du serveur web
server.handleClient();
// Mise à jour de l'heure
unsigned long currentMillis_Update_Time = millis();
if (currentMillis_Update_Time - prevMill_Update_Time >= interval_Update_Time) {
prevMill_Update_Time = currentMillis_Update_Time;
get_Time();
blink_Colon = !blink_Colon;
}
// Affichage de l'horloge
unsigned long currentMillis_Show_Clock = millis();
if (currentMillis_Show_Clock - prevMill_Show_Clock >= interval_Show_Clock) {
prevMill_Show_Clock = currentMillis_Show_Clock;
display.setTextSize(1);
// Couleur selon le mode
if (input_Display_Mode == 1) {
clock_Color = display.color565(Color_Clock_R, Color_Clock_G, Color_Clock_B);
} else {
clock_Color = myCOLOR_ARRAY[cnt_Color];
}
// Calcul de la position centrée pour l'horloge (adapté à la largeur totale)
int clock_width = 30; // Approximation pour "HH:MM"
int clock_x = (TOTAL_WIDTH - clock_width) / 2;
if (clock_x < 1) clock_x = 1;
// Effacer et afficher les heures
if (last_minute_Val != minute_Val) display.fillRect(clock_x, 0, 11, 7, myBLACK);
display.setTextColor(clock_Color);
display.setCursor(clock_x, 0);
display.print(chr_t_Hour);
// Position des deux points (centrée)
int colon_x = clock_x + 14;
if (blink_Colon) {
drawColon(colon_x, 1, clock_Color);
} else {
drawColon(colon_x, 1, myBLACK);
}
// Effacer et afficher les minutes
if (last_minute_Val != minute_Val) display.fillRect(clock_x + 19, 0, 11, 7, myBLACK);
display.setTextColor(clock_Color);
display.setCursor(clock_x + 19, 0);
display.print(chr_t_Minute);
last_minute_Val = minute_Val;
}
// Gestion du texte défilant
if (reset_Scrolling_Text) {
start_Scroll_Text = false;
set_up_Scrolling_Text_Length = true;
reset_Scrolling_Text = false;
}
if (start_Scroll_Text == false) {
scrolling_text_Display_Order++;
if (input_Display_Mode == 1) {
if (scrolling_text_Display_Order > 2) scrolling_text_Display_Order = 1;
} else {
if (scrolling_text_Display_Order > 3) scrolling_text_Display_Order = 1;
}
// Affichage de la date
if (scrolling_text_Display_Order == 1) {
get_Date();
display.setTextSize(1);
scrolling_Y_Pos = 8;
if (input_Display_Mode == 1) {
scrolling_Text_Color = display.color565(Color_Date_R, Color_Date_G, Color_Date_B);
} else {
int next_cnt_Color = (cnt_Color + 1) % myCOLOR_ARRAY_Length;
scrolling_Text_Color = myCOLOR_ARRAY[next_cnt_Color];
}
strcpy(text_Scrolling_Text, day_and_date_Text);
}
// Affichage du texte personnalisé
if (scrolling_text_Display_Order == 2) {
display.setTextSize(1);
scrolling_Y_Pos = 8;
if (input_Display_Mode == 1) {
scrolling_Text_Color = display.color565(Color_Text_R, Color_Text_G, Color_Text_B);
} else {
int next_cnt_Color = (cnt_Color + 2) % myCOLOR_ARRAY_Length;
scrolling_Text_Color = myCOLOR_ARRAY[next_cnt_Color];
}
strcpy(text_Scrolling_Text, input_Scrolling_Text);
}
// Changement de couleur (mode 2 seulement)
if (scrolling_text_Display_Order == 3 && input_Display_Mode == 2) {
cnt_Color = (cnt_Color + 1) % myCOLOR_ARRAY_Length;
strcpy(text_Scrolling_Text, "");
}
start_Scroll_Text = true;
}
if (start_Scroll_Text) {
run_Scrolling_Text(scrolling_Y_Pos, input_Scrolling_Speed, text_Scrolling_Text, scrolling_Text_Color);
}
// Petit délai pour éviter la surcharge du processeur
delay(1);
}