Lecture de capteur PNP 12V avec ESP32

Bonjour à tous,

Mon projet porte sur la lecture de deux capteurs PNP fonctionnant en 12Vcc sur un ESP32 afin de connaitre en temps réel la position d’un portail affiché sur un serveur.

Voici le schéma de branchement que j’ai réalisé :

J’ai positionné une diode zener de 5.1V sur chaque capteur et en testant le signal à l’oscilo, ma tension est de 5V sans métal devant le capteur et passe à 0V avec une détection métalique.

Voici le programme que j’ai réalisé :

// _________________________________________________________   Connection wifi  __________________________________________________________

#include <WiFi.h>

#define ssid "C18" // MSE-PAIMPOL ou Livebox-CB66
#define password "Udinabugz22?!"  // AccesPasseMSE-01 ou Udinabugz22?!

unsigned long tempsPrecedentRedemarrage = 0;
unsigned long tempsPrecedentStatusWifi = 0;

unsigned long tempsDeRebootESP = 30000;
const int tempsDeStatusWifi = 3000;

bool etatConnexionDebug = false;

void setupWifi() { 

  Serial.println("\n");
  WiFi.begin(ssid, password);
  Serial.print("Tentative de connexion...");

 while(WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(1000);
      
  }

  Serial.println("\n");
  Serial.println("Connexion etablie : ");
  Serial.print("Adresse IP : ");
  Serial.println(WiFi.localIP());
  Serial.print("Force du signal RSSI: ");
  Serial.println(WiFi.RSSI());
  delay(1000);

}  

// ________________________________________________________   Connection au borker MOSQUITTO  ____________________________________________________________

#include <PubSubClient.h>

#define mqtt_server "192.168.1.13"
const char* mqttUser = "serveur-maison";
const char* mqttPassword = "Udinabugz22?!"; 

char message_buff[100];
long lastMsg = 0;   
// long lastRecu = 0;
bool debug = false;  
char msg[50];
int value = 0;
String consigne;

WiFiClient espClient;
PubSubClient client(espClient);

// ----------------- déclaration des topics de souscription MQTT --------------------

String callbackOuvertureFermeturePortail;
String callbackOuverturePortailPortillon;

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");

  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]); 
  }

  payload[length]='\0';
  String cons = String((char*)payload);
  consigne = cons;
  Serial.println();

// _______________________________________  Exécution des souscription au topic MQTT  _______________________________________________

if (topic[7] == 'p') {                                          // On va choisir le bon topic que l'on veut recupérer avec des lettres ici la lettre o de osmolation.
   payload[length]='\0';                                        // Ensuite on recupére la valeur entière (length) du topic.
   callbackOuverturePortailPortillon = String((char*)payload);  // On la stock dans une variable pour l'utiliser ailleurs dans le code.
   Serial.println();
 } else if(topic[8] == 'p') {                                                                                  
    payload[length]='\0';                                 
    callbackOuvertureFermeturePortail = String((char*)payload);    
    Serial.println();
 }
}

void reconnect() {                                         //Boucle jusqu'à obtenur une reconnexion
    
  while (!client.connected()) {
    Serial.println("Connexion au serveur MQTT...");
    
    if (client.connect("Portail exterieur", mqttUser, mqttPassword )) {
      Serial.println("Connexion réussie à : Portail exterieur");
      
// ________________________________________  Souscription au topic nodered   _______________________________________________
      
client.subscribe("Gestion/portail");
client.subscribe("Relais/portillon");
     
debug = true;
      
    } else {
      Serial.println("Erreur de connexion au serveur MQTT : ");
      debug = false;
      Serial.println("5 secondes avant de recommencer une tentative de connexion");
      delay(5000);
  }
 } 
}

// _______________________________  Déclaration du luxmètre  ____________________________________

#include <DFRobot_B_LUX_V30B.h>
DFRobot_B_LUX_V30B  myLux(13);

// _______________________________  Déclaration des capteurs de position du portail  ___________________________________

const int capteurPositionOuvert = 39;
const int capteurPositionFerme = 35;

bool etatCapteurPositionOuvert = false;
bool etatCapteurPositionFerme = false;

// _______________________________  Dclaration des relais du portail  _____________________________________

