[아두이노] 아두이노와 스마트폰의 만남

IOT/아두이노|2019. 8. 27. 09:00

[아두이노] 아두이노와 스마트폰의 만남



아두이노에 스마트폰을 연동하면 어떤 일이 벌어질까요. 지금까지 아두이노 실험에서는 아두이노와 스마트폰 간의 Bluetooth 통신이였습니다. 아두이노에서 측정한 센서값을 Bluetooth 통신을 통해 스마트폰에 그 결과를 출력하거나 스마트폰의 조정기 어플을 이용하여 아두이노를 컨트롤 하는 실험만 했었습니다. 단순히 아두이노와 스마트폰 사이에 무선 통신을 통해 데이터를 주고 받는 동작만이 전부였었죠. 사실 아두이노와 스마트폰의 사이에 딱 하나 Bluetooth 기능만 있는게 아닙니다. 스마트폰에 내장된 다양한 센서 부품들이 있는데 이 기능들을 잘만 아두이노와 연동하면 많은 것들을 만들어 낼 수 있습니다.

스마트폰에 내장된 고급 부품들이 많고 그 부품들의 데이터를 손쉽게 얻을 수 있습니다. 아두이노를 공부하시는 분들은 스마트폰에 내장된 부품의 기능을 사용할 때 해당 부품에 대한 오류 처리 코딩 부분을 생략 할 수 있습니다. 실제 아두이노에서 해당 부품을 구매해서 아두이노에 연결 할 경우 거기서 발생 할 수 있는 문제와 오류들을 해결하고 거기에 맞는 코딩을 수작업으로 일일히 체크하고 코딩해야 합니다. 하지만 스마트폰에 내장 되 부품을 이용하면 해당 부품의 데이터만 읽는 부분만 신경 쓰면 되기 때문에 코딩하기가 편해집니다. 참고로, 센서 읽기와 그 센서 데이터를 Bluetooth 통신을 통해 아두이노에게 명령만 내리면 되기 때문에 아두이노를 컨트롤 하기 쉽고 고퀄리티 작품을 제작하기에 효과적입니다.


스마트폰을 이용하려면 아두이노와 연동 할 스마트폰 센서는 어떻게 접근 할 수 있어야 합니다. 그 부분을 오늘 이야기 할까 합니다. 스마트폰 센서와 어플에 대해 간단히 소개하고 아두이노와 스마트폰이 연동을 하면 어떤 가능성이 있는지 살펴보도록 합시다.

1. 스마트폰 센서


스마트폰에는 어떤 센서가 내장되어 있을까요?


스마트폰에는 가속센서, 중력센서, 자이로센서, 온도센서, 압력센서, 조도센서, 근접센서, GPS센서, 지자기센서, 방향센서 ... 등이 탑재되어 있습니다. 스마트폰에 내장 된 센서들을 보면 아두이노에서 실험했던 일부 센서들이 있습니다. 그리고 특정 센서는 고가로 아두이노에서 실험을 한다면 부품 가격 때문에 저가의 부품을 사용하게 되고 그러면 만족할 만한 정확한 결과를 얻기 힘듭니다. 실험 제작 단가가 올라가겠죠.

아두이노에서 스마트폰과 연동을 하면 스마트폰에 탑재된 센서들을 다 사용할 수 있습니다. 스마트폰의 다양한 센서를 이용하여 아두이노를 동작시킬 수 있습니다.

예를 들면, 스마트폰으로 모바일 비행 시뮬레이터 게임 같은 것을 할 때 스마트폰 몸체를 좌/우 위/아래로 움직이면 모바일 게임 내 비행기 조정하는 게임을 한번 쯤 해보셨을 꺼에요. 바로 스마트폰 내에 내장된 자이로/가속 센서 값을 이용하여 조정을 하게 되는데 현실에서 이 조정값을 Bluetooth를 통해 아두이노로 보내면 그 값을 토대로 RC카 or 로보팔 같은 것을 실제 조정을 할 수 있게 됩니다.

다양한 센서를 읽을 수 있게 되면 Bluetooth를 통해 아두이노에 활용한다면 꽤 재밌는 것들을 만들 수 있겠죠.

2. 안드로이드 폰 센서 읽기



안드로이드 폰을 기준으로 이야기 하면 위 출처에 가시면 Sensor 부분을 읽으시면 됩니다.


안드로이든 폰에 내장된 센서를 어떻게 읽을 수 있는지 그 방법에 대해 자세히 나와 있습니다.

자바스크립트로 코딩부분까지 자세히 나와 있는데 어플로 센서 값을 읽고 어플 안에 Bluetooth 통신 코딩까지 합쳐진다면 이 어플을 통해서 아두이노를 제어 할 수 있게 되겠죠.

어플을 만들려면 아래 안드로이드 스튜디오와 같은 어플 개발 툴들을 사용 할 수 있어야 겠죠.



몇년 전에 봤던 강좌인데 나름 볼만 하네요. 최근판은 어떤지 모르겠네요.

직접 안드로이드 어플로 만들어 봐야 하는데 오래 전에 잠깐 재미로 봤던 거라서 다시 안드로이드 스튜디오를 사용 하려면 공부를 다시 해야하기 때문에 시간이 좀 소요되어 이 부분을 못 보여드리네요.

나중에 안드로이드 스튜디오를 다시 공부하게 된다면 한번 만들어 볼 날이 오겠죠.

스마트폰에 내장된 센서들을 사용하기 위해서는 어플 공부를 하셨으면 합니다.

스마트폰을 아두이노와 연동을 하면 뭘 할 수 있을까요?

간단히 사례와 상상을 이야기 해보겠습니다.

3. 아두이노와 스마트폰의 만남 후 가능성



위 그림을 폰드론 에토스 이미지 입니다. 보시면 아두이노 관점으로 해석하면 드론의 조정 핵심 부분을 스마트폰이 대신하게 됩니다 .스마트폰이 두뇌가 됩니다. 스마트폰에는 드론 컨트롤에 필요한 부품들이 내장되어 있기 때문에 어플로 로직만 잘 짜시면 나머지 아두이노는 폰이 명령한대로 드론모터만 제어하면 됩니다. 이렇게 스마트폰으로 드론을 컨트롤하면 다양한 것들을 할 수 있게 됩니다. 스마트폰에 카메라를 이용하여 고급 촬영이 가능하고 드론에 필요한 고급부품을 스마트폰이 대신하기 때문에 아두이노는 실질적으로 드론모터를 컨트롤하는 기능만 잘 표현하면 됩니다. 제작비를 대폭 줄이고 고급기능을 사용할 수 있게 됩니다.

미래의 전자기기는 이처럼 스마트폰과 연동한 제품들이 많이 만들어 질거라 생각됩니다.

한가지 가능성을 상상을 해보면 저번에 post한 [아두이노] 시각장애인을 위한 스마트 지팡이 원리 이해 내용에서 스마트 지팡이를 만약 스마트폰에 연동을 하게 된다면 어떤 것들을 할 수 있을까요.

위 그림처럼 스마트폰의 카메라를 이용 할 수 있게 되면 어떻게 될까요. 정면의 보행길과 사물을 인식할 수 있는 영상처리를 할 수 있겠죠. 이말은 실제 보행유도선이 깔림 보드블록이 없어도 영상으로 가상 보행유도선을 만들어 낼 수 있고 그 정보로 시각장애인을 안내할 수 있게 될거라 생각됩니다. 이걸로 자율보행스마트지팡이를 제작 하면 좋겠죠. 그리고 현재의 위치를 GPS 정보를 알 수 있는데 이 센서를 이용하여 주변의 건물이나 사물을 식별하고 그 정보를 스마트폰으로 제공받을 수도 있겠죠. 시각장애인은 이어폰으로 현재 상황 정보를 소리로 들을 수 있게 되겠죠. 간단히 상상을 해봤습니다. 아두이노 스마트지팡이에 스파트폰을 연결하면 다양한 결과물을 만들어 낼 수 있기 때문에 그 가능성은 엄청납니다.

참고로, 디지털 영상처리에 대해 관심을 가졌으면 합니다. 요즘 핫한 자율주행차에 핵심 기술입니다. 자율보행스마트지팡이로 주변 환경과 사물 인식에 대해 연구하시면 스마트지팡이에서 끝나지 않고 나중에 자율주행차에서도 그 기술을 활용할 수 있을 거라 생각됩니다. 프로그램을 배우는 학생분들은 서점에 가셔서 디지털 영상처리 책을 한번 읽어보시고 관심을 가졌으면 합니다. 저도 영상처리에 관심이 한때 많았고 3D Rendering 쪽으로 코딩 공부를 했었고 영상 인식부분은 자료가 부족하여 제대로 공부를 제대로 못해 봤습니다. 혹시 프로그램에 관심있으신 분이라면 자율주행차나 뭔가 영상인식에 관심을 가진 분들이라면 영상처리를 공부해 보셨으면 합니다. 이 기술은 나중에 아두이노와 같은 것들과 접목하면 고퀄리티 작품을 만들어 낼 수 있는 기반이 됩니다.

마무리


아두이노와 스마트폰을 연동하기 위해서는 어플을 필수로 배우셔야 합니다. 어플 공부가 쉽지는 않습니다. 코딩에 대해서 어느정도 능력이 탑재되어 있어야 합니다. 그럼에도 어플 공부를 추천하는 이유는 스마트폰의 다양한 센서 기능을 활용할 수 있고 그걸 활용하면 아두이노로 엄청난 걸 만들 수 있기 때문입니다. 뭔가 제대로 아두이노 작품을 만들어 보고 싶다면 스마트폰과의 연동에 관한 연구를 하셨으면 합니다. 그리고 영상인식에 관심이 있다면 디지털 영상처리 책을 구매하셔서 공부해보셨으면 합니다.

스마트폰을 활용하기 위해서는 스마트폰의 센서값을 읽을 수 있어야 합니다. 안드로이드폰이면 안드로이드 폰에서 센서값을 읽는 함수를 사용할 수 있어야 합니다. 읽은 센서값에 대한 동작 명령을 아두이노에 보내야 하기 때문에 Bluetooth 코딩도 알아야 합니다. 그러면 어플을 만들 수 있는 개발 툴을 사용 할 수 있어야 합니다. 앱 제작 공부를 해야 합니다. 어플을 만들 수 있는 능력이 있어야 아두이노와 스마트폰의 연동을 제대로 할 수 있게 됩니다. 스마트폰의 센서를 사용하기 위해서는 어플 공부를 해야 하는 어려움이 있지만 꼭 공부해보셨으면 해요.

어플을 공부하시면 나중에 스팀 블록체인과 관련한 어플도 제작 가능하기 때문에 꼭 이쪽 분야가 아니더라도 다른 분야에서도 많이 활용되니깐 공부해보셨으면 합니다.

댓글()

[아두이노] 아두이노 간 I2C 통신 응용

IOT/아두이노|2019. 8. 26. 09:00

[아두이노] 아두이노 간 I2C 통신 응용



지난 시간까지는 가상시뮬레이터로만 I2C 통신에 대해 실험했었는데 오늘은 몇가지 실제 부품을 가지고 아두이노 간 I2C 통신 실험을 할까 합니다. 상황 설정은 슬레이브 아두이노에 조도센서를 연결하여 조도센서 값을 측정하고 마스터 아두이노는 조도센서값을 슬레이브 아두이노에게 요청하고 응답 받은 조도센서값을 I2C 통신을 통해 16x2 LCD 모듈에 결과를 출력해보면 재밌을 것 같아서 한번 도전해봤습니다. 사실 부품이 몇개 없어서 좀 더 새로운 실험을 하고 싶었는데 있는 부품으로만 I2C 통신을 하다 보니깐 부품의 제약이 따라 기존의 실험했던 부품을 다시 사용하여 약간 복습 실험이 되고 말았네요.

이제 실험을 본격적으로 시작해 봅시다.


1. 회로도


  • 준비물 : 조도센서 1개, 저항 1k옴 1개, 16x2 LCD 모듈 1개, 뻥판, 아두이노우노, 아두이노마이크로
  • 내용 : 아두이노우노, 아두이노마이크로, 16x2 LCD SDA, SCL핀을 서로 공유한다.

아두이노우노가 2대 였다면 좋았을텐데 아두이노우노가 1대뿐이고 다행히 아두이노마이크로가 있어서 마스터/슬레이브 아두이노로 I2C 통신을 할 수 있었네요.

참고로 아두이노우노와 아두이노마이크로의 SDA, SCL핀 번호가 다릅니다.

