FrontPage

2012/11/10からのアクセス回数 5660

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番ピンから反時計回りに割り振ることにしました。

My-Pin-Layout.jpg

これをfilePinNames.hに定義しました。

wait関数

mbed互換ライブラリにはwait_usしかありませんが、mbedのwait_api.hの関数をfilewait_api.cに実装しました。残念ながら、wait_usはnanosleepシステム関数を使った場合、TextLCDが正常に動作しなかったためビジーウェイトで実装しました。

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のライブラリを使用したので、とてもすっきり実装できました。

fileDigitalOut.hで保持しているのは、ピン名(_pin)と対応するWiringPiのピン番号(_wiring)のみです。

protected:
	PinName        _pin;
	int                 _wiring;

fileDigitalOut.cpp の実装は、ピン名のチェック以外はそのままWiringPiの関数digitalWrite, digitalReadを呼び出すだけです。

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はそのまま使用しました。

残るはfileMakefileですが、以下の部分を変更しました。 WiringPiのライブラリが/usr/local/includeにインストールされているので、-I, -Lオプションで指定しています。また、wiringPiライブラリを使用しているので、LIBSに追加しています。

#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

LCD.png

を使って、TextLCD.cppをテストしました。このLCDの接続は、

3LineLCD-sch.png

でデータ転送には、4bitのみを使っています。

私の備忘録として、接続コネクタのピンは以下のようになっています。

  • 1(白)5V
  • 2 DB7
  • 3 DB6
  • 4 DB5
  • 5 DB4
  • 6 E
  • 7 RS
  • 8, 9 は未接続
  • 10 GND

fileLCDTest.cpp でのlcdの定義は、

lcd(p4, p7, p8, p16, p18, p19)

とし、

  • p4: RS
  • p7: E
  • p8: DB4
  • p16: DB5
  • p18: DB6
  • p19: DB7

に接続しました。

以下に動作中の様子を示します。

TextLCD-Sample.png

I2Cの追加

RaspberryPi版の追加機能として、I2Cを実装しました。

fileI2C.cpp では、デバイス/dev/i2c-0をオープンし、ioctlを使ってI2Cアドレスをセットした後に、 read, writeを行う簡単なものです。

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を使って温度を読み取るクラスを作成します。

fileLM73.cpp

#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との接続は以下のようにしました。

LM73-setting.png

システムのIOを使用するため、互換ライブラリを使ったプログラムの実行には、sudoコマンドが必要です。

以下のようにI2CTestを実行します。

$ sudo ./I2CTest 
22.18
22.21
22.21

Raspberry版mbed互換ライブラリのソース

今回作成したRaspberry版mbed互換ライブラリを以下におきます。

SPIを追加したバージョンは、以下を参照してください。

コメント

選択肢 投票
おもしろかった 11  
そうでもない 0  
わかりずらい 0  

皆様のご意見、ご希望をお待ちしております。


(Input image string)


添付ファイル: fileLM73-setting.png 550件 [詳細] fileLM73.cpp 543件 [詳細] fileI2C.cpp 755件 [詳細] fileRaspberry-Pi.tgz 338件 [詳細] fileLCDTest.cpp 369件 [詳細] file3LineLCD-sch.png 504件 [詳細] fileTextLCD-Sample.png 542件 [詳細] fileLCD.png 527件 [詳細] fileMakefile 371件 [詳細] fileDigitalOut.cpp 420件 [詳細] fileDigitalOut.h 453件 [詳細] filewait_api.c 410件 [詳細] filePinNames.h 434件 [詳細] fileMy-Pin-Layout.jpg 592件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-08-26 (水) 16:59:32 (726d)
SmartDoc