반응형

시리얼 통신을 함에있어 필요한 주요 함수와 그 함수의 예제 그리고 들어온 데이터를 String으로 처리할 때 사용하는 String Class 함수 들에관해 살펴 보겠다. 

 

1. Serial.print() 

앞선 글에서 Serial.write()와 Serial.print()의 차이에 대해 다루었었다. 이 글에서는 Serial.print() 함수를 좀 더 알아보자.

 

앞선 글에서도 언급했듯이 Serial.print() 함수는 입력된 값을 사람들이 인지하기 편하도록 스트링(문자열)로 변환하여 출력한다.

Serial_print.ino
0.00MB

 

void setup() {
  Serial.begin(9600);
  Serial.println(78); // "78"을 스트링 형태로 출력한다.
  Serial.println(1.23456); // 스트링 형태로 출력하되, 소수점 옵션이 없는 소수의 경우 소수점 2자리 "1.23"까지 출력한다.
  Serial.println('N'); // 문자 "N" 출력한다.
  Serial.println("Hello world"); // 문자열 "Hello world." 출력한다.
  Serial.println(78, BIN); // 2진수를 사람들이 인지하기 편하도록 스트링 형태 "1001110"으로 출력한다.
  Serial.println(78, OCT); // 8진수값을 스트링 형태 "116"으로 출력한다.
  Serial.println(78, DEC); // ASCII 숫자 "78"
  Serial.println(78, HEX); // 16진수 "4E"
  Serial.println(1.23456, 0); // (실수, 소수점 자리 옵션), 소수점 자리가 없으므로 "1"을 출력한다.
  Serial.println(1.23456, 4); // (실수, 소수점 자리 옵션), 소수점 자리 4까지 반올림하여 "1.2346"을 출력한다.
}

 

2. Serial.write() 

Serial.write() 함수는 입력값으로 byte형 데이터를 사용해야하고 그 입력값을 아스키코드로 변환하여 출력한다. 아스키코드 변환에 대한 설명 역시 앞선글을 참조하면 된다.

입력값으로 byte형 데이터를 사용한다고 했는데 byte형 데이터 대신 문자나 문자열을 바로 보내고 싶다면 문자라는 표시 ' '와 문자열이라는 표시 " "를 사용하여 보낼수 있다.

Serial_write.ino
0.00MB

 

void setup() {
  Serial.begin(9600);
  const byte temp_write[5] = {'1', '2', '3', '4', '5'}; // ' ' 사용 문자임을 표시
  int temp_print = 12345;
  Serial.write(1); // write()함수로 1 전송 - ASCII 코드 번호 1 = ┏
  Serial.println(1); // print()함수로 1 전송 - 문자 1
  Serial.write(49); // write()함수로 49 전송 - ASCII 코드 번호 49 = 문자 1
  Serial.println(49); // print()함수로 49 전송 - 문자열 "49"
  Serial.write('a'); // write()함수로 문자 'a' 전송 - 문자 a
  Serial.println('a'); // 문자 표시(' ') 없이 a를 입력하면 변수로 인식한게 된다.
  Serial.write(temp_write, 5); // write()함수로 temp배열을 5만큼 전송 - 12345
  Serial.println(temp_print);
  Serial.write("12345"); // write()함수로 string값 전송 - 12345
  Serial.println(12345); // print()함수로 12345출력
}

 

시리얼 모니터에 출력된 결과

1

149

aa

1234512345

1234512345

 
3. Serial.available() 
시리얼버퍼에 수신되어 저장된 데이터의 바이트 수를 반환 - 64바이트까지, 버퍼가 비어 있으면 0을 반환한다. 
 
4. Serial.read()
시리얼 버퍼의 데이터를 1byte씩 읽고 읽은 데이터는 지운다.
Serial_read.ino
0.00MB

 

void setup(){
  Serial.begin(9600);     
}

void loop(){
  if (Serial.available() > 0) {  // 시리얼 버퍼에 데이터가 있으면 
    byte value = Serial.read();    
    Serial.write(value);
    Serial.print(", ");
    Serial.println(value);               
  }
}

시리얼 모니터에 "hello"를 입력하면 아래와 같이 출력된다.

