아두이노 간 I2C 통신 응용(아두이노)

in #kr-arduino6 years ago

아두이노 간 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 통신을 이용하면 많은 부품을 아두이노 한대로 제어하는 것보다 여러대로 나누어 제어를 할 수 있습니다. 한곳에서 많은 부품을 제어하려면 각각의 부품의 소요되는 시간과 중간에 다른 동작의 개입할 때 까다로운 코딩을 설계해야 하는데 여러대로 분산 제어한다면 분산된 부품은 각각의 아두이노에서 해당 동작만 코딩하면 되기 때문에 코딩이 어느정도 쉬워질 거라 생각되네요.

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

Sort:  

즐거운 스팀잇 생활하시나요?
무더위야 가라!!!!

네! 즐거운 스팀잇 활동을 하고 있네요!
짱짱맨 응원에 언제나 감사하게 생각합니다.

LCD 모듈도 I2C로 동작하는군요. 처음 알았습니다. 무식해서..ㅠㅠ

16x2 LCD모듈 뒤에 I2C모듈이 따로 붙어있어요.
안붙어 있는 것도 있고 붙어 있는 것이 있는데 컨트롤 하기에는 I2C 모듈이 붙어 있는게 편하긴 해요.

위 post 가시면 LCD 모듈도 I2C 통신 모듈이 붙어 있는 경우 데이트시트 보시면 주소지를 코딩을 지정하는 게 아니라 드웨어에서 I2C 모듈에 A0, A1, A2 핀쪽에 jumper 을 어떻게 시키느냐에 따라서 주소지를 별도로 지정할 수 있어요 다수의 LCD도 SDA, SCL 핀을 공유해서 제어할 수 있어 다양한 응용을 할 수 있어요.

감사합니다. 좋은 정보네요. I2C로 제어 하면 LCD 동작도 심플해 지겠네요.

저한테는 알아들을 수 없는 외계어 이지만.... 이렇게 포스팅하시는거 꾸준히 보면 알아 들을거라 생각됩니다. ㅋㅋㅋㅋㅋㅋ
공부도 해야되는데...ㅜㅜ 작심 1시간도 안가네요..ㅋㅋㅋ

스팀블로그 초반 아두이노 글을 보시면서 시작하시면 어느정도 따라 오실 수 있을거에요.
아두이노를 배우게 되면 할 수 있는게 많고 일상의 전자기기에 관련된 모든 것을을 표현이 어렵지 않기 때문에 배울 가치가 있을 꺼에요.

아하!! 감사합니다!!
다른 스티미언 분들과 마찬가지로 생업이 따로 있어서 집중해서 공부는 못하겠지만 찬찬히 훑어 봐야겠네요. :)

아두이노를 중독되면 빠져나오기 힘들어요.
암튼 한번 관심을 가져 보세요. ^^

Coin Marketplace

STEEM 0.24
TRX 0.11
JST 0.031
BTC 60936.15
ETH 2921.43
USDT 1.00
SBD 3.70