본문 바로가기
Arduino/닭치고 Arduino

닭치고 아두이노 5 시리얼통신(Serial Communication)

by OneHundredPlan 2020. 3. 1.
반응형

닭치고 아두이노 5 시리얼통신(Serial Communication)

 

좋아요 구독 해 주세요. 이제는 학원을 다니지 않아도 충분히 학습할 수 있는 아두이노 영상들이 많으니 차근차근 공부하시면 좋은 결과가 나올 겁니다.

기초적인 아두이노 코딩과 작동을 해보는 시간입니다. 교재 내용을 꼼꼼히 읽어보시기 바랍니다. 아두이노 설치부터 차근 차근 공부해서 나중에 자율자동차, 드론제작 등을 실습을 해 보도록 해봅시다. 프로그램 언어는 C 언어입니다. 교재는 네이버 카페 백년지계 에 올리도록 하겠습니다. 책과 아두이노 키트를 구매코자 하시는 분은 시중에서 파는 아두이노, 상상을 현실로 만드는 프로젝트 입문편을 사시면 모두 구매 하실 수 있습니다.

 

[동영상강의]

https://youtu.be/ekWP-ljt_Wo

 

닭치고아두이노-5-시리얼통신.pdf
0.84MB

 

시리얼통신(Serial Communication)

아두이노 보드와 PC는 시리얼 모니터(Serial monitor)를 이용해 통신할 수 있습니다.

이것을 시리얼 통신(Serial Communication)이라고 부릅니다.

아두이노 보드의 센서 값을 확인하거나 아두이노 보드로 명령을 보낼 때 주로 사용합니다.

뒷 부분 강의에서는 다소 C 언어를 접한 초보자들을 위해 다양한 방법으로 시리얼 통신으로 앞 강의에서 구현하였던 Blink.ino 를 수정해서 여러가지로 구현해 보도록 하겠습니다.

시리얼 통신

serial 은 직렬이라는 뜻으로 시리얼 통신은 직렬 통신을 말합니다.

연속적으로 통신 채널을 거쳐 한 번에 하나의 비트 단위로 데이터를 전송하는 과정을 말합니다.

아두이노 우노는 통신채널로 RX(0번핀 : Receiver X-tal : 수신단자)와 TX(1번핀 : Transmitter : 송신단자)을 물리적 통신 채널로 1개 가지고 있습니다.

 

 

그러므로 아두이노 우노는 0번 핀, 1번 핀, USB 연결을 통해서 통신을 할 수 있습니다.

시리얼 통신을 사용하는 경우 0번과 1번 핀을 디지털 입출력으로 사용할 수 없습니다.

소스코드를 컴파일하고 USB를 통해 아두이노 보드로 업로드하는 과정 역시 시리얼 통신을 통해 이루어지며, 컴퓨터의 가상 시리얼 포트와 아두이노의 Serial 을 통해 통신이 이루어집니다.

시리얼모니터 선택

 

 

잠깐 여기서 PC 와 USB B 선이 연결되지 않은 상태이면 에러를 냅니다.

 

 

 

 

USB B선을 PC와 연결한다음 시리얼모니터 메뉴를 다시 선택해 하세요.

시리얼모니터(Serial monitor)

 

전송옵션

 

  • line ending 없음

    • CR/LF 모두 사용하지 않는다

  • 새 줄

    • LF만 사용

  • 캐리지 리턴

    • CR만 사용

  • Both NL & CR

    • CR/LF 모두 사용합니다.

전송옵션과 CR/LF 에 관한 이론은 뒷부분에서 코딩할 PC에서 아두이노보드로 메시지 보내기  에서 다루도록 하고 지금은 line ending없음 을 선택합니다.

 

 

 

통신 속도(Baud Rate : 보드레이트)

 

Baud Rate 는 시리얼 라인으로 전송되는 데이터 속도를 말합니다.

Bits-per-second(bps)단위로 표시하는데 이 값을 바탕으로 1 bit 가 전송되는데 필요한 시간을 알 수 있습니다.