h, 104

e, 101

l, 108

l, 108

o, 111

 

5. Serial.readBytes(buffer, length)

선언된 배열 변수(buffer)에 정해진 length만큼 byte형식으로 저장

Serial_readBytes.ino
0.00MB

 

void setup(){
   Serial.begin(9600);
 }


void loop(){
  char temp[20];  
  if(Serial.available()){  // 시리얼에 입력된 값이 있으면
    byte leng = Serial.readBytes(temp, 20); // (버퍼, 길이) - 길이 초과시 나누어 실행
    Serial.print("Input data Lenght : ");
    Serial.println(leng);  
    for(int i = 0; i < leng; i++) Serial.print(temp[i]);  
    Serial.println();
  }    
}

시리얼 모니터에 "abcdefghijklmnopqrstuvwxyz"를 입력하면 아래와 같이 출력된다. 

Input data Lenght : 20
abcdefghijklmnopqrst
Input data Lenght : 6
uvwxyz

 

6. Serial.peek()
시리얼 버퍼를 읽지만 버퍼에서 지우지는 않는다.
 
7. Serial.readString()
시리얼 버퍼를 Serial.setTimeout() 설정값 까지 계속해서 읽고 읽은데이터는 지운다.
Serial.setTimeout()의 기본값은 1000 밀리초(1초)이다.
Serial.readString()를 실행하면 1초동안 딜레이가 발생하게 된다. 
 
8. Serial.readStringUntil()
Serial.readStringUntil(종료문자), 시리얼 버퍼를 종료 문자까지 읽고 읽은 데이터는 지운다. 
일치하는 종료문자가 없을경우 Serial.setTimeout() 설정값 까지 계속해서 읽는다. 설정 예: Serial.setTimeout(10) // 10 밀리초
종료문자를 '\n'로 지정하고 시리얼 모니터 전송옵션을 새글('\n')로 설정하고 텍스트를 입력하면 딜레이없이 종료되고 line ending 없음으로 설정하고 전송하면 1초간 딜레이가 발생한다.
Serial_peek_readstring.ino
0.00MB
 
void setup(){
   Serial.begin(9600);
 }
 
void loop(){
  if(Serial.available()){
    char temp_peek = Serial.peek();
    Serial.print(temp_peek);
    char temp_read = Serial.read();
    Serial.println(temp_read);  // 읽어온 데이터는 buffer에서 삭제
    String temp_string = Serial.readString();
    Serial.println(temp_string);
  }
}

 

시리얼 모니터에 "abcd"를 입력하면 아래와 같이 출력되는데 Serial.peek() 함수로 읽은 값 'a'가 지워지지 않고 Serial.read() 함수에서 다시 읽혀져 aa 가 출력된것을 볼 수있고, Serial.read() 함수에서 읽혀진 'a'는 지워져서 Serial.readString() 함수가 읽을때에는 'a' 없이 "bcd"만 출력된것을 볼 수 있다. 또한 Serial.readString()의 Serial.setTimeout() 기본 설정값 1초동안 딜레이가 발생하여 aa 출력 후 1초뒤 bcd가 시리얼 모니터에 출력되는 것을 확인 할 수 있다.
aa     
bcd
 
위 코드의 Serial.readString()을 Serial.readStringUntil('\n')으로 바꾸어 코딩하고 코드를 업로드 해보자.

 

void setup(){
   Serial.begin(9600);
 }
 
void loop(){
  if(Serial.available()){
    char temp_peek = Serial.peek();
    Serial.print(temp_peek);
    char temp_read = Serial.read();
    Serial.println(temp_read);  // 읽어온 데이터는 buffer에서 삭제
    String temp_string = Serial.readStringUntil('\n');
    Serial.println(temp_string);
  }
}

 

시리얼 모니터에서 전송옵션을 새글('\n')로 설정하고 "abcd"를 입력하면 출력되는 결과는 같으나, 전과는 다르게 aa와 "bcd" 출력사이에 딜레이가 줄었음을 확인할 수 있다. 다시, 시리얼 모니터에서 전송옵션을 line ending 없음으로 하고 똑같이 입력하면 aa와 bcd 출력사이에 딜레이 1초가 발생하는 것을 확인 할 수 있다. 

 

 

