ESP32

How to work with RS485 interface on ESP32

기하 2021. 8. 23. 22:16

앞선 기사 에서 , 내가 가진 RS485 모듈 XY-485을 ESP8266와 함께 사용하는 법을 설명했습니다.
여기서는 ESP32와 사용하는 법을 설명하겠습니다.
다음 기사 에서는 번개에 대한 어떤 보호 가능도 없는 아주 싼 MAX485 기반 보드사용을 검토합니다.

 

테스트용 하드웨어:

물론 30핀 대신 38핀 보드 ESP32를 구입하는 것이 좋습니다. 

가격 차이는 약 1,5 USD이지만 GPIO 핀이 더 많습니다. 보드 크기는 거의 동일합니다.

 


30핀 보드 ESP32

38핀 보드 ESP32

직렬 포트 ESP32

ESP32에서는 U0UXD, U1UXD, U2UXD로 알려진 3개의 UART 포트가 있습니다.

  • U0UXD는 USB 인터페이스 변환기 칩에서 사용됩니다(핀아웃 ESP32 DevKit V1 참조 ).
  • U1UXD는 자체 프로젝트에 사용할 수 있습니다. 일부 보드는 이 핀을 SPI 플래시에 사용했습니다. 
    이 경우 직렬 포트를 요청하면 프로그램이 충돌합니다. 
    프로그램충돌을 피하기 위해 UART1을 다른 GPIO로 이동할 수 있습니다.
  • U2UXD는 자체 프로젝트에 사용할 수 있습니다.

대부분의 ESP8266 보드에서 U0UXD는 ESP32의 경우와 같이 USB 인터페이스 변환기가 차지합니다. 
따라서 USB인터페이스가 있는 ESP8266 보드에서 사용할  UART는 없습니다.

 

시리얼포트 부족 문제를 해결하기 위해 ESP8266에서는 두 가지 변형을 사용할 수 있습니다.

  • 우리는 추가 컨버터 보드의 I2C를 사용하여  UART 로추가의8 SC16IS750 칩의 GPIO  . 또는 칩 SC16IS752를 기반으로 하는 2개의 UART에 대한 보다 강력한 변환기 I2C 
  • ESPSoftwareSerial 라이브러리의 도움으로 소프트웨어 에뮬레이션을 사용할 수 있습니다 . 직렬 포트 소프트웨어 에뮬레이션은 RS485에서 매우 안정적으로 작동하지만 하드웨어 직렬 포트를 사용하는 것이 좋습니다.

ESP32를 사용하는 경우 두 개의 추가 직렬 UART 포트가 있습니다. 컨버터 보드의 경우 ESP32 보드의 절반 수준인 약 4달러입니다. 다음 GPIO 핀에 연결된 기본 RX/TX:

 

Device Function GPIO    
UART 0 TX 1
UART 0 RX 3
UART 1 TX 10
UART 1 RX 9
UART 2 TX 17
UART 2 RX 16

30핀 ESP32 DevKit V1의 핀 배치를 보면 UART1 포트를 사용할 수 없으며

38핀 마더보드에 있음을 알 수 있습니다.

ESP32 DevKit V1 핀아웃

 

그러나 ESP32에서는 포트가 초기화될 때 UART1 직렬 포트를 다른 GPIO로 마이그레이션할 수 있습니다.

RS485 모듈에 ESP32 연결

ESP32에서는 하드웨어 UART를 사용합니다. 이전 기사 에서 언급하였습니다

RX / TX 핀은 XY-485 및 XY-017 보드에 혼합되어 있습니다!!!

ESP32 XY-485
Rx (PIN RX2, GPIO16) RXD
Tx (PIN TX2, GPIO17) TXD
  VCC(3,3V )
GND GND
 
ESP32 XY-017
Rx (PIN RX1, GPIO15) RXD
Tx (PIN TX1, GPIO4) TXD
  VCC(3,3V )
GND 접지

RS485 모듈용 전원 공급 장치는 3,3V여야 합니다.

그렇지 않으면 ESP32의 GPIO를 태울 수 있습니다!!!
아니면 TTL레벨 변환기 사용하세요

 

 XY-485/XY-017모듈과  RS485 열 센서의 연결은 다음과 같습니다.

 

Thermal sensor 1 XY-485   
A+ A+
B- B-
GND 접지
GND(전원 공급 장치 -)  
VCC(전원 +5V)  
Thermal sensor 2 XY-017
A+ A+
B- B-
GND GND
GND(전원 공급 장치 -)  
VCC(전원 +5V)  

 

ESP32 보드의 RS485 인터페이스와 함께 작동하는 프로그램

