fbpixel
Configurer une redirection de Port

Configurer une redirection de Port

Lorsqu’on veut se connecter à un appareil en dehors de son réseau Wifi, il est nécessaire de configurer une redirection de port. Une fois votre Raspberry Pi ou ESP connecté à votre routeur internet, il est possible d’y accéder de n’importe où en configurant une redirection de port ou port forwarding.

N.B: Pour des raisons de cybersécurité, il peut être très dangereux de faire une redirection de port sans faire attention. Pour cette raison, vous ne devez mettre en place une redirection seulement si vous êtes sûr de ce que vous faites et vous devriez mettre en place les protections nécessaires (mot de passe, etc.).

Principe

Sur un même réseau, les appareils vont communiqué avec leurs adresses locales (ex: 192.168.x.xxx). Seul le routeur à une adresse public. Lorsqu’on configure une redirection de port, on demande au routeur d’ouvrir un port public et de le relier à une adresse locale.

Ex:

  • router public IP : 82.95.256.144
  • router local IP: 192.168.1.254
  • device local IP: 192.168.1.17 (port par défaut 80)

Ainsi si on redirige le port 600 vers l’adresse IP de l’appareil, on pourra accéder à l’appareil en tapant 82.95.256.144:600

Cette procédure peut-être très utile pour développer des fonctions avancées de domotique ou d’IoT nécessitant un accès à distance sur Raspberry Pi, ESP8266, EP32 ou tout autres appareils possédant une connexion internet.

Trouver l’adresse IP de votre routeur

  • Sous Raspberry Pi ou Linux
ip route
  • Sous Windows
ipconfig

Ces commandes donnent, entre autre, l’adresse IP locale de votre routeur (ici 192.168.1.254)

Vous pouvez utiliser la commande netstat -a pour obtenir la liste des connexions à l’équipement ainsi que les ports utilisés.

Configurer la redirection de port

Dans votre navigateur, vous pouvez entrer l’adresse IP pour accéder à la page d’accueil du routeur. Il vous sera demandé vos identifiants pour vous connecter.

N.B: La procédure de redirection de port est différente d’une box à une autre, En recherchant “nom-de-la-box Port Forwarding” sur internet, vous devriez tomber sur la marche à suivre.

Ensuite chercher l’option “Redirection de port” ou NAT/PAT. Sur une bbox, Services de la Box > Redirection de Port> Configuration

Cliquez sur “Ajouter une règles” et entrez les informations de redirections

D’après l’exemple précédent:

  • Nom de la règle: MyPortForwarding
  • Protocole: TCP
  • Adresse IP locale de l’équipement : 192.168.1.17
  • Port interne: 80 (peut être un ensemble de valeur)
  • Port externe: 600

N.B: Le port externe peut prendre une valeur entre 0 et 65535. Les numéros de port inférieurs à 1024 ou supérieurs à 49150 sont réservés au système.

Applications

Sources

Création d’un lampe avec un interrupteur tactile

Création d’un lampe avec un interrupteur tactile

Une des applications des capteurs capacitifs est la création d’un interrupteur tactile pour allumer une lampe, par exemple. Dans ce projet, nous allons concevoir un capteur capacitif avec Arduino que nous allons utiliser comme un interrupteur tactile pour allumer et éteindre une lampe.

Matériel

  • Arduino Nano
  • Résistance 10M Ohm
  • Relais
  • fil électrique ou matériau conducteur
  • Convertisseur AC/DC

Schéma de câblage

Attention: ce projet utilise la tension 220V. Prenez les précautions nécessaires afin de ne pas vous électrocuter.

Code

Pour créer un capteur capacitif, nous utilisons la librairie CapacitiveSensor. Lorsque le capteur capacitif change d’état, nous modifions l’état envoyer au relais pour ouvrir ou fermer le circuit.

#include <CapacitiveSensor.h>
#define DEBUG 0

//Capacitive sensor
CapacitiveSensor   cs_6_2 = CapacitiveSensor(6, 2);       // 10M resistor between pins 6 & 2, pin 2 is sensor pin, add a wire and or foil if desired
const int sensitivity  = 50;
long val;

//Light
const int lightPin = 9;
bool lightState = false;
bool btnState = false, oldState = false;

//smooth
long smoothval, total;
const int numReadings  = 3;
long readings[numReadings] = {0};
int readIndex;

long threshVal=500;