const int relaisOuvertureFermeturePortail = 19;
const int relaisPortillonPortail = 18;

// _______________________________  Déclaration des abonnements MQTT  _____________________________________

#define sonde1_topic "Etat/capteur/portail/ferme"
#define sonde2_topic "Etat/capteur/portail/ouvert"
#define sonde3_topic "Debug/ESP32/portail/exterieur"
#define sonde4_topic "Etat/capteur/luxmetre"

// _________________________________________________________________________________________________ SETUP  ______________________________________________________________________________________________________

void setup() {
  
Serial.begin(115200);

setupWifi();

delay(1000); 
  
client.setServer(mqtt_server, 1883);
client.setCallback(callback);

delay(500);

// ___________________________________  Déclaration des capteurs de positiion du portail  _________________________________

pinMode(capteurPositionOuvert, INPUT);
pinMode(capteurPositionFerme, INPUT);

// ___________________________________  Déclaration des relais du portail  ____________________________________

pinMode(relaisPortillonPortail, OUTPUT);
digitalWrite(relaisPortillonPortail, LOW);

pinMode(relaisOuvertureFermeturePortail, OUTPUT);
digitalWrite(relaisOuvertureFermeturePortail, LOW);

// ___________________________________  Lancement du luxmètre  _______________________________________

myLux.begin();

}

// _________________________________________________________________________________________________  LOOP  ______________________________________________________________________________________________

void loop() {

client.loop();

  if (!client.connected()) {
    reconnect();
  }
  
unsigned long tempsActuelStatus = millis();

  if (( WiFi.status() == WL_CONNECTED ) && ( tempsActuelStatus - tempsPrecedentStatusWifi ) >= tempsDeStatusWifi ) {
   
    Serial.print("ESP32 correctement connnecter au reseau wifi : ");
    Serial.println(WiFi.SSID());
    etatConnexionDebug = true;
    tempsPrecedentStatusWifi = tempsActuelStatus;
  } 

  if ( WiFi.status() != WL_CONNECTED ) {     
    Serial.println("Problème de connection de l'ESP32");
    etatConnexionDebug = false;
    unsigned long tempsActuelRedemarrage = millis();
 
    if ((tempsActuelRedemarrage - tempsPrecedentRedemarrage) >= tempsDeRebootESP ) {   
      Serial.println("preparation au reboot ESP32");
      delay(3000);
      Serial.println("Reboot de l'ESP32");
      ESP.restart();
      tempsPrecedentRedemarrage = tempsActuelRedemarrage;
   } 
  }

// _____________________________________________  Lecture de l'état des capteurs de position du portail  ________________________________________________

 etatCapteurPositionOuvert = digitalRead(capteurPositionOuvert);
 etatCapteurPositionFerme = digitalRead(capteurPositionFerme);

  if(etatCapteurPositionOuvert == true) {
    Serial.println(etatCapteurPositionOuvert);
  } else {
  }

  if(etatCapteurPositionFerme == true) {
    Serial.println(etatCapteurPositionFerme);
  } else {
  }

// __________________________________________  Lecture des conditions de déclenchement des relais pilotés MQTT  ___________________________________________

  if(callbackOuvertureFermeturePortail == "true") {
    digitalWrite(relaisOuvertureFermeturePortail, HIGH);
    delay(500);
    digitalWrite(relaisOuvertureFermeturePortail, LOW);
  } else {
    digitalWrite(relaisOuvertureFermeturePortail, LOW);
  }

  if(callbackOuverturePortailPortillon == "true") {
    digitalWrite(relaisPortillonPortail, HIGH);
    delay(500);
    digitalWrite(relaisPortillonPortail, LOW);
  } else {
    digitalWrite(relaisPortillonPortail, LOW);
  }

// ______________________________________  Lecture du luxmètre  __________________________________________________

double lumiere = myLux.lightStrengthLux();
/*Serial.print("value: ");
Serial.print(myLux.lightStrengthLux());
Serial.println(" (lux).");
delay(1000);*/
 
 
// _______________________________________  Envoi des données à NodeRed  _____________________________________________

bool sonde1 = etatCapteurPositionOuvert;
bool sonde2 = etatCapteurPositionFerme;
bool sonde3 = etatConnexionDebug;
double sonde4 = lumiere;
  
//Publication des mesures:
  
   if(debug) {

  client.publish(sonde1_topic, String(etatCapteurPositionOuvert).c_str(), true);
  client.publish(sonde2_topic, String(etatCapteurPositionFerme).c_str(), true);
  client.publish(sonde3_topic, String(sonde3).c_str(), true);
  client.publish(sonde4_topic, String(lumiere).c_str(), true);
  }
}