일반적으로 두 개의 RS485 인터페이스 보드를 ESP32에 연결하는 것은 의미가 없습니다. 

RS485 라인 길이는 RS485 연결 장치 32개를 포함하여 약 1200미터입니다. 

일반적으로 이 수의 장치로 충분합니다.

 

이 경우 예제는 ESP32 보드에서 두 개의 UART를 사용할 가능성을 보여줍니다. 

예를 들어, RS485 인터페이스 보드와 함께 GSM 또는 GPS 모듈을 사용하는 경우 2개의 UART가 좋은 옵션입니다.

 

/*
 * There are three serial ports on the ESP known as U0UXD, U1UXD and U2UXD.
 * 
 * U0UXD is used to communicate with the ESP32 for programming and during reset/boot.
 * U1UXD is unused and can be used for your projects. Some boards use this port for SPI Flash access though
 * U2UXD is unused and can be used for your projects.
 * 
 * Tested on the 30 pin ESP32 DevKit V1 board
 * 
 */

#include "ModbusMaster.h" //https://github.com/4-20ma/ModbusMaster
#include <HardwareSerial.h>

#define Slave_ID1 2
#define Slave_ID2 1

// instantiate ModbusMaster object
ModbusMaster modbus1;
ModbusMaster modbus2;

//HardwareSerial Serial1(1);
//HardwareSerial Serial2(2); //- there is no any sense to define since it already defined in HardwareSerial.h 

#define RXD1 15 //RX1 pin
#define TXD1 4 //TX1 pin

#define RXD2 16 //RXX2 pin
#define TXD2 17 //TX2 pin

void setup() 
{
  // Modbus communication runs at 9600 baud
  Serial.begin(9600, SERIAL_8N1);
  Serial1.begin(9600, SERIAL_8N1, RXD1, TXD1);
  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);

  // Modbus slave ID 1
  modbus1.begin(Slave_ID1, Serial1);
  modbus2.begin(Slave_ID2, Serial2);
  modbus1.idle(yield);
  modbus2.idle(yield);
}

long lastMillis = 0;
void loop() 
{
  long currentMillis = millis();
  if (currentMillis - lastMillis > 5000) 
  {
    // Read 2 registers starting at 0x01
    uint8_t result1 = modbus1.readInputRegisters(0x01, 2);
    if (getResultMsg( & modbus1, result1)) 
    {
      Serial.println();

      double res_dbl = modbus1.getResponseBuffer(0) / 10;
      String res = "Temperature1: " + String(res_dbl) + " C\r\n";
      res_dbl = modbus1.getResponseBuffer(1) / 10;
      res += "Humidity1: " + String(res_dbl) + " %";
      Serial.println(res);
    }

    uint8_t result2 = modbus2.readInputRegisters(0x01, 2);
    if (getResultMsg( & modbus2, result2)) 
    {
      Serial.println();

      double res_dbl = modbus1.getResponseBuffer(0) / 10;
      String res = "Temperature2: " + String(res_dbl) + " C\r\n";
      res_dbl = modbus1.getResponseBuffer(1) / 10;
      res += "Humidity2: " + String(res_dbl) + " %";
      Serial.println(res);
    }
    lastMillis = currentMillis;
  }
}

bool getResultMsg(ModbusMaster *node, uint8_t result) 
{
  String tmpstr2 = "\r\n";

  switch (result) 
  {
  case node->ku8MBSuccess:
    return true;
    break;
  case node->ku8MBIllegalFunction:
    tmpstr2 += "Illegal Function";
    break;
  case node->ku8MBIllegalDataAddress:
    tmpstr2 += "Illegal Data Address";
    break;
  case node->ku8MBIllegalDataValue:
    tmpstr2 += "Illegal Data Value";
    break;
  case node->ku8MBSlaveDeviceFailure:
    tmpstr2 += "Slave Device Failure";
    break;
  case node->ku8MBInvalidSlaveID:
    tmpstr2 += "Invalid Slave ID";
    break;
  case node->ku8MBInvalidFunction:
    tmpstr2 += "Invalid Function";
    break;
  case node->ku8MBResponseTimedOut:
    tmpstr2 += "Response Timed Out";
    break;
  case node->ku8MBInvalidCRC:
    tmpstr2 += "Invalid CRC";
    break;
  default:
    tmpstr2 += "Unknown error: " + String(result);
    break;
  }
  Serial.println(tmpstr2);
  return false;
}

 

 

 

 

에서 다음 기사 나는 MAX3485에 따라 매우 칩 RS485 인터페이스 보드를 검토합니다.