Étiquettes : ,

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