아두이노우노 A4(SDA), A5(SCL) => 아두이노마이크로 D2(SDA), D3(SCL)

보드마다 핀번호가 다르니깐 꼭 확인하시고 연결하세요.


위 그림을 보시면 아두이노우노(마스터)와 아두이노마이크로(슬레이브)는 각각 다른 역할을 수행합니다.

  • 아두이노우노 : 16x2 LCD 모듈에 결과 출력을 담당
  • 아두이노마이크로 : 조도센서에 연결되어 조도센서값 읽기를 담당

아두이노우노는 아두이노마이크로에게 조도센서값을 요청하고 아두이노마이크로는 요청에 대해 응답하고 조도센서값을 아두이노우노에게 보내게 됩니다. 아두이노우노는 조도센서값을 읽은 후 16x2 LCD 모듈에 결과를 출력하게 됩니다.

2. 코딩



1) 마스터 아두이노 코딩


설계 :

  • 슬레이브 아두이노에게 조도센서값 요청과 수신
  • 16x2 LCD 모듈에 조도센서값 출력

슬레이브 아두이노에게 조도센서값을 요청

조도센서값은 0~1023사이의 아날로그 신호를 읽게 됩니다. 그러면 슬레이브 아두이노에서 조도센서값을 byte 단위로 보내면 총 4자리 숫자가 전송됩니다. 원래 다른방법이 있지만 왠지 4자리 숫자를 쪼개고 합치는 방식으로 처리하고 싶어지더군요.

우선, 요청을 하면 최대 4자리이기 때문에 아래와 같이 요청을 하게 했습니다.

 Wire.requestFrom(1,4); 

문제는 조도센서값이 0~1023이기 때문에 한자리~네자리로 숫자 데이터로 표현되니깐 최대 4자리 4byte형태를 유지해서 데이터를 수신하게 설정한다면 다음과 같습니다.

[합치기]

  while(Wire.available())
  {
    byte a=Wire.read(); //1의자리
    byte b=Wire.read(); //10의자리
    byte c=Wire.read(); //100의자리
    byte d=Wire.read(); //1000의자리
    m_cds = d*1000+c*100+b*10+a;     
  }

사실 int형의 데이터를 전송하고 int형이 2byte이니깐

int형 <= (앞byte<<8)|뒤byte)

예)

  int k = 1023;
  
  //쪼개기
  byte a = k>>8;
  byte b = k;
    
  //합치기
  int c = (a<<8)|b;

이렇게 하면 되겠지만 한번 색다르게 접근 했네요.

16x LCD모듈에 조도센서값을 출력

LiquidCrystal_I2C 라이브러리 함수를 이용합니다.

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,16,2);  // 0x27 or 0x3F

출력은 슬레이브 아두이노에서 요청한 값이 m_cds변수에 저장되니깐 그 값을 lcd.print(m_cds)함수로 출력하면 됩니다.

void output(){
 lcd.print("                "); //지우기
 lcd.setCursor(0, 1); //2번째 줄의 0번째칸
 lcd.print("CDS : "); 
 lcd.setCursor(7, 1); //2번째 줄의 7번째칸
 lcd.print(m_cds);    
}

2) 슬레이브 아두이노 코딩


설계 :

  • 조도센서값 읽기
  • 마스터 아두이노 요청 시 응답처리

조도센서값 읽기

m_cds = analogRead(cdspin);

마스터 아두이노 요청 시 응답 처리

Wire.onRequest(requestEvent);

[쪼개기]

void requestEvent() {
  int val = m_cds; //조도센서값
  for(int i=0;i<4;i++){
    Wire.write(val%10);  //자리수 출력
    val=val/10;
  }  
}

3) 종합 코딩


[마스터 아두이노]

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
 
LiquidCrystal_I2C lcd(0x3F,16,2);  // 0x27 or 0x3F
int m_cds=0;
void setup()
{
  lcd.init(); //초기화
  lcd.backlight(); //배경불켜기
  lcd.setCursor(0, 0);
  lcd.print("Hello World");
  delay(1000);
  lcd.clear();  
}

void loop() {

  Wire.requestFrom(1,4); //슬레이브(1)에 4byte 요청   
  while(Wire.available())
  {
    byte a=Wire.read();
    byte b=Wire.read();
    byte c=Wire.read();
    byte d=Wire.read();
    m_cds = d*1000+c*100+b*10+a;     
  }
  output();  
  delay(500);
}

void output(){
 lcd.print("                ");
 lcd.setCursor(0, 1);
 lcd.print("CDS : ");
 lcd.setCursor(7, 1);
 lcd.print(m_cds);    
}

[슬레이브 아두이노]

#include <Wire.h>

const byte cdspin = A0;
int m_cds = 0;

void setup() {
  Wire.begin(1);
  Wire.onRequest(requestEvent);
}

void loop() {  
  m_cds = analogRead(cdspin);
  Serial.println(m_cds);   
  delay(500);   
}

void requestEvent() {
  int val = m_cds;
  for(int i=0;i<4;i++){
    Wire.write(val%10);  
    val=val/10;
  }  
}

3. 결과


영상을 보시면 좀 지져분하게 만들어 졌네요. 조도센서를 손으로 가리면 조도센서값이 작아지는데 이 조도센서값은 아두이노마이크로에서 측정이 됩니다. 그리고 아두이노우노, 아두이노마이크로, 16x2 LCD I2C 모듈은 SDA, SCL 핀은 공유되어 있고 아두이노우노에서 16x2 LCD I2C모듈을 제어합니다. 아두이노마이크로에서 조도센서측정 작업을 수행하고 아두이노우노는 조도센서값을 요청과 조도센서값을 출력 작업을 수행합니다. 그 결과가 아래 영상에서 확인 할 수 있습니다.


마무리


오늘 실험 내용은 예전 실험 했던 내용인데 하나의 아두이노우노에서 조도센서를 측정하고 16x2 LCD 모듈에 출력해도 됩니다. 이 작업을 구지 나누어 두 대의 아두이노에 역할을 분담 시켰습니다. 이렇게 I2C 통신을 이용하면 많은 부품을 아두이노 한대로 제어하는 것보다 여러대로 나누어 제어를 할 수 있습니다. 한곳에서 많은 부품을 제어하려면 각각의 부품의 소요되는 시간과 중간에 다른 동작의 개입할 때 까다로운 코딩을 설계해야 하는데 여러대로 분산 제어한다면 분산된 부품은 각각의 아두이노에서 해당 동작만 코딩하면 되기 때문에 코딩이 어느정도 쉬워질 거라 생각되네요.

조도센서로 실험했지만 여러분들은 다른 부품을 가지고 실험을 해보세요. 다양한 실험을 해야지 다양한 상상을 할 수 있으니깐요.


댓글()

[아두이노] n:m 아두이노 간 I2C 통신

IOT/아두이노|2019. 8. 23. 09:00

[아두이노] n:m 아두이노 간 I2C 통신



지난 시간에 마스터 아두이노와 슬레이브 아두이노 간 통신을 기본적으로 다뤘습니다. post를 정리하다가 문득 슬레이브 간의 I2C 통신이 하고 싶어져서 한번 도전을 해보았습니다. 지난 시간의 코딩한 방법으로 반복 코딩하면 재미가 없기 때문에 print(), println()함수를 이용하여 데이터를 전송하고 수신할 때는 문자열로 읽는 방식으로 코딩을 해봤습니다.

그러면, 어떻게 처리했는지 살펴보도록 하죠.

1. 1:1 슬레이브 아두이노 I2C 통신 회로도


준비물 : 아두이노우노 2개
내용 : 아두이노우노의 A4(SDA), A5(SCL)핀을 서로 공유한다.


가정은 마스터 아두이노는 있다고 가정한 상태에서 슬레이브 간 통신을 실험으로 각 아두이노에 주소를 부여하고 주소 간의 통신을 하는 실험으로 1:1 통신을 실험합니다.


실험은 1:1 통신이지만 연결하는 갯수에 따라서 n:m 통신이 가능합니다. post를 읽은 후 2대 이상의 아두이노를 서로 데이터를 전송해 보세요.

2. 코딩



코딩은 슬레이브 아두이노 간의 데이터 전송을을 해보도록 하죠.

슬레이브 아두이노 간 데이터 전송


설계 :

  • A 슬레이브 아두이노에서 B 슬레이브 아두이노로 데이터 전송

[데이터 전송] : print(), println()함수로 이번에 실험을 했습니다.

  Wire.beginTransmission(2);                
  Wire.println("a1/test1!");           
  Wire.endTransmission(); 

데이터 전송은 슬레이브 간 보낼 수 있다고 했죠. 그래서 기존 데이터 전송 코딩은 동일 합니다.

[문자열 데이터 수신] : 문자열로 이번에 읽는 실험을 했습니다.

void receiveEvent(int howMany) { //전송 데이터 호출시 명령
  while (Wire.available()) { 
    String inString = Wire.readStringUntil('\n'); 
    Serial.println(inString);         
  }      
}

데이터 전송과 수신은 지난 시간과 동일하게 표현하면 재미 없기 때문에 좀 색다르게 표현 했네요. 반대의 경우 방금했던 코딩을 동일하게 코딩하시면 됩니다.

슬레이브 아두이노 1,2 코딩을 해볼까요.

[슬레이브 아두이노 1]

#include <Wire.h>

void setup() {
  Wire.begin(1); //슬레이브 주소                  
  Wire.onReceive(receiveEvent); //마스터 데이터 전송시 receiveEvent함수 호출
  Serial.begin(9600); 
}

void loop() {
  Wire.beginTransmission(2);                
  Wire.println("a1/test1!");           
  Wire.endTransmission();  
  delay(200);  
}
void receiveEvent(int howMany) { //전송 데이터 호출시 명령
  while (Wire.available()) { 
    String inString = Wire.readStringUntil('\n');      
    Serial.println(inString);
  }      
}

[슬레이브 아두이노 2]

#include <Wire.h>

void setup() {
  Wire.begin(2); //슬레이브 주소                  
  Wire.onReceive(receiveEvent); //마스터 데이터 전송시 receiveEvent함수 호출
  Serial.begin(9600); 
}

void loop() {
  Wire.beginTransmission(1);                
  Wire.println("b2/test2!");           
  Wire.endTransmission();  
  delay(500);  
}

void receiveEvent(int howMany) { //전송 데이터 호출시 명령
  while (Wire.available()) { 
    String inString = Wire.readStringUntil('\n');      
    Serial.println(inString);
  }      
}

참고로 딜레이 시간이 동일하게 되면 같은 시간에 데이터를 보내고 같은 시간에 데이터를 읽게 됩니다. 그러면 좀 문제가 생기겠지요. 가상시뮬레이터에서 데이터를 정상적으로 읽지 못하더군요. 그래서 시간 차를 다르게 했습니다. 즉, 시분할 스케줄링 처리를 해줘야 할 듯 싶네요. 아니면 지난 시간에 했던 1:N 연결을 통해서 마스터 아두이노에서 컨트롤 타워 연결을 수행하여 각 슬레이 간의 데이터 통신을 제어하는 방법이 가장 쉬울 듯 싶네요.

추가로, delay()함수를 쓰기 싫으면 다음과 같이 코딩하면 됩니다.

unsigned long timeVal = 0;

void loop() {
  if(millis()-timeVal>200){
     Wire.beginTransmission(2);                
     Wire.println("a1/test1!");           
     Wire.endTransmission();  
     timeVal=millis();
  }
}

3. 결과


각 슬레이브 아두이노가 상대 슬레이브 아두이노에 데이터를 전송하고 그 결과를 문자열로 읽고 시리얼모니터로 결과를 출력합니다. 나중에 여기에 마스터 아두이노를 연결하여 마스터와 슬레이브 아두이노 간 통신을 하는 동시에 슬레이브 간의 통신을 별도로 수행할 때 오늘 배운 내용을 적용하면 되겠죠.


마무리


오늘은 print(), println()함수로 데이터를 보내봤습니다. 그리고 수신할 때는 한번에 문자열로 읽어 보았습니다. 문자열로 읽을 경우 문자열 안에 데이터를 보낸 슬레이브주소코드를 같이 넣어서 보내면 누가 어떤 데이터를 보냈는지 쉽게 확인 할 수 있습니다. 쉽게 말해서, 문자열 "식별코드주소/전송데이터" 형태로 데이터를 보내고 수신하는 아두이노는 식별코드주소와 전송데이터를 분리해 내면 다수의 아두이노를 식별하고 해당 명령을 적절하게 수행할 수 있습니다.

