first commit
This commit is contained in:
+42
@@ -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_*
|
||||||
Vendored
+10
@@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+21
@@ -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
|
||||||
|
}
|
||||||
Vendored
+200
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -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 |
@@ -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.
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 516 KiB |
@@ -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
@@ -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
@@ -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**
|
||||||
@@ -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
|
||||||
@@ -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 |
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
@@ -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
@@ -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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user