2021정보영재>피지컬컴퓨팅

2주차

아두이노의 통신 - UART, I2C, SPI

아두이노 직렬(Serial) 통신

직렬(Serial) 통신 vs 병렬(Oarallel) 통신

출처] https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=prnbada7&logNo=221377457826

동기(Synchronous) vs 비동기(Asynchronous)

출처]https://sites.google.com/site/jaesoon01050987702/studying-robotics/microprocessor/serialcommunicationinterface-02

아두이노 UART(범용 비동기 송수신) - 병렬 데이터를 직렬로 전송

직렬 통신 실습

[실습1] 직렬 통신 송신 1_serial_output.ino

// 1초에 한번씩 문자열 송신

void setup() {

Serial.begin(9600); //통신속도 9600으로 직렬 통신 시작

}


void loop() {

Serial.println("hello"); // 문자열 송신

delay(1000); // 1초 기다리기

}


/* 더 알아보기

* Serial.print()

* 숫자 1씩 증가시키면서 출력하기

*/

[실습1] 출력 화면

[실습2] 직렬 통신 문자 수신 2_serial_input_read.ino

// 시리얼통신 입력 버퍼값 읽기

void setup() {

Serial.begin(9600);

}


void loop() {

Serial.print("수신버퍼 문자 수: ");

Serial.println(Serial.available());


//수신버퍼 데이터 읽기

if(Serial.available()>0)

Serial.println((char)Serial.read()); // 문자로 출력

delay(1000);

}


/* 더 알아보기

* a와 97은 같은가? ASCII코드란?

* 문자로 출력하려면? char 캐스팅

* 'line ending 없음'과 '새줄'의 차이는?

*/

[실습2] 출력 화면

  • 노트북 → 아두이노

abcde 를 입력하고 [전송]한다.

*'새줄'을 포함하여 전송함


  • 아두이노 → 노트북

수신한 a,b,c,d,e,엔터 총 6개 문자를 버퍼에서 하나씩 읽어서 노트북으로 전송

[실습3] 직렬 통신 문자열 수신 3_serial_input_string.ino

// 시리얼통신 입력 문자열 읽기


String inString = "";

char inChar;


void setup() {

Serial.begin(9600);

Serial.println("Serial begin.");

}


void loop() {

if(Serial.available()>0){

while(Serial.available()>0){

inChar = (char)Serial.read();

inString = inString + inChar;

}

Serial.println("읽은 값: " + inString);

inString = ""; //다음번 읽기를 위해 초기화

}else{

Serial.println("버퍼 비었음");

}

delay(1000);

}


/* 더 알아보기

* 한 줄 더 나오는 이유는?

*/


[실습3] 출력 화면

  • 노트북 → 아두이노

abcde 를 입력하고 [전송]한다.

*'새줄'을 포함하여 전송


  • 아두이노 → 노트북

수신한 "abcde엔터" 총 6개 문자를 문자열로 만들어 노트북으로 전송

[실습4] 수신 문자열 살펴보기 4_serial_input_buffer.ino

// 시리얼통신 입력 문자열 들여다 보기


String inString = "";

char inChar;


void setup() {

Serial.begin(9600);

Serial.println("Serial begin.");

}


void loop() {

if(Serial.available()>0){

int cnt=0;

while(Serial.available()>0){

inChar = (char)Serial.read();

inString = inString + inChar;

Serial.print("inString["+ (String)cnt +"] == ");

Serial.print(inString[cnt]);

Serial.print(" : ");

Serial.println(inString[cnt],DEC);


cnt++;

}

Serial.println("읽은 문자열: " + inString);

inString = ""; //다음 수신을 위해 초기화

}

delay(100);

}



[실습4] 출력 화면

  • 노트북 → 아두이노

abcde 를 입력하고 [전송]한다.

*'새줄'을 포함하여 전송함


  • 아두이노 → 노트북

수신한 "abcde엔터" 총 6개 문자가 저장된 수신 버퍼의 내용을 하나씩 거내어 노트북으로 전송

[실습5] 직렬 통신 명령어로 내장 LED 제어 5_serial_control_led.ino

// 시리얼통신 입력 명령어 수행 - 전등(LED) 제어


#define LAMP 13 // 내장 LED를 램프로 정의


String inString = "";

char inChar;


void setup() {

Serial.begin(9600);

Serial.println("Arduino ready.");

Serial.println("[USAGE] L1: LED ON, L0: LED OFF");

Serial.println("* Note: set to 'line ending 없음'");

pinMode(LAMP, OUTPUT);

}


void loop() {

if(Serial.available()>0){

while(Serial.available()>0){

inChar = (char)Serial.read();

inString = inString + inChar;

}

if(inString=="L1"){

digitalWrite(LAMP, HIGH);

Serial.println("LAMP ON");

}else if(inString=="L0"){

digitalWrite(LAMP, LOW);

Serial.println("LAMP OFF");

}else{

Serial.println("What? [USAGE] L1: LED ON, L0: LED OFF");

}

// 다음 문자열 수신 준비

inString = "";

}

delay(100);

}


[실습5] 출력 화면

  • 노트북 → 아두이노

다음의 명령어를 전송한다.

> L0: LED 끄기

> L1: LED 켜기

* 'line ending 없음'으로 전송


  • 아두이노 → 노트북

수신한 명령을 수행하고 결과를 노트북으로 전송

[실습6] 직렬 통신 명령어로 신호등 LED 제어 6_serial_conrol_RGB.ino

// 시리얼 통신으로 신호등 LED 제어하기

// [가정] 빨강led:전등(L), 노랑led:에어컨(A), 초록led:출입문(D)

// [명령어] 0: 끄기(닫기), 1: 켜기(열기)

// 예)L0(전등 끄기), A1(에어컨 켜기), D1(문 열기)


#define LED_R 13 // 빨강led, 전등(L)

#define LED_Y 12 // 노랑led, 에어컨(A)

#define LED_G 11 // 초록led, 출입문(D)


String inString = "";

char inChar;


void setup() {

Serial.begin(9600);

Serial.println("Arduino ready.");

pinMode(LED_R, OUTPUT);

pinMode(LED_Y, OUTPUT);

pinMode(LED_G, OUTPUT);

}


void loop() {

if (Serial.available()){

while(Serial.available()){

inChar = (char)Serial.read();

inString += inChar;

}


// 수신 문자열 파싱

String inNumber = inString.substring(1, inString.length()); // 제어값 x만 취함

int inValue = inNumber.toInt(); // 제어값 x를 정수로 변환


if(inString[0]=='L'){

digitalWrite(LED_R, inValue); // 전등 제어

Serial.println("Lamp "+(String)inValue);


}else if(inString[0]=='A'){

digitalWrite(LED_Y, inValue); // 에어컨 제어

Serial.println("Aircon "+(String)inValue);


}else if(inString[0]=='D'){

digitalWrite(LED_G, inValue); // 출입문 제어

Serial.println("Door "+(String)inValue);

}else

Serial.println("What?");

// 다음 문자열 수신 준비

inString = "";

}


delay(100);

}




[실습6] 회로 구성

  • 아두이노와 삼색신호등 연결

[아두이노]-[삼색신호등]- [기능]

13번 - 빨강LED - 전등(L)

12번 - 노랑LED - 에어컨(A)

11번 - 초록LED - 출입문(D)

GND - GND

  • 명령어(프로토콜)

  • L0: 전등 끄기, L1: 전등 켜기

  • A0: 에어컨 끄기, A1: 에어컨 켜기

  • D0: 출입문 닫기, D1: 출입문 열기