9. Serial.find()
Serial.find(target); // target: 검색할 문자 또는 문자열 단 "" 로 묶어서 표시 예) "Y", "YES",  
                              시리얼 버퍼에서 타겟이 있으면 true, 없으면 false 리턴후 타겟은 시리얼 버퍼에서 삭제
Serial_find.ino
0.00MB
 
void setup(){
   Serial.begin(9600);
 }
 
void loop(){
  while(Serial.available()){  // 시리얼 버퍼에 데이터 있으면
    if(Serial.find("123")){  // 시리얼 버퍼에 스트링 "123"이 있으면, 조건이 스트링: 관련 변수 스트링 기준
      String temp = Serial.readString(); // "123" 이후 들어온 스트링 저장
      Serial.print("Temp Value = "); Serial.println(temp);
    } 
  }
}

시리얼 모니터에 123a 입력후 결과

Temp Value = a
시리얼 모니터에 123a123b 입력후 결과
Temp Value = a123b

 

10. parseInt()

','에 의해 구분되어진 데이터가 연속으로 들어올 때 버퍼에 구분되어진 데이터를 분리하고 그 데이터에서 숫자가 없으면 데이트는 무시하고 문자와 숫자가 섞인 경우 문자는 무시하고 숫자(int)를 추출해낸다. 추출한 값을 자료형 long 값으로 반환한다. 

 

문법 설명에 stream.parseInt(''list', char skipchar') 표시되어 있다. 하지만 우리가 수정하거나 지정할 수는 없으며 char skipchar는 ','로 고정되어 변경되지 않도록 되어 있고 list는 parseInt()함수가 실행될 때 ','를 구분자로 하여 생성되는 내부적으로 사용하는 목록인 것 같다. 

 

사용 방법은 다음 parseFloat() 함수에서 설명하겠다. 

 

11. parseFloat()

parseInt() 함수와 같고 추출한 값을 자료형 float 값으로 반환한다. 

 

사용방법은 반드시 다음과 같은 형식을 따라야 한다. 

 

시리얼 모니터 입력 값(stream) 예: 23, test3, int, 45.2, 78

추출 가능한 값: 23 또는 23.0 / 3 또는 3.0 / 45 또는 45.2/ 78 또는 78.0 이다. 

만약 이러한 값을 추출하고 저장하려면 코드를 코딩할 때 순서에 맞게 변수를 설정하고 parseInt()와 parseFloat() 함수를 실행 시키면 된다.

parse_int_float.ino
0.00MB

 

void setup() {
  Serial.begin(9600);
}


void loop() {
  while (Serial.available() > 0) {
    int red = Serial.parseInt();
    int green = Serial.parseInt();
    int blue = Serial.parseInt();
    String temp = Serial.readStringUntil('\n'); // 시리얼 버퍼를 비워서 받은값이 0으로 초기화되지 않도록 한다.
    Serial.print("red: "); Serial.println(red);    // Serial.available() == 0으로 만든다. -> while루프 재실행 방지 
    Serial.print("green: "); Serial.println(green);
    Serial.print("blue: "); Serial.println(blue);
  }
}

시리얼 모니터에 34, 567, 78을 입력하면 int 값을 추출한다. 

 

■ String Class
String 객체를 생성하여 사용하고 문자열의 형태이다.

String 객체이름 = 초기화할 문자열

String str = "This is a String";  // " " 큰따옴표로 문자열 표시
String str = String('a');         // ' ' 작은따옴표로 묶은 char형 문자를 String으로 변경 저장
String str = String(13);          // 숫자 13을 문자열로 저장
String str = String(13, HEX);     // 숫자 13을 16진수로 저장
String str = String(13, BIN);     // 숫자 13을 2진수로 저장
String str = String(10.1435, 3);  // 실수를 소수점 3번째 자리까지 끊어 저장

입력값을 스트링으로 변환해주는 String() 함수의 사용법을 다음과 같이 요약할 수 있다.
String('문자' 혹은 "문자열");
String(정수값, 진법종류);
String(실수값, 소수점자리수);

