fbpixel
Etiquetas: ,
5
(4)

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
NodeMCU32S ESP32, shift register 74HC595 and 8 relays module schematics

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».

Próximos pasos

Fuentes

¿De cuánta utilidad te ha parecido este contenido?

¡Haz clic en una estrella para puntuarlo!

Promedio de puntuación 5 / 5. Recuento de votos: 4

Hasta ahora, ¡no hay votos!. Sé el primero en puntuar este contenido.

Ya que has encontrado útil este contenido...

¡Sígueme en los medios sociales!

¡Siento que este contenido no te haya sido útil!

¡Déjame mejorar este contenido!

Dime, ¿cómo puedo mejorar este contenido?