fbpixel
Etiquetas: ,

En este tutorial, veremos cómo dirigir cada relé individualmente con un microcontrolador NodeMCU32S y registros de desplazamiento 74HC595. Al final de este tutorial, también serás capaz de manejar cada relé utilizando el monitor en serie. Este tutorial es una continuación del proyecto Piloto 8 relés utilizando un ESP32 y un registro de desplazamiento.

Este tutorial se puede aplicar a cualquier microcontrolador. Tendrá que tener cuidado de modificar el esquema de conexión y el código para que se ajuste a su uso.

Hardware

  • NodeMCU 32S
  • Breadboard
  • Jumper cable
  • Módulo de 8 relés
  • Registro de desplazamiento 74hc595

Principio

Hemos visto, en el tutorial anterior, cómo gestionar 8 relés utilizando un registro de desplazamiento. Ahora pasaremos a dirigirnos a cada relé de forma independiente utilizando el monitor de serie de Arduino IDE. Es posible comunicarse con el microcontrolador a través del puerto USB utilizando el puerto serie. Por lo tanto, definiremos una estructura de mensajes para especificar al microcontrolador qué relé debe encender.

Esquema

A modo de recordatorio, este es el diagrama de conexión del proyecto

  • GND tierra del circuito integrado
  • Pin de alimentación Vdc. Normalmente se conecta a 5V
  • SH_CP o RCLK conectado al pin 33
  • ST_CP o SRCLK conectado al pin 32
  • DS o SER conectado al pin 25
esp32_74HC595x1_8relays_bb-1280x1082 Control de 8 relés mediante ESP32 y monitor de serie

Código

Vamos a tomar el código del tutorial anterior y añadir las funciones para recibir mensajes del monitor serie y recuperar los comandos de control del relé. Para los mensajes de comando, elegimos la forma «YYxZ», con YY, el identificador del relé, un número de 0 a 7; y Z, el estado del relé 0-abierto, 1-cerrado.

La función readSerialPort, recupera los caracteres enviados por el monitor serie en la cadena «msg».

la función convertMsgToCmd traducirá la cadena en un número de identificación relayId y el estado 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 = "";
  }
}

Una vez recuperados los valores relayId y relayState, podemos ponerlos a la entrada de la función setRegisterPin (relayId, relayState); para activar o desactivar el relé. Es posible crear tantos mensajes como quieras. Aquí, por ejemplo, he añadido el comando «reset» para abrir todos los relés y el comando «states» para mostrar los estados de cada relé.

//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 = "";
  }
}

Resultado

Una vez cargado el código en el microcontrolador, abre el monitor de serie. Puede introducir el identificador del relé (0 – 7) y el estado deseado (0-abierto, 1-cerrado). Por ejemplo, para cerrar el relé 2, escriba 2×1 y luego «enter» o «send».

nodemcu32s-74hc595-16relays-monitor-control Control de 8 relés mediante ESP32 y monitor de serie

Próximos pasos

Fuentes