void setup()
{
  pinMode(lightPin, OUTPUT);
  cs_6_2.set_CS_AutocaL_Millis(0xFFFFFFFF);     // turn off autocalibrate on channel 1 - just as an example
  Serial.begin(9600);
  Serial.println("Touchless lamp initialized");
  delay(2000);

  for (int i = 0; i < numReadings; i++) {
    val =  cs_6_2.capacitiveSensor(sensitivity);// increase for hi
    smoothval = smooth(val);
  }
}

void loop()
{
  val =  cs_6_2.capacitiveSensor(sensitivity);// increase for hi
  smoothval = smooth(val);

  if (DEBUG) {
    //Serial.print(millis() - timeStart);        // check on performance in milliseconds
    Serial.print("\t");                    // tab character for debug window spacing
    Serial.print(val);                  // print sensor output 1
    Serial.print("\t");
    Serial.print(smoothval);                  // print sensor smooth output
    Serial.println();                  // print sensor smooth output
  }

  // condition
  if (btnState == false && smoothval > threshVal) {
    btnState = true;
  }
  if (btnState == true && smoothval <= threshVal*0.8) {
    btnState = false;
  }

  if (oldState != btnState) {
    if (oldState == false) {
      lightState = !lightState;
    }
    digitalWrite(lightPin, lightState);
    delay(200);
  }
  oldState = btnState;

  delay(100);         // arbitrary delay to limit data to serial port
}

long smooth(long val) { /* function smooth */
  ////Write data on device

  long average;
  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = val;//cs.capacitiveSensor(sensitivity);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits

  return average;
}

Résultat

Lorsqu’on approche la main du fil conducteur qui sert d’interrupteur tactile, la lampe devrait s’allumer ou s’éteindre. A vous de régler la sensibilité (sensitivity) du capteur, la résistance et la valeur seuil (threshVal) afin d’obtenir le comportement voulu.

Prochaines étapes

  • Améliorer la robustesse du capteur capacitif aux perturbations extérieures
  • Ajouter une fonctionnalité pour éteindre la lampe automatiquement après un certain temps

Source

Pilotez 8 relais à l’aide d’un ESP32 et d’une interface Web

Pilotez 8 relais à l’aide d’un ESP32 et d’une interface Web

Dans ce tutoriel, nous allons créer une interface web permettant de piloter 8 relais individuellement. Ce tutoriel peut être appliqué à n’importe quel microcontrôleur avec une connexion Wifi ou Ethernet. Il faudra faire attention à modifier le schéma de connexion et le code pour qu’ils correspondent à votre usage.

Ce tutoriel fait suite au projet Pilotez 8 relais à l’aide d’un ESP32 et du moniteur série.

Matériel

  • NodeMCU 32S
  • Breadboard
  • Jumper cable
  • Module 8 relais
  • Registre à décalage 74hc595

Principe

Nous avons vu, dans le tutoriel précédent, comment piloter 8 relais indépendamment à l’aide du moniteur série de l’IDE Arduino. Lorsqu’une connexion internet est disponible, comme sur le NodeMCU ESP32, il est possible de transformer votre microcontrôleur en serveur et d’héberger une page web. Cette page web peut servir d’interface graphique pour piloter votre projet. Nous allons créer une page Web, accessible via le réseau local, avec des boutons permettant d’activer les relais.

Code

Nous allons reprendre le code du tutoriel précédent et le combiner au code permettant de créer une Interface Web pour le NodeMCU ESP32. Sur la page Web, nous allons créer un tableau contenant 16 boutons correspondant aux actions “Activate”, et “Reset” des 8 relais. Afin de visualiser certaines actions, nous ajoutons un encart afin d’afficher des messages provenant du microcontrôleur.

