みなさん,こんにちは
おかしょです.
センサーを使ってロボットの状態や湿度などの環境を測定するときは,マイコンと通信をしなければなりません.
通信方法はさまざまな種類がありますが,この記事ではI2C通信について解説します.
I2C通信については過去にも解説をしたのですが,この記事では1byteだけ通信する関数の作り方について解説します.
この記事を読むと以下のようなことがわかる・できるようになります.
- 1byteだけI2C通信する方法
- 1byte通信する関数の作り方
- Arduinoのプログラムの書き方
この記事を読む前に
I2C通信を1byteだけ行う方法を解説するのですが,そもそもI2C通信をする方法を知らない方は以下の記事を先に読んでおくことをおすすめします.
Arduinoではないマイコンを使う方でも参考になると思います.
1byteだけ通信をする意味
1byteは8bitのデータ量を表します.
センサーのデータの多くは2byteで構成されることが多いので,一見すると1byteでデータのやり取りをする必要はないように思えます.
しかし,実際は1byteの通信は絶対に必要になります.むしろ,1byteの通信をしなければ2byteの通信なんてできません.
センサーを使用する場合は,最初にセンサーの設定をする必要があります.
多くのセンサーにはモードがあって,精度やデータの通信速度などがバランスよくとれたノーマルモードや精度は低くても良いから通信速度重視のスピードモードなどがあります.
また,データの範囲なども設定する必要があるので,センサーにそれらの情報を書き込まなければなりません.
これらの設定の書き込みはたいてい,1byteの通信で行われます.
また,どんな種類のデータが欲しいのかを知らせるレジスタの送信も1byteの通信で行われます.
これらのデータを送信して初めてデータを取得することができるようになります.
センサーによってモードの設定やレジスタの設定が異なっていますが,データシートに必ず書いてありますのでデータシートは隅々まで確認するようにしましょう.
I2C通信を行う準備
1byteの通信を行う関数の作り方を解説する前に,以下の記事でも解説していますがI2C通信を行う方法について簡単に解説します.
まず,Wire.hというヘッダファイルをインクルードします.
#include <Wire.h>
そして,setup関数内でI2C通信の初期化を行います.
Wire.begin();
これだけです.この2文だけでI2C通信の準備は終了です.
他のマイコンの場合はI2C通信を行うプログラムはもっと複雑になったりするのですが,Arduinoの場合は以上のように非常に簡単にI2C通信を行うことができるようになっています.
1byteだけ通信をする関数
通信には2種類があります.
センサーに設定を書きこむ送信とセンサーからデータを読み取る受信です.
まずは送信を行う関数の作り方から解説していきます.
1byte分送信する関数
プログラミングで関数を作る時は,引数と戻り値を何にするのかを決めます.
データを送信する関数の場合は,送信するだけなので返り値は必要ありません.なのでvoidとします.
引数にはセンサー自身の名前に相当するデバイスアドレス,書き込む先の場所を意味するスレーブアドレス,実際に書き込むデータの3つが必要になります.
なので,関数の冒頭は以下のようになります.
void I2Cwrite1byte(uint8_t DeviceAddress, uint8_t SlaveAddress, uint8_t data)
返り値 関数の名前(引数)
引数はすべて1byteで符号はないのでuint8_tで宣言しています.
あとは1byte分のデータを送信するプログラムを書くだけです.そのプログラムが以下になります.
void I2Cwrite1byte(uint8_t DeviceAddress, uint8_t SlaveAddress, uint8_t data)
{
Wire.beginTransmission(DeviceAddress); // 通信を開始する
Wire.write(SlaveAddress); // スレーブアドレスを送信
Wire.write(data); // データを書き込み
Wire.endTransmission(); // 通信を終了する
}
各行の解説はコメントにある通りです.
この関数を使用するときは以下のようにします.
I2Cwrite1byte(AG_DEVICE_ADDRESS, CTRL_REG1_G, RegisterData);
このように書くだけで,面倒なI2C通信でセンサーの設定が簡単にできてしまいます.本来,4行は必要なプログラムをたった1行にまとめられるので,これを使わない手はありません.
1byte分受信する関数
次は1byteのデータを受信する関数の作り方を解説します.
どのようなセンサーにもWHO_AM_Iというレジスターが用意されていて,このレジスターを使用してセンサーとマイコンが通信できているのかを確認します.このときの確認は1byteのデータを受信することで行われるので,そのようなときにこの関数は役に立ちます.
受信する関数も送信する関数を作った時と同様に,引数と戻り値から決定します.
引数は先ほどと同じでデバイスアドレスとスレーブアドレスが必要です.今回は書き込んだりはしないので,引数にデータは必要ありません.
その代わりに,戻り値として1byteの読み込んだデータを設定します.
以上のことを考えると,関数の冒頭は以下のようになります.
uint8_t I2Cread1byte(uint8_t DeviceAddress, uint8_t SlaveAddress)
返り値 関数の名前(引数)
そして,関数の中身は以下のようになります.
uint8_t I2Cread1byte(uint8_t DeviceAddress, uint8_t SlaveAddress)
{
Wire.beginTransmission(DeviceAddress); // 通信を開始する
Wire.write(SlaveAddress); // スレーブアドレスを送信
Wire.endTransmission(false); // リスタートメッセージをリクエストの後に送信し,接続を続ける
Wire.requestFrom(DeviceAddress, (uint8_t) 1); // 1 byte分のデータを要求する
return Wire.read(); // データを返す
}
この関数を使用することで,1byteのデータを受信することが可能です.
例として以下のように使用します.
who_ag = I2Cread1byte(AG_DEVICE_ADDRESS, AG_WHO_AM_I);
上記のプログラムの場合はwho_agに1byteのデータが格納されます.
これがデータシートに書いてある通りの値になるのかを以下のようにして確認することによって,センサーとの通信が正常に行えているのか確認できます.
if (who_ag==0x68)
{
return true;
}
まとめ
この記事ではArduinoで1byte分のデータをI2C通信する際に便利な関数の作り方を解説しました.
この記事では示してあるプログラムは実際に動作することが確認されていますので,皆さんもお手持ちのセンサーを使って確認してみてください.
続けて読む
以下の記事では,今回解説したプログラムを使ってセンサーとデータのやり取りをしています.ぜひ続けて読んでみてください.
Twitterでは記事の更新情報や活動の進捗などをつぶやいているので気が向いたらフォローしてください.
それでは最後まで読んでいただきありがとうございました.
コメント