그리고, 식별코드주소 뿐 아니라 여기에 요청코드를 넣게 되면 요청코드를 확인 후 요청한 식별코드주소을 토대로 상대 아두이노로 응답 메시지를 보내면 쌍방 통신도 가능해 지겠죠. Wire 라이브러리 요청/응답 함수를 사용하지 않더라도 데이터 전송함수를 이용하면 그 전송 된 메시지를 가지고 응답 처리를 유사하게 표현이 가능합니다. 한번 연구해 보세요.

여러분들은 계속 I2C 통신을 이용하는데 여러대의 아두이노가 있을 때 여러가 상황을 만들고 각 상황에 대해서 어떤식으로 통신을 할 것인지 상상의 나래를 펼쳐 보셨으면 합니다.

댓글()

[아두이노] 1:N 아두이노 간 I2C 통신

IOT/아두이노|2019. 8. 22. 09:00

[아두이노] 1:N 아두이노 간 I2C 통신



지난시간에 아두이노간 I2C 통신 실험을을 하기 위해서 공유선을 A4(SDA), A5(SCL)핀에 연결하여 2대의 아두이노 간 통신을 했었습니다. 오늘은 마스터 아두이노와 2대의 슬레이브 아두이노 간의 통신을 연장해서 실험을 해보겠습니다. 지난 시간의 실험 내용에서 아두이노가 한 대 더 추가되었을 뿐 변동 사항은 거의 없습니다. 오늘 실험은 마스터 아두이노에 슬레이브 아두이노 2대를 연결하여 실험하지만 더 많은 아두이노로 통신 하시고 싶다면 2대 이상 연결하여 실험을 하셔도 됩니다. 슬레이브 아두이노의 갯수는 여러분들이 정해서 실험하시면 됩니다.

이제 1:N 아두이노들 간의 I2C 통신 실험을 해보도록 하죠.

1. 1:N 아두이노 I2C 통신 회로도


준비물 : 아두이노우노 3개
내용 : 아두이노우노의 A4(SDA), A5(SCL)핀을 서로 공유한다.



회로도의 선 연결은 지난 시간에 아두이노 간의 I2C 통신 회로도에서 아두이노 한대가 더 추가 된 회로도 입니다.

2. 코딩



사전 학습에서 사용된 코딩을 약간만 수정하시면 됩니다.

1) 마스터 아두이노 코딩


설계 :

  • 각 슬레이브 아두이노에 데이터 전송
  • 각 슬레이브 아두이노에 데이터 요청과 수신

동작은 위 2가지 형태로 실험이 이루어 집니다. 아래 그림처럼 그림A와 그림B 동작을 마스터 아두이노는 각 슬레이브 아두이노 간의 순차적으로 동작하게 됩니다.


[지난소스]

  //데이터 전송
  Wire.beginTransmission(1);                 
  Wire.write("good ");       
  Wire.write(x);             
  Wire.endTransmission();    
     
  delay(500);
    
  //데이터 요청 & 수신
  Wire.requestFrom(1, 4); //슬레이브(1)에 4byte 요청
  while (Wire.available()) {
    char c = Wire.read(); 
    Serial.print(c);        
  }  

지난시간에 슬레이브 아두이노에 특정 데이터를 전송한 뒤에 다시 데이터를 요청 했었습니다. 1대가 아니고 2대의 슬레이브 아두이노에 데이터를 전송하고 데이터를 요청하도록 수정 한다면 어떻게 해야 할까요.

동작은 설계에서 딱 두개의 동작만을 수행 합니다. 데이터를 전송하고 데이터를 요청한다. 이 두가지 동작을 2대의 슬레이브 아두이노와 통신을 해야 한다면 지난 소스을 적용한다면 2번 반복 수행해야 겠죠. 그러면, 위 코딩을 복사해서 길게 두번 코딩해야 할까요. 그럴 필요는 없습니다. for문으로 두번만 위 코딩을 반복시키면 됩니다.

각 슬레이브 주소를 1, 2번으로 지정해 주고 아래와 같이 코딩하면 됩니다.

  for(int i=1;i<3;i++){
    Wire.beginTransmission(i);                
    Wire.write("test ");       
    Wire.write(i);             
    Wire.endTransmission();    
     
    delay(500);
    Wire.requestFrom(i, 4);   
    while (Wire.available()) {
        char c = Wire.read(); 
        Serial.print(c);        
    }
  }   

간단하죠. 여기서, 아두이노가 N대를 연결한다면 for문의 i값의 N 횟수 만큼 반복되도록 숫자만 변경해주면 여러대의 슬레이브 아두이노와 통신을 할 수 있게 됩니다.

2) 슬레이브 아두이노 코딩


설계 :

  • 데이터 수신 처리
  • 데이터 요청 응답

지난 시간의 코딩과 동일합니다. 식별 번호만 바꿨네요. "ok1"으로 해당 슬레이브 아두이노의 요청 메시지만 수정했네요.

  Wire.onRequest(requestEvent); //요청시 requestEvent함수 호출
  Wire.onReceive(receiveEvent); //데이터 전송 받을 때 receiveEvent함수 호출
void receiveEvent(int howMany) { //전송 데이터 호출시 명령
  while (Wire.available()>1) { 
    char ch = Wire.read(); 
    Serial.print(ch);         
  }
  int x = Wire.read();    
  Serial.println(x);      
}
void requestEvent() { //마스터 요청 시 수행 함수
  Wire.write("ok1\n");   
}

여기서, 두 대의 슬레이브 아두이노로 실험하니깐 요청이 들어오면 "ok1", "ok2"로 메시지가 출력되게 코딩하면 됩니다.

종합해보면,

[마스터 아두이노]

#include <Wire.h>

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

void loop() {  
  for(int i=1;i<3;i++){
    Wire.beginTransmission(i);                
    Wire.write("test ");       
    Wire.write(i);             
    Wire.endTransmission();    
     
    delay(500);
    Wire.requestFrom(i, 4);   
    while (Wire.available()) {
        char c = Wire.read(); 
        Serial.print(c);        
    }
  }   
}

[슬레이브 아두이노 1]

#include <Wire.h>

void setup() {
  Wire.begin(1); //슬레이브 주소                
  Wire.onRequest(requestEvent); //마스터 요청시 requestEvent함수 호출
  Wire.onReceive(receiveEvent); //마스터 데이터 전송시 receiveEvent함수 호출

  Serial.begin(9600);           
}

void loop() {
  delay(500);
}

void receiveEvent(int howMany) { //전송 데이터 호출시 명령
  while (Wire.available()>1) { 
    char ch = Wire.read(); 
    Serial.print(ch);         
  }
  int x = Wire.read();    
  Serial.println(x);      
}
void requestEvent() { //마스터 요청 시 수행 함수
  Wire.write("ok1\n"); 
  
}

[슬레이브 아두이노 2]

#include <Wire.h>

void setup() {
  Wire.begin(2);                
  Wire.onRequest(requestEvent); //마스터 요청시 requestEvent함수 호출
  Wire.onReceive(receiveEvent); //마스터 데이터 전송시 receiveEvent함수 호출
  Serial.begin(9600); 
}

void loop() {
  delay(500);
}

void receiveEvent(int howMany) { //전송 데이터 호출시 명령
  while (Wire.available()>1) { 
    char ch = Wire.read(); 
    Serial.print(ch);         
  }
  int x = Wire.read();    
  Serial.println(x);      
}
void requestEvent() { //마스터 요청 시 수행 함수
  Wire.write("ok2\n");   
}

3. 결과


위 코딩으로 1:N 아두이노 간의 I2C 통신을 할 수 있게 되었습니다. 가상시뮬레이터에서 결과가 어떻게 나오는지 영상으로 살펴보세요.


마무리


오늘은 1:1 I2C 통신하는 방식에서 1:N I2C 통신을 실험 했습니다. 오늘 내용은 지난 시간에 했던 내용을 for문 하나가 추가 되었을 뿐 따로 추가된 부분은 없습니다. 여러대를 연결하면 각 슬레이브 아두이노로 데이터를 보내고 각 슬레이브 아두이노에 데이터를 요청하면 거기에 맞게 각 슬레이브 아두이노는 데이터 수신과 데이터 요청에 대한 응답 처리 코딩만 하면 됩니다.

오늘은 그냥 복습차원으로 반복 학습 post입니다. 1:1 통신을 할 수 있으면 1:N 통신을 잘 생각하면 쉽게 떠올릴 수 있는데 혹시 1:N이 잘 연상이 안되는 분들이 있을 것 같아서 지난시간에 마무리 글로 1:N 통신으로 연장해서 상상을 해보시라고 했는데 못하시는 분들을 위해 이렇게 post로 다시 이야기를 하게 되었습니다.


댓글()

[아두이노] 아두이노 간 I2C 통신

IOT/아두이노|2019. 8. 21. 09:00

[아두이노] 아두이노 간 I2C 통신



오늘은 아두이노 간 통신을 I2C 방식을 이용하여 실험을 할까 합니다. 예전에 시리얼통신을 할 때 한꺼번에 소개 했어야 했는데 미뤄졌네요. 지난 시간에 시리얼 통신으로 다수 명령 처리 방법에 대한 post를 하다 보니 다수 아두이노 통신을 통해 명령을 처리해보고 싶어져서 다수 통신 실험을 위해 I2C 방식을 소개하면서 다뤄보고 싶어 이렇게 post를 쓰게 되었습니다. 통신에 대한 복습차원으로 좋을 것 같아서 겸사겸사 이야기를 이여 갑니다.

이제부터, I2C 방식으로 어떻게 통신이 이루어지는지 살펴 보겠습니다.

1. I2C 통신을 위한 Wire 라이브러리



위 참고 출처에 가시면 아두이노 공식 홈페이지에 Wire 라이브러리에 대해 자세히 나와 있습니다. 그리고, Master Reader/Slave Writer, Master Writer/Slave receiver 예제가 있는데 이 예제를 통해서 아두이노 간 통신을 배우시면 되겠습니다.

아두이노 간 통신을 하기 위해서 Wire 라이브러리를 이용하여 I2C 통신을 할 수 있는데 아두이노우노의 A4(SDA), A5(SCL)핀에 아두이노들 간의 공유선을 이용하여 통신이 이루어 집니다. 만약, 다른 보드를 이용할 경우 해당 보드의 SDA, SCL핀이 몇번 핀인지 확인하시고 해당핀을 공유선에 연결하시면 됩니다.

Boardpins
UnoA4 (SDA), A5 (SCL)
Mega256020 (SDA), 21 (SCL)
Leonardo, Micro2 (SDA), 3 (SCL)
Due20 (SDA), 21 (SCL), SDA1, SCL1

이제 아두이노홈페이지에 나와 있는 Master Reader/Slave Writer, Master Writer/Slave receiver 예제로 기반으로 간단히 설명을 드리겠습니다.

1) 아두이노 주소 지정


아두이노 간의 식별은 주소로 구별합니다. 주소를 지정하는 방식은 다음과 같습니다.

Master : Wire.begin()
Slave : Wire.begin(address)

위 함수를 보면 아무것도 안적혀 있으면 Master가 되고 address를 지정해 주면 그 address가 해당 아두이노의 슬레이브 주소(7bit)가 됩니다. 이렇게 주소를 지정하면 상대 아두이노에서 해당 주소을 통해서 데이터를 보낼 수 있고 받을 수 있습니다.

2) 데이터 전송


Wire.beginTransmission(1); // 슬레이브주소 1번 전송시작
Wire.write("good\n");        // 문자열 전송
Wire.endTransmission();    // 전송 중단

데이터를 보낼 때 beginTransmission(address)와 endTransmission()함수가 쌍을 이루고 write()함수로 데이터를 해당 주소지로 보내게 됩니다. write()함수가 쓰기 불편하시면 print() println()함수로 쓰셔도 됩니다. 참고로 Wire.send()함수와 같이 봐주시기 바랍니다.

3) 데이터 수신


setup()함수에 한번만 표현하고 데이터가 수신이 되면 receiveEvent 함수가 호출이 됩니다.

Wire.onReceive(receiveEvent); //데이터 수신 시  receiveEvent()함수 호출

호출된 함수 내부의 코딩은 시리얼통신 때 배웠던 코딩과 동일합니다.

void receiveEvent(int howMany) { //전송 데이터 처리 명령
  while (Wire.available()) { 
    char ch = Wire.read(); 
    Serial.print(ch);         
  }  
}

4) 요청/응답


위에서는 단순히 일방적으로 데이터를 보내고 받는 방식이라면 여기에서는 데이터를 특정 슬레이브 아두이노에게 데이터를 요청하고 해당 슬레이브 아두이노는 요청을 확인 한 후 데이터를 보내게 됩니다.