void webpage(WiFiClient client) { //Send webpage to browser
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<head>");
  client.println("<title> AranaCorp </title>");
  client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
  client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
  client.println("<meta charset='UTF-8'>");
  client.println("");
  client.println("");
  client.println("");
  client.println("</head>");
  client.println("<body> ");
  client.println("<div id='page'>");
  client.println("<div id='content'>");
  client.println("<hr/><hr>");
  client.println("<h1><center> AranaCorp - Relay Controller Web Interface </center></h1>");
  client.println("<hr/><hr>");
  client.println("<br><br><div id='m' class='box'><center><table>");
  client.println("<tr><td>Console </td><td><input id='senM1' class='sensor'  value='" + String(console) + "' readonly></input></td></tr> </table>");

  client.println("  <table><tr><td>Relay 0</td>");
  client.println("   <td><a href='/light0on' class='button activate'> Activate </a>");
  client.println("  <a href='/light0off' class='button reset'> </a></td><td>Relay 1</td>");
  client.println("   <td><a href='/light1on' class='button activate'> Activate </a>");
  client.println("  <a href='/light1off' class='button reset'> Reset </a></td><td>Relay 2</td>");
  client.println("   <td><a href='/light2on' class='button activate'> Activate </a>");
  client.println("  <a href='/light2off' class='button reset'> Reset </a></td><td>Relay 3</td>");
  client.println("   <td><a href='/light3on' class='button activate'> Activate </a>");
  client.println("  <a href='/light3off' class='button reset'> Reset </a></td></tr><tr><td>Relay 4</td>");
  client.println("   <td><a href='/light4on' class='button activate'> Activate </a>");
  client.println("  <a href='/light4off' class='button reset'> Reset </a></td><td>Relay 5</td>");
  client.println("   <td><a href='/light5on' class='button activate'> Activate </a>");
  client.println("  <a href='/light5off' class='button reset'> Reset </a></td><td>Relay 6</td>");
  client.println("   <td><a href='/light6on' class='button activate'> Activate </a>");
  client.println("  <a href='/light6off' class='button reset'> Reset </a></td><td>Relay 7</td>");
  client.println("   <td><a href='/light7on' class='button activate'> Activate </a>");
  client.println("  <a href='/light7off' class='button reset'> Reset </a></td></tr>");
  client.println("</table></center></div>");

  client.println("</div><footer><div><p style='text-align:left;float:left;padding:0px;margin:0px;'>&copy; Copyright 2020 AranaCorp. All rights reserved</p><p style='float:right;padding:0px;margin:0px;'><a style='color:#3aaa35;' href='https://www.aranacorp.com/fr/evidence'>www.aranacorp.com</a><p></div></footer></div></body></html>");
  delay(1);
  client.stop();
}

Une fois la page web fonctionnelle, il ne nous reste plus qu’à gérer les requêtes du navigateur dans la fonction loop().

void loop() {
  WiFiClient client = server.available();
  if (client) {
    if (client.connected()) {
      String request = "";
      if (client.available()) {
        request = client.readStringUntil('\r');
        if (request != "") {
          client.print( header );
          handleRequest(request);
          webpage(client);//Return webpage
        }
      }
    }
  }
}

void handleRequest(String request) { /* function handleRequest */
  ////Handle web client request
  String pwmCmd;
  //Digital Ouputs
  for (int i = 0; i < 16; i++) {
    if (request.indexOf("/light" + String(i) + "on") > 0) {
      Serial.print("Relay n° "); Serial.print(i); +Serial.println(" ON ");
      setRegisterPin(i, 0);
      writeRegisters();
      console = String("Relay n°" + String(i) + " ON");
    }
    if (request.indexOf("/light" + String(i) + "off") > 0) {
      Serial.print("Relay n° "); Serial.print(i); +Serial.println(" OFF ");
      setRegisterPin(i, 1);
      writeRegisters();
      console = String("Relay n°" + String(i) + " OFF");
    }
  }
}

Vous trouverez ci-dessous, le code complet intégrant la gestion de la page web ainsi que du registre à décalage vue dans les articles précédents. N’oubliez pas de mettre à jour les variables ssid et password avec les valeurs de votre réseau.

//Libraries
#include <WiFi.h>//https://www.arduino.cc/en/Reference/WiFi

//Constants
#define number_of_74hc595s 2
#define numOfRegisterPins number_of_74hc595s * 8
#define SER_Pin 25
#define RCLK_Pin 33
#define SRCLK_Pin 32

//Variables
boolean registers[numOfRegisterPins];

char* ssid  = "*****";
char* password  = "*****";


String nom  = "ESP32";
//Objects
WiFiServer server(80);
WiFiClient client;

String header = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
String console = "System initialized";

void setup() {
  //Init Serial USB
  Serial.begin(115200);
  Serial.println(F("Initialize System"));
  //Init ESP32Wifi
  Serial.print("Connecting to "); Serial.println(ssid);
  WiFi.begin(ssid, password);
  // Connect to Wifi network.
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500); Serial.print(F("."));
  }
  server.begin();
  Serial.println();
  Serial.println(F("ESP32Wifi initialized"));
  Serial.print(F("IP Address: "));
  Serial.println(WiFi.localIP());

  //Init register
  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);
  clearRegisters();
  writeRegisters();
  delay(500);
}

