< 오늘의 과제 >

1. 위의 소스코드 중 available()함수를 활용하여 내가 보낸 문자를 다시 출력해주는 코드에서 Serial.write()함수 대신에 print함수를 쓰면 어떤 문제가 발생하는지 확인하고, 이를 해결하기 위해서는 어떻게 수정해주어야 하는지 생각해보세요.

  우선 Serial.read()함수의 경우 이전 글에서 설명했듯이, return type이 int형입니다. 즉 입력받은 문자의 ASCII 값을 숫자로 반환이 된다고 이해를 하시면 쉽습니다. 그러한 이유로 읽어온 데이터를 Serial.write()함수를 이용해 출력한 것 입니다. Serial.write()는 괄호 안의 값을 byte 단위로 전송하여 괄호 안의 숫자 값을 ASCII코드에서 일치하는 값의 문자를 찾아 문자로 전송하게 됩니다.

  그런데 여기서 Serial.print()함수로 바꿔주게 된다면, Serial.print()함수는 String type으로 전송을 해버리게 됩니다. 다시말해서, Serial.read()에서 문자를 ASCII코드에서 해당하는 숫자로 바꿔서 return을 했는데 그 숫자를 문자 그대로 전송을 해버리는 것입니다.

예시)

- A라는 문자를 전송했을때, Serial.write(Serial.read())의 경우

- A라는 문자를 전송했을때, Serial.print(Serial.read())의 경우

  이러한 이유 때문에 이 오류를 해결하려면 Serial.read()에서 return한 값을 char변수로 강제 형 변환을 해주면 문자로 바뀌게 됩니다. 즉 , (char)를 추가해주는 것으로 해결할 수 있습니다.

void setup() {
  Serial.begin(9600); 
  // 컴퓨터와 통신을 위해 초당 비트 전송률을 9600bps로 설정
}