마스터 아두이노에서 요청은 다음과 같습니다.

Wire.requestFrom(1, 4); //슬레이브(1)에 6byte 요청

while (Wire.available()) { //보내온 데이터가 있을 시 데이터 읽기
  char c = Wire.read(); 
  Serial.print(c);        
}  

슬레이브 아두이노에서 응답은 다음과 같습니다.

Wire.onRequest(requestEvent); //요청할 때마다 호출

위 함수는 setup()함수에 한번만 표현하고 데이터 요청이 올 때 requestEvent()함수가 호출되게 됩니다.

호출된 함수 내부의 코딩은 간단한 메세지 전송만 보내게 표현해 보겠습니다.

void requestEvent() { //요청 시 수행 함수
  Wire.write("ok!\n");   
}

정리를 하면, Wire.requestFrom(1, 4) 함수은 마스터 아두이노에서 슬레이브(1) 아두이노에게 요청을 하고 4byte을 읽겠다는 의미이고, Wire.onRequest(requestEvent) 함수는: 슬레이브(1) 아두이노는 요청을 받게 되면 requestEvent()함수를 호출하고 그 안에 있는 write()함수를 통해 마스터 아두이노에 데이터를 보내게 됩니다.

2. I2C 아두이노 간 통신 회로도


준비물 : 아두이노우노 2개
내용 : 아두이노우노의 A4(SDA), A5(SCL)핀을 서로 공유한다.


회로도의 선 연결은 어렵지 않죠. A4, A5 선만 잘 연결하시면 됩니다. 참고로 실제로 실험하실 때는 여러분들이 사용하시는 보드에 따라 선 연결이 다릅니다. 여러분들이 사용하는 보드의 SDA, SCL 핀이 몇번인지 확인하시고 연결하셔야 합니다. 아두이노우노의 경우는 A4, A5로 연결하면 됩니다.

3. 코딩



사전 학습으로 위 아두이노공식 홈페이지에 가시면 Master Reader/Slave Writer, Master Writer/Slave receiver 예제가 있는데 있는데 위 회로도에다가 코딩만 복사하셔어 가상시뮬레이터에서 돌려 보세요.

Master Reader/Slave Writer, Master Writer/Slave receiver 예제를 합쳐진 코딩으로 실험을 해보겠습니다.

위 공식홀페이지의 예제에서는 마스터 아두이노에서 x값을 순차적으로 슬레이브 아두이노에 보내는 동작과 마스터 아두이노에서 데이터 요청하고 슬레이브 아두이노에서 응답하는 동작을 하는 예제입니다.

실험은 마스터에서 x값을 순차적으로 슬레이브로 보내면서 슬레이브 아두이노에게 데이터 요청을 동시에 수행하고 슬레이브 아두이노는 데이터는 수신하면서 요청이 들어오면 응답을 수행하도록 해보겠습니다.

1) 마스터 아두이노 코딩


설계 :

  • 데이터 전송
  • 슬레이브 아두이노에 데이터 요청과 수신

먼저, Wire 라이브러를 함수를 사용하기 때문에 아래와 같인 선언 해주셔야 합니다.

#include <Wire.h>

그리고, 마스터 아두이노이기 때문에 주소지정은 다음과 같습니다.

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

한번만 수행되면 되니깐 Setup()함수 내에서 표현합니다.

데이터 전송하기

int x = 0;
Wire.beginTransmission(1);                
Wire.write("good\n");       
Wire.write(x);             
Wire.endTransmission();
x++;
if(x==6)x=0;  

데이터 요청과 수신

Wire.requestFrom(1, 4); //슬레이브(1)에 4byte 요청
while (Wire.available()) {
    char c = Wire.read(); 
    Serial.print(c);        
}    

2) 슬레이브 아두이노 코딩


설계 :

  • 데이터 수신 처리
  • 데이터 요청 응답

슬레이브 아두이노는 다음과 같이 코딩합니다.

#include <Wire.h>

void setup() {
  Wire.begin(1); //슬레이브 주소                
  Wire.onRequest(requestEvent); //요청시 requestEvent함수 호출
  Wire.onReceive(receiveEvent); //데이터 전송 받을 때 receiveEvent함수 호출
    
  Serial.begin(9600);           
}

마스터 아두이노와 다른 접은 Wire.begin(address) 함수의 주소를 지정해 줘야 합니다. 데이터 수신과 요청에 대한 onReceive()함수와 onRequest()함수를 setup()함수에 한번만 표현합니다.

이제 데이터 수신과 요청에 대한 이벤트 호출함수에 대한 동작만 코딩하면 됩니다.

데이터 수신하기

void receiveEvent(int howMany) { //전송 데이터 읽기
  while (Wire.available()>1) { 
    char ch = Wire.read(); 
    Serial.print(ch);         
  }
  int x = Wire.read();    
  Serial.println(x);      
}

데이터 요청 응답하기

void requestEvent() { //요청 시 수행 함수
  Wire.write("ok!\n");   
}

종합해보면,

[마스터 아두이노 소스]

#include <Wire.h>

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

byte x = 0;

void loop() {
  Wire.beginTransmission(1);                
  Wire.write("good ");       
  Wire.write(x);             
  Wire.endTransmission();    
     
  delay(500);
  
  Wire.requestFrom(1, 4); //슬레이브(1)에 4byte 요청
  while (Wire.available()) {
    char c = Wire.read(); 
    Serial.print(c);        
  }    
  x++;
  if(x==6)x=0;  
}

위 코딩을 보면 데이터 전송과 데이터 요청 사이의 delay()함수를 주었습니다. 그 이유는 서로 충돌이 일어나지 않게 일정시간 딜레이 주었는데 한번 딜레이 함수없이 가상시뮬레이터에서 실행 시켜보세요. 어떤 결과가 나오는지 확인을 하시기 바랍니다.

[슬레이브 아두이노 소스]

>#include <Wire.h>

void setup() {
  Wire.begin(1); //슬레이브 주소                
  Wire.onRequest(requestEvent); //요청시 requestEvent함수 호출
  Wire.onReceive(receiveEvent); //데이터 전송 받을 때 receiveEvent함수 호출

  Serial.begin(9600);           
}

void loop() {
  delay(500);
}

void receiveEvent(int howMany) { //전송 데이터 읽기
  while (Wire.available()>1) { 
    char ch = Wire.read(); 
    Serial.print(ch);         
  }
  int x = Wire.read();    
  Serial.println(x);      
}
void requestEvent() { //요청 시 수행 함수
  Wire.write("ok!\n");   
}

여기서 available()함수에서 왜 1보다 커야 하는지 한번 0보다 크다일 때와 1보다 크다 일때는 비교해보세요. 그 차이점을 구별하시기 바랍니다.

4. 결과


결과는 마스터 아두이노는 "good " 문자열과 x값을 0~5까지의 값을 슬레이브 아두이노에 보내고 슬레이브 아두이노는 전송 된 "good 숫자"의 값을 읽고 시리얼모티너로 출력합니다. 그리고 슬레이브 아두이노는 데이터 요청이 오면 "ok!\n"문자열 값을 마스터 아두이노에 보내고 마스터 아두이노는 "ok!\n"문자열을 읽고 시리얼모니터로 요청/응답이 정상적으로 처리 되었는지 해당 메시지로 확인 할 수 있습니다.


마무리


오늘은 아두이노 간 I2C 통신을 실험 해 보았습니다. 2대의 아두이노 간 통신이였지만 여러 대의 슬레이브 아두이노에 주소 지정을 하시게 되면 1:N 통신이 가능합니다. 다수의 아두이노 통신을 할 수 있는데 한번 오늘 배운 내용을 기반으로 연장해서 실험을 해보세요.


댓글()

[아두이노] 시리얼 통신으로 다수 명령 처리 방법

IOT/아두이노|2019. 8. 19. 09:00

[아두이노] 시리얼 통신으로 다수 명령 처리 방법



시리얼통신으로 통해 전송되는 하나의 패턴 문자열에 대한 처리에 대해 다뤘습니다. 문득 아두이노에 연결 된 여러개의 부품을 통신을 통해 제어를 할 경우에 대해 어떻게 처리하면 좋을지 궁금해 지더군요. 하나의 패턴 문자열을 통해 A부품을 제어했다면 또다른 패턴문자열로 B부품을 제어할 일이 생길 경우가 있습니다. 여러개의 서로 다른 패턴 문자열을 아두이노우노에서 동시에 처리하고자 할 때 기초적인 방법으로 처리하는 상상코딩을 해보도록 하겠습니다.

1. 부품 패턴 문자열


LED와 Servo Motor를 통신을 통해 제어를 한다면 어떻게 할까요.

LED(A부품)패턴 문자열 : LED 핀이 13번일 경우를 가정해 봅시다.

String inString = "a13,1" or "a13,0";
  • "a13,1" => a부품이고 13번 pin에 상태는 1이다.
digitalWrite(13,1);
  • "a13,0" => a부품이고 13번 pin에 상태는 0이다.
digitalWrite(13,0);

위 A 패턴문자열을 통해서 13번 핀을 HIGH(1) or LOW(0) 상태를 지정할 수 있게 됩니다.

Servo Motor(B부품)패턴 문자열" : Servo pin이 7번일 경우를 가정해 봅시다.

String inString = "b90";
  • "b90" => b부품이고 회전각 90도이다.
servo.write(90);

위 B 패턴문자열을 통해서 고정 Servo Motor 핀을 특정각으로 회전 시킬 수 있게 됩니다.

예를들어, 2개의 패턴 문자열을 통신을 통해 전송되고 아두이노는 서로 다른 문자열이 입력되면 해당 문자열에 맞은 동작을 처리하도록 하기 위해서는 어떻게 할까요. 바로, 문자열을 분해하여 부품 패턴형태를 선택문(switch)문으로 분리해 내면 됩니다.

2. 다수 패턴 문자열을 선택


패턴 형태를 앞글자 첫번째 알파벳으로 지정하게 했습니다. 즉, a,b로 2개의 부품의 패턴부품으로 분류가 됩니다.

a,b의 부품 패턴을 선택문을 통해서 해당 부품을 지정할 수 있습니다.

  • 문자열 읽기 :
String inString = Serial.readStringUntil('\n');   
  • 첫번째 문자(부품패턴) 읽기 : 문자열에서 특정 위치의 알파벳은 charAt(위치)함수로 해당 문자를 읽어옴
char ch = inString.charAt(0); //문자열에서 첫문자 읽기
  • 패턴 선택
switch(ch){
  case 'a':  
           A부품 문자열 읽기;
           A부품 LED동작;
           break;
  case 'b':
           B부품 문자열 읽기;
           B부품 Servo Motor동작;
           break;
}

예를 들어, 두개의 부품 a,b 부품를 제어하는 명령인데 실제로 뭔가를 만들 때는 여러개 부품을 통신에을 통해 제어 할때는 여러개의 case를 만들면 되겠죠.

2개 부품을 읽을 때는 아래와 같이 2개의 case를 살펴봅시다.

  • "a13,1" or "a13,0" 읽기(A부품)
index_pin = inString.indexOf(',');     
index_state = inString.length(); 
pin = inString.substring(1, index_pin).toInt();     
state = inString.substring(index_pin+1,index_state).toInt(); 
  • "b90" 읽기(B부품)
index_servo = inString.length();   
angle = inString.substring(1, index_servo).toInt(); 
  • "a13,1" or "a13,0" 동작(A부품)
void LedOutput(int pin, int state){
  digitalWrite(pin, state);
}
  • "b90" 동작(B부품)
void ServoOutput(int angle){
  servo.write(angle);  
}

처리 동작을 보면 단순합니다. 실제는 좀 복잡한 제어 명령으로 출력함수를 코딩하겠죠.

종합해보면,

#include <Servo.h>

Servo servo;
const byte servoPin = 7;
const byte redPin = 13;
const byte greenPin = 11;
const byte bluePin = 9;

int index_pin, index_state;
int pin, state;
int index_servo, angle;


void setup()
{
  Serial.begin(9600); 
  pinMode(redPin,OUTPUT);
  pinMode(greenPin,OUTPUT);
  pinMode(bluePin,OUTPUT);
  
  servo.attach(servoPin); 
  servo.write(0);
  delay(1000);
}