Les deux comparaisons ne fonctionnent pas en retour sur moniteur série, le signal est à 1 mais ne passe pas à 0 lorsque je passe un objet métalique devant.

L’esp32 accepte il 5V en INPUT ou dois je mettre une diode zener de 3.3V ?

Merci par avance pour vos éclaircissement.s

Bonsoir,

L'ESP32 accepte théoriquement 3,3V Max en entrée.

Un diode zener, pour ce que vous voulez en faire, se câble de cette façon


Pour en savoir plus.

Pour ne pas dépasser 3.3V, la tension zener doit être <= 3.3V

Vous pouvez aussi envisager un pont diviseur suffisamment chargé en sortie du PNP.

Séquence culturelle :grinning_face:
Ce que l'on appelle diode zéner est le plus souvent non pas une zéner mais une diode à avalanche controlée.
Ce type de diode à un coude très franc et permet de réaliser des limitations de tension efficace. Une "zéner" 5 V est une diode à avalanche contrôlée.

Hélas à 3,3 V ce sont presque des vraies zéners.
Le véritable effet zéner présente un coude très mollasson.
Pour être certain de ne pas dépasser la tension d'alimentation de l'ESP32 il faudrait prendre une diode 2,7 V au maximum.
-------------------------

Voyons le problème autrement.
Le principe de la zéner est utile si la tension à abaisser est trop fluctuante.
Mais si la tension de 12 V est bien connue et stable un pont diviseur fera l'affaire.

Comment se comporte la tension 12 V ?

Merci pour ces infos, je teste cela demain avec un diviseur de tension. Merci à vous

Re:

Pour rappel, un diviseur de tension, c'est
Vs = (Ve x R1) / (R1 + R2)
A condition que (R1 + R2) soit environ 10 fois + petit que l'impédance d'entrée de l'entrée ESP à laquelle est connectée le pont.

Et d'autres part, pour que le transistor de la sortie PNP soit bien saturé, il faut regarder dans la datasheet du PNP s'il ne faut pas respecter un courant Minimum en sortie PNP.

Sinon (R1 + R2) environ 2k Ohms le semble correct.

Ou un courant maximum.

la saturation d'un transistor bipolaire c'est quand on impose dans la base un courant supérieur à celui dont le transistor à besoin.
Donc si on ne maitrise pas le courant de base il ne reste plus que la solution de diminuer le courant de collecteur. Le sujet avait été abordé lors d’un sujet sur la lecture des Linky.

Mais c'est secondaire.
Déjà il faudrait bien connaitre ce que veut dire "sortie PNP" dans les capteurs de @udina.

J'ai trouvé les significations suivantes, liste non limitative.

  • un transistor bipolaire PNP en collecteur ouvert
  • un transistor mosFet canal P en drain ouvert
  • un simple relai.

Cela me choque, mais l'expression "PNP" est très souvent utilisé pour signifier que la charge, obligatoire, doit être cablée entre l masse et la sortie "dite" PNP.

Question : référence des capteurs ?

Bonjour,

Si par exemple vous consultez un catalogue ou un site Internet d'un fournisseur européen de composants autre qu'un vendeur de chinoiseries, et que vous lancez une recherche sur "capteurs PNP", vous aurez en résultat une dizaine de milliers de composants
COMME CEUX LÀ

Et toujours à la même source utilisée par des milliers de professionnels de l'Automatisme entre autre, vous trouverez ce genre de littérature

Alors c'est vrai, les initiales NPN ou PNP, pour un puriste en électronique, font référence à d'autres choses que pour un automaticien.

