fbpixel
Etiquetas: ,
0
(0)

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

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

Próximas etapas

Fontes

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?