void loop()
{  
  if(Serial.available()){
    String inString = Serial.readStringUntil('\n');    
    
    char ch = inString.charAt(0);
    
    switch(ch){
      case 'a':                 
                index_pin = inString.indexOf(',');     
                index_state = inString.length(); 
                pin = inString.substring(1, index_pin).toInt();     
                state = inString.substring(index_pin+1,index_state).toInt(); 
                LedOutput(pin,state);
                break;
      case 'b':
                index_servo = inString.length();   
                angle = inString.substring(1, index_servo).toInt();       
                ServoOutput(angle);
                break;                                
    }      
  } 
}

void LedOutput(int pin, int state){
  digitalWrite(pin, state);
}

void ServoOutput(int angle){
  servo.write(angle);  
} 

부품 2개를 시리얼통신을 통해서 제어해 보는 간단한 코딩입니다. 여러 부품을 제어할 때는 switch문을 이용하여 여러개의 패턴 문자열에 대한 처리 동작을 코딩을 표현하시면 다수의 부품을 제어할 수 있습니다.

위 코딩이 실제로 동작하는지 가상시뮬레이터로 돌려 볼까요.

3. 회로도


준비물 : LED 3개, 저항 220옴 3개, Servo Motor 1개, 아두이노우노
내용 : LED은 13, 11, 9번 핀에 연결하고 Servo Motor은 7번핀에 연결하시오.


LED핀은 12,11,10이렇게 하셔도 됩니다. 사실 회로도의 배선을 가상시뮬레이터에서 디자인할 때 최소화 하기 위해서 한칸씩 띄워서 연결햇네요.


4. 결과


LED와 Servo Motor에 대한 명령을 시리얼 통신을 통해 패턴 문자열을 아두이노에 보내고 그 명령들을 아두이노가 처리하는 과정을 간단히 테스트 했습니다.


마무리


오늘은 다수의 패턴 문자열을 만들고 각 문자열에 맞는 동작처리를 하는 방법을 살펴 보았습니다. 이 방법은 어디에다가 쓸까요. 가령, 다양한 부품들을 통신을 통해 한꺼번에 제어할 할때 유용합니다. 즉, 다양한 명령을 문자열로 아두이노로 전송을 하게 되면 각 문자열의 명령들을 아두이노가 식별하고 해당 부품의 동작 명령을 내릴 수 있습니다.

예를 들어, 아두이노가 웹서버에 연결되어 있다고 상상해 봅시다. 웹서버에서는 아두이노로 "A 모터를 돌려라!", "B 부품의 전원을 공급하라", "C 부품으로 온도를 측정하여 온도를 알려달라!" 등 다양한 명령을 내린다고 상상해 봅시다. 아두이노는 이런 다양한 명령을 어떻게 처리해야 할까요. 바로 오늘 소개한 방식으로 다양한 명령 패턴문자열로 보내오고 그 문자열을 위에서 코딩했던 방식으로 switch문을 통해서 분류하여 선택한다면 원하는 동작을 수행 할 수 있게 됩니다.

간단한 원리지만 활용도 면에서 꽤 유용하니깐 참고해 주세요.


댓글()

[아두이노] Serial 통신 때 String 사용

IOT/아두이노|2019. 5. 11. 09:00

[아두이노] Serial 통신 때 String 사용



오늘은 간단히 Serial 통신을 할 때 String으로 접근하는 방법을 알아보고자 합니다. 지금까지는 간단히 Sensor의 값을 Serial 통신을 통해 값을 전송할 때는 하나의 값만 주고 받아 왔습니다. 조이스틱에서는 두개의 x,y값을 만들어 내지만 이것 역시 간단히 하나씩 키 값으로 해서 전송해 왔는데 이제는 여러개의 값을 한번에 전송하고 그 값을 수신하는 쪽에서 분리해 내는 과정을 설명하면 좋을 것 같아서 오늘 Post 주제로 결정했습니다. 대부분 실험이 한개의 데이터만 Serial 통신에 주고 받기 때문에 필요 없을 수 도 있지만 한번은 접해 놓으셔야 나중에 필요하실 때 기억해 내서 활용 할 수 있으니깐 한번은 접해 보셨으면 합니다. 이제부터서 String에 대해 이야기를 하겠습니다.

1. Serial 통신 함수


[시리얼 통신]

  • Serial.begin(9600) : 시리얼 통신 시작(9600 통신속도)
  • Serial.println(값) : 시리얼모니터 출력
  • Serial.available() : 시리얼통신으로 데이터가 들어놨는지 상태 확인
  • Serial.read() : Int형으로 데이터를 읽음

[Bluetooth(SoftwareSerial 통신)]

#include <SoftwareSerial.h>
  • SoftwareSerial mySerial (rx, tx) : 소프트시리얼 객체선언(rx(수신), tx(전송))
  • mySerial.begin(9600) : 시리얼 통신 시작(예로 9600 통식속도를 사용해 봤네요.)
  • mySerial.println(값) : 데이터 전송
  • mySerial.read() : Int형으로 데이터를 읽음

[기본소스]

Serial 통신

void setup() {
  Serial.begin(9600);    //시리얼 통신 9600 통신속도로 시작
}
void loop() {
  
  if (Serial.available() > 0) { //데이터가 수신되는지 확인
    char ch = Serial.read(); //1byte 읽음
    Serial.println(ch); //1byte 읽은거 출력
  }
}

SoftwareSerial 통신

#include <SoftwareSerial.h>

const int rx = 2; //Bluetooth TX 핀
const int rx = 3; //Bluetooth RX 핀
SoftwareSerial mySerial (rx, tx) : 소프트시리얼 객체선언(rx(수신), tx(전송))

void setup() {
  mySerial.begin(9600);    //시리얼 통신 9600 통신속도로 시작
}
void loop() {
  
  if (mySerial.available() > 0) { //데이터가 수신되는지 확인
    char ch =mySerial.read(); //1byte 읽음
    mySerial.println(ch); //1byte 읽은거 출력
  }
}

기본 동작은 Serial.read() 함수로 1byte씩 읽어와 다시 시리얼모니터로 1byte을 출력하는 방법은 예전에 post로 설명을 했었습니다. 복습차원으로 다시 한번 살펴 봐 주세요. 그리고 Bluetooth의 SoftwareSerial 통신도 Serial에 mySerial로 작명한 Serial 객체변수명으로 접근하는데 기본 함수명과 동작은 동일합니다. Serial 통신을 할 수 있으면 SoftwareSerial로 Bluetooth 통신도 할 수 있겠죠.

복습이 끝났다면 본격적으로 사용할 String 대해서 살펴보도록 하죠.

2. String 함수



아두이노 공식 홈페이지에 가면 String 함수들이 나열 되어 있습니다. 링크된 곳에 가셔서 한번씩 테스트 해보셨으면 합니다.
오늘 post에 사용 할 몇개 String 함수에 대해서 살펴보도록 하겠습니다.

위 링크쪽을 가시면 Serial 통신 시 관련 함수들이 있습니다. 문자열을 Serial 통신을 통해 읽을때 readString(), readStringUntil() 두개의 함수가 있습니다. 둘 다 사용해도 되지만 readStringUntil()함수를 사용합니다.

 if(Serial.available()){
    String inString = Serial.readStringUntil('\n');
 }

문자열 변수 선언

  • String inString : 문자열 객체변수 선언

문자열 Serial 통신 읽기

  • Serial.readStringUntil('\n') : '\n' 문자를 만날때까지 문자열을 읽는 함수

문자열 공백 제거

  • String.trim() : 문자열변수안에 공백을 제거

문자열 분리에 사용할 함수

  • String.indexOf('찾을문자') : 문자열에 '찾을문자'가 있는 위치(index) 값을 반환
  • String.indexOf('찾을문자',시작위치) : 문자열의 시작위치에서 시작하고 '찾을문자'가 있는 위치(index) 값을 반환
  • String.substring(시작위치, 종료위치) : 시작~종료위치까지의 문자열을 반환한다. 전체 문자열에서 부분 문자열 추출.

3. 문자열 분리


String inString = "111,222";
int index1 = inString.indexOf(','); 
Serial.println(index1);   

결과 : 3


이렇게 하면 inString에 저장된 "111,222" 문자열에서 ','가 있는 위치값 '3'을 반환합니다. 위치는 0부터 시작하니깐 네번째인 3이 반환됩니다. 혼동하지 마세요. 여기서 ','를 기준으로 "111"과 "222"의 문자열을 분리해 낼려면 substring()함수를 사용하게 됩니다.

String inString = "111,222";
int index1 = inString.indexOf(','); 
int index2 = inString.length();
String inString1 = inString.substring(0, index1);
String inString2 = inString.substring(index1+1,index2);
Serial.println(inString1);   
Serial.println(inString2);   

결과 :
111
222

여기서, 문자열이 숫자면 숫자형으로 변환 시켜야 합니다. 그냥 사용 한다면 문자열이지 숫자형이 아닙니다. 문자열을 숫자형으로 변환 하기 위해서는 다음과 같은 함수를 사용해야 합니다.

  • String.toInt() : 문자열을 정수형으로 변환
String inString = "111,222";
int index1 = inString.indexOf(','); 
int index2 = inString.length();
int inString1 = inString.substring(0, index1).toInt();
int inString2 = inString.substring(index1+1,index2).toInt();
Serial.print(inString1);   
Serial.print('+');  
Serial.print(inString2);  
Serial.print('=');  
Serial.println(inString2+inString2);  

결과 : 111+222=333

int inString1 = inString.substring(0, index1).toInt();
자료형 변수 = 전체문자열.부분문자열추출.정수형변환;

inString의 문자열 "111,222" 값에서 substing(0,3)함수로 "111"문자열이 추출되고 이 값을 toInt()로 정수형으로 변환 합니다.

substring(from, to)함수의 혼동 주의를 하세요. substring(인자1, 인자2)에서 두 인자는 위치를 가리키지만 정확히 말하면 인자1과 인자2의 의미는 좀 다른 것 같습니다. 문자열이 0부터 시작한다고 했죠. 그러면, 시작 위치가 0부터 하셔야 첫번째 문자 '1'의 값을 가리키게 됩니다. 그런데 뒤에 콤마(,) 문자의 위치를 가리키면 위치값이 3이 됩니다. substring(0,3)의 문자열을 추출하게 됩니다. 이럴 때 3이니깐 4번째 콤마(,)까지 추출되어 나오는 거 아냐 하실 수 있는데 그 전 문자열 index(2)까지의 부분 문자열을 추출합니다. 간혹, 콤마(,)의 위치가 3이니깐 필요한 문자열이 "111"로 index(0~2)의 문자 3개가 필요하니깐 콤마(,) index 값에서 -1을 해서 부분문자열을 추출하려고 잘못된 코딩을 하실 수 있습니다. 처음에는 이런 문제로 시행착오를 거치실 수 있지만 금방 문제의 원인을 찾아서 수정하실 수 있을 꺼에요. 하지만, 실제 실험을 안하고 글을 읽고 상상코딩을 하신다면 이부분을 고려하시고 상상코딩을 하셔야 합니다.

substring(인자1, 인자2)함수가 좀 그렇더군요. 명확하게 인자2를 문자열의 정확한 추출위치 인자 index로 해 놓았다면 좋았을 것을 왜! 이런식으로 표현했는지 아쉬움이 남는 함수입니다. 마지막 널문자를 나타내기 위한 의도인지 아니면 뒤에 인자2는 몇번째 인지를 나타내는 숫자인지 참 모호한 인자인 것 같아요. 나중에 문자열을 좀 더 많은 데이터를 쪼갤때 혼동하실 수 있으니깐 잘 기억해 두세요.

예) String inString = "1,2,3,4,5";

콤마(,)인덱스는

int index1 = inString.indexOf(',');
int index2 = inString.indexOf(',',index1+1);
int index3 = inString.indexOf(',',index2+1);
...

이렇게 각 콤마(,) 문자의 위치를 얻고 이것을 분리해 낼때는
int inString1 = inString.substring(0, index1).toInt();
int inString2 = inString.substring(index1+1, index2).toInt();
int inString3 = inString.substring(index2+1, index3).toInt();
...
이렇게 해야하는데 인덱스 위치를 혼동해서 잘못 위치를 지정하게 될 수 있으니 주의하세요. 혼동을 피하기 위해서는 인자1은 배열 index 위치라고 생각하고 인자2은 문자열의 몇번째 위치라고 생각하시면 될 듯 싶네요. 이게 더 혼동이 될려나 모르겠군요.

indexOf(0,3) 이면 배열[0]에서 문자열 3번째 배열[2]까지의 부분 문자열을 추출한다. 이렇게 전 정리했네요. 아무튼 요상한 함수입니다. 이게 원래는 배열[0]~배열[3]까지 부분 문자열을 추출하는데 마지막 배열[3]은 문자열 끝을 나타내는 널문자가 들어가기 때문에 실제로 문자열 배열[0]~배열[2]까지의 글자가 출력되는지 모르겠지만요. 좀 혼동되는 함수이니깐 주의해서 코딩해 주세요.