void loop() {
  WiFiClient client = server.available();
  if (client) {
    if (client.connected()) {
      String request = "";
      if (client.available()) {
        request = client.readStringUntil('\r');
        if (request != "") {
          client.print( header );
          handleRequest(request);
          webpage(client);//Return webpage
        }
      }
    }
  }
}


void handleRequest(String request) { /* function handleRequest */
  ////Handle web client request
  String pwmCmd;
  //Digital Ouputs
  for (int i = 0; i < 16; i++) {
    if (request.indexOf("/light" + String(i) + "on") > 0) {
      Serial.print("Relay n° "); Serial.print(i); +Serial.println(" ON ");
      setRegisterPin(i, 0);
      writeRegisters();
      console = String("Relay n°" + String(i) + " ON");
    }
    if (request.indexOf("/light" + String(i) + "off") > 0) {
      Serial.print("Relay n° "); Serial.print(i); +Serial.println(" OFF ");
      setRegisterPin(i, 1);
      writeRegisters();
      console = String("Relay n°" + String(i) + " OFF");
    }
  }
}




void webpage(WiFiClient client) { //Send webpage to browser
  /* client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println("");*/
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<head>");
  client.println("<title> AranaCorp </title>");
  client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
  client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
  client.println("<meta charset='UTF-8'>");
  //client.println("<meta http-equiv='refresh' content='1'>");
  client.println("");
  client.println("<style>");
  client.println("");
  client.println("   body {");
  client.println("   font-size:100%;");
  client.println("   color:white;");
  client.println("   background-color: #111111;");
  client.println("   margin:0px;");
  client.println("   } ");
  client.println("  ");
  client.println("  #page {");
  client.println("width:100%;");
  client.println("  position: relative;");
  client.println("  min-height: 99vh;");
  client.println("}");
  client.println("");
  client.println("#content {");
  client.println("  padding-bottom: 2.5rem;    /* Footer height */");
  client.println("}");
  client.println("");
  client.println("footer {");
  client.println("  background-color:black;");
  client.println("  position: absolute;");
  client.println("  bottom: 0;");
  client.println("  width: 100%;");
  client.println("  height: 2.5rem;            /* Footer height */");
  client.println("}");
  client.println("   ");
  client.println("   h1 {color: #3AAA35;}");
  client.println("   p { text-align:center; }");
  client.println("");
  client.println("   table {");
  client.println("   width=80%;");
  client.println("margin: 40px 40px 40px 40px;");
  client.println("   }");
  client.println("   tr{");
  client.println("border: 1px solid black;");
  client.println("padding: 20px 20px 20px 20px;");
  client.println("   }");
  client.println("   td{");
  client.println("padding: 10px 10px 10px 10px;");
  client.println("   }");
  client.println("   .wrapper {");
  client.println("display: grid;");
  client.println("/*grid-template-columns: 1fr 1fr 1fr;*/");
  client.println("");
  client.println("margin: 60px 20px 60px 20px;");
  client.println("}");
  client.println(".box {");
  client.println("  border-radius: 10px;");
  client.println("  border: 2px solid white;");
  client.println("  font-size: 150%;");
  client.println("  /*height: 120px;*/");
  client.println("  margin: 5px 5px 5px 5px;");
  client.println("}");
  client.println("");
  client.println(".button {");
  client.println("  background-color: #111111; /* Green */");
  client.println("  border: none;");
  client.println("  color: white;");
  client.println("  padding: 16px 32px;");
  client.println("  text-align: center;");
  client.println("  text-decoration: none;");
  client.println("  display: inline-block;");
  client.println("  font-size: 16px;");
  client.println("  margin: 4px 2px;");
  client.println("  transition-duration: 0.4s;");
  client.println("  cursor: pointer;");
  client.println("  border-radius: 12px;");
  client.println("}");
  client.println("");
  client.println(".activate {");
  client.println("  color: white; ");
  client.println("  border: 2px solid #3AAA35;");
  client.println("}");
  client.println("");
  client.println(".activate:hover {");
  client.println("  background-color: #3AAA35;");
  client.println("  color: white;");
  client.println("}");
  client.println("");
  client.println(".reset { ");
  client.println("  color: white; ");
  client.println("  border: 2px solid #f44336;");
  client.println("}");
  client.println("");
  client.println(".reset:hover {");
  client.println("  background-color: #f44336;");
  client.println("  color: white;");
  client.println("}");
  client.println("");
  client.println("    .sensor {");
  client.println("  background-color: #ffffff;");
  client.println("  border: none;");
  client.println("  color: black;");
  client.println("  padding: 16px 32px;");
  client.println("  text-align: center;");
  client.println("  text-decoration: none;");
  client.println("  display: inline-block;");
  client.println("  font-size: 16px;");
  client.println("  margin: 4px 2px;");
  client.println("  transition-duration: 0.4s;");
  client.println("  cursor: pointer;");
  client.println("  border-radius: 2px;");
  client.println("}");
  client.println("");
  client.println(".status {");
  client.println("  color: white; ");
  client.println("  border: 5px solid #3AAA35;");
  client.println("  border-radius: 12px;");
  client.println("}");
  client.println("");
  client.println("");
  client.println("@media (min-width: 1050px){ /*screen and*/");
  client.println("  .wrapper {");
  client.println("grid-template-columns: repeat(2, 1fr);");
  client.println("  }");
  client.println("  ");
  client.println("@media (min-width: 1500px){");
  client.println("  .wrapper {");
  client.println("grid-template-columns: repeat(3, 1fr);");
  client.println("  }");
  client.println("}");
  client.println("");
  client.println(" </style>");
  client.println("");
  client.println("");
  client.println("</head>");
  client.println("<body> ");
  client.println("<div id='page'>");
  client.println("<div id='content'>");
  client.println("<hr/><hr>");
  client.println("<h1><center> AranaCorp - Relay Controller Web Interface </center></h1>");
  client.println("<hr/><hr>");
  client.println("<br><br><div id='m' class='box'><center><table>");
  client.println("<tr><td>Console </td><td><input id='senM1' class='sensor'  value='" + String(console) + "' readonly></input></td></tr> </table>");

  client.println("  <table><tr><td>Relay 0</td>");
  client.println("   <td><a href='/light0on' class='button activate'> Activate </a>");
  client.println("  <a href='/light0off' class='button reset'> Reset </a></td><td>Relay 1</td>");
  client.println("   <td><a href='/light1on' class='button activate'> Activate </a>");
  client.println("  <a href='/light1off' class='button reset'> Reset </a></td><td>Relay 2</td>");
  client.println("   <td><a href='/light2on' class='button activate'> Activate </a>");
  client.println("  <a href='/light2off' class='button reset'> Reset </a></td><td>Relay 3</td>");
  client.println("   <td><a href='/light3on' class='button activate'> Activate </a>");
  client.println("  <a href='/light3off' class='button reset'> Reset </a></td></tr><tr><td>Relay 4</td>");
  client.println("   <td><a href='/light4on' class='button activate'> Activate </a>");
  client.println("  <a href='/light4off' class='button reset'> Reset </a></td><td>Relay 5</td>");
  client.println("   <td><a href='/light5on' class='button activate'> Activate </a>");
  client.println("  <a href='/light5off' class='button reset'> Reset </a></td><td>Relay 6</td>");
  client.println("   <td><a href='/light6on' class='button activate'> Activate </a>");
  client.println("  <a href='/light6off' class='button reset'> Reset </a></td><td>Relay 7</td>");
  client.println("   <td><a href='/light7on' class='button activate'> Activate </a>");
  client.println("  <a href='/light7off' class='button reset'> Reset </a></td></tr>");
  client.println("</table></center></div>");

  client.println("</div><footer><div><p style='text-align:left;float:left;padding:0px;margin:0px;'>&copy; Copyright 2020 AranaCorp. All rights reserved</p><p style='float:right;padding:0px;margin:0px;'><a style='color:#3aaa35;' href='https://www.aranacorp.com/fr/evidence'>www.aranacorp.com</a><p></div></footer></div></body></html>");
  delay(1);
  client.stop();
}