Baud Rate 값은 여러가지 값으로 설정할 수 있지만 통신속도에 크게 영향을 받지 않는 경우 일반적으로 9600 bps 를 사용합니다.

Baud Rate 값이 높을수록 송수신 속도가 빠르지만 값이 너무 높거나 양쪽의 설정값이 다른 경우 데이터 수신에 문제가 발생합니다. 아두이노에서는 300 ~ 250000 bps까지 지원하지만,

Serial 라이브러리에서는 115200 bps 까지 지원하므로 115200 bps 를 초과하지 않도록 주의해야 합니다.

 

 

아두이노 보드에서 PC로 메세지 보내기

파일->예제->SoftwareSerial->SoftwareSerialExample  를 열어서 [다른이름으로 저장]을 합니다.

아래와 같이 수정을 합니다. 필요없는 부분들은 다 지워야 깔끔하겠죠.

 

SoftwareSerialExample_01

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600); //시리얼통신 설정
  //begin(매개변수)
  //9600 : 보드레이트(Baud rate : bit per second 단위)
  //보드레이트는 시리얼 통신할 때 통신 속도를 뜻합니다.
  //아두이노 보드와 PC쪽에 보드레이트를 동일하게 설정해야 정상적인 통신을 할 수 있습니다. 
}

void loop() { // run over and over
  Serial.println("Hello my PC!");//마지막에 줄을 바꿔 출력합니다.
  //아두이노보드가 PC로 메세지를 보내는 부분
  //숫자, 글자 
    
  delay(1000);
} 

 

아두이노에서 PC로 메세지를 1초 간격으로 보냅니다.

 

 

 

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600); //시리얼통신 설정

}

void loop() { // run over and over
  //Serial.println("Hello my PC!");//마지막에 줄을 바꿔 출력합니다.
  Serial.print("Hello my PC!"); //줄을 바꾸지 않고 출력합니다.
    
  //아두이노보드가 PC로 메세지를 보내는 부분
  //숫자, 글자 
    
  delay(1000);
} 

 

 

 

 

 

PC에서 아두이노보드로 메시지 보내기

SoftwareSerialExample_02

 

void setup() {
	Serial.begin(9600); //시리얼통신 설정
}

void loop() { // run over and over
    if(Serial.available()){ //아두이노가 상대방으로부터 받은 데이터가 있는지 확인
        char c=Serial.read();
        //시리얼 통신으로 들어온 데이터 중 한 바이트를 잘라내 읽는 명령어
        
        if(c == 'a'){
            //들어온 문자가 a와 같다면 
            
            Serial.println("A"); //PC에게 A라는 글자를 보냅니다.
        }
    }
} 

 

 

 

 

  • line ending 없음

    • CR/LF 모두 사용하지 않는다

    • 입력한 메세지 뒤에 아무것도 붙이지 않고 전송을 합니다.

  • 새 줄(Newline)

    • LF만 사용

    • 입력한 메세지 뒤에 새 줄, 즉, 줄 바꿈 문자(LF=0x0A or \n) 가 추가되어 전송을 합니다.

  • 캐리지 리턴

    • CR만 사용

    • 입력한 메세지 뒤에 캐리지 리턴 문자(CR=0x0D or \r)가 추가되어 전송을 합니다.

  • Both NL & CR

    • CR/LF 모두 메세지 뒤에 붙여 전송을 합니다.

ASCII코드

ASCII 코드는 영문 알파벳 대소문자 52개, 숫자 10개, 특수 문자 32개, 널 문자 1개로 이루어져 있으며 나머지는 제어 문자입니다.

10 진수16 진수

0 0x00
1 0x01
2 0x02
3 0x03
4 0x04
5 0x05
6 0x06
7 0x07
8 0x08
9 0x09
10 0x0A
11 0x0B
12 0x0C
13 0x0D
14 0x0E
15 0x0F

CR(Carriage return)

타자기 시절 CR 은 현재 라인에서 커서의 위치를 맨 앞으로 옮기는 동작을 의미합니다.

\r 을 사용합니다.

 