이야기가 삼천포로 빠졌지만 계속 이야기를 이여 가겠습니다.

자이로센서와 같은 센서를 사용할 경우 값이 실수형으로 표현될 경우 문자열을 실수형 값으로 전송하게 된다면 다음과 같이 변경하시면 됩니다.

  • String.toFloat() : 문자열을 실수형으로 변환

예) String inString = "111.11,-222.22";

이와 같이 문자열이 주어졌다면

float inString1 = inString.substring(0, index1).toFloat();

결과 : 111.11

이렇게 문자열을 실수형으로 변환하고 그 값을 실수자료형 변수에 저장하게 됩니다.

4. Serial 통신으로 테스트



간단히, 시리얼 모니터로 두개의 실수형 데이터 x,y 값을 Serial 통신을 통해 문자열로 한번에 전송한다고 가정하고 이 두값을 구분하는 문자 콤마(,)로 구분자를 만들어 보낸다고 설정 했습니다. Serial 통신을 통해 문자열을 읽고 그 문자열을 다시 x,y값으로 분리해 내서 각 데이터를 실수형 변수에 저장하고 정상적으로 분리가 되었는지 시리얼모니터로 출력하는 소스입니다.

분리된 문자열이 실수형으로 정확히 변환이 되었는지 확인하기 위해서 간단히 두 실수값을 더한 값을 시리얼모니터로 출력하여 확인합니다.

[소스]

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

void loop()
{  
  if(Serial.available()){
    String inString = Serial.readStringUntil('\n');    
        
    int index_x = inString.indexOf(',');     
    int index_y = inString.length(); 
    float x = inString.substring(0, index_x).toFloat();     
    float y = inString.substring(index_x+1,index_y).toFloat(); 
 
    Serial.print(x);
    Serial.print('+');
    Serial.print(y);
    Serial.print('=');
    Serial.println(x+y);
  } 
}

[결과]


마무리


오늘은 간단히 Serial 통신으로 여러개의 데이터를 하나의 문자열로 보내지면 그 문자열을 다시 여러개의 데이터로 분리해내는 과정을 실험 하였네요.

이 원리는 다양한 데이터를 측정할 때 그 값을 한번에 전송하는데 사용하면 좋습니다. 예를 들어, MPU6050 자이로센서의 경우는 가속도 x,y,z 온도, 각속도 x,y,z 값으로 총 7개의 데이터를 측정하게 됩니다. 이것을 하나씩 개별적으로 보낸다면 불편하겠죠. 이 데이터 7개를 한번에 보내고 형식에 맞춰 분리하여 원하는 동작 제어를 한다면 편하게 제어 할 수 있게 됩니다.

하나씩 전송하게 되면은 데이터를 읽을 때 x값인지 y값인지 구분해서 읽는 코딩은 좀 복잡해집니다. 하지만 이렇게 문자열로 보내고 문자열로 읽고 해당 x, y값의 위치 문자열에서 분리해 내서 읽게 되면 좀 더 편하게 코딩을 할 수 있습니다. 사실 문자열 Serial 통신을 사용할 경우는 극히 드물지만 참고로 이런게 있다는 것만 알아만 두세요


댓글()

[아두이노] 조도센서 + Bluetooth 통신 제어

IOT/아두이노|2019. 4. 23. 09:00

[아두이노] 조도센서 + Bluetooth 통신 제어



오늘은 지난시간에 배운 Bluetooth를 이용하여 Servo Motor를 제어 해볼려고 했지만 스마트폰의 데이터를 아두이노로 읽었으면 그 반대로 보내는 실험을 하는 것이 더 좋을 것 같아서 반대로 보내는 실험을 해볼까 합니다. 조도센서에서히 조도 값을 아두이노에서 측정하여 Bluetooth을 이용하여 스마트폰으로 보내는 실험을 하겠습니다.


1. 조도센서



링크 된 곳은 예전에 포스트 한 내용입니다. 회로도를 공개 모드로 변경해서 올려 놨습니다. 포스트에서 두가지 타입이 있는데 아래 타입으로 조도 센서를 배치 했습니다.


2. Bluetooth 연결


링크 : [아두이노] Bluetooth 통신 제어



  • Bluetooth Rx -> Arduino txPin - pin3
  • Bluetooth TX -> Arduino rxPin - pin2

지난 시간에 설명했기 때문에 설명은 생략하겠습니다. 혹시, 기억이 안나면 위에 걸어 놓은 링크 주소로 가셔서 다시 살펴보시기 바랍니다.

3. 회로도 구성


  • 준비물 : - Bluetoooth HC-06 1개, 조도센서 1개, 저항 10k옴, 아두이노우노
  • 내용 : A0핀은 조도센서 입력핀으로 사용하고 2,3번 Bluetooth 통신핀으로 사용한다.


여기서, 제어를 담당하는 세개의 핀이 있는데 조도센서 입력 받을 핀과 Bluetooth rx, tx 핀만 정확히 연결하시면 됩니다.

4. 코딩


  • 내용 : 조도센서를 아두이노에서 측정한 데이터를 Bluetooth로 스마트폰에 보내고 그 결과를 출력하도록 하자.

SoftwareSerial 통신

#include <SoftwareSerial.h>
  • SoftwareSerial mySerial (rx, tx) : 소프트시리얼 객체선언(rx(수신), tx(전송))
  • mySerial.begin(9600) : 시리얼 통신 시작(예로 9600 통식속도를 사용해 봤네요.)
  • mySerial.println(값) : 데이터 전송

따로 코딩을 새로 만들지 않았습니다. 기존에 조도센서를 시리얼모니터로 출력 했던 소스를 그대로 bluetooth통신에 적용하겠습니다.

[조도센서+시리얼출력] : 조도센서 제어(아두이노)

int greenpin = 13;
int cdspin = A0;

void setup()
{
  Serial.begin(9600);
  pinMode(greenpin, OUTPUT);
}

void loop()
{
  int m_cds = map(analogRead(cdspin),0,1023,0,255);
  
  Serial.print("CDS =  ");
  Serial.println(m_cds);
  
  if(m_cds<100) { 
     digitalWrite(greenpin, HIGH);  
  }
  else {
      digitalWrite(greenpin, LOW);  
  }
  
}

위 소스에서 필요한 부분만 뽑아내면은

int cdspin = A0;
void setup()
{
    Serial.begin(9600);
}

void loop()
{
    int m_cds = map(analogRead(cdspin),0,1023,0,255);
 
    Serial.print("CDS =  ");
    Serial.println(m_cds);
}

이렇게 이 소스만 필요합니다. 여기서 Serial 개체변수명만 여러분이 선언한 블루투스객체명으로만 바꾸면 끝납니다.

수정을 하면.

#include <SoftwareSerial.h>

const int rxPin = 2;
const int txPin = 3;

SoftwareSerial mySerial(rxPin, txPin);

int cdspin = A0;

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

void loop()
{
  int m_cds = map(analogRead(cdspin),0,1023,0,255);
  
  mySerial.print("CDS =  ");
  mySerial.println(m_cds);  
  delay(1000);
}

이렇게 수정이 완료 되었네요. Serial 이름을 블루투스 통신에 사용할 객체명 mySerial로 "my"라는 단어가 앞에 추가되고 변경된 부분은 없네요.

간단하게 코딩을 완료 했습니다. 어렵게 생각하시지 마시고 평소 시리얼 모니터로 출력하는 식으로 코딩을 표현하시면 됩니다.

5. Bluetooth 통신을 하기 위한 세팅


지난 시간에는 "Controller mode"에서 실험 했다면 오늘은 "Terminal mode"에서 실험하시면 됩니다. 실행하시면 자동으로 아두이노에서 조도값을 측정하면 그 값을 바로 스마트폰으로 출력이 되어 나옵니다. "Terminal mode"에서는 스마트폰에서 데이터를 아두이노로 보낼 수 있고 아두이노에서 읽어온 데이터를 바로 출력해주는 모드입니다. 채팅모드라고 생각하시면 됩니다.

6. 결과


아래 동영상은 실행 과정을 PC에서 녹화한 장면입니다.


마무리


원래는 앱인벤터로 직접 만들어서 자신이 원하는 스타일로 앱을 만드는게 가장 좋습니다. 이미 만들어진 앱들이 구글스토어에 많지만 여러분들이 원하는 기능으로 딱 맞게 세팅 되어 있지 않습니다. 오늘 실험은 단순히 출력 데이터를 수치 상으로 보여 주기만 하면 되기 때문에 구글스토어에 등록된 앱을 사용했지만 그래프와 같은 시각적 표현을 하시고 싶다면 직접 블루투스 앱을 만드셔야 합니다.

혹시 스마트폰과 특정 센서를 연동한 뭔가를 제작 싶다면 앱인벤터를 구글에서 검색하시면 강좌가 많기 때문에 한번 제대로 공부해 보셨으면 해요.

블루투스는 사용범위가 넓기 때문에 상상를 어떻게 하냐에 따라 재밌는 작품들을 많이 만드실 수 있을거에요. 실제로 어떤 분은 자외선 센서를 이용했는데 소형으로 만들어서 스마트폰과 연동하여 실시간으로 자외선 관련 데이터 모니터링하면서 서버와 연동해서 자외선 정보를 알려주는 어플을 만드신 분도 있으시더군요. 이처럼 스마트폰과 연동하면 재밌는 것들을 만들 수 잇습니다.

여러분들도 상상력을 발휘해 보세요.


댓글()

[아두이노] Bluetooth 통신 제어

IOT/아두이노|2019. 4. 22. 09:00

[아두이노] Bluetooth 통신 제어



오늘은 Bluetooth 통신을 주제로 이야기를 할가 합니다. 원래는 나중에 할 예정이였는데 Servo Motor를 조이스틱으로 제어하고 스위치 버턴으로 제어하는 포스프를 쓰다 보니깐 나중에 Bluetooth를 포스트하고 응용 예제로 LED나 Servo Motor를 복습차원을 포스팅을 할 것 같아서 이참에 한번에 해버리는게 좋을 것 같아서 오늘의 포스트 주제로 선정했네요. 이제 본격적으로 Bluetooth 통신으로 들어 가겠습니다.


1. Bluetooth HC-06 모듈



  • Rx - 데이터 읽기
  • Tx - 데이터 보내기

두 개의 Rx, Tx만 무슨 핀인지만 아시면 됩니다. 두 핀만 잘 아두이노에 연결하면 무선 통신을 할 수 있게 됩니다.

하지만 이 Bluetooth HC-06 모듈을 아두이노에 연결할 때 잘 생각하고 연결하셔야 합니다. 물론 아무 핀에다 연결해도 상관은 없습니다만 아두이노에 연결 했을 때 해당 핀이 어떤 핀인지에 대한 정의를 머리속에서 내리셔야 합니다.

다음 회로도에서 설명하겠지만 Bluetooth Rx핀은 아두이노에서 사용 할 Tx핀에 연결해야 하고 Bluetooth Tx핀은 아두이노에서 사용 할 Rx핀에 연결해야 합니다. 이 부분만 주의하시면 됩니다. 즉, 아두이노가 보내는 데이터 핀은 아두이노 자체니깐 Tx핀이겠죠. 그게 Bluetooth가 읽으니간 Rx에 연결하는 것이고 Bluetooth가 보내는 데이터는 Bluetooth의 Tx핀에서 나와서 아두이노가 그 데이터를 읽기 위해서는 아두이노의 Rx핀에서 읽어들이겠죠. 이렇게 생각하시면 될 듯 싶네요.

2. 회로도 구성


  • 준비물 : - Bluetoooth HC-06 1개, 아두이노우노
  • 내용 : 0,1핀을 제외한 아무핀에다 연결하시오.

0,1 은 아두이노 자체 시리얼통신 핀입니다. 이곳에 Bluetooth를 연결해도 되긴 하는데 처음에 따로 연결해 주세요.


Bluetooth Tx 핀은 아두이노의 Rx 2번핀에 연결하고 Bluetooth Rx 은 아두이노의 Tx 3번핀에 연결합니다. 왜 이렇게 복잡하게 말하냐면 나중에 SoftwareSerial 라이브러리를 통해서 통신을 할 때 통신 함수의 인자 변수명을 일치시키기 위해서 입니다.