//SR
void clearRegisters() { /* function clearRegisters */
  //// Clear registers variables
  for (int i = numOfRegisterPins - 1; i >=  0; i--) {
    registers[i] = HIGH;
  }
}

void writeRegisters() { /* function writeRegisters */
  //// Write register after being set
  digitalWrite(RCLK_Pin, LOW);
  for (int i = numOfRegisterPins - 1; i >=  0; i--) {
    digitalWrite(SRCLK_Pin, LOW);
    digitalWrite(SER_Pin, registers[i]);
    digitalWrite(SRCLK_Pin, HIGH);
  }
  digitalWrite(RCLK_Pin, HIGH);
}

void setRegisterPin(int index, int value) { /* function setRegisterPin */
  ////Set register variable to HIGH or LOW
  registers[index] = value;
}

void printRegisters() { /* function clearRegisters */
  //// Clear registers variables
  for (int i = 0; i < numOfRegisterPins; i++) {
    Serial.print(registers[i]); Serial.print(F(" ,"));
  }
  Serial.println();
}

Résultat

Une fois le code chargé dans le microcontrôleur, entrez l’adresse IP qui s’affiche dans le moniteur série (ici 192.168.1.64), dans votre navigateur web. La page suivante devrait s’afficher.

Vous pouvez ensuite fermer les relais avec les boutons “Activate” et les ouvrir avec les boutons “Reset” correspondants.

