본문 바로가기

개발환경/Arduino IDE

아두이노 1대 N - RS485 통신 테스트

Arduino Uno, MAX485 TTL to RS-485 컨버터 모듈을 사용하였고, 개발 환경은 Arduino IDE 2.2.1 입니다.

 

구상도

 

송수신 과정

1번: Master "A LED ON"을 전송한다.

 

2번: Slave A/B가 "A LED ON"을 수신받는다. 그리고 Slave A는 LED를 켠다.

 

3번: Slave A가 "A LED ON"을 전송한다. 그리고 Master는 LED(A 상태)를 킨다.

 

4번: Master가 "B LED ON"을 전송한다.

 

5번: Slave A/B가 "B LED ON"을 수신받는다. 그리고 Slave B는 LED를 켠다.

 

6번: Slave B가 "B LED ON"을 전송한다. 그리고 Master는 LED(B 상태)를 킨다.

 

7번: Master가 "A LED OFF"을 전송한다.

 

8번: Slave A/B가 "A LED OFF"을 수신받는다. 그리고 Slave A는 LED를 끈다.

 

9번: Slave A가 "A LED OFF"을 전송한다. 그리고 Master는 LED(A 상태)를 끈다.

 

10번: Master가 "B LED OFF"을 전송한다.

 

11번: Slave A/B가 "B LED OFF"을 수신받는다. 그리고 Slave B는 LED를 끈다.

 

12번: Slave B가 "B LED OFF"을 전송한다. 그리고 Master는 LED(B 상태)를 끈다.

 

배선

<참고 자료>

https://blog.naver.com/kwy1052aa/221740261100

 

아두이노 VS 아두이노 RS485 데이터 송수신

책상 한쪽 구석에서 항상 굴러다니고 있는 아두이노들을 이용해서 RS485 통신으로 데이터를 송수신 해보...

blog.naver.com

 

코드 - Master

#include <SoftwareSerial.h>
#define RS485Control 7
#define ledA  8
#define ledB  9
SoftwareSerial rs485(2, 3);
char* commandStr[] = {"A LED ON!", "B LED ON!", "A LED OFF!", "B LED OFF!"};
unsigned char receiveEndFlag = 0;
unsigned char sendFlag = 1;
unsigned char commandCnt = 0;
unsigned int sendBufCnt = 0;
unsigned int receiveBufCnt = 0;
char sendBuff[50] = {0};
char receiveBuff[50] = {0};

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("=========Master START========");
  rs485.begin(9600);
  pinMode(RS485Control, OUTPUT);
  pinMode(ledA, OUTPUT);
  pinMode(ledB, OUTPUT);
  digitalWrite(RS485Control, HIGH);
}

void loop() {
  // put your main code here, to run repeatedly:
  if(receiveBuff[0] == 0 && sendFlag == 1)  { // send command
    digitalWrite(RS485Control, HIGH);
    strcpy(sendBuff, commandStr[commandCnt]);
    while(1){
      rs485.write(sendBuff[sendBufCnt]);
      Serial.print(sendBuff[sendBufCnt]);
      if(sendBuff[sendBufCnt++] == '!') {
        sendBufCnt = 0;
        break;
      }
      delay(100);
    }
    Serial.print("\tMASTER 전송 완료\n");
    delay(3000);
    if(commandCnt == 3) commandCnt = 0;
    else  commandCnt++;
    digitalWrite(RS485Control, LOW);
    sendFlag = 0;
  }

  if(rs485.available()) { // receive command
    receiveBuff[receiveBufCnt] = rs485.read();
    Serial.print(receiveBuff[receiveBufCnt]);
    if(receiveBuff[receiveBufCnt++] == '!') {
      receiveEndFlag = 1;
      receiveBufCnt = 0;
      Serial.print("\tMASTER 수신 완료\n");
      delay(3000);
    }
    delay(100);
  }

  if(receiveBuff[0] != 0 && receiveEndFlag == 1)  { //process receive message

    if(receiveBuff[0] == 'A') {
      if(strncmp(&receiveBuff[6], "ON", 2) == 0)  digitalWrite(ledA, HIGH);
      else if(strncmp(&receiveBuff[6], "OFF", 3) == 0)  digitalWrite(ledA, LOW);
      else  Serial.println("receive Fail");
    }
    else if(receiveBuff[0] == 'B')  {
      if(strncmp(&receiveBuff[6], "ON", 2) == 0)  digitalWrite(ledB, HIGH);
      else if(strncmp(&receiveBuff[6], "OFF", 3) == 0)  digitalWrite(ledB, LOW);
      else  Serial.println("receive Fail");
    }
    else  Serial.println("receive Fail");
    memset(receiveBuff, 0, sizeof(receiveBuff));
    receiveEndFlag = 0;
    sendFlag = 1;
  }
}

 

코드 - Slave A