Bien que l'automaticien, avec son language, fasse référence uniquement au "type" de sortie de ces capteurs "sortie type NPN ou PNP" car c'est l'info dont il a besoin pour piloter sa charge (relais, entrée automate...) et faire son schéma de câblage.

Ce language est communément comprit et utilisé par les automaticiens, les câbleurs, les fournisseurs de composants... même si "historiquement" il n'est pas tout à fait exacte, il décrit clairement de quoi il s'agit quand un automaticien parle de "sortie de type PNP".

Bravo !

Mais on ne sait toujours pas si la sortie est un transistor bipolaire, mosFet ou un relai.

On ne connait toujours pas le courant maximal ou minimal dans la sortie.
Parce que on ne sait toujours rien sur le capteur.

Dans ces conditions je suis incapable de donner des conseils.
je ne veux pas ergoter, je cède ma place.

ref (dans l'image du 1er message) LJ18A3-B-Z/BY
Imax 200mA et c'est bien un BJT de type PNP

mais comme le demandeur a déjà lancé tant de sujets qui sont restés sans réponse finale malgré les multiples participations ...

Un exemple d'application "Arduinisée" sans diode zener ni pont diviseur.

This example code sets up an Arduino UNO to read the output from the LJC18A3-B-Z/BY capacitive proximity sensor and print the results to the serial monitor. The sensor's black wire is connected to digital pin 2, the brown wire to the 5V pin, and the blue wire to GND.
Pour Arduino

Ce capteur m'a tout l'air d'être un capteur chinois au datasheet quelque peu approximatif.

Technical Specifications

Key Technical Details

  • Supply Voltage (Vcc): 6-36V DC
  • Output Current: 300 mA (max)
  • Output Type: PNP NO (Normally Open)

PNP NO (Normally Open)
Je n'ai pas de boule de cristal, mais "Normaly open" est un terme utilisé pour les contacts d'un relai.

Bonjour,

Si les sondes renvoient un état logique de 0 ou 12V, pourquoi ne pas tout simplement utiliser un convertisseur de niveau logique ?

On en trouve plein a pas cher sur internet et leur mise en place est bien plus simple qu’une diode Zener…

Bonjour,

Un pont diviseur aussi.

Oui, mais les pont diviseur :

  • n'existe pas vraiment sous forme de circuit pre-fabriqué plug and play
  • on une consommation interne potentiellement plus élevée que le convertisseur de niveau logique
  • sont soumis au tolérance des composants utiliser

En électronique industriel, et par extension, cela s'applique aussi pour les "contacts électroniques"
NO = transistor bloqué par défaut
NC = transistor passant par défaut

@guillaume_lrt

C'est une façon de voir, certains auront sous la main des résistances mais pas des convertisseurs de niveaux.

  • Oui, enfin câbler 2 résistances ce n'est pas non plus le bout du monde
  • alors là pour la consommation on pourrait en discuter. Le circuit convertisseur de niveau consomme peut-être peu mais en revanche il sera sous tension 100% du temps alors que le diviseur de tension ne consommera que lorsque le capteur sera actif et on n'est pas obligé d'utiliser des résistances de faibles valeurs car on est quasi statique.
  • il faut générer à partir du 12V un niveau entre 2.5V et 3.6V ce qui laisse quand même pas mal de marge même avec un jeu de résistances limité.

Bonjour à tous, désolé mais je n’ai pas pu répondre aujourd’hui, je recherche le capteur qui est fabriqué ici : PULSOTRONIC

J’essai de vous trouver la datasheet précise.

Bonjour à tous,

Voici la documentation du capteur :

Datasheet capteur

Voici à quoi il ressemble physiquement :

Pour le brochage des trois fils :

Marron => 12Vdc

Bleu => 0V

Noir => Signal de sortie du capteur

Voici le relevé de signal à l’osciloscope avec le capteur alimenté en 12Vdc sans diode ou diviseur de tension :

Sans détection métalique :

Avec détection métalique :

Bonjour,
Pour ma part, dans ce cas, j'installerais plutôt un module opto-coupleur beaucoup plus luxueux que des résistances mais assurant la séparation avec le 12V.
Si cette approche vous convient, je vous invite à effectuer des recherches "module optocoupleur 817" (consulter les modules sans relais) sur les sites de vente bien connus.

A+