N’hésitez pas à nous laisser un commentaire pour nous donner votre avis, vos retours et pistes d’améliorations pour ce tutoriel.

Sources

Pilotez 8 relais à l’aide d’un ESP32 et du moniteur série

Pilotez 8 relais à l’aide d’un ESP32 et du moniteur série

Dans ce tutoriel, nous allons voir comment adresser chaque relais individuellement avec un microcontrôleur NodeMCU32S et des registres à décalages 74HC595. A l’issue de ce tutoriel, vous serez aussi capable de piloter chaque relais à l’aide du moniteur série. Ce tutoriel fait suite au projet Pilotez 8 relais à l’aide d’un ESP32 et un registre à décalage.

Ce tutoriel peut être appliqué à n’importe quel microcontrôleur. Il faudra faire attention à modifier le schéma de connexion et le code pour qu’ils correspondent à votre usage.

Matériel

  • NodeMCU 32S
  • Breadboard
  • Jumper cable
  • Module 8 relais
  • Registre à décalage 74hc595

Principe

Nous avons vu, dans le tutoriel précédent, comment gérer 8 relais à l’aide d’un registre à décalage. Nous allons à présent venir adresser chaque relais indépendamment à l’aide du moniteur série de l’IDE Arduino. Il est possible de communiquer avec le microcontrôleur via le port USB en utilisant le port série. Nous allons donc définir une structure de message pour spécifier au microcontrôleur quel relais allumer.

Schéma

Pour rappel, voici le schéma de connexion du projet

  • GND masse du circuit intégré
  • Vcc broche d’alimentation. Généralement connecté à 5V
  • SH_CP ou RCLK relié à la broche 33
  • ST_CP ou SRCLK reliée à la broche 32
  • DS ou SER reliée à la broche 25
NodeMCU32S ESP32, shift register 74HC595 and 8 relays module schematics

Code

Nous allons reprendre le code du tutoriel précédent et rajouter les fonctions pour recevoir les messages du moniteur série et récupérer les commandes de pilotage des relais. Pour les messages de commande, nous choisissons la forme “YYxZ”, avec YY, l’identifiant du relais , un chiffre de 0 à 7; et Z, l’état du relais 0-ouvert, 1-fermé.

La fonction readSerialPort, récupère les caractères envoyés par le moniteur série dans la chaîne de caractère “msg”.

la fonction convertMsgToCmd va traduire la chaine de caractère en un numéro d’identification relayId et l’état du relais relayState.

void readSerialPort() {
  while (Serial.available()) {
    delay(10);
    if (Serial.available() > 0) {
      char c = Serial.read();  //gets one byte from serial buffer
      msg += c;
    }
  }
}

void convertMsgToCmd() {
  relayId = -1;
  relayState = -1;
  if (msg.length() > 0) {
    Serial.println(msg);
    sep = msg.indexOf('x');
    if (sep > 0) {
      m1 = msg.substring(0, sep); //get servo id
      m2 = msg.substring(sep + 1, msg.length()); //get servo pos

      char carray1[6]; //magic needed to convert string to a number
      m1.toCharArray(carray1, sizeof(carray1));
      relayId = atoi(carray1);

      char carray2[6];
      m2.toCharArray(carray2, sizeof(carray2));
      relayState = atoi(carray2);

      relayState = 1 - relayState;
      Serial.print(F("Set relay n° ")); Serial.print(relayId); Serial.print(F(" to ")); Serial.println(!relayState ? "HIGH" : "LOW");
    }

    sep = msg.indexOf("reset");
    if (sep == 0) {
      m1 = "reset";
    }

    sep = msg.indexOf("states");
    if (sep == 0) {
      m1 = "states";
    }
    msg = "";
  }
}

