Salut, après avoir passé (beaucoup trop) de temps à analyser ce visiophone (Extel LENA 11.3 js-s436e0). J’arrive à la fin du projet. J’ai pu récupérer le signal vidéo composite PAL, récupérer les états des boutons (quelqu’un sonne, active la vidéo, ouvre le portail…), et aussi agir sur le visiophone (demander l’activation de la vidéo, l’ouverture du portail etc.).
Comme tout est en 5 volts, cela peut se faire avec un arduino. J’ai tenté avec un ESP32 C3 Mini car avec le wifi intégré ça serait plus pratique pour manipuler le visiophone que de passer par le serial.
L’ESP32 fonctionne aussi mais il faut jouer avec des transistors et mosfets pour rehausser ou abaisser le voltage de 3.3V à 5V quand on s’interface avec le microcontrôleur du visiophone.
Voici une partie des infos que j’ai pu recueillir avec un oscilloscope
# Hack Extel LENA 11.3
La documentation suivante s'applique uniquement au boitier noir situé à l'intérieur du logement.
La platine de rue n'a pas été analysée.
On considère que le boitier est positionné avec l'écran vers le haut et que l'on a vue sur l'arrière du boitier.
## Microcontrôleur
Le microcontrôleur est un TM57FLA80A dans un format DIP20. Il est situé en bas à gauche sur la carte mère.
### Assignation des pins
On considère le microcontrôleur orienté avec sa marque ronde vers le bas. Les pins sont listées de haut en bas.
#### Partie gauche (nommée A)
* A0 : état du 12 volts (activé 0V, désactivé 5V)
* A1 : état du microphone intérieur (activé 5V, désactivé 0V)
* A2 : entrée analogique du bouton portail (activé 0V, désactivé 5V)
* A3 : entrée analogique du bouton clé (activé 0V, désactivé 3V)
* A4 : inconnu (5V)
* A5 : inconnu (5V)
* A6 : envoi de commandes vers la platine de rue (signal de 5V, repos 0V)
* A7 : entrée analogique du bouton caméra (activé 0V, désactivé 5V)
* A8 : entrée analogique du bouton microphone (activé 0V, désactivé 5V)
* A9 : alimentation Vcc (5V)
#### Partie gauche (nommée B)
* B0 : état du bouton microphone, du bouton choix sonnette et activation de la sonnette (impulsions activé 5V, désactivé 0V)
* B1 : idem B0
* B2 : état du bouton choix sonnette (activé 0V, désactivé 5V)
* B3 : états des boutons (voir paragraphe dédié)
* B4 : état du microphone extérieur (activé 0V, désactivé 5V)
* B5 : inconnu (activé 0V, désactivé 5V)
* B6 : inconnu (5V)
* B7 : sinusoïde, clock ? (33 Hz)
* B8 : inconnu (activé 0V, désactivé 2V)
* B9 : masse Vss (GND)
### Pin A6
La pin A6 envoie des commandes pour la platine de rue.
Le signal est un signal PWM de 0 volt à 5 volts.
Le signal change de voltage toutes les 10 us.
La commande est déterminée suivant la durée d'activation du signal.
* Pas de commande : 0 volt
* Sonnette : signal pendant 10000 us
* Désactivation vidéo : signal pendant 20000 us
* Activation microphone : signal pendant 30000 us
* Activation vidéo: signal pendant 50000 us
* Activation du rélai portail: signal pendant 60000 us
* Activation du rélai clé : signal pendant 80000 us
### Pin B3
La pin B3 indique un changement d'état d'un bouton.
La valeur est encodée sur 30 bits pendant 3000 us.
Un bit à donc une durée de 100 us.
5 volts est un 0 et 0 volt est un 1.
Liste des valeurs décimales pour l'état d'un bouton:
* Sonnette : 266873596
* Désactivation vidéo : 266900220
* Activation microphone : 266920700
* Activation vidéo : 266898172
* Activation du rélai portail : 266922748
* Activation du rélai clé : 266924796
## Carte fille des boutons
Les 4 boutons caméra, microphone, portail et clé sont sur une carte fille situé en haut à gauche.
La carte fille est reliée à la carte mère avec 6 fils.
Assignation des pins sur le port CM2 de la carte mère. En partant du pin le plus proche de la marque CM2 :
Bouton microphone, bouton vidéo, bouton clé, bouton portail, masse ?, masse ?
## Carte fille décodage vidéo
La carte de décodage vidéo est soudée sur la carte mère avec 5 pins en bas à gauche. Juste au dessus du microcontrôleur.
On considère la carte fille orientée avec ses 5 pins vers le bas. Les pins sont listées de gauche à droite.
* Signal vidéo composite
* Alimentation Vcc (12V)
* Masse Vss (GND)
* Masse du signal vidéo composite
* Signal vidéo non décodé (13V)
## Fonctionnement
Lors de l'appui sur le bouton de la sonnette ou le bouton vidéo, du 12 volts est envoyé :
* à l'alimentation de la carte fille de décodage vidéo
* à l'alimentation du microcontrôleur de l'écran LCD (autour de R75)
* à la LED en haut du boitier pour changer sa couleur en vert
Le temps d'activation de la caméra dépend du bouton appuyé :
* Bouton sonnette : 30 secondes
* Bouton caméra : 60 secondes
Le programme arduino associé
#define PIN_READ_STATE 2 // From IC, B3 pin
#define PIN_SEND_COMMAND 3 // To IC, A6 pin
#define COMMAND_BELL 10000
#define COMMAND_VIDEO_OFF 20000
#define COMMAND_MICROPHONE_ON 30000
#define COMMAND_VIDEO_ON 50000
#define COMMAND_FRONT_GATE_RELAY 60000
#define COMMAND_KEY_RELAY 80000
#define STATE_BIT_DURATION 100 // Bit duration, in microseconds
#define STATE_FRAME_DURATION 3000 // Total frame duration, in microseconds
#define STATE_MAX_SAMPLE_COUNT STATE_FRAME_DURATION / STATE_BIT_DURATION
#define STATE_BELL 266873596
#define STATE_VIDEO_OFF 266900220
#define STATE_MICROPHONE_ON 266920700
#define STATE_VIDEO_ON 266898172
#define STATE_FRONT_GATE_RELAY 266922748
#define STATE_KEY_RELAY 266924796
volatile long long onStateChanges[STATE_MAX_SAMPLE_COUNT] = {};
volatile byte onStateChangesIndex = 0;
void onState() {
const long long now = micros();
if (abs(now - onStateChanges[0]) > STATE_FRAME_DURATION)
onStateChangesIndex = 0;
if (onStateChangesIndex > STATE_MAX_SAMPLE_COUNT)
return;
onStateChanges[onStateChangesIndex] = now;
onStateChangesIndex++;
}
void sendCommand(long long command) {
const long long deadline = micros() + command;
pinMode(PIN_SEND_COMMAND, OUTPUT);
digitalWrite(PIN_SEND_COMMAND, LOW);
while (micros() < deadline) {
digitalWrite(PIN_SEND_COMMAND, HIGH);
delayMicroseconds(10);
digitalWrite(PIN_SEND_COMMAND, LOW);
delayMicroseconds(10);
}
pinMode(PIN_SEND_COMMAND, INPUT);
}
void setup() {
Serial.begin(9600);
while (!Serial) {}
pinMode(PIN_SEND_COMMAND, INPUT);
pinMode(PIN_READ_STATE, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PIN_READ_STATE), onState, CHANGE);
digitalWrite(PIN_READ_STATE, LOW);
}
bool screenRelayStatus = false;
void loop() {
while (Serial.available() > 0)
Serial.read();
Serial.print("Enter action: ");
int action = 0;
while (action < 1 || action > 7) {
while (Serial.available() <= 0);
action = Serial.parseInt();
}
Serial.println(action);
if (action == 1){
Serial.println("COMMAND_BELL");
sendCommand(COMMAND_BELL);
}
else if (action == 2){
Serial.println("COMMAND_VIDEO_OFF");
sendCommand(COMMAND_VIDEO_OFF);
}
else if (action == 3){
Serial.println("COMMAND_MICROPHONE_ON");
sendCommand(COMMAND_MICROPHONE_ON);
}
else if (action == 4){
Serial.println("COMMAND_VIDEO_ON");
sendCommand(COMMAND_VIDEO_ON);
}
else if (action == 5){
Serial.println("COMMAND_FRONT_GATE_RELAY");
sendCommand(COMMAND_FRONT_GATE_RELAY);
}
else if (action == 6){
Serial.println("COMMAND_KEY_RELAY");
sendCommand(COMMAND_KEY_RELAY);
}
else if (action == 7){
long long stateChanges[STATE_MAX_SAMPLE_COUNT] = {};
cli();
const byte stateChangesIndex = onStateChangesIndex;
memcpy(stateChanges, (const void *)onStateChanges, sizeof(onStateChanges[0]) * STATE_MAX_SAMPLE_COUNT);
sei();
uint32_t state = 0;
uint32_t level = LOW;
byte stateIndex = 0;
for (byte i = 1; i < stateChangesIndex; i++) {
const unsigned long elapsed = stateChanges[i] - stateChanges[0];
const unsigned long bitCount = (elapsed + (STATE_BIT_DURATION / 2)) / STATE_BIT_DURATION;
for (; stateIndex < bitCount; stateIndex++)
state |= level << stateIndex;
level = level == LOW ? HIGH : LOW;
}
switch (state) {
case 0:
if (stateIndex == 1)
Serial.println("Start/stop");
else
Serial.println("None");
break;
#define SWICTH_CASE_DEBUG(_case) case _case: Serial.println(#_case); break;
SWICTH_CASE_DEBUG(STATE_BELL)
SWICTH_CASE_DEBUG(STATE_VIDEO_OFF)
SWICTH_CASE_DEBUG(STATE_MICROPHONE_ON)
SWICTH_CASE_DEBUG(STATE_VIDEO_ON)
SWICTH_CASE_DEBUG(STATE_FRONT_GATE_RELAY)
SWICTH_CASE_DEBUG(STATE_KEY_RELAY)
#undef SWICTH_CASE_DEBUG
default:
Serial.print("Unkown state: ");
Serial.println(state, BIN);
Serial.println(state, DEC);
break;
}
}
}
@seb821 @aladin