void loop() {
  if (Serial.available()) // 현재 수신된 Data가 있는지 확인( 전송중이면 false, 아니라면 true )
  {
    Serial.print((char)Serial.read());
    // print함수는 Serial.read에서 받은 int타입의 값을 스트링 자체로 받아주기 때문에 char로 강제
    // 형 변환을 해주어서 char형태로 출력한다.
  }

 

2. SoftwareSerial를 활용하여 두 대의 아두이노를 연결하고 아래의 조건에 맞는 환경을 만들어 보세요.

  - 2명의 사용자가 사용하는 USART 채팅 프로그램

  - Client1이 컴퓨터를 통해 문자열을 입력하면, Arduino가 수신하여 client2와 연결된 Arduino로 전송하고, Client2의 Arduino가 Client2의 컴퓨터에 수신된 문자열을 출력

  - Client2의 입력 역시 동일하게 Client1의 컴퓨터에 출력되어야 합니다.

// 이 예제의 경우 아두이노 스케치는 1개의 아두이노의 시리얼 모니터를 지원합니다 그렇기 때문에, 다른 한개의 아두이노는 putty 와 같은 Serial 터미널 프로그램을 활용하여 열 수 있습니다.

  이 문제를 풀려면 두가지 개념을 숙지하고 있어야 합니다. 우선 String클래스를 활용할 수 있는 점과, 문자열이 전송되었을때, 그것을 문자 하나하나가 아닌 문자열로 통으로 저장하게 하는 방법이 필요합니다.

  첫번째로 String클래스를 이용하는 것입니다. 기존에 C언어만 공부하신 분들은 문자열을 활용하셔도 문제 없습니다. String클래스를 두개를 선언하여, 한개의 아두이노의 데이터를 저장하는 문자열을 저장하는 변수와 또 다른 하나의 아두이노의 데이터를 저장하는 문자열 변수를 선언해야합니다. 그리고 초기에 ""로 아무런 데이터가 들어있지 않은 상태로 초기화 해 줍니다. 그래야 전송받은 문자를 이어 붙일 수 있기 때문입니다. 전송받은 문자열을 출력한 이후에는 필수적으로 다시 변수를 ""로 초기화 해주어야 정상적인 작동을 하는 것을 볼 수 있습니다.

  두번째로 전송된 값을 문자열로 한번에 저장하는 방법에 대해 알려드리겠습니다. 우선 이전 글을 보면 if문을 활용하여 전송된 데이터를 바로바로 출력해본 예제가 있습니다. 이 코드에서 if문을 while문으로 바꿔주게 되면, 현재 전송된 데이터가 다 처리가 될때까지만 반복하는 반복문을 만들 수 있습니다. 이 방법을 활용하여 while문 내에서 전송된 문자를 읽어온 후 전역변수로 선언한 string type의 문자열 변수에 이어붙여주면 됩니다. 여기서 이어붙여준다는 말은, string함수 특성을 활용하여 +=연산자를 활용한다는 말입니다. 이 두 줄을 while문 안에 넣어주게 되면 아두이노가 문자열을 받았을때, 전송받은 값을 string type으로 저장하게 할 수 있습니다.

  이 두가지를 활용하게 되면, while문과 if문으로 유선 챗봇을 만들 수 있습니다. 윗 문단에서 설명한 while문을 활용한 후 if문에서 문자열이 ""이 아닌 경우 입력받은 데이터가 있다는 것으로 판단하여 그것을 출력하고 ""로 다시 초기화만 해준다면 큰 오류 없이 설계하실 수 있으실 겁니다.

  추가적으로 두개의 Serial을 써야하기 때문에 SoftwareSerial.h를 활용하해야 합니다. 그리고 두개의 아두이노에 같은 코드를 업로딩 하시면 됩니다.

#include <SoftwareSerial.h> // 이 헤더파일을 추가하면서 GPIO를 USART를 추가로 사용가능

String myString = ""; // 컴퓨터와 통신하여 받은 Data값을 String을 사용하여 문자열로 저장하는 공간
String chatString = ""; // 외부 아두이노와의 통신으로 받은 Data값을 String을 사용하여 문자열로 저장하는 공간

SoftwareSerial chat(10, 11); // 외부 아두이노와 USART를 클래스로 선언 Rx : pin 10, Tx : pin 11

void setup() {
  Serial.begin(9600); // 컴퓨터와의 통신 초당 비트 전송률을 9600bps로 설정
  chat.begin(9600); // 외부 아두이노와 통신 초당 비트 전송률을 9600bps로 설정
}

void loop() {
  // 외부 아두이노에서 들어온 Data가 전송중인지 아닌지 판별 (전송중 : False, 전송중이 아닐 때 : True)
  while (chat.available()) {
    char receive = (char)chat.read(); // 외부 아두이노에서 보내온 Data를 int형으로 읽어 char로 강제 형 변환 하여 receive변수에 저장
    chatString += receive; // receive에 저장된 문자를 chatString 문자열에 추가
    delay(10); // 전송되는 Data가 잘리거나 분리되어 저장되는 것을 막기위해 delay를 추가함
  }

  // 위의 while문에서 Data전송이 끝나 chatString에 문자열이 저장되어 Data값을 가지고 있음을 확인하고 출력하는 조건문 ( 있으면 : True , 비어있으면 : False )
  if (chatString != "") {
    Serial.println(chatString); // 외부에서 온 Data를 내 Serial모니터에 출력하고 줄바꿈
    chatString = ""; // 출력 후 다시 chatString을 비워 다음 Data를 저장할 수 있도록 초기화함 
  }

  // 내 컴퓨터와 Serial통신으로 들어온 Data가 전송중인지 아닌지 판별 (전송중 일 때 : False. 전송중이 아닐 때 : Tre)
  while (Serial.available()) {
    char transmit = (char)Serial.read(); // 내 컴퓨터에서 전송한 Data를 int형으로 읽어들이고 char로 강제 형 변환 하여 transmit변수에 저장
    myString += transmit; // transmit에 저장된 문자를 myString 문자열에 추가
    delay(10); // 전송되는 Data가 잘리거나 분리되어 저장되는 것을 막기위해 delay를 추가함
  }

  // 위의 두번째 while문에서 Data전송이 끝나 myString에 문자열이 저장되어 Data값을 가지고 있는지 확인하고 출력하는 조건문 ( 있으면 : True , 비어있으면 : False )
  if (myString != "") {
    chat.println(myString); // 컴퓨터에서 읽어들인 문자열 myString을 외부로 전송하여 출력 후 줄바꿈
    Serial.println(myString); // 컴퓨터에서 전송하려 하는 문자열을 내 Serial모니터에 출력 후 줄바꿈
    myString = ""; // 전송이 끝난 후 다시 myString을 비워 다음 Data를 저장할 수 있도록 초기화
  }
}

 

+ Recent posts