2012/11/10からのアクセス回数 10613 mbed互換ライブラリ †mbedはC++のクラスライブラリとユーザの作成したデバイス用のソースコードが豊富で、 デバイスを接続して新しいガジェットを作るのに適しています。 このような環境を別のハードにも欲しいと思う人はいるもので、そらみみの声に IDEを使わずにLPCXpresso LPC1768のプログラムを開発する というブログにLPC1768用にmbed互換ライブラリの作成記事がありました。 mbed互換ライブラリでは、mbedのDigitalOut, BusOut, TextLCDが実装されているだけですが、 これをRaspberryPiに移植すれば、mbedユーザが作った豊富なライブラリを活用できるのではないかと思い移植してみることにしました。 WiringPiライブラリのインストールについては、 raspberrypi/Raspberry PiでIO制御 を参照してください。 mbed互換ライブラリのRaspberryPiへの移植 †ピン定義(PinNames.h) †最初にRaspberryPiのピン番号をmbedに習い1番ピンから反時計回りに割り振ることにしました。 これを wait関数 †mbed互換ライブラリにはwait_usしかありませんが、mbedのwait_api.hの関数を wait_msの実装は以下のような感じです。 void wait_ms(int ms) { struct timespec sleeper, dummy ; sleeper.tv_sec = (time_t)(ms / 1000) ; sleeper.tv_nsec = (long)(ms % 1000) * 1000000 ; nanosleep (&sleeper, &dummy) ; } DigitalOutクラス †DigitalOutには、WiringPiのライブラリを使用したので、とてもすっきり実装できました。
protected: PinName _pin; int _wiring;
void DigitalOut::write(int value) { if (_wiring > 0) { if (value) { digitalWrite (_wiring, 1); } else { digitalWrite (_wiring, 0); } } } int DigitalOut::read() { if (_wiring > 0) { return (digitalRead(_wiring)); } else { return (0); } } Makefileの変更 †上記以外のBusOut.h, BusOut.cpp, TextLCD.h, TextLCD.cppはそのまま使用しました。 残るは #DEBUG = -g -O0 INCLUDE = -I/usr/local/include -I. CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe LDFLAGS = -L/usr/local/lib LIBS = -lwiringPi LED点滅プログラム †GPIO18を使ってLEDを1秒間隔で点滅させるプログラムをLEDTest.cppを以下のように作成しました。 #include <mbed.h> #include <stdlib.h> #include <unistd.h> DigitalOut led(p21); int main() { while(1) { led = !led; wait_us(1000000); } } ほとんどmbedのテンプレートと同じ形式でRaspberryPiで動かすことができます。 TextLCDを試す †後閑さんの「C言語によるPICプログラミング入門」で紹介されていた3行表示のLCD を使って、TextLCD.cppをテストしました。このLCDの接続は、 でデータ転送には、4bitのみを使っています。 私の備忘録として、接続コネクタのピンは以下のようになっています。
lcd(p4, p7, p8, p16, p18, p19) とし、
に接続しました。 以下に動作中の様子を示します。 I2Cの追加 †RaspberryPi版の追加機能として、I2Cを実装しました。
I2C::I2C(PinName sda, PinName scl, const char *name) { _name = (char *)name; _fd = -1; // ハードI2Cのみをサポート(ピン固定) if (sda == SDA && scl == SCL) { _fd = open("/dev/i2c-0", O_RDWR); } } int I2C::read(int address, char *data, int length, bool repeated) { int len; if (_fd >= 0) { ioctl(_fd, I2C_SLAVE, address>>1); if ((len = ::read(_fd, data, length)) > 0) { // 今は、戻り値のサイズをチェックしない return (0); } else return (-1); } else return (-1); } int I2C::write(int address, const char *data, int length, bool repeated) { int len; if (_fd >= 0) { int addr = address>>1; ioctl(_fd, I2C_SLAVE, addr); if ((len = ::write(_fd, data, length)) > 0) { // 今は、戻り値のサイズをチェックしない return (0); } else return (-1); } else return (-1); } LM73の例題 †I2Cの例題として、LM73を使って温度を読み取るクラスを作成します。 #include <mbed.h> #include "LM73.h" LM73::LM73(PinName sda, PinName scl) : i2c(sda, scl) { char cmd[2]; // LM73設定 cmd[0] = 0x04; // register 4 cmd[1] = 0x60; // 14bit resolution i2c.write( LM73_ADDR, cmd, 2); // ポインタを0にしておく(readするだけで温度が読めるようになる) cmd[0] = 0x00; i2c.write( LM73_ADDR, cmd, 1); } LM73::~LM73() { } float LM73::read() { char cmd[2]; i2c.read( LM73_ADDR, cmd, 2); // Send command string int int_val = cmd[0] <<1 | cmd[1]>>7; int ceil_val = ((cmd[1] & 0x7f)*200) >>8; return float(int_val + ceil_val/100.0); } LM73との接続は以下のようにしました。 システムのIOを使用するため、互換ライブラリを使ったプログラムの実行には、sudoコマンドが必要です。 以下のようにI2CTestを実行します。 $ sudo ./I2CTest 22.18 22.21 22.21 Raspberry版mbed互換ライブラリのソース †今回作成したRaspberry版mbed互換ライブラリを以下におきます。 SPIを追加したバージョンは、以下を参照してください。 コメント †皆様のご意見、ご希望をお待ちしております。 Tweet |