Codex-generated pull request #2

Merged
electron-rare merged 2 commits from codex/find-best-solutions-for-esp32-project-mftfkg into main 2026-02-13 13:17:30 +00:00
5 changed files with 334 additions and 0 deletions
+15
View File
@@ -4,6 +4,21 @@ Projet PlatformIO ESP32 pour recycler un téléphone RTC ancien (combiné, clavi
## Démarrage rapide
1. Ouvrir le dossier dans PlatformIO.
2. Compiler et flasher l'environnement `esp32-s3-devkitc-1` (par défaut).
3. Ouvrir le moniteur série à 115200 bauds.
4. Utiliser les commandes série (`h`, `r`, `o`, `d`, `c`) pour piloter la machine d'états.
## Choix de cartes ESP32
Voir `docs/solutions_rtc_phone_esp32.md` pour la shortlist des DevKit utilisables (ESP32-DevKitC, ESP32-S3-DevKitC-1, NodeMCU-32S, LOLIN32), les liens de référence web, et les solutions dinterface (direct combiné/clavier, SLIC/FXS, ATA externe), dont une variante AG1171S (Silvertel).
## Plan projet (chef de projet)
Voir `docs/plan_chef_projet_esp32s3_ag1171s.md` pour le planning en phases, les risques, les critères d'acceptation et les livrables de la version ESP32-S3 + AG1171S.
## Contenu
- `platformio.ini`: configuration multi-env (ESP32-S3 par défaut + ESP32 legacy).
- `src/main.cpp`: squelette firmware machine d'états pour intégration AG1171S.
- `docs/solutions_rtc_phone_esp32.md`: comparaison des architectures et recommandations.
- `docs/plan_chef_projet_esp32s3_ag1171s.md`: plan d'exécution projet version V0.1.
2. Compiler et flasher l'environnement `esp32dev`.
3. Ouvrir le moniteur série à 115200 bauds.
+51
View File
@@ -0,0 +1,51 @@
# Plan chef de projet — ESP32-S3 + AG1171S (Silvertel)
## 1) Objectif projet
Livrer un prototype fonctionnel "téléphone analogique ancien" piloté par ESP32-S3, avec interface 2 fils privée via AG1171S, sans connexion PSTN publique.
## 2) Périmètre (version V0.1)
- Détection hook (on/off hook).
- Commande d'activation ligne (line enable).
- Commande de sonnerie (ring command/cadence côté analogique).
- Journal série + machine d'états téléphonie basique.
- Cible matérielle principale: **ESP32-S3-DevKitC-1**.
## 3) Planning macro
### Phase A — Cadrage & schéma (Semaine 1)
- Valider broches AG1171S retenues (hook detect, ring control, line feed control).
- Produire schéma de câblage V0.1 (alims, masses, protections, découplage).
- Sortie: checklist sécurité + BOM V0.1.
### Phase B — Firmware fondation (Semaine 2)
- Mettre en place environnement PlatformIO `esp32-s3-devkitc-1`.
- Implémenter machine d'états: `ON_HOOK`, `OFF_HOOK`, `DIALING`, `IN_CALL`, `RINGING`.
- Ajouter commandes série pour tests rapides (`r/o/d/c`).
- Sortie: build firmware de base + logs validés.
### Phase C — Intégration hardware (Semaine 3)
- Câblage réel ESP32-S3 ↔ AG1171S.
- Test de robustesse hook (anti-rebond + stabilité).
- Test commande ring/line sans charge puis avec téléphone analogique.
- Sortie: matrice de tests V0.1 avec résultats.
### Phase D — Validation système (Semaine 4)
- Campagne tests end-to-end: raccroché/décroché, sonnerie, transitions d'état.
- Vérifier alimentation et thermique.
- Corriger pinout/temporisations selon résultats.
- Sortie: release candidate V0.1.
## 4) Risques & mitigation
- **Risque analogique (niveaux/impédance):** prévoir test progressif et instrumentation (oscillo, multimètre).
- **Risque sécurité téléphonie:** rester hors PSTN publique tant que conformité non traitée.
- **Risque planning:** découper firmware et hardware en jalons testables hebdomadaires.
## 5) Critères d'acceptation V0.1
- Boot stable sur ESP32-S3.
- Hook detect stable (> 100 transitions sans faux positif en test de banc).
- Commande `RINGING` active le signal de commande attendu.
- Retour `ON_HOOK` coupe ligne et ring command.
## 6) Suite (V0.2+)
- Ajout décodage numérotation (DTMF/pulse).
- Ajout audio (codec I2S) et scénarios d'appel avancés.
- Option passerelle SIP locale.
+73
View File
@@ -41,6 +41,41 @@ Créer un projet PlatformIO sur ESP32 pour réutiliser un ancien téléphone ana
- Design analogique + sécurité plus exigeants.
- Debug plus long.
### Variante concrète: module **Silvertel AG1171S**
Si tu veux garder un ancien téléphone tel quel (2 fils TIP/RING) avec une carte ESP32, l'AG1171S est une piste concrète côté **FXS/SLIC**.
#### Ce que ça apporte
- Génération de la boucle analogique pour alimenter un poste RTC ancien.
- Interface pensée pour créer une "ligne privée" locale (pas une connexion directe PSTN brute).
- Réduction de la complexité analogique par rapport à un design SLIC discret from-scratch.
#### Comment l'intégrer proprement avec ESP32
1. **AG1171S = étage ligne analogique** (alimentation de boucle, interface 2 fils).
2. **ESP32 = logique et signalisation** (états off-hook/on-hook, numérotation, scénarios).
3. **Chemin audio**:
- soit via codec audio externe (I2S) + adaptation vers l'étage ligne,
- soit via une architecture où l'audio analogique reste majoritairement côté téléphonie, et l'ESP32 pilote surtout la logique.
4. **Détection d'événements**: exposer vers GPIO les états utiles (hook, ring detect selon schéma d'application).
#### Points d'attention (importants)
- Respecter strictement les notes d'application Silvertel (DC feed, protection, découplage, routage).
- Ne pas connecter à une ligne publique sans conformité réglementaire et schéma adapté.
- Prévoir protections (surintensité/surtension) et isolation selon l'usage final.
- Valider impédance et niveau audio pour éviter faible volume, saturation, écho/larsen.
#### Recommandation projet
- **MVP rapide**: continuer Option A (combiné + clavier en hard) pour avancer sur firmware.
- **Version "vraie ligne 2 fils"**: passer en Option B avec AG1171S quand la logique applicative est stable.
### Proposition de mapping initial (ESP32-S3-DevKitC-1)
- `GPIO4` : Hook sense (entrée, `INPUT_PULLUP`, actif bas selon câblage).
- `GPIO5` : Ring command (sortie logique vers étage de commande sonnerie).
- `GPIO6` : Line enable (sortie logique vers activation ligne AG1171S).
- `GPIO48`: LED debug état firmware.
> Ce mapping est un **point de départ firmware** et doit être validé/ajusté selon le schéma AG1171S final.
## Option C — Passerelle hybride (ATA/FXS externe + ESP32 contrôle)
### Principe
- L'audio et la boucle téléphonique sont gérés par un matériel externe (ATA/box FXS).
@@ -101,6 +136,41 @@ Créer un projet PlatformIO sur ESP32 pour réutiliser un ancien téléphone ana
- Ajouter journal série détaillé dès le début.
- Écrire des tests de mapping clavier (table de correspondance).
## Solutions existantes pour interfacer un ancien téléphone à un microcontrôleur
Oui, il existe plusieurs familles de solutions déjà utilisées en pratique:
1. **Interface combiné “en direct” (hook + clavier + audio séparé)**
- Tu nutilises pas la ligne RJ11 dorigine: tu récupères seulement le crochet, le clavier, le micro et l’écouteur.
- Cest la méthode la plus simple pour ESP32 et la plus sûre pour un prototype.
- Très bien pour interphone, SIP local, Bluetooth, domotique vocale.
2. **Interface FXS/SLIC (émuler une vraie ligne analogique privée)**
- Le microcontrôleur pilote un front-end téléphonique spécialisé qui fournit tension de ligne, courant de boucle et sonnerie.
- Cest la solution “propre téléphonie” si tu veux brancher un poste analogique sur 2 fils comme à l’époque.
- Plus complexe en électronique et en sécurité CEM/isolement.
3. **Interface FXO/DAA (recevoir ou analyser une ligne analogique existante)**
- Utilisée quand on veut interfacer une ligne analogique côté “réseau”.
- Demande encore plus de prudence réglementaire/sécurité selon le pays.
4. **Passerelle ATA externe (FXS déjà intégrée)**
- Exemple courant: un ATA SIP/FXS fait tout le travail téléphonique analogique.
- LESP32 ne gère que la logique (capteurs, scénarios, UI, automation).
- Super choix pour aller vite avec une bonne qualité audio.
5. **Décodage DTMF / cadran impulsionnel dédié**
- Si ton téléphone est à cadran ou clavier ancien, tu peux ajouter un étage dédié:
- décodage DTMF matériel,
- ou capture dimpulsions du cadran via GPIO + anti-rebond/filtrage.
- Souvent combiné avec lOption A.
### Ce qui marche le mieux pour ton cas
- Vu ton besoin ("combiné + clavier en hard"), la meilleure approche reste:
- **MVP: interface directe (Option A)**,
- puis migration vers **ATA externe** ou **SLIC/FXS** si tu veux une expérience “ligne RTC” complète.
## Sources web utiles
- Espressif DevKitC: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/esp32-devkitc/index.html
- Espressif S3 DevKitC-1: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/esp32-s3-devkitc-1/index.html
@@ -109,6 +179,9 @@ Créer un projet PlatformIO sur ESP32 pour réutiliser un ancien téléphone ana
- PlatformIO `nodemcu-32s`: https://docs.platformio.org/en/latest/boards/espressif32/nodemcu-32s.html
- PlatformIO `lolin32`: https://docs.platformio.org/en/latest/boards/espressif32/lolin32.html
- PlatformIO `esp32-c3-devkitc-02`: https://docs.platformio.org/en/latest/boards/espressif32/esp32-c3-devkitc-02.html
- Asterisk documentation (PBX/VoIP): https://docs.asterisk.org/
- Exemple ATA FXS (Grandstream HT801): https://www.grandstream.com/products/gateways-and-atas/analog-telephone-adaptors/product/ht801
- Silvertel (catalogue modules téléphonie): https://www.silvertel.com/
## Décision proposée
Pour ton besoin immédiat (PLIP / combiné + clavier en hard), la **meilleure balance risque/temps** est:
+10
View File
@@ -1,4 +1,8 @@
[platformio]
default_envs = esp32-s3-devkitc-1
[env]
platform = espressif32
default_envs = esp32dev
[env:esp32dev]
@@ -8,5 +12,11 @@ framework = arduino
monitor_speed = 115200
build_flags =
-DCORE_DEBUG_LEVEL=1
[env:esp32-s3-devkitc-1]
board = esp32-s3-devkitc-1
[env:esp32dev]
board = esp32dev
lib_deps =
bblanchon/ArduinoJson@^7.0.4
+185
View File
@@ -1,5 +1,190 @@
#include <Arduino.h>
/*
RTC_BL_PHONE - ESP32-S3 + AG1171S control skeleton
Goal:
- Provide a practical firmware base for a private analog line project.
- Keep telephony analog front-end on AG1171S side.
- Let ESP32 manage call-state logic and debug observability.
Notes:
- Pin mapping must be validated against your AG1171S application schematic.
- Never connect to PSTN without compliant isolation/protection design.
*/
enum class PhoneState : uint8_t {
ON_HOOK,
OFF_HOOK,
DIALING,
IN_CALL,
RINGING
};
struct PhonePins {
uint8_t pinHookSense;
uint8_t pinRingCmd;
uint8_t pinLineEnable;
uint8_t pinLed;
};
#if CONFIG_IDF_TARGET_ESP32S3
constexpr PhonePins PINS{
.pinHookSense = 4, // AG1171S hook/off-hook indication input to ESP32-S3
.pinRingCmd = 5, // ESP32-S3 output: request ring cadence generator/enable
.pinLineEnable = 6, // ESP32-S3 output: line feed enable (through safe driver)
.pinLed = 48 // ESP32-S3 DevKitC-1 RGB/Status-compatible GPIO
};
#else
constexpr PhonePins PINS{
.pinHookSense = 27,
.pinRingCmd = 26,
.pinLineEnable = 25,
.pinLed = 2
};
#endif
constexpr uint32_t SERIAL_BAUD = 115200;
constexpr uint32_t DEBOUNCE_MS = 25;
PhoneState g_state = PhoneState::ON_HOOK;
bool g_hookOffHook = false;
uint32_t g_lastHookEdgeMs = 0;
const char* stateToString(PhoneState state) {
switch (state) {
case PhoneState::ON_HOOK: return "ON_HOOK";
case PhoneState::OFF_HOOK: return "OFF_HOOK";
case PhoneState::DIALING: return "DIALING";
case PhoneState::IN_CALL: return "IN_CALL";
case PhoneState::RINGING: return "RINGING";
}
return "UNKNOWN";
}
void setState(PhoneState newState) {
if (newState == g_state) {
return;
}
g_state = newState;
Serial.printf("[RTC_PHONE] state=%s\n", stateToString(g_state));
switch (g_state) {
case PhoneState::ON_HOOK:
digitalWrite(PINS.pinLineEnable, LOW);
digitalWrite(PINS.pinRingCmd, LOW);
digitalWrite(PINS.pinLed, LOW);
break;
case PhoneState::OFF_HOOK:
digitalWrite(PINS.pinLineEnable, HIGH);
digitalWrite(PINS.pinRingCmd, LOW);
digitalWrite(PINS.pinLed, HIGH);
break;
case PhoneState::DIALING:
digitalWrite(PINS.pinLineEnable, HIGH);
digitalWrite(PINS.pinRingCmd, LOW);
digitalWrite(PINS.pinLed, HIGH);
break;
case PhoneState::IN_CALL:
digitalWrite(PINS.pinLineEnable, HIGH);
digitalWrite(PINS.pinRingCmd, LOW);
digitalWrite(PINS.pinLed, HIGH);
break;
case PhoneState::RINGING:
digitalWrite(PINS.pinLineEnable, HIGH);
digitalWrite(PINS.pinRingCmd, HIGH);
digitalWrite(PINS.pinLed, HIGH);
break;
}
}
void printHelp() {
Serial.println("[RTC_PHONE] Commands:");
Serial.println(" h -> help");
Serial.println(" r -> enter RINGING");
Serial.println(" o -> force ON_HOOK");
Serial.println(" d -> force DIALING");
Serial.println(" c -> force IN_CALL");
}
void handleSerialCommands() {
while (Serial.available() > 0) {
const char cmd = static_cast<char>(Serial.read());
switch (cmd) {
case 'h':
printHelp();
break;
case 'r':
setState(PhoneState::RINGING);
break;
case 'o':
setState(PhoneState::ON_HOOK);
break;
case 'd':
setState(PhoneState::DIALING);
break;
case 'c':
setState(PhoneState::IN_CALL);
break;
default:
break;
}
}
}
void updateHookState() {
const bool rawOffHook = (digitalRead(PINS.pinHookSense) == LOW);
const uint32_t nowMs = millis();
if (rawOffHook != g_hookOffHook && (nowMs - g_lastHookEdgeMs) > DEBOUNCE_MS) {
g_lastHookEdgeMs = nowMs;
g_hookOffHook = rawOffHook;
Serial.printf("[RTC_PHONE] hook=%s\n", g_hookOffHook ? "OFF_HOOK" : "ON_HOOK");
if (g_hookOffHook) {
setState(PhoneState::OFF_HOOK);
} else {
setState(PhoneState::ON_HOOK);
}
}
}
void setup() {
Serial.begin(SERIAL_BAUD);
pinMode(PINS.pinHookSense, INPUT_PULLUP);
pinMode(PINS.pinRingCmd, OUTPUT);
pinMode(PINS.pinLineEnable, OUTPUT);
pinMode(PINS.pinLed, OUTPUT);
digitalWrite(PINS.pinRingCmd, LOW);
digitalWrite(PINS.pinLineEnable, LOW);
digitalWrite(PINS.pinLed, LOW);
Serial.println("\n[RTC_PHONE] Boot OK");
#if CONFIG_IDF_TARGET_ESP32S3
Serial.println("[RTC_PHONE] Target: ESP32-S3");
#else
Serial.println("[RTC_PHONE] Target: ESP32 (legacy mapping)");
#endif
Serial.println("[RTC_PHONE] Profile: AG1171S control skeleton");
printHelp();
setState(PhoneState::ON_HOOK);
}
void loop() {
updateHookState();
handleSerialCommands();
delay(10);
// Prototype minimal pour valider le câblage d'un téléphone RTC recyclé.
// - Hook switch: détection décroché/raccroché
// - Clavier: lecture en matrice (adaptateur nécessaire selon le modèle)