n:m 아두이노 간 I2C 통신(아두이노)

in #kr-arduino6 years ago

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 통신을 이용하는데 여러대의 아두이노가 있을 때 여러가 상황을 만들고 각 상황에 대해서 어떤식으로 통신을 할 것인지 상상의 나래를 펼쳐 보셨으면 합니다.

Sort:  

날이 너무 덥습니다......덥다 ㅠ

일기예보는 계속 비온다는 소식이 있는데 비는 안오고 불쾌지수만 커지네요.
비나 쏴! 하고 내렸으면 하네요. ^^

안녕하세요 짱짱맨홍보요원 마이입니다.
출석부에 출첵하시고 좋은이웃들 많이 만드세요~

네! 알겠습니다. ^^

무슨일을 하시는지 궁금합니다.

아두이노는 그냥 재미로 즐겨요.
상황을 만들고 그걸 코딩화 하면서 매일 저녁에 실험하네요.

pairplay 가 kr-dev 컨텐츠를 응원합니다! :)

dev 컨텐츠 응원에 감사합니다.

Coin Marketplace

STEEM 0.25
TRX 0.11
JST 0.032
BTC 63517.53
ETH 3062.83
USDT 1.00
SBD 3.81