前回、パラレル通信を使いArduinoにLCDモジュールを接続し文字を表示させてみました。
Arduinoの通信、データのやり取りには主に「パラレル通信」と「シリアル通信」という通信方法が使われます。
前回使ったパラレル通信方式は複数本の信号線を使う方式となり、LCDモジュールとの接続には多くの配線が必要でした。
前回少し触れましたがシリアル通信方式の一種であるI2C通信を使えばその接続には信号線が2本(SCL・SDA)、電源としてVccとGNDの計4本で接続することが出来ます。
今回はI2C通信方式を使いLCDモジュールに文字を表示させてみたいと思います。
目次
【Arduino】I2C通信の基礎&基本的な使い方!
今回の目的
Arduino(こちらではArduino Unoで説明していきます)とセンサーなど他のデバイスを接続する際の通信方式には主に「パラレル通信方式」と「シリアル通信方式」があります。
パラレル通信とは複数本の信号線を使い接続し通信する方式となり前回、ArduinoにLCDモジュールを接続し文字を表示させてみました。
今回はシリアル通信方式を使って同様にLCDに文字を表示させてみたいと思います。
シリアル通信のシリアルとは「連続した(Serial)」という意味があり、HIGHとLOWの連続したデータを1本の信号線を使って連続的にやり取りする方式となります。
そしてシリアル通信にはI2C通信やSPI通信、UART通信などがあります。
例えば普段Arduinoを使う際にPCからArduinoにスケッチを書き込みしますが、これもシリアル通信の1つとなります。
PCからArduino内のUSB-シリアル変換器を経由してTX(送信用)・RX(受信用)ピンからデータのやり取りを行っています。
シリアルモニタも同様な方法によりPCとデータのやり取りを行っています。
シリアル通信は先述のようにいろいろな方式がありますが、今回はI2C(アイ・スクエアド・シー)通信を使いArduinoにLCDモジュールやセンサーなどI2C対応デバイスを接続する方法をご紹介したいと思います。
たった2本の信号線(SCL・SDA)の接続で複数の対応デバイスとのやり取りを行うことができ大変便利となります。
マスタ側からのクロック(SCL)のタイミングで送信データ(SDA)を同期させ・・・とI2C通信の転送タイミングや通信データフォーマットなど少し複雑なやり取りが行われますが、実際にはArduinoにはI2Cデバイスに対応したライブラリが提供されているので概要が分かれば比較的簡単に使うことが出来ます。
I2C通信の概要の理解、そして対応デバイスのArduinoとの接続方法が理解できるまでを今回の目標としたいと思います。
1602 LCDモジュールを使い今回はI2C通信により文字を表示させて見たいと思います。
I2C(アイ・スクエアド・シー)とは?
I2Cとはフィリップス社が開発したシリアル・インターフェースで、複数のデバイスを同一バスライン上で接続することが可能なものとなります。
Inter Integrated Circuitの略となり、「アイ・スクエアド・シー」が正式な読みとなるようです。
I2CやIICと表記されることが多く「アイ・ツー・シー」と発音や表記されることもあるようですね。
I2Cデバイスはそれぞれ個別にアドレスを持っており同一バスライン上でアドレスにより識別され複数のデバイスを接続することが出来る仕組みとなっています。
I2C通信は、「SDA(シリアルデータ)」「SCL(シリアルクロック)」の2本の線のみでデータのやり取りが出来るようになっているのが特徴です。
実際には電源も必要なので、Vcc・GND・SDA・SCLの計4本でデバイスとの接続&データのやり取りが行われます。
I2C通信ではこれに対応したデバイスを複数接続することが可能です。
そのためI2C対応デバイスには「I2Cアドレス」が個別に割り振られています。
複数デバイスを接続している場合、そのアドレスにより対象デバイスを指定して制御する形となります。
このアドレスは7bitのうち予約アドレスの16個を引いた112個から割り当てることが出来るためこれがアドレス数の上限となり、理論的にはこれだけのデバイスを少ない信号線で制御することが出来ます。
こちらが基本的なI2Cデバイスの接続方法となります。
マスタ側とスレーブ側を分け、マスタ側が全ての制御を行う構造となっています。
ここでマスタ側とは全てを制御するArduinoとなり、スレーブ側にはI2Cに対応したデバイス(LCDディスプレイやセンサー、ドライバーなど)となります。
もちろんスレーブ側にもArduinoを繋ぎ、Arduino同士でのデータのやり取りなんかも行えます。
ここで注意したいのがI2C通信で使われるSDA・SCLはプルアップされているという点です。(オープンコレクタかオープンドレインになっているので)
通常10kΩ程度の抵抗でプルアップさせる必要がありますが、デバイスによっては基板内にプルアップ抵抗が付けられているものもあります。(またArduinoにはプルアップ機能が付いています。)
上記図のように1台のマスタ(Arduino)と1台または複数のスレーブとの間をSCLとSDAの2本の信号線でプルアップ接続します。
そしてマスタ側が常に制御を行い(権限を持っている)、マスタが送信するクロック信号SCLを基準にデータ信号がSDAライン上でやり取りされるというものです。
- マスタ側とスレーブ側を分けて、マスタ側が全ての制御を行っている
- 信号線が2本と少ない(SDA/SCL)
- 個々のスレーブがそれぞれアドレスを持っている
- 伝送速度は遅い(100kbps~1Mbps)
I2C対応デバイス
I2Cに関して雰囲気が分かったところで、Arduinoで使えるI2Cデバイスを少し見てみましょう。
こちらは前回使った1602 LCDモジュールとなります。
前回はパラレル通信方式を使い接続しましたがかなり配線が多いものとなりました。
そしてこのLCDを制御できArduinoとI2C接続できるシリアルインターフェースモジュールを取り付けてみました。
I2C通信でのやり取りではSCLとSDA、電源としてVccとGNDの計4本のみの配線でArduinoと接続できるようになります。
I2Cアドレス設定用のジャンパーパッドが備わっているのでアドレスを変えれば理論的には8台同時にこの1602 LCDモジュールを制御することが出来ます。
今回はこのLCDモジュールを使いI2C通信により文字を表示させてみるまでを目標としたいと思います。
またこちらは時刻情報を扱えるDS3231 RTC(リアルタイムクロック)というモジュールとなります。
Arduinoと接続し時刻情報のやりとりを行うものです。
こちらもI2C対応デバイスとなっています。
Arduinoの電源を落としても時刻を保持することができ時計などによく使われます。
そしてこちらはPCA9685というサーボモータードライバーとなりこれもI2Cに対応したデバイスとなります。
同様にArduinoとの接続はケーブル4本のみで接続できこれ1台で16台のサーボモーターを同時に制御することが出来ます。
こちらもI2Cアドレスを変更することによりこのボードを62枚まで連結でき最大992台のサーボモーターを制御することが出来ます。
このようにI2C対応デバイスは、信号線2本(SCL・SDA)とVcc・GNDの計4本のみの接続でArduinoから制御することが出来ます。
そしてI2Cデバイスはそれぞれ「I2Cアドレス」が割り振られているので(上記のように変更が可能なものもあります)、アドレスを変えればデバイスを複数同時に接続してArduinoから制御することが出来ます。
I2C対応デバイスの接続
ArduinoとI2C対応デバイスとの接続には、それぞれのSCL(シリアルクロック)ピンとSDA(シリアルデータ)ピンを接続する形で配線します。
Arduino UnoではこちらがSCLピンとSDAピンになってます。
Arduino Uno | I2Cデバイス |
SCL(またはA5ピン) | SCL |
SDA(またはA4ピン) | SDA |
I2C通信で使うSCLピンとSDAピンはプルアップ抵抗でプルアップさせて使う必要があることは先述しました。
ArduinoのI2C通信用で用意されている標準ライブラリ「Wireライブラリ」は内部のプルアップ抵抗を有効にするため通常は外部にプルアップ抵抗を接続する必要はありません。
そして複数のI2Cデバイスを接続する場合も同様に全てのデバイスをArduinoのSCLピン・SDAピンに接続する形となります。
接続されている各デバイスはI2Cアドレスで識別されます。
そのため同一のI2Cアドレスを持ったデバイスは1つしか接続することが出来ません。
しかしI2Cデバイスにはこのアドレスを変更できるタイプのものもあります。
このようにアドレス設定用パッドをはんだブリッジすることによりアドレスを変更(設定)出来るようになっているものもあります。
この場合、同一デバイスをアドレスを変え複数台同時に接続することも出来ます。
今回文字を表示させようと考えている1602 LCDモジュールでは、I2Cアドレスを変更することにより同時に8台までの1602 LCDモジュールを接続し制御することが出来ます。
I2Cアドレスを調べる
このようにI2C通信では、マスタに接続された1台または複数台のスレーブのI2Cアドレスを指定して制御(データの送受信)を行います。
通常I2Cアドレスには7ビットのアドレスが使われるようです。(10ビットアドレスもあります)
クロックで同期を取りデータを送信して・・・タイミングチャートを説明すると少し複雑で難しくなるので今回は割愛しますが、基本的にライブラリがこの部分を処理してくれるので、個々に割り振られたI2Cアドレスのみの話に今回は止めておきます。
1602 LCDモジュールをI2C通信で制御するというのが今回の目的なので、このモジュールのI2Cアドレスを見ていきます。
今回使っている1602 LCDに接続したI2C対応のシリアルインターフェースモジュールは、データシートを見るとI2Cアドレスに0x20~0x27まで設定できデフォルトでは0x27となっていました。
0xは16進数表記ですが、2進数表記や10進数表記などもあり、さらに7ビット表記や8ビット表記などI2Cアドレスの表記方法は少し分かりにくいのですが・・・詳しく理解できなくても大丈夫です。
データシートや製品ページには大抵の場合、そのデバイスのI2Cアドレスが記載されています。
先述したようにこのモジュールのデフォルトのI2Cアドレスは0x27と書かれていました。
そして他の機器とこのI2Cアドレスがかぶってしまう場合や複数このデバイスを接続したい場合などは設定用ジャンパーパッド(A0/A1/A2)をはんだブリッジすればアドレスの設定(変更)もできます。
I2Cアドレス | A0 | A1 | A2 |
0x27 | OFF | OFF | OFF |
0x26 | ON | OFF | OFF |
0x25 | OFF | ON | OFF |
0x24 | ON | ON | OFF |
0x23 | OFF | OFF | ON |
0x22 | ON | OFF | ON |
0x21 | OFF | ON | ON |
0x20 | ON | ON | ON |
このようにジャンパーパッドの設定により8通りのI2Cアドレスを設定できます。
という事は最大8台の1602 LCDモジュールを同時に接続&制御出来るということになりますね。
2進数や16進数の計算に慣れていない方は少し上記のON/OFFが分かりにくいかと思いますが、I2Cアドレスを調べる便利なスケッチ(プログラム)があるので大丈夫です。
I2CScanner
Githubで提供されているI2CScannerというプログラムを使えばI2Cアドレスを簡単に調べることが出来ます。
ArduinoにI2C対応機器を接続(SCL/SDA/Vcc/GND)しシリアルモニタからI2Cアドレスを確認することが出来ます。
こちらからダウンロードできますが、短いスケッチなので記載しておきます。
参考 I2CScannerGithub1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | // reference: https://playground.arduino.cc/Main/I2cScanner // -------------------------------------- // i2c_scanner // // Version 1 // This program (or code that looks like it) // can be found in many places. // For example on the Arduino.cc forum. // The original author is not know. // Version 2, Juni 2012, Using Arduino 1.0.1 // Adapted to be as simple as possible by Arduino.cc user Krodal // Version 3, Feb 26 2013 // V3 by louarnold // Version 4, March 3, 2013, Using Arduino 1.0.3 // by Arduino.cc user Krodal. // Changes by louarnold removed. // Scanning addresses changed from 0...127 to 1...119, // according to the i2c scanner by Nick Gammon // http://www.gammon.com.au/forum/?id=10896 // Version 5, March 28, 2013 // As version 4, but address scans now to 127. // A sensor seems to use address 120. // Version 6, November 27, 2015. // Added waiting for the Leonardo serial communication. // // // This sketch tests the standard 7-bit addresses // Devices with higher bit address might not be seen properly. // #include <Wire.h> void setup() { #ifdef _ESP32_HAL_I2C_H_ Wire.begin(26,25); #else Wire.begin(); #endif Serial.begin(115200); while (!Serial); // Wait for starting serial monitor Serial.println("\nI2C Scanner"); } void loop() { byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for(address = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address<16) { Serial.print("0"); } Serial.print(address,HEX); Serial.println(" !"); nDevices++; } else if (error==4) { Serial.print("Unknown error at address 0x"); if (address<16) Serial.print("0"); Serial.println(address,HEX); } } if (nDevices == 0) { Serial.println("No I2C devices found\n"); } else { Serial.println("done\n"); } delay(5000); // Wait 5 seconds for next scan } |
接続したI2Cデバイスのアドレスをシリアルモニタに表示させることが出来ます。(複数同時接続も可)
I2Cアドレスは0x27と表示されました。
このアドレスさえ分かればI2C通信の難しいタイミングなどはライブラリが担当してくれるので比較的簡単に制御することが出来ます。
もちろんこのモジュールははんだブリッジによりI2Cアドレスを変更することが出来るので、上記表のようにブリッジ位置によりアドレスが変化するか試してみると分かりやすいと思います。
1602 LCDモジュールを接続する
I2C通信についての概要、そしてI2Cアドレスについて理解できたところで実際に動かしてみたいと思います。
I2C通信にはArduino IDE標準ライブラリとして[Wire]ライブラリというI2C通信用の標準ライブラリが用意されています。
本来このライブラリを使って分かりやすいスケッチをご紹介したかったのですが、なかなか分かりやすい作例がないので前回の続きとして[LiquidCrystal_I2C]ライブラリを使って制御してみたいと思います。
LiquidCrystal_I2Cライブラリは、ArduinoでLCDディスプレイを使用する際によく使われるI2C用ライブラリとなります。
まずはArduinoとの接続からです。
先述したようにI2C通信には2本の信号線(SCL/SDA)と電源(Vcc/GND)の接続のみで完了します。
今回このように電源はArduinoから直接取り、それぞれのSCLピン・SDAピンを接続しただけのシンプルな配線となります。(上記I2CScannerを使用する際も同様の接続となります)
前回のパラレル通信での接続と比べかなりシンプルになりますね!
前回同様、LCDディスプレイに文字を表示させるシンプルなスケッチを作ってみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | // Arduino入門編⑱ I2C通信を使ってLCDに文字を表示させる // https://burariweb.info #include <LiquidCrystal_I2C.h> // ライブラリのインクルード // LiquidCrystal_I2C型変数の宣言 LiquidCrystal_I2C lcd(0x27, 16 , 2); // 0x27のアドレス,16列2行のLCDを使用 void setup(){ lcd.init(); // LCDの初期化 lcd.backlight(); // LCDバックライトの点灯 lcd.setCursor(0, 0); // カーソルの位置を指定 lcd.print("I2C connect"); // 文字の表示 lcd.setCursor(0, 1); // カーソルの位置を指定 lcd.print(" Arduino Uno "); // 文字の表示 } void loop(){ } |
スケッチ解説
①ライブラリのインクルード
今回『LiquidCrystal_I2C』というライブラリを使いました。
Arduino IDE標準ライブラリではないので新たにインストールする必要があります。
[スケッチ]→[ライブラリをインクルード]から[ライブラリを管理]へ進みます。
『LiquidCrystal_I2C』で検索しインストールします。
またGithubからダウンロードも可能です。
ZIP形式でダウンロードして、[スケッチ]→[ライブラリをインクルード]→[ZIP形式のライブラリをインストール]からライブラリのインストールを完了して下さい。
②LiquidCrystal_I2C型変数の宣言
LiquidCrystal_I2C型変数を宣言します。
0x27のアドレスを使用し、16列2行のLCDであることを示しています。
6 7 | // LiquidCrystal_I2C型変数の宣言 LiquidCrystal_I2C lcd(0x27, 16 , 2); // 0x27のアドレス,16列2行のLCDを使用 |
③LCDの初期化&バックライトの制御
12 13 | lcd.init(); // LCDの初期化 lcd.backlight(); // LCDバックライトの点灯 |
前回パラレル通信での表示ではArduino IDE標準の「LiquidCrystal」ライブラリを使いました。
「LiquidCrystal_I2C」ライブラリでは初期化コードが[lcd.clear]から[lcd.init]に変わっているので注意が必要です。
またバックライトの制御ができその初期化[lcd.backlight]を行っています。
④文字の表示
16 17 18 19 20 | lcd.setCursor(0, 0); // カーソルの位置を指定 lcd.print("I2C connect"); // 文字の表示 lcd.setCursor(0, 1); // カーソルの位置を指定 lcd.print(" Arduino Uno "); // 文字の表示 |
LCDの初期化やバックライトの項目が異なるくらいで標準の[LiquidCrystal]とほぼ同じコードが使えるので以下サイトも参考にしてみて下さい。
参考 LiquidCrystalArduino 日本語リファレンスI2C通信の概要およびLCDディスプレイに文字を表示することが出来ました。
これで今回の目標は達成です。
複数I2Cデバイスを接続
折角なので複数のI2Cデバイスを接続した例を見てみたいと思います。
こちらは先程使用した回路にRTC(リアルタイムクロック)モジュールを追加しそれぞれI2C通信により接続し時計として機能させているものとなります。
このように対応デバイスをArduinoのSCLピン・SDAピンにそれぞれ接続するだけとシンプルに配線出来るのがI2C通信の特徴の一つでもあります。
もちろんI2Cアドレスさえ適切に設定できれば(一致するものがなければ)さらに多くのデバイスを同時に制御(通信でのやり取り)することができ大変便利となります。
RTCモジュールは後日、詳しくやってみたいと思います。
今回使ったアイテム
1602 LCDモジュール
Arduinoでよく使われるポピュラーなLCDモジュール(16×2)となります。
下記Arduinoスターターキットにも含まれています。
今回は、I2Cシリアルインターフェースボードモジュールが付属したこちらを使用しました。
Arduino UNO
Arduinoはオープンソースのハードウェアなので正規品以外にも互換品が多数メーカーから販売されています。
互換品でも正規品と比べて特に問題なく使用でき数百円程度で購入が可能なのでArduino学習用としていいですね!
Arduino スターターキット
これからArduino学習を進めていくにあたりArduino UNO(互換品)やブレッドボード、ジャンパーピンなどがセットになったスターターキットが販売されています。
私はGeekcreit製のスターターキットを使っていますが、ELEGOO製のものは国内Amazonなどでも購入可能で人気があるようです。(セット内容はほぼ同じです!)
そしてELEGOOのサイトからスターターキット用サンプルスケッチのダウンロードも可能です。(Geekcreitのキットでも使えます)
参考 チュートリアルダウンロードELEGOO基本的にこれからこのセットで出来るものから紹介していこうと考えていますが、かなり多くのことが出来ます。
電子工作を始めるにはまずブレッドボードやジャンパーピン、メインとなるArduino UNOやサーボ、LEDなどの基本的なパーツがないと実際に動かすことが出来ませんが、個々にパーツを購入して回路を組んでとなるとかなりの手間がかかります。
スターターキットがあればArduinoの初歩的なことはかなりの数こなすことが出来るのでオススメです!
そこからスキルアップに伴い個別でセンサーなど必要なものを増やしていくのがいいと思います。
今回使った1602 LCDモジュールはArduinoスターターキットに含まれています。
最後に!
I2C通信によりLCDディスプレイに文字を表示させることが出来ました。
パラレル通信方式と比べ4本と少ないケーブルで接続することができ、アドレスを変えれば複数のデバイスの接続も容易に出来ることも分かりました。
この投稿をInstagramで見る
データのやり取りには少し複雑なタイミングチャートを用意し説明する必要がありますが、Arduinoではこのような面倒な部分をライブラリが担当して処理してくれるのである程度の概要が分かっていれば比較的簡単に動作させることができます。
Arduinoって大変便利なマイコンボードですよね!
コメントを残す