LF(Line Feed)

타자기 시절 LF 는 커서의 위치는 그대로 두고 종이를 한 라인 위로 올리는 동작입니다.

\n 을 사용합니다.

 

CR/LF

커서를 다음 라인의 맨 앞으로 옮겨주는 것을 의미합니다.

입력한 문자를 출력하는 코딩을 해 봅시다.

 

SoftwareSerialExample_04

 

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
}

void loop(){
  if (Serial.available()){
   
    Serial.write(Serial.read());
  }  
}

 

1 글을 입력하고 전송하고

2 글, 3 글을 차례로 계속 해 봅니다.

 

 

 

 

 

 

이렇게 line ending 없음은 다음 글 입력하고 전송을 하면 줄바꿈 자체가 안되고 앞 글에 띄움 없이 이어서 붙여서 나옵니다.

새 줄 을 선택한 다음 1 글, 2글, 3 글을 차례로 전송을 해보면 다음 줄에 출력되는 것을 볼 수 있습니다.

 

 

 

 

참,,,참고로 화면에 나타난 글들을 지우고 싶으면 출력지우기 로 화면을 깨끗하게 지우면 됩니다.

 

 

 

캐리지리턴 을 선택해서 입력을 계속해보면 line ending 없음 과 같은 출력을 볼 수 있습니다.

 

 

Both NL & CR새 줄 과 같은 결과를 출력합니다.

 

 

 

차이점을 알고 싶으니 16진수로 출력하는 코딩을 짜 봅시다.

 

HexOutput.ino

 

void setup() {
  Serial.begin(9600);   //시리얼 통신 초기화
}


void loop() {
    if (Serial.available()){
      char c = Serial.read();
      Serial.print(c,HEX); // 입력한 값을 ASCII 코드 16진수로 출력        
    }
}

 

 

전송옵션을 line ending 없음 으로 하고 CRLF 를 입력해 봅시다.

 

 

 

문자 출력 맨 뒤에 새줄 0x0A 의 A, 캐리지 리턴 0x0D 의 D 가 붙어 있지 않습니다.

 

 

 

 

전송옵션을 새 줄 로 하고 CRLF 를 입력해 봅시다.

문자 출력 맨 뒤에 새줄 0x0A 의 A 가 붙어서 출력됩니다.

 

 

 

전송옵션을 캐리지 리턴 으로 하고 CRLF 를 입력해 봅시다.

문자 출력 맨 뒤에 캐리지 리턴 의 D 가 붙어서 출력됩니다.

 

 

 

전송옵션을 Both NL & CR 으로 하고 CRLF 를 입력해 봅시다.

문자 출력 맨 뒤에 CR/LF 의 순서대로 캐리지 리턴 0x0D 의 D, 새줄 0x0A 의 A 가 붙어서 출력됩니다.

 

 

 

이제 전송옵션에 따라 메세지 끝에 무엇이 붙어서 같이 전송되는지 확실히 알게 되었습니다.

시리얼 통신을 이용하면 아두이노 보드로 특정 글자를 전송함에 따라 원하는 동작을 할 수 있도록 만들 수 있습니다.

Blink.ino 를 수정하여 시리얼 통신으로 on 을 입력하면 내장 LED 가 켜지고

off 를 입력하면 내장 LED 가 꺼지는 것을 코딩해 봅시다.

 

Blink3.ino

void setup() {
  Serial.begin(9600); //Serial Communication Start
  pinMode(13, OUTPUT); // 13 : LED_BUILTIN
}

void loop() {
  if(Serial.available()){ // data input
    String s;             // s 변수를 문자열로 선언
    s = Serial.readString(); // 데이터를 문자열로 읽어들여 s 에 넣음
    if(s == "on")            //읽어 들인 문자열이 on 이면
      digitalWrite(LED_BUILTIN, HIGH); //내장 LED 를 켠다
    else if(s == "off")      // 읽어 들인 문자열이 off 이면
      digitalWrite(LED_BUILTIN, LOW); //내장 LED 를 끈다
  }
}

 