SoftwareSerial::SoftwareSerial(uint8_t rxPin, uint8_t txPin, bool inverse_logic)
  • SoftwareSerial(rxPin, txPin) : 시리얼통신 핀을 세팅합니다.

여기서 인자값은 bluetooth의 Tx=rxPin, Rx=txPin으로 넘겨지기 때문입니다.

const int rxPin = 2;
const int txPin = 3;

SoftwareSerial mySerial(rxPin, txPin);
  • Bluetooth Rx -> Arduino txPin
  • Bluetooth TX -> Arduino rxPin

대충 변수명은 SoftwareSerial 생성자 함수의 인자 명하고 일치 시켜 유사한 이름을 써주세요.

간혹 Bluetooth 이름으로 짓는 경우가 많은데 그러면 혼동이 생길 수 있습니다.

int BT_TX = 2;
int BT_RX = 3;

이럴때

SoftwareSerial mySerial(BT_TX, BT_RX);

이렇게 이름을 짓는 경우가 많습니다. Bluetooth 관점으로 핀이름을 만들다 보니 이렇게 되죠. 엄밀히 말하면 생성자 함수의 인자 네임음 (rx, tx)입니다. 그런데 들어가는 값이 블루투스의 (tx, rx)다고 해서 이렇게 이름 만들면 혼동할 수 있습니다. 될 수 있으면 함수 인자의 네임을 일치시켜 주세요.

3. 코딩


  • 내용 : 스마트폰 연결 Bluetooth를 연결하여 간단히 스마트폰에서 입력한 값을 아두이노에서 읽고 아두이노 IDE 시리얼모니터로 읽은 값을 출력을 해보자.

함수

  • Serial.begin(9600) : 시리얼통신 시작
  • Serial.write(출력값) : 시리얼모니터로 출력

SoftwareSerial 통신

#include <SoftwareSerial.h>
  • SoftwareSerial mySerial (rx, tx) : 소프트시리얼 객체선언(rx(수신), tx(전송))
  • mySerial.begin(9600) : 시리얼 통신 시작(예로 9600 통식속도를 사용해 봤네요.)
  • mySerial.write(값) : 데이터 전송
  • mySerial.available() : 데이터 들어왔는 확인
  • mySerial.read() : 전송된 데이터 1byte 읽기

SoftwareSerial 라이브러리에서 제공되는 기본 예제로 테스트




해당 소스에서 2,3핀을 시리얼통신 핀으로 사용 했습니다. 그리고 전송속도는 9600으로 둘 다 해버렸네요.

  • 전송 속도 : 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 31250, 38400, 57600, 115200
    다른 속도로 하셔도 됩니다.

[기본 소스] : 이 코딩은 위 아두이노공식홈페이지에 있는 기본 예제를 기반으로 약간만 수정한 소스입니다. 제가 만든게 아니라 위 아두이노 공식홈페이지에서 제공되는 오픈 예제 소스입니다.

#include <SoftwareSerial.h>

const int rxPin = 2;
const int txPin = 3;

SoftwareSerial mySerial(rxPin, txPin); // RX, TX

void setup()  
{
  Serial.begin(9600);
  while (!Serial) {
    ; 
  }
  Serial.println("Bluetooth Start!");
  mySerial.begin(9600);  
}

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

딱히, 어려운 건 없습니다. 링크 예제를 안하더라도 대부분 Bluetooth 샘풀 테스트를 하면 위 소스와 비슷한 방식으로 다들 실험을 합니다.

(1) SoftwareSerial 헤더파일 연결
(2) SoftwareSerial 객체변수 선언
(3) 객체변수.begin(전송속도)
(4) if(객체변수.available()) { byte ch = 객체변수.read(); }
(5) Serial.write(ch);

누가 실험을 하든 이게 젤 처음 다들 하는 Bluetooth 실험 소스입니다. 그냥 자연스럽게 이렇게 코딩하게 됩니다.

여기서 loop()문은 통신을 수행하는 문장입니다.

예전에 시리얼 통신을 할 때 시리얼모니터에서 데이터를 입력하면
if (Serial.available()) {
byte ch = Serial.read();
}

이렇게 읽었습니다. 시리얼 모티터로 출력 한다면
Serial.write(출력값); 
이렇게 사용했습니다. 블루투스 통신에서도 이와 같습니다. 

if (mySerial.available()){
    Serial.write(mySerial.read()); 
}

블루투스를 통해 들어온 데이터를 시리얼모니터로 출력하는 문장입니다. 이것과 반대로 시리얼모니터로 입력한 데이터를 블루투스로 반대로 보내는 동작은 다음과 같습니다.

  if (Serial.available()) {
        mySerial.write(Serial.read()); 
    }

이전에 시리얼 통신을 해왔던 방식 그대로 표현 하시면 됩니다. 단지 블루투스를 SoftwareSerial 라이브러리를 이용하기 때문에 따로 SoftwareSerial 의 객체 변수를 선언해주고 그 객체명으로 시리얼통신함수를 사용하시면 됩니다.

간단히 정리하자면 평소 Serial 통신에서 시리얼모니터에 아두이노의 결과물을 출력했던 방식으로 동일하게 Bluetooth도 동일한 방식으로 푠현한다고 생각하시면 됩니다.

4. Bluetooth 통신을 하기 위한 세팅


1) 스마트폰에서 Bluetooth 등록


위 그림 처럼 HC-06의 이름을 가진 Blutooth가 잡힙니다. 등록하기 위해서는 비번을 쳐야 하는데 초기 비번은 "0000", "1234" 둘 중 하나로 초기 비번으로 설정 되어 있습니다. 둘 중 하나니깐 두 개 다 입력해서 잡히면 그걸로 등록하시면 됩니다. 참고로 AT 명령어로 비번을 변경할 수 있습니다.

2) 스마트 폰 Bluetooth 통신 앱 설치

전 느낌 오는 걸로 구글스토어에서 블루투스 컨트롤을 쳐서 아래 그림의 어플을 설치했네요. 결과만 보기 위해서 대충 선택했네요. 다른 것들도 많으니간 편한 걸로 설치 하시면 됩니다.


혹시, 직접 만드시고자 하시는 분들은 웹인벤터에서 앱을 만들 수 있습니다. 스크래치 방식으로 블록으로 배치하여 직접 만들 수 있는데 구글 검색 키워드로 "bluetooth 앱인벤터"로 치시면 동영상하고 블로그 게시물이 엄청 많습니다. 유튜브에서 검색하셔도 됩니다. 동영상을 보고 따라 만드시면 나중에 자신이 원하는 스타일로 개조 할 수 있습니다.

3)실행



Bluetooth를 잡아놓은 상태어서 HC-06으로 제가 현재 쓰는 Bluetooth 모듈 명이 검색 되어 있네요. 초기 이름울 AT명령으로 Bluetooth 이름을 변경 할 수 있습니다. 그냥 초기 이름을 그대로 사용합니다. 클릭을 하면 옆 그림처럼 선택 목록이 있는데 젤 위의 Controller mode를 누르면 다음과 같이 조종기가 나옵니다.



오른쪽 상단에 톱니모양을 누르면 환경 설정을 할 수 있습니다.


간단히 방향버턴을 1,2,3,4 로 세팅했네요.

이제 아두이노 IDE를 열고 결과를 테스트 하면 됩니다.

5. 결과



스마트폰에서 방향 스위치를 누르면 아두이노에 연결된 Bluetooth가 방향 스위치 값을 읽고 그 값을 아두이노에서 PC에 연결된 아두이노 IDE 시리얼모니터로 결과가 출력된다.

아래 실험 영상 녹화는 데스크탑 PC에서 녹화한 영상입니다. PC에서 스마트폰을 원격접속하여 스마트폰을 PC에서 볼 수 있게 하였고, 아두이노는 라즈베리파이에 연결되어 작동하고 라즈베리파이에 설치된 아두이노 IDE 의 시리얼모니터로 Bluetooth에서 들어온 데이터를 출력하도록 해놓았습니다. 참고로 라즈베리파이도 데스크탑 PC에서 원격 접속을 하였습니다. 결론은 녹화를 하기 위해서 PC가 스마트폰과 라즈베리파이를 동시에 원격접속하여 PC 모니터에 띄워서 둘을 동시에 조정하여 그 결과를 녹화한 영상물입니다.


위 그림처럼 스마트폰과 라즈베리파이를 원격 접속하여 창을 띄운 화면입니다. 참 번거롭게 녹화을 했네요. 스마트폰으로 찍자니 그러면 Bluetooth 어플 조정을 못하니깐 어쩔 수 없이 원격 접속하여 PC로 녹화를 하게 되었습니다.


아 'Start' 단어에 오타가 다시 녹화 하기 귀찮아서 그냥 올립니다. 참고로 영상에서 처음 실행이 되면 "AT"라는 단어를 쳐보세요 그리고 보내면 "OK"라는 단어로 리턴된 값이 시리얼모니터로 출력됩니다. 이 말은 Bluetooth가 정상적으로 동작한다는 의미가 되겠습니다.

6. AT 명령어



구글 검색하시면 레퍼런스가 많습니다. 제가 봤던 사이트 레퍼런스인데 명령어들을 잘 살펴보시면 됩니다.

Bluetooth 설정된 값을 변경할 수 있는 명령어입니다. 현재 Bluetooth 버전, 이름, 비번, 전속속도, Master와 Slave 설정 등을 할 수 있습니다. 참고로 버전이 낮을 경우 Master와 Slave은 고정되어 있는데 구매하실 때 자신이 쓰는 모델이 고정인지 겸용인지를 꼭 확인하세요.

  • AT : "OK" 메세지가 나오면 Bluetooth 정상
  • AT+VERSION : 현재 Bluetooth 사양 정보
  • AT+NAMEaaa 이름(aaa)
  • AT+PIN1234 비번(1234)
  • AT+BAUE1 전송속도(1200) 1~9,A,B,C(레퍼런스참조)

이름과 비번만 바꿔주시고 사용하시면 돼요. 추가적으로 레퍼런스를 읽어보시기 바랍니다.

마무리


if (mySerial.available()) Serial.write(mySerial.read()); 

이 한줄의 명령을 수행하기 위해서 엄청 글을 썼네요. 이 한줄이 오늘 동작하는 명령의 전부입니다. 이걸 하기 위해서 세팅하는 과정이 꽤 길었네요.

지금까지 Serial 통신으로 시리얼모니터로 결과를 출력했던 방식으로 Serial 대신에 여러분들이 작명한 이름으로 변경만 하면 통신을 할 수 있게 됩니다.

마지막으로 방향 버턴을 1,2,3,4 로 값을 세팅했잖아요. 그 값을 기준으로 Servo 머턴을 제어를 코딩해 보세요. 어제 스위치 버턴으로 Servo Motor를 제어 했는데 그 소스랑 오늘 통신 소스를 합쳐서 코딩해보시면 아마도 쉽게 코딩을 할 수 있을 거라 생각됩니다.

이걸 또 내일 포스팅하기 그러니깐요 이 부분은 여러분들이 Servo Motor를 제어하는 하는 걸로 마무리 할까 합니다.

나중에 다른 주제에 오늘 사용한 Bluetooth를 활용하는 것을 포스트 하겠습니다.


댓글()

[아두이노] 아두이노 끼리 통신하기

IOT/아두이노|2019. 3. 17. 09:00

[아두이노] 아두이노 끼리 통신하기



시리얼통신에서 블루투스 실험을 하면 좋은데 가상 시뮬레이터에서 블루투스를 제공하지 않아서 그 대안으로 2대의 아두이노를 연결해서 시리얼통신하는 실험을 갖도록 하겠습니다. 지난시간에 배웠던 시리얼통신을 이용하여 한쪽에서는 명령을 내리고 한쪽에서 시리얼통신으로 통해서 받은 명령을 실행하는 동작을 간단하게 어떤식으로 수행되는지 진행해 보겠습니다.

1. SoftwareSerial 라이브러리


아두이노는 내장된 0,1번 핀이 시리얼 통신핀입니다. SoftwareSerial는 소프트웨어를 사용하여 아두이노의 다른 디지털 핀에서 직렬 통신을 허용하게 하기 위해서 개발된 라이브러리 입니다.

#include <SoftwareSerial.h>

  • SoftwareSerial mySerial (rx, tx) : 소프트시리얼 객체선언(rx(수신), tx(전송))
  • mySerial.begin(2400) : 시리얼 통신 시작(예로 2400 통식속도를 사용해 봤네요.)
  • mySerial.write(값) : 데이터 전송
  • mySerial.available() : 데이터 들어왔는 확인
  • mySerial.read() : 전송된 데이터 1byte 읽기

