아두이노 i2c 센서 여러개 연결 - adu-ino i2c senseo yeoleogae yeongyeol

	

안녕하세요

아두이노를 접한지 얼마 안되어서 도움을 구하고자 질문 드립니다.

먼저 제가 처한 상황입니다.

아두이노 i2c 센서 여러개 연결 - adu-ino i2c senseo yeoleogae yeongyeol
 

제가 MPU6050 가속도 센서와 DS3231를 사용하여 받는 가속도 데이터에 시간을 넣어서 같이 출력 하려고합니다

그런데 두 모듈 모두 A4 A5 핀을 사용하여서 단순히 동시 접지를 하면 원활하게 통신이 이루어 지지 않습니다(서로 간섭이 일어나서 정상적인 데이터가 나오지 않습니다.)

아두이노 우노 R3 쓰고있습니다!! 

#include

#include

#include

#include

RTC_DS3231 rtc;  // RTC 구조체 변수 선언

const int chipSelect = 4;

const int MPU=0x68;  //MPU 6050 의 I2C 기본 주소

int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;

void setup(){

#ifndef ESP8266

  while (!Serial); // for Leonardo/Micro/Zero

#endif

  Wire.begin();      //Wire 라이브러리 초기화

  Wire.beginTransmission(MPU); //MPU로 데이터 전송 시작

  Wire.write(0x6B);  // PWR_MGMT_1 register

  Wire.write(0);     //MPU-6050 시작 모드로

  Wire.endTransmission(true); 

  Serial.begin(9600);

}

void loop(){

 DateTime now = rtc.now();   // 현재 날짜, 시간을 모듈에서 가져옵니다.

  Wire.beginTransmission(MPU);    //데이터 전송시작

  Wire.write(0x3B);               // register 0x3B (ACCEL_XOUT_H), 큐에 데이터 기록

  Wire.endTransmission(false);    //연결유지

  Wire.requestFrom(MPU,14,true);  //MPU에 데이터 요청

  //데이터 한 바이트 씩 읽어서 반환

  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)    

  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)

  AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)

  Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)

  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)

  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)

  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

    Serial.print(now.year(), DEC);  // 년도 표시

    Serial.print('/');

    Serial.print(now.month(), DEC); // 월 표시

    Serial.print('/');

    Serial.print(now.day(), DEC);   // 일 표시

    Serial.print(" (");

    Serial.print(now.hour(), DEC);  // 시간 표시

    Serial.print(':');

    Serial.print(now.minute(), DEC);// 분 표시

    Serial.print(':');

    Serial.print(now.second(), DEC);// 초 표시

    Serial.print(") ");

    Serial.print("AcX = "); Serial.print(AcX);

    Serial.print("      | AcY = "); Serial.print(AcY);

    Serial.print("      | AcZ = "); Serial.print(AcZ);

    Serial.print("      | Tmp = "); Serial.println(Tmp/340.00+36.53);  

    //Serial.print(" | GyX = "); Serial.print(GyX);

    //Serial.print(" | GyY = "); Serial.print(GyY);

    //Serial.print(" | GyZ = "); Serial.println(GyZ);

     delay(1000);

    // print to the serial port too:

  }

제가 입력한 코드이구요.

위 두개의 가속도 모듈, RTC 모듈 말고 한개의 모듈을 더 사용할 생각입니다 BMP180

총 3개의 I2C 모듈을 하나의 아두이노를 통해서 데이터를 저장 하고 싶은데 

1:N연결이 가능하다고 인터넷에 나와있지만 도무지 어떻게하는지 모르겠습니다

답변해주시는분들 모두모두 감사합니다.

Skip to content

아두이노끼리 연결, 2대 연결방법 (Serial, I2C, SPI)

아두이노끼리 연결, 2대 연결방법 (Serial, I2C, SPI)

아두이노를 2대 혹은 그 이상 서로 연결해서 통신하는 방법을 모아봤습니다. 적외선, BT, WiFi 등 장치간 연결 방법이 아닌 시리얼(UART), I2C, SPI 통신을 이용해서 연결하는 방법입니다.

시리얼(UART) 통신으로 연결

시리얼 통신은 1:1 통신만 지원되므로 2대 연결시에만 사용 가능합니다. (단방향 통신일 때만 1:N 가능) 먼저 하드웨어 시리얼(아두이노 0, 1 번 핀)을 이용하는 방법입니다.

테스트를 위해 2 대의 아두이노를 사용합니다. 아두이노 2 는 주기적으로 문자 ‘1’ 과 ‘0’ 을 번갈아 전송합니다. 아두이노 1은 데이터를 받아 문자 ‘1’ 인 경우 내장한 LED 를 on 시키고 다른 문자인 경우 LED 를 off 시킵니다.

아두이노 두 대를 아래와 같이 TX – RX 크로스 해서 연결하면 됩니다. 각각의 아두이노는 USB를 통해 전원이 공급되는 상태여야 합니다.

연결 방법

  • 아두이노1 ==> 아두이노 2
  • 1번 핀(TX) ==> 0번 핀(RX)
  • 0번 핀(RX) ==> 1번 핀(TX)
  • GND ==> GND

스케치를 확인해 보겠습니다.

아두이노 1 (데이터 받아 LED 표시)

void setup(){
  Serial.begin(115200);
  pinMode(13, OUTPUT);
}

