PR
スポンサーリンク

【初心者】I2Cとは?Arduino、可変抵抗を使って試してみた

皆さんこんにちは!メカ旦那です。

先日I2Cの概要について解説しましたが、実際に使ってみた方がイメージしやすいと思います。Arduinoを使って通信してみたので解説します。

I2Cについて基礎から理解したい方はまず下記をご覧ください。

ラズパイを使った事例も紹介しています。

ArduinoのI2Cについて

ArduinoでI2Cを使うにあたり事前に理解しておくべき事について解説します。

I2Cピン

I2CにはSDA、SCL、GNDの3つが必要になります。Arduino Uno はD18がSDA、D19がSCLになります。Arduino LeonardはD2がSDA、D3がSCLになります。GNDは3つあり任意のピンで結構です。

プルアップ抵抗

別記事で解説しましたが、I2C出力はオープンドレインになるため、別途プルアップ抵抗が必要になります。Arduinoの場合、関数で内部プルアップを有効にすることもできます。興味のある方はこちらをぜひご覧ください!

Arduino UNO ⇔ Leonard 間でI2C

ArduinoのI2Cについて説明が終わりましたので、早速事例紹介に行きたいと思います。

動画

イメージはこんな感じです。
可変抵抗のアナログ信号がArduino Unoへ送られ、I2CでArduino Leonardに送ります。そして、LeonardからLEDへPWM制御を行い、明るさを変えています。

PWMって何、、、という方は過去に解説していますのでこちらをご覧ください!

使用部品

今回使用する部品はこちらです。

Arduino Leonard以外はまとめて購入することも可能です。

回路

回路はこちらで、ポイントは以下になります。

  • Arduino Unoをマスター、Leonardをスレーブとして、I2Cの配線をしています。(Arduinoのデータシートではマスターをコントローラ、スレーブをペリフェラルという呼称になっていることもあります。)
  • 可変抵抗(10kΩ)はUnoのA0(アナログ入力端子)に接続しています。
  • Arduino Leonardの5ピンに抵抗(1kΩ)、LEDを接続しています。

プログラム マスター

//Arduino用I2Cライブラリのインポート
#include <Wire.h>        

//初期設定
void setup() {
  Serial.begin(9600);     //シリアル通信開始
  Wire.begin();           //I2C通信開始
}

int resistorData = 0;     //可変抵抗から受信したアナログデータ(10 bit)     
float resistorVolt = 0;   //上記を0~5Vの電圧に変換した値(シリアルモニタに映す)

//メイン処理
void loop() {
  //可変抵抗器から受信データを読み取り、変数へ格納
  resistorData = analogRead(0);              //可変抵抗から入力されたアナログデータ(10bit)を変数に格納
  resistorData /= 4;                         //10bitを8bitに変換 (I2Cは8bit送信の為)
  resistorVolt = 5*(resistorData/255.75);    //0~5Vの電圧に変換    
  
  //電圧値をシリアルモニタに表示
  Serial.print("resistorVolt = ");         
  Serial.println(resistorVolt);

  //i2cでスレーブへ送信
  Wire.beginTransmission(9);                 //スタートコンディション発行とアドレス送信。またスレーブのアドレスを9で設定。
  Wire.write(resistorData);                  //データの準備
  Wire.endTransmission();                    //データ送信とストップコンディション発行 
  delay(500);
}

こちらがマスター(Arduino Uno) に書き込むプログラムになります。ポイントは以下です。

  • Arduino用I2Cライブラリ「Wire.h」を使用します。
  • 可変抵抗から受信するアナログデータは10bitです。I2Cは8bit単位での通信になるため、10bitを4(2bit)で割って8bitにしています。
  • 8bitにしたデータ範囲は0~255です。こちらを0~5の電圧に変換します。
  • 電圧はシリアルモニタに映します。
  • 後述しますがスレーブアドレスは9で設定しているので、引数として記載します。

プログラム スレーブ

// Leonard(slave)経由でLED制御(PWM)
// 本コードはleonard向け

//Arduino用I2Cライブラリのインポート
#include "Wire.h"

//初期設定
volatile byte receiveData;        //LEDに出力する変数receiveDataを宣言

void setup() {
  Wire.begin(9);                  //スレーブにアドレス9を設定
  Wire.onReceive(turnOnLED);      //I2C受信時に関数「turnOnLED」を呼び出す
  pinMode(5, OUTPUT);             ///LEDが接続されている5ピンを出力に設定
}

//メイン処理
void loop() {
  analogWrite(5, receiveData);    //LEDピンに変数receiveDataをアナログ出力。つまりPWMでLEDの明るさを制御。
}

//呼び出し関数
void turnOnLED(int Number) {        
  if(Wire.available())        
    receiveData = Wire.read();    //I2C受信データを変数receiveDataに格納
}

こちらがスレーブ(Arduino Leonard)側 に書き込むプログラムになります。ポイントは以下です。

  • Arduino用I2Cライブラリ「Wire.h」を使用します。
  • 今回はArduino間のI2C通信の為、スレーブアドレスはスレーブ側で設定する事が出来ます。今回は「9」にしました。
  • I2C受信時に関数「turnOnLED」を呼び出し、データを変数receiveDataに格納します。
  • LEDが繋がる5ピンにreceiveDataをアナログ出力します。つまりPWMでLEDの明るさを制御します。

まとめ

いかがでしたでしょうか。
I2Cと聞くと一見難しそうに聞こえますが、ライブラリを使う事で手軽に利用できる事がお分かりになったかと思います。

ただし、プルアップ抵抗が必要、長距離配線・接触不良に弱い等、I2Cにも弱点は存在します。もし通信が上手くいかない場合、こちらもぜひご参考にしてみてください。

今回はArduino間のI2C事例を紹介しましたが、ラズパイ⇔Arduino間や、ラズパイ⇔LCD間のI2C通信も試してみたので、良かったらご覧ください!

メカ旦那

旧帝大工学部を卒業後、電気制御設計職をしています。生産設備や産業用ロボット等、様々な開発に取り組んでいます。電験三種も保持しています。イラストや画像を用いて電気・電子・制御をわかりやすく解説します!

メカ旦那をフォローする
Arduino
スポンサーリンク

コメント