String Class 함수
str.charAt(index);          //  스트링 str의 특정 문자 액세스, "str[index];" 코드와 같다
str.compareTo(string2);  // 스트링 str과 string2의 문자배열을 비교하고 같으면 0, 다른경우에는 비교 과정중 첫번째로 다른 문자들의 아스키값 차이를 표시
str.equals(string2);        // 두 스트링이 같은지 비교. 대소문자 구별 - 참(1), 거짓(0) 반환
str.equalsIgnoreCase(string2);   // 두 스트링이 같은지 비교. 대소문자 무시 - 참(1), 거짓(0) 반환
str.concat(parameter);   // 매개변수를 스트링에 더함.  매개변수: String 함수에 사용할 수 있는 타입(String, char, byte, int, unsigned int, long, unsigned long, float, double, __FlashStringHelper(F() macro))
str.startsWith(string2);   // 스트링 str이 다른 스트링의 문자들로 시작하는지 아닌지 확인 - 참(1), 거짓(0) 반환
str.endsWith(string2);    // 스트링 str이 다른 스트링의 문자들로 끝나는지 아닌지 확인 - 참(1), 거짓(0) 반환
str.length();                  // 스트링 str의 길이를 반환(뒤따라오는 널 문자(\0)를 포함하지 않음)
str.indexOf(string1);      // 스트링 str에서 스트링1 문자열을 앞에서 부터 찾아 첫문자 인덱스값 반환, 못 찾을경우 -1 반환
str.indexOf(string1, from);  // 검색 시작 위치 지정
str.lastIndexOf(string1); // 스트링 str에서 스트링1 문자열을 뒤에서부터 찾아 첫문자 인덱스값 반환, 못 찾을경우 -1 반환
str.lastIndexOf(string1, from);  // 검색 시작 위치 지정
str.toCharArray(buf, len); // str 문자열을 len(복사 문자수 +1('\0'))만큼 복사하고 배열 buf에 저장(char)
str.toCharArray(buf, len, index); // 지정 인덱스부터 len 만큼 복사
str.getBytes(buf, len);    // 스트링 str의 문자를 len 길이만큼 배열 buf에 복사(byte)
str.getBytes(buf, len, index); // 지정 인덱스부터 len 만큼 복사
str.substring(start index); // 스트링 str에서 새로운 스트링을 반환 - 시작 인덱스에서 끝까지
str.substring(start index, end index); // 스트링 str에서 새로운 스트링을 반환 - 시작 인덱스에서 끝 인덱스까지
str.setCharAt(index, c);  // 스트링 str의 한 문자를 변경한다 index = 변경할 인덱스, c = 교체할 문자
str.replace(substring1, substring2); // 스트링 str에서 substring1를 찾아 substring2로 변경
str.remove(index);        // 지정 인덱스에서 끝까지 삭제
str.remove(index, count) // 지정 인덱스에서 + count까지 삭제
str.toInt();                   // 타당한 스트링(숫자)을 정수로 변환,  -값도 변환
                                          "1234" -> 1234, "-1234" -> -1234, "123abc" -> 123, "abc123" -> 0
str.toFloat();                // 타당한 스트링을 float 으로 변환
                                          "123.456" -> 123.46, "-123.45" -> -123.45, "123.abc" -> 123.00, "abc123" -> 0.0
str.toLowerCase();       // 스트링 str의 대문자를 모두 소문자로 변경
str.toUpperCase();       // 스트링 str의 소문자를 모두 대문자로 변경
str.trim();                         // 스트링 str의 앞뒤 공백문자를 없앤다

 

 

 

 

관련 글

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 1편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 2편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 3편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 4편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 5편

[arduino] - 블루투스 4.0 BLE 이용 아두이노 및 ESP32 원격제어

 

[arduino] - 아두이노 - 시리얼통신 주요함수와 예제, String class

[arduino] - 아두이노 - ESP01 wifi 모듈 무선 원격제어 그리고 시리얼 통신 - 6편

[arduino] - ESP8266 - NodeMcu 1.0 와이파이 이용 원격제어(soft AP, wifi)

[arduino] - ESP32 - Dev Module 와이파이 이용 원격제어(soft AP, wifi)

 

 

+ Recent posts