void loop(){
  if(Serial.available()){
   char c = (char)Serial.read();
    if(c == '1') {
      digitalWrite(13, HIGH);
    } else {
      digitalWrite(13, LOW);
    }
  }  
}

아두이노 SLAVE (데이터 보내는 부분)

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

void loop(){
  Serial.print("1");   // LED on
  delay(500);
  Serial.print("0");   // LED off
  delay(500);
}

아두이노 1 이 내장한 LED가 0.5 초 간격으로 on/off 를 반복하면 정상입니다.

하드웨어 시리얼 대신 SoftwareSerial 을 사용해도 같은 결과를 얻을 수 있습니다.

I2C 통신으로 연결

I2C 통신은 Master/Slave 구분이 있습니다.

앞서와 같이 아두이노 2(Master)에서 데이터를 보내고 아두이노 1(Slave) 에서 데이터를 받아 내장 LED를 깜빡이도록 하겠습니다.

연결은 간단합니다. GND-GND 연결, A4(SDA, 데이터 라인) – A4 연결, A5(SCL, 클럭 라인) – A5 연결해주면 됩니다.

  • 아두이노1 (Slave) ==> 아두이노 2 (Master)
  • SDA ==> SDA
  • SCL ==> SCL
  • GND ==> GND

https://hardcopyworld.com/wp-content/uploads/2021/06/Master_Sender_bb-1.png

연결이 되면 코드는 아래와 같이 작성해서 올립니다.

아두이노 2 MASTER  코드 (데이터 보내는 부분)

#include <Wire.h>

boolean isOn = false;

void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
}

void loop() {
  Wire.beginTransmission(8);    // send to address #8 (0x08)
  if(isOn)
    Wire.write('1'); 
  else
    Wire.write('0'); 
  Wire.endTransmission();  

  isOn = !isOn;
  delay(500);
}

아두이노 1 SLAVE (데이터 받는 부분)

#include <Wire.h>

void setup() {
  Wire.begin(8);                // use address #8 (0x08)
  Wire.onReceive(receiveData); 
}

void loop() {
  delay(100);
}

void receiveData(int size) {
  while(1 < Wire.available()) {
    char c = Wire.read(); 
    if(c == '1')
      digitalWrite(13, HIGH);
    else
      digitalWrite(13, LOW);
  }
}

SPI 통신으로 연결

SPI 도 I2C 와 마찬가지로 Master/Slave 가 나뉩니다. 아두이노 1을 Slave(데이터 받는 용도), 아두이노 2를 Master(데이터 보내는 용도)로 설정해서 쓰겠습니다.

SPI 는 연결을 위해 4개의 디지털 핀을 사용합니다. D10(SS, Slave Select), D11(MOSI, Master Out Slave In), D12(MISO, Master In Slave Out), D13(SCLK, Serial Clock). 각각의 핀을 서로 연결해주면 됩니다.

그런데 SPI 경우 아두이노 내장 LED가 연결된 13번 핀과 겹칩니다. 앞서처럼 LED를 on/off 하기 위해 LED 하나를 디지털 5번 핀에 붙이도록 하겟습니다.

연결 방법

  • 아두이노 1 (Slave) ==> 아두이노 2 (Master)
  • (D10) SS ==> (D10) SS
  • (D11) MOSI ==> (D11) MOSI
  • (D12) MISO ==> (D12) MISO
  • (D13) SCLK ==> (D13) SCLK
  • GND ==> GND
  • 아두이노 1 – 디지털 5번 핀에 LED, 저항을 연결

아두이노 i2c 센서 여러개 연결 - adu-ino i2c senseo yeoleogae yeongyeol

스케치는 아래와 같이 올립니다.

아두이노 2 MASTER  코드 (데이터 보내는 부분)

#include <SPI.h>

void setup (void) {
  digitalWrite(SS, HIGH);
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV8);
}

void loop (void) {
  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  SPI.transfer('1');

  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (1000);
}

아두이노 1 SLAVE (데이터 받는 부분)

#include <SPI.h>

volatile boolean isOn = false;

void setup() {
  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  // turn on SPI in slave mode
  SPCR |= _BV(SPE);
  // now turn on interrupts
  SPI.attachInterrupt();

  pinMode(5, OUTPUT);
}


// SPI interrupt routine
ISR (SPI_STC_vect) {
  byte c = SPDR;  // grab byte from SPI Data Register

  if (c == '1')
    isOn = true;
  else
    isOn = false;

  // turn on interrupts
  SPCR |= _BV(SPIE);
}

void loop() {
  if(isOn) {
    digitalWrite(5, HIGH);
  } else {
    digitalWrite(5, LOW);
  }
  delay(50);
}

SPI 통신 라이브러리는 인터럽트 서비스 루틴(ISR) 으로 데이터를 받습니다. 데이터가 오면 ISR 함수가 자동으로 호출됩니다. 따라서 ISR 함수 내부에서 변경하는 전역 변수(isOn)는 volatile 로 선언되어야 합니다.

참고자료

  • UART/SoftwareSerial: [출처] [아두이노]아두이노끼리 통신하기
  • I2C/TWI: F*CKING COREA, Arduino, Maker’s Diary(by manyonglee)
  • http://forum.arduino.cc/index.php?topic=184527.0
  • http://www.arduino.cc/en/Tutorial/MasterReader
  • http://electronics.stackexchange.com/questions/42197/making-two-arduinos-talk-over-spi
  • http://www.gammon.com.au/forum/?id=10892

.

Share This Story!

Page load link