전송옵션은 line ending 없음 을 선택하고 on 을 입력하고 [전송] 을 합니다.

그리고 off 를 입력하고 [전송] 을 합니다.

 

 

잘 되는 것을 볼 수 있습니다.

 

이젠 on 이나 off 를 타이핑 한 다음 [전송] 버튼을 누르지 않고 엔터키를 눌렀을 때 켜고 끄는 것을 해 봅시다.

loop 를 돌면서 엔터를 치기 전까지 문자를 전부 합쳐서 on 인지 off 인지 판별해서 LED 를 켜고 끄는 거을 만들어 봅시다. 다른 문자열로 엔터를 치면 문자열을 비워 LED를 제어 못하게 합니다.

 

Blink4.ino

 

String s; //값을 가지고 있어야 하므로 전역변수로 문자열 변수 선언

void setup() {
  Serial.begin(9600); //Serial Communication Start
  pinMode(13, OUTPUT); // 13 : LED_BUILTIN
}

void loop() {
  if(Serial.available() > 0 ){ // data input
    char c;
    c = Serial.read();
    if(c == '\n'){      //줄이 바뀌면 (엔터를 눌렀을 경우)
      if(s == "on"){    //문자열이 on 이라면
        digitalWrite(13, HIGH); //내장 LED 를 켜라
        s = "";         //문자열을 비운다
      }
      else if(s == "off"){ //문자열이 off라면
        digitalWrite(13, LOW); //내장 LED 를 끔
        s = "";        
      }
      else   //on이나 off 이외의 문자가 들어왔을 경우
        s = ""; //문자열을 비움
      
    }
    else    //엔터가 눌리기 전 까지는
      s = s + c; // 입력된 문자를 문자열ㄹ로 합친다.
      // s += c;     
   
  }
}

 

엔터키(새줄: \n)를 인식하기 위해 전송옵션을 새 줄 로 변경해 줍니다.

on 을 입력하고 엔터키를 누릅니다. LED가 켜집니다.

off 를 입력하고 엔터키를 누릅니다. LED가 끄집니다.

다른 문자들을 입력하고 엔터키를 누릅니다. 아무 반응이 없습니다.

 

조금 더 개선해서 화면에 LED ON OFF 메세지를 출력을 해 봅시다.

 

Blink5.ino

 

String s; //값을 가지고 있어야 하므로 전역변수로 문자열 변수 선언
boolean ledOnOff = false; // LED 초기값 0 끄짐

void setup() {
  Serial.begin(9600); //Serial Communication Start
  pinMode(13, OUTPUT); // 13 : LED_BUILTIN
}

void loop() {
  if(ledOnOff){ // LED On
    digitalWrite(13, HIGH);
  }
  else{         // LED Off
    digitalWrite(13, LOW);
  }
}

void serialEvent(){
  
  while(Serial.available())
  {
    char inChar = (char)Serial.read();// 1 byte 를 읽어들임
    if(inChar == '\n' || inChar == '\r') // 문자열 종료 검사
    {
      if(s.equals("on")) // on
      {
        ledOnOff = true; //LED on
        Serial.println("LED_BUILTIN ON");
        s = ""; // 문자열을 비움
      }
      else if(s.equals("off")){  // off 
        ledOnOff = false; //LED off
        Serial.println("LED_BUILTIN OFF");
        s = ""; // 문자열을 비움
      }
      else {
   //     ledOnOff = false; //LED off
    //    Serial.println("LED_BUILTIN OFF");
        s = ""; // 문자열을 비움
      }
    }
    else{
      
      s += inChar;
    }
  }
} 

 

on 을 입력하고 엔터키를 누릅니다. LED가 켜집니다. 화면에 LED_BUILTIN ON이 출력됩니다.

off 를 입력하고 엔터키를 누릅니다. LED가 끄집니다. 화면에 LED_BUILTIN OFF가 출력됩니다.

다른 문자들을 입력하고 엔터키를 누릅니다. 아무 반응이 없습니다.

 

 

 

댓글