시리얼통신 함수와 별다를 게 없죠. 단지 객체변수로 선언할대 rx, tx 핀번호를 지정해 줘야 한다는 것 외에는 다 동일합니다. 시리얼통신에서 배웠던 함수들임으로 별로 어렵지 않을꺼에요.

2. 회로도 구성


  • 준비물 : Red LED 1개, 저항 220옴 1개, 아두이노우노 2개
  • 내용 : Red LED 깜박이는 기본 예제 회로도


2대의 아두이노를 보면 10, 11번의 두개의 핀을 시리얼 통신용으로 사용 됩니다. 아두이노의 전용 시리얼통신핀은 0, 1번핀입니다. 이 핀을 사용할 수는 있지만 사용을 안하는 걸 추천 드려요. 나중에 블루투스 통신에서 0,1핀을 사용하기는 하지만 여기에서는 아두이노 IDE 시리얼모니터를 사용하기 때문에 이쪽 0,1 핀을 제외한 다른 핀을 시리얼통신으로 사용할려고 10, 11번 핀을 임의로 지정했습니다.

3. 코딩


[ 시리얼통신 기본예제 소스 ]

void setup() {
  Serial.begin(9600);    //시리얼 통신 9600 통신속도로 시작
}
void loop() {
  
  if (Serial.available() > 0) { //데이터가 수신되는지 확인
    char ch = Serial.read(); //1byte 읽음
    Serial.println(ch); //1byte 읽은거 출력
  }
}

[ LED 기본예제 소스(1초 단위로 LED 깜박이기) ]

void setup() {
    pinMode(13, OUTPUT);
}

void loop() {
    digitalWrite(13, HIGH);
    delay(1000);
    digitalWrite(13, LOW);
    delay(1000); 
}

위 기본예제를 2번 아두이노에 합쳐서 동작하게 되는데 1번 아두이노의 명령에 의해서 깜박이게 코딩하도록 하죠.

시리얼통신에 사용되는 라이브러리는 SoftwareSerial 라이브러리입니다. SoftwareSerial 클래스을 이용하여 2대의 아두이노의 통신을 하게 됩니다.

전제척으로 코딩을 하면

[ 1번 아두이노 ]

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10,11); //시리얼통신 핀

void setup()
{
    mySerial.begin(2400); //기존 9600이여서 다른 통신속도를 사용해야함
}

void loop()
{
  mySerial.write('1'); // 2번 아두이노에 '1'값 전송
  delay(1000);
  
  mySerial.write('0');  // 2번 아두이노에 '1'값 전송
  delay(1000);
}

간단하죠. SoftwareSerial를 인쿠루드 시키고 SoftwareSerial 객체변수를 선언할대 아두이노에서 사용될 디지털 핀을 10, 11번으로 지정했습니다. 그리고 나서 따로 할 것은 없고. write()함수 명령어로 값을 2번 아두이노에 보내는 명령 코드가 되겠습니다.


[ 2번 아두이노 ]

#include <SoftwareSerial.h>
SoftwareSerial mySerial(10,11);

char state;
int rPin=13;

void setup()
{
  Serial.begin(9600);
  mySerial.begin(2400);
  pinMode(rPin, OUTPUT);
}

void loop()
{ 
  if(mySerial.available() > 0) { //수신되었는지 상태 확인
    state = mySerial.read(); //수신된 데이터를 1byte 읽어와서 state 변수에 저장함
    
    if(state=='1') digitalWrite(rPin, HIGH); //읽어온 값이 '1'이면 참으로 Red에 HIGH로 불이 들어옴
    else digitalWrite(rPin, LOW); //'0'이면 1이 아니기 때문에 거짓으로 Red에 LOW로 불이 꺼짐
    
    Serial.println(state);  //정상적으로 읽은 값이 들어왔는지 아두이노 IDE 시리얼모니터로 출력
  }
  
}

2번 아두이노는 좀 코딩이 긴 편입니다. 정상적으로 값을 가져왔는지 아두이노 IDE 시리얼모니터로 그 값을 찍어봐야 하기 때문에

 Serial.begin(9600);
 erial.println(state);

이 두문장으로 아두이노 IDE로 state 값을 전송하게 됩니다. 여기서 state 값은 1번 아두이노에서 보내진 데이터를 수신한 값이 되겠습니다.

1번 아두이노에서 데이터를 수신하여 state 변수에 저장되는데 그 로직은 시리얼통신에서 기본적으로 사용하는 시리얼통신으로 데이터가 들어왔을때 그 값을 읽는 로직은 아래와 같습니다. 이건 왠만하면 계속 사용하기 때문에 숙지해 주세요.

  if(mySerial.available() > 0) {
        state = mySerial.read();
    }

if 조건문으로 '1'이면 불이 들어오고 '0'이면 불이 꺼진다는 조건을 만든다.

if(state=='1') 불켜!
else 불꺼;

간단하지요.

4. 결과


오른쪽 아두이노가 SoftwareSerial 을 사용하여 왼쪽 아두이노에게 '1'과 '0'의 값을 전달하고 왼쪽 아두이노도 전송된 값을 읽어서 Red LED가 깜박이게 동작을 수행하게 하는 사진입니다.


마무리


시리얼통신과 차이가 없습니다. 단지 SoftwareSerial 라이브러리를 이용하여 소프트웨어적으로 제어 했다는 것만 다를 뿐이죠.
실험에서는 코드를 따로 어떻게 가상시뮬레이터에서 하냐고 생각 하실 수 있습니다. 그냥 코딩창을 띄워놓은 상태에서 해당 아두이노를 클릭하면 해당 아두이노의 코딩창으로 바뀌게 됩니다. 그리고 해당 아두이노 코딩에 맞게 개별적으로 시뮬레이션이 되니간 쉽게 생각하세요.


그리고 이 그림처럼 직접 마우스로 해당 아두이노를 선택하시면 됩니다. 참고로 이 소스를 기반으로 블루투스를 실제 가지고 있는 분이라서 블루투스 통신 코드로 활용하셔도 됩니다.

마지막으로, 이걸로 뭘 할 수 있을지 한번 상상의 나래를 펼쳐보세요.

댓글()

[아두이노] Serial 통신 제어

IOT/아두이노|2019. 3. 13. 09:00

[아두이노] Serial 통신 제어



원래 시리얼 통신은 초반부에 자세히 소개 했어야 했는데 프로세싱+아두이노 연결을 하면서 그냥 넘어가면 안될 것 같아서 이제서야 소개하게 되었네요. 센서 부품를 다룰때 그 결과를 출력하는데 많이 사용하기 때문에 매우 중요합니다. 나중에 블루투스 통신에서도 사용하니깐 위에 참고출처를 링크한 아두이노 홈페이지의 레퍼런스를 잘 살펴보시기 바래요. 오늘은 시리얼통신 기본만 소개하겠습니다.

1. Serial 통신



그림에서 보듯이 아두이노 IDE 시리얼모니터에서 아두이노로 "123"이란 값을 보내게 됩니다. 그리고 나서 아두이노는 이 값을 읽어서 다시 아두이노 IDE로 데이터를 보내고 시리얼모니터로 그 값을 출력합니다.

[ 기본 소스 ]

void setup() {
  Serial.begin(9600);    //시리얼 통신 9600 통신속도로 시작
}
void loop() {
  
  if (Serial.available() > 0) { //데이터가 수신되는지 확인
    char ch = Serial.read(); //1byte 읽음
    Serial.println(ch); //1byte 읽은거 출력
  }
}

기본 소스의 주석을 다 달았습니다. 주석만 읽으시면 대충 어떻게 통신이 이루어지는 아시겠지요.

위 이미지에서 123을 보내면 아두이노에서 1, 2, 3 이렇게 하나씩 아두이노 IDE에 출력되는 이유가 과연 뭘까요. 이것은 123을 전송했는데 byte 단위로 읽고 char(문자형) 변수 ch에 1byte 문자가 저장되는데 "123" 값에서 순차적으로 '1','2','3'을 저장하고 순자척으로 Serial.println('1'), Serial.println('2'), Serial.println('3') 이렇게 출력하게 됩니다.
이걸 정수형으로 받으면

2. 시리얼 통신 함수


기본

  • Serial.begin(통신속도) : 시리얼통신 시작. 기본통신속도는 9600을 많이 사용합니다.
    많은 아두이노 시리얼통신에서 9600을 사용합니다.
    통신속도 : 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200
  • Serial.end() : 시리얼통신 중단
  • Serial.available() : 데이터 도착했는지 확인
  • Serial.println(데이터) : 데이터를 상대쪽으로 전송(출력)
  • while(!Serial) : 통신 연결 확인(연결 안되면 무한 루프를 돌면서 연결을 기다림)

위 함수중에서 abailable()함수만 좀 더 살펴보도록 하죠.

예제)


데이터가 들어왔는지 상태값을 확인하는게 available()함수라고 했죠. 그러면 정확히 어떤값이 들어있는지 시리얼 모니터에 출력을 해봤습니다. 'a'라는 문자를 보내면 아두이노는 available()함수에 수신이 되면 수신되었다고 1의 상태값을 갖게 됩니다. 그러면 if문이 참이고 첫라인에서 출력이 '1'이 나오게 됩니다. 그다음 read()함수로 데이터를 읽고 정상적으로 시리얼모니터로 'a'가 두번째라인에 출력 됩니다. 그러면 데이터를 read()함수로 읽었다면 다음 available()함수의 상태값은 데이터를 읽었기 때문에 지워지고 상태값은 '0'이 됩니다 즉, read()으로 읽고 나면은 abailable()은 초기화 상태가 되는 것이죠. 그래서 세번째 라인이 0이 출력 됩니다.
쉽게 말해서, 데이터가 전송되면 available() 함수는 '1'의 상태가 되고 데이터를 읽고나면 '0'의 상태가 됩니다. 아래 그림을 보시면 좀 더 쉽게 이해가 되시겠지요.


begin(), available(), read(), print(), println() 정도만 우선 알아두시고 아래에서 소개하는 함수들 읽기와 출력에 대해 몇가지 소개만 하고 나머지는 레퍼런스를 참고해 주세요. 나중에 센서값을 어떻게 읽고 어떻게 출력할지 그 센서에 따라서 표현이 좀 달라지니깐요 레퍼런스를 꼭 봐주셔야 해요. 가상시뮬레이터에서는 위 5가지 함수만 기본 베이스로 이해하시고 사용하시면 쉽게 실험하실 수 있을꺼에요.


읽기

  • Serial.read() : 1byte 읽음
  • Serial.readBytes(buffer, length) : buffer에 length 길이만큼 읽음
  • Serial.readBytesUntil(character, buffer, length) : buffer에 length 길이만큼 읽어오는데 character가 끝문자 표시로 이문자가 있는 곳까지 읽어오게 됨.
    예) Serial.readBytesUntil('s', buffer, 10)일때 전송데이터 "100s1000"이면 buffer "100"이 첨에 저장되고 다음에 "1000"이 저장됨.
  • Serial.parseInt() : 정수형으로 읽기
  • Serial.parseFloat() : 실수형으로 읽기

출력

  • print(값) : 데이터를 출력하고 현재 라인에 커서가 그대로 유지됨.
  • println(값) : 데이터를 출력하고 새로운 라인으로 커서가 이동함.(Enter로 생각하시면됨)

주의 :

  • print(값) : 데이터를 아스키코드값 바꿔서 전송.
  • wirte(값) : 데이터를 그대로 전송.


위 그림에서 보는 것 처럼 print()함수는 '7'이란 값을 전송할때 '55'라는 아스키코드값으로 전송하고 그 값이 출력되는 걸 보실꺼에요. 하지만 write()함수는 '7'을 그래도 전송하고 받는쪽에서는 '7'을 아스키코드값으로 여기고 출력된다는 차이점을 보입니다. 둘 차이를 잘 비교하세요.


마무리


그외도 여러 함수들이 있는데 오늘 소개한 함수들도 몇개를 제외하고는 잘 사용하지 않습니다. 가상시뮬레이터에서는 그냥 단순하게 read(), print(), println()정도로 데이터를 읽거나 쓰는 정도만 합니다.

- if(Serial.available()) {  }
- while(!Serial){  }
- Serial.read()
- Serial.print()
- Serial.println()

이정도 함수만 외워두시면 기본적인 통신을 할 수 있습니다. 나중에 센서를 이용한 특정값이나 부품을 제어하는 통신을 할 경우에는 레퍼런스를 살펴 보셔야 겠지만 우선은 시리얼통신이 어떻게 이루어지는지만 살펴보세요.

댓글()