Une fois les valeurs relayId et relayState récupérées, nous pouvons les placer en entrée de la fonction setRegisterPin(relayId, relayState); afin d’activer ou non le relais. Il est possible de créer autant de messages que vous le souhaitez. Ici, par exemple, j’ai rajouté la commande “reset” pour ouvrir tous les relais et la commande “states” pour afficher les états de chaque relais.

//Constants
#define number_of_74hc595s 1
#define numOfRegisterPins number_of_74hc595s * 8
#define SER_Pin 25
#define RCLK_Pin 33
#define SRCLK_Pin 32

//Variables
boolean registers[numOfRegisterPins];
String msg, m1, m2;
int sep, relayId, relayState;

void setup() {
  delay(100);
  //Init Serial USB
  Serial.begin(115200);
  Serial.println(F("Initialize System"));
  //Init register
  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);
  clearRegisters();
  writeRegisters();
  delay(500);
  Serial.println(F("Enter Relay ID ans state (IDxSTATE):"));
}

void loop() {
  readSerialPort();
  convertMsgToCmd();
  if (relayId >= 0 and relayState >= 0) {
    setRegisterPin(relayId, relayState);
    writeRegisters();
  }
  if (m1 == "reset") {
    Serial.println(F("Reset all relays"));
    clearRegisters();
    writeRegisters();
  }
  if (m1 == "states") {
    Serial.println(F("print relays states"));
    printRegisters();
  }
  m1 = "";
}

void clearRegisters() { /* function clearRegisters */
  //// Clear registers variables
  for (int i = numOfRegisterPins - 1; i >=  0; i--) {
    registers[i] = HIGH;
  }
  printRegisters();
}

void writeRegisters() { /* function writeRegisters */
  //// Write register after being set
  digitalWrite(RCLK_Pin, LOW);
  for (int i = numOfRegisterPins - 1; i >=  0; i--) {
    digitalWrite(SRCLK_Pin, LOW);
    digitalWrite(SER_Pin, registers[i]);
    digitalWrite(SRCLK_Pin, HIGH);
  }
  digitalWrite(RCLK_Pin, HIGH);
}

void setRegisterPin(int index, int value) { /* function setRegisterPin */
  ////Set register variable to HIGH or LOW
  registers[index] = value;
}

void printRegisters() { /* function clearRegisters */
  //// Clear registers variables
  for (int i = 0; i < numOfRegisterPins; i++) {
    Serial.print(registers[i]); Serial.print(F(" ,"));
  }
  Serial.println();
}

void readSerialPort() {
  while (Serial.available()) {
    delay(10);
    if (Serial.available() > 0) {
      char c = Serial.read();  //gets one byte from serial buffer
      msg += c;
    }
  }
}

void convertMsgToCmd() {
  relayId = -1;
  relayState = -1;
  if (msg.length() > 0) {
    Serial.println(msg);
    sep = msg.indexOf('x');
    if (sep > 0) {
      m1 = msg.substring(0, sep); //get servo id
      m2 = msg.substring(sep + 1, msg.length()); //get servo pos

      char carray1[6]; //magic needed to convert string to a number
      m1.toCharArray(carray1, sizeof(carray1));
      relayId = atoi(carray1);

      char carray2[6];
      m2.toCharArray(carray2, sizeof(carray2));
      relayState = atoi(carray2);

      relayState = 1 - relayState;
      Serial.print(F("Set relay n° ")); Serial.print(relayId); Serial.print(F(" to ")); Serial.println(!relayState ? "HIGH" : "LOW");
    }

    sep = msg.indexOf("reset");
    if (sep == 0) {
      m1 = "reset";
    }

    sep = msg.indexOf("states");
    if (sep == 0) {
      m1 = "states";
    }
    msg = "";
  }
}

Résultat

Une fois le code chargé dans le microcontrôleur, ouvrez le moniteur série. Vous pouvez entrer l’identifiant du relais (0 – 7) ainsi que l’état désiré (0-ouvert, 1- fermé). Exemple , pour fermer le relais 2, tapez 2×1 puis “entrée” ou “Envoyer”.

Prochaines étapes

Sources

Piloter 8 relais avec un ESP32 et un registre à décalage

Piloter 8 relais avec un ESP32 et un registre à décalage

Dans cette série de tutoriels, nous allons voir comment piloter une multitude de relais avec un microcontrôleur NodeMCU32S et des registres à décalages 74HC595. Nous allons ensuite voir comment adresser chaque relais individuellement. Enfin, nous allons créer une interface Web pour piloter chaque relais par internet. Ce projet est une bonne base pour développer un système domotique pour chez vous.

