2018年5月11日金曜日

RaspberryPiでラズベリー栽培 I2CをCで使う

3年ぶりのRaspbery栽培ネタですが、皆様いかがお過ごしでしょうか。私は元気です。

ラズベリーはどうなったか

結局のところ、気象とか水分とか測定しても天気を変えられるわけでもなく、あまり意味がないことに気が付きました。また我が家の場合、近所の田畑で石灰を撒いている影響もあったようで、なかなかうまく育ちませんでした。3年前のラズベリーは見事に枯れてしまいましたが、3代目ラズベリーは順調に育っていて、実が付き始めました。本来山間部に生息する植物を、平野部で育てようとしてるのだから、それはまぁ苦労しますね。今年はまだ枝が短いのでジャムを作るほど実がなってはくれないと思いますが、来年に期待です。


さて本題。前回、GPIOをShellでコントロールする方法を紹介しましたが、今回はI2CをCのソースコードからコントロールします。

使用する材料

使用するセンサは、前回購入していたBoschのBME280を搭載したモジュールです。気温、湿度、気圧が測定できてお値段もお安いです。
秋月電子→http://akizukidenshi.com/catalog/g/gK-09421/
RaspberryPi2。前回使用したRaspberryPi1でも大丈夫ですが、シングルコアのくせに消費電流が多いので、Pi2に変更しました。(Pi1:Typ500mA Pi2:Typ350mA wikiより)
電源は5V2A出力できるものを使用。普通のスマホ充電器です。今回のケースでは1Aでも動くと思います。(実測で250mAでした)

接続

まずはBME280モジュールのジャンパを設定します。I2CのプルアップはRaspberryPi側でされているので、J3のみ半田を盛ってください。

RaspberryPiとの接続は以下の通り
BME280モジュールのSDO(5ピン)はモジュール基板上でGNDまたはVDDに接続しておくと、RaspberryPiとの接続線を減らせて綺麗に見えます

WiringPiのダウンロードとインストール

始めにGitをインストールします。既にインストールしてる方は不要です
$ sudo apt-get install git-core

WiringPiをクローンして、buildします

$ git clone git://git.drogon.net/wiringPi
$ cd ~/wiringPi
$ ./build

途中だいぶ省略しましたが、詳しくはwiringPiのHPを参照してください。

WiringPiを使ってセンサを読む

ここではWiringPiライブラリのなかの、WiringPiI2Cのみ使用します。他にもGIPOやSPIなどのライブラリも含まれていますので、必要な方はIncludeしてください。
メイン関数で BME280Interfaceのインスタンスを作成してmeasurement()を呼ぶと、humidity, temperature, pressureの数値が更新されます。

コンパイル

$ gcc -Wall getTempHumPres.cpp -l wiringPi -o getTempHumPres
これでBME280から気温、湿度、気圧を読み取ることができました。
あとはシェルから呼ぶなりPythonから呼ぶなり、
ソースコードを改造して全てCで書くなりお好きなように調理してください。

おまけ1 ソースコードの解説


メイン関数で BME280Interfaceのインスタンスを作成してmeasurement()を呼ぶと、humidity, temperature, pressureの数値が更新されます。bme280Interface.cppのほうはデバイスIDなどを変更したい場合以外、基本的に修正する必要はありません。
キャリブレーションは本来なら固定小数点で計算すべきなのですが、めんどくさ(ry
doubleにそのまま代入しております。
固定小数点が必要な場合は、Arduino用のソースコードを参考にしてみてください。
↓スイッチサイエンスさんのBME280 Arduinoスケッチのサンプル
http://trac.switch-science.com/wiki/BME280

おまけ2 wiringPiI2Cの関数について

int wiringPiI2CSetup(int deviceID)
  • deviceID : デバイスIDは、I2Cデバイスのマニュアルに書かれています。BME280の場合、デフォルトで0x76です。
  • 戻り値 : 通常はstandard Linux filehandleが戻ってきます。-1が出たら接続エラーです。

int wiringPiI2CRead(int fd)
int wiringPiI2CReadReg8(int fd, int reg)
int wiringPiI2CReadReg16(int fd, int reg)
  • fd : setupで取得したファイルハンドル
  • reg : I2Cデバイスのレジスタアドレス
  • 戻り値 : I2Cデバイスのレジスタの内容。Reg8は8ビット、Reg16は16bit

一番目のwiringPiI2CReadは、こちらはSMBUSプロトコルを使わないI2Cデバイスとの通信に利用する関数なので今回は使いません。 Reg8,Reg16はそれぞれ8bitのデータ読み込み、16bitのデータ読み込みが実行されます。
int wiringPiI2CWrite(int fd, int data)
int wiringPiI2CWriteReg8(int fd, int reg, int data)
int wiringPiI2CWriteReg16(int fd, int reg, int data)
  • fd : setupで取得したファイルハンドル
  • reg : I2Cデバイスのレジスタアドレス
  • data : 書き込むデータ
  • 戻り値 : 不明。本家マニュアルに記載なし。

おまけ3 細かいこと

WireingPiI2CのReadWriteは8bitと16bitしか用意されていません。ブロック転送、バースト転送が出来ないので、直接I2Cをコントロールする場合よりバス占有時間が長くなります。(ほんの数十uSecですが)

参照

WiringPi http://wiringpi.com/
スイッチサイエンス http://trac.switch-science.com/wiki/BME280
秋月電子 http://akizukidenshi.com/catalog/g/gK-09421/

0 件のコメント:

コメントを投稿