#include <SoftwareSerial.h>
#define RS485Control  7
#define ledA  8
SoftwareSerial rs485(2, 3);
unsigned char receiveEndFlag = 0;
unsigned char sendFlag = 0;
unsigned int sendBufCnt = 0;
unsigned int receiveBufCnt = 0;
unsigned char ledState = 0;
char sendBuff[50] = {0};
char receiveBuff[50] = {0};

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.write("==========Slave START==========\n");
  rs485.begin(9600);
  pinMode(RS485Control, OUTPUT);
  pinMode(ledA, OUTPUT);
  digitalWrite(RS485Control, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:
  if(receiveBuff[0] == 0 && sendFlag == 1)  { // send command
    digitalWrite(RS485Control, HIGH);

    if(ledState == 1) strcpy(sendBuff, "A LED ON!");
    else  strcpy(sendBuff, "A LED OFF!");

    while(1){
      rs485.write(sendBuff[sendBufCnt]);
      Serial.print(sendBuff[sendBufCnt]);
      if(sendBuff[sendBufCnt++] == '!') {
        sendBufCnt = 0;
        break;
      }
      delay(100);
    }
    Serial.print("\tSLAVE 전송 완료\n");
    delay(3000);
    digitalWrite(RS485Control, LOW);
    sendFlag = 0;
  }

  if(rs485.available()) { // receive command
    receiveBuff[receiveBufCnt] = rs485.read();
    Serial.print(receiveBuff[receiveBufCnt]);
    if(receiveBuff[receiveBufCnt++] == '!') {
      receiveEndFlag = 1;
      receiveBufCnt = 0;
      Serial.print("\tSLAVE 수신 완료\n");
      delay(3000);
    }
    delay(100);
  }

  if(receiveBuff[0] != 0 && receiveEndFlag == 1)  { //process receive message

    if(receiveBuff[0] == 'A') {
      if(strncmp(&receiveBuff[6], "ON", 2) == 0)  {
        digitalWrite(ledA, HIGH);
        ledState = 1;
      }
      else if(strncmp(&receiveBuff[6], "OFF", 3) == 0)  {
        digitalWrite(ledA, LOW);
        ledState = 0;
      }
      else  Serial.println("receive Fail");
    
      memset(receiveBuff, 0, sizeof(receiveBuff));
      receiveEndFlag = 0;
      sendFlag = 1;
    }
    else{
      memset(receiveBuff, 0, sizeof(receiveBuff));
      receiveEndFlag = 0;
    }
  }
}

 

코드 - Slave B

#include <SoftwareSerial.h>
#define RS485Control  7
#define ledB  8
SoftwareSerial rs485(2, 3);
unsigned char receiveEndFlag = 0;
unsigned char sendFlag = 0;
unsigned int sendBufCnt = 0;
unsigned int receiveBufCnt = 0;
unsigned char ledState = 0;
char sendBuff[50] = {0};
char receiveBuff[50] = {0};

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.write("==========Slave START==========\n");
  rs485.begin(9600);
  pinMode(RS485Control, OUTPUT);
  pinMode(ledB, OUTPUT);
  digitalWrite(RS485Control, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:
  if(receiveBuff[0] == 0 && sendFlag == 1)  { // send command
    digitalWrite(RS485Control, HIGH);

    if(ledState == 1) strcpy(sendBuff, "B LED ON!");
    else  strcpy(sendBuff, "B LED OFF!");

    while(1){
      rs485.write(sendBuff[sendBufCnt]);
      Serial.print(sendBuff[sendBufCnt]);
      if(sendBuff[sendBufCnt++] == '!') {
        sendBufCnt = 0;
        break;
      }
      delay(100);
    }
    Serial.print("\tSLAVE 전송 완료\n");
    delay(3000);
    digitalWrite(RS485Control, LOW);
    sendFlag = 0;
  }

  if(rs485.available()) { // receive command
    receiveBuff[receiveBufCnt] = rs485.read();
    Serial.print(receiveBuff[receiveBufCnt]);
    if(receiveBuff[receiveBufCnt++] == '!') {
      receiveEndFlag = 1;
      receiveBufCnt = 0;
      Serial.print("\tSLAVE 수신 완료\n");
      delay(3000);
    }
    delay(100);
  }

  if(receiveBuff[0] != 0 && receiveEndFlag == 1)  { //process receive message

    if(receiveBuff[0] == 'B') {
      if(strncmp(&receiveBuff[6], "ON", 2) == 0)  {
        digitalWrite(ledB, HIGH);
        ledState = 1;
      }
      else if(strncmp(&receiveBuff[6], "OFF", 3) == 0)  {
        digitalWrite(ledB, LOW);
        ledState = 0;
      }
      else  Serial.println("receive Fail");
    
      memset(receiveBuff, 0, sizeof(receiveBuff));
      receiveEndFlag = 0;
      sendFlag = 1;
    }
    else{
      memset(receiveBuff, 0, sizeof(receiveBuff));
      receiveEndFlag = 0;
    }
  }
}

 

테스트 결과

Master 전송 및 수신 메시지

 

 

 

 


<참고 자료>

https://powerdeng.tistory.com/213

 

RS-485 통신

RS-485 통신이란? RS-232는 전송 속도가 낮고 전송 거리가 짧으며 1대1 통신만 가능하다. 이를 보완하기 위해 개발된 RS-422는 한 개의 마스터 장치와 슬레이브 장치 간에 데이터를 주고 받는 방식으로

powerdeng.tistory.com

 

<첨부 자료>

rs485_slave_B.ino
0.00MB
rs485_slave_A.ino
0.00MB
rs485_master.ino
0.00MB

 

'개발환경 > Arduino IDE' 카테고리의 다른 글

Timer Interrupt 설정 - ATSAMD21G18A  (1) 2023.11.19