1:N 아두이노 간 I2C 통신(아두이노)

in #kr-arduino7 years ago

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로 다시 이야기를 하게 되었습니다.

Sort:  

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

어제는 소나기가 내려서 잠깐 시원했는데 오늘은 다시 후덥지근 하네요.

약간 스파업했습니다. 미약합니다 ^^

good21님은 요새 글을 안쓰시네요.
많이 바쁘신가 보네요.

@resteemator is a new bot casting votes for its followers. Follow @resteemator and vote this comment to increase your chance to be voted in the future!

속도도 빠르고 쓰임새가 많은 통신 방식같습니다.

여러 대 아두이노를 연결하면 delay()함수에 고민 할 필요 없이 분산 처리가 가능해서 활용도가 높을 것 같아요. A아두이노 A동작만 B아두이노는 B동작만 수행하면 되니깐 개별 처리가 쉬워질 듯 싶네요.

1:1이랑 1:N이랑 뭐가 달라지는 거죠? ㅇ_ㅇ 궁금합니다.

앞에 1은 마스터 아두이노고요 뒤에 N은 슬레이브 아두이노로 다수의 아두이노나 I2C 통신을 하는 LCD 같은 다양한 부품들을 지칭 하지요.
서로 통신하는 형태를 말한다고 생각하시면 될 듯 싶네요.
즉, 마스터가 다수의 슬레이브와의 통신으로 이해하시면 될 듯 싶네요.

대충 위그림과 같은 느낌이라고 이해하시면 될 듯 싶네요.

예. 이거는 이해가 가는데요. 예를 들면 충돌이라든가 그런 거는 문제가 없는지 궁금합니다.

1:n의 경우는 순차적으로 데이터를 전송하고 데이터 요청도 순차적으로 하기 때문에 post 실험에서는 충돌이 발생하지 않네요.
참고로 n:m 의 경우는 마스터 아두이노를 경유하지 않고 슬레이브 간에도 통신을 하게 되면은 충돌이 발생하게 되네요. 같은 시간대에 데이터를 요청과 전송이 발생할 때에는 문제가 생기더군요.
그래서 이 post 말고 다음 post에서는 딜레이 시간대를 다르게 해서 일종의 시분할 스케줄링을 혹시 아시죠. 시분할 스케줄링으로 직접 짜면 좋은데 그건 좀 단시간에 힘들고요 느낌만 좀 유사하게 시간대를 다르게 해서 충돌을 회피했네요. 그런데 마스터 아두이노를 경유하면 마스터 아두이노에서 순차적으로 처리하면 충돌은 발생하지 않네요.
이부분은 운영체제에서 배운 CPU 스케줄링을 기법을 이용해서 코딩해야하는 숙제가 남네요.

오호. 저도 단순하게 생각해보니깐 여러개 보내면 충돌 날텐데 어떻게 하는거지? 하는 생각이 들었는데. 1군데서 보내면 당연히 시분할로 보낼 수 있게 되는군요. n:m일 때가 문제군요. ㅇ_ㅇ 음... 그 부분은 저도 좀 더 공부해보고 싶네요. 덕분에 아주 재밌는 걸 배웠습니다. ㅎㅎㅎㅎ

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

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

Coin Marketplace

STEEM 0.13
TRX 0.34
JST 0.035
BTC 108074.45
ETH 4399.12
USDT 1.00
SBD 0.83