fbpixel
Etiquetas: ,

Neste tutorial, veremos como endereçar cada relé individualmente usando um microcontrolador NodeMCU32S e registos de deslocamento 74HC595. No final deste tutorial, será também capaz de acionar cada relé utilizando o monitor série. Este tutorial vem na sequência do projeto Controlar 8 relés usando um ESP32 e um registo de deslocamento.

Este tutorial pode ser aplicado a qualquer microcontrolador. Terá de ter o cuidado de modificar o diagrama de ligação e o código para se adequar à sua utilização.

 

Hardware

  • NodeMCU 32S
  • Prancheta
  • Cabo de ligação
  • Módulo de 8 relés
  • 74hc595 registo de deslocação

 

Princípio

No tutorial anterior, vimos como gerir 8 relés usando um registo de deslocamento. Agora vamos endereçar cada relé independentemente usando o monitor serial do Arduino IDE. É possível comunicar com o microcontrolador através da porta USB utilizando a porta série. Assim, vamos definir uma estrutura de mensagem para dizer ao microcontrolador qual o relé a ligar.

Diagrama

Para recordar, eis o esquema de ligação do projeto

  • GND Terra do circuito integrado
  • Pino de alimentação Vdc. Normalmente ligado a 5V
  • SH_CP ou RCLK ligado ao pino 33
  • ST_CP ou SRCLK ligado ao pino 32
  • DS ou SER ligado ao pino 25
esp32_74HC595x1_8relays_bb-1280x1082 Controlo de 8 relés utilizando um ESP32 e o monitor série

Código

Vamos repetir o código do tutorial anterior e adicionar funções para receber mensagens do monitor de série e obter comandos de controlo do relé. Para as mensagens de comando, escolhemos a forma “YYxZ”, sendo YY, o identificador do relé, um número de 0 a 7; e Z, o estado do relé 0-aberto, 1- fechado.

A função readSerialPort recupera os caracteres enviados pelo monitor de série na cadeia de caracteres “msg”.

a função convertMsgToCmd traduzirá a cadeia de caracteres num número de identificação relayId e no 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 = "";
  }
}

Depois de termos recuperado os valores relayId e relayState, podemos utilizá-los como entrada para a função setRegisterPin(relayId, relayState) para ativar ou desativar o relé. Pode criar o número de mensagens que quiser. Aqui, por exemplo, adicionei o comando “reset” para abrir todos os relés e o comando “states” para mostrar os 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 = "";
  }
}

Resultados

Uma vez carregado o código no microcontrolador, abrir o monitor série. Pode introduzir o identificador do relé (0 – 7) e o estado desejado (0-aberto, 1- fechado). Por exemplo, para fechar o relé 2, digite 2×1 e depois “enter” ou “send”.

nodemcu32s-74hc595-16relays-monitor-control Controlo de 8 relés utilizando um ESP32 e o monitor série

Próximas etapas

Fontes