Ce tutoriel peut être appliqué à n’importe quel microcontrôleur. Il faudra faire attention à modifier le schéma de connexion et le code pour qu’ils correspondent à votre usage.

Matériel

  • NodeMCU 32S
  • Breadboard
  • Jumper cable
  • Module 8 relais
  • Registre à décalage 74hc595

Principe

Pour piloter le module 8 relais, il faut réserver 8 sorties digitales du microcontrôleur. Afin d’économiser le nombre d’entrée/sortie du microcontrôleur, différent circuit intégrés peuvent être utilisé. Notamment, le registre à décalage (ou shift register). Le registre à décalage 74HC595 possède 8 sorties programmables, pouvant prendre comme valeur 0 ou 5V et ne nécessite que 3 entrées digitales. Cette solution est donc idéale pour nous permettre de piloter les relais et garder les sorties du microcontrôleur pour d’autres fonctionnalités.

Schéma

Pour piloter le registre à décalage, le NodeMCU se connecte de la manière suivante:

  • GND masse du circuit intégré
  • Vcc broche d’alimentation. Généralement connecté à 5V
  • SH_CP ou RCLK relié à la broche 33
  • ST_CP ou SRCLK reliée à la broche 32
  • DS ou SER reliée à la broche 25

Les sorties du circuit intégré 74HC595 (Q0-Q7) sont directement connectés aux entrées du module 8 relais. Dans ce tutoriel, nous n’utilisons pas les broches Enable (OE) et Reset(MR).

  • OE Output enable, active LOW. Broche connectée à GND pour activer les sorties
  • MR Master reset, active LOW. Broche de remise à zéro. Connectée au 5V

Attention: Les sorties d’un microcontrôleur sont limités en courant. Pour piloter autant de relais, il est fortement conseillé d’utiliser une source extérieure de tension.

NodeMCU32S ESP32, shift register 74HC595 and 8 relays module schematics

Code

Dans le code suivant, nous allons tout d’abord définir les fonctions de base pour gérer le registre à décalage. Puis, nous allons actionner les relais un par un en utilisant une boucle for.

//Constants
#define number_of_74hc595s 1
#define numOfRegisterPins number_of_74hc595s * 8
#define SER_Pin 25
#define RCLK_Pin 33
#define SRCLK_Pin 32

//Variables
boolean registers [numOfRegisterPins];


void setup() {
  //Init Serial USB
  Serial.begin(115200);
  Serial.println(F("Initialize System"));
  //Init register
  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);
  pinMode(OUT_Pin, INPUT);
  clearRegisters();
  writeRegisters();
  delay(500);
}
void loop() {
  writeGrpRelay();
}

void clearRegisters() { /* function clearRegisters */
  //// Clear registers variables
  for (int i = numOfRegisterPins - 1; i >=  0; i--) {
    registers[i] = HIGH;//LOW;
  }
}

void writeRegisters() { /* function writeRegisters */
  //// Write register after being set
  digitalWrite(RCLK_Pin, LOW);
  for (int i = numOfRegisterPins - 1; i >=  0; i--) {
    digitalWrite(SRCLK_Pin, LOW); int val = registers[i];
    digitalWrite(SER_Pin, val);
    digitalWrite(SRCLK_Pin, HIGH);
  }
  digitalWrite(RCLK_Pin, HIGH);
}

void setRegisterPin(int index, int value) { /* function setRegisterPin */
  ////Set register variable to HIGH or LOW
  registers[index] = value;
}

void writeGrpRelay() { /* function writeGrpRelay */
  for (int i = numOfRegisterPins - 1; i >=  0; i--) {
    Serial.print(F("Relay ")); Serial.print(i); Serial.println(F(" HIGH"));
    setRegisterPin(i, LOW);
    writeRegisters();
    delay(200);
    Serial.print(F("Relay ")); Serial.print(i); Serial.println(F(" LOW"));
    setRegisterPin(i, HIGH);
    writeRegisters();
    delay(500);

  }
}

Résultat

Une fois les composants branchés correctement et le code chargé dans le microcontrôleur, les relais devrait s’activer les uns à la suite de autres.

Bonus: Contrôler 16 relais avec deux registres à décalage

Schéma

NodeMCU32S ESP32, shift registers 74HC595 and 16 relays module schematics

Code

La beauté de ce code est que pour le faire fonctionner avec un second registre à décalage il suffit de modifier le paramètre:

#define number_of_74hc595s 2

Résultat

Prochaines étapes

Sources