2013年10月1日火曜日

Arduino 自作ライブラリを作る

Arduino では C++ でライブラリを自作できるので、試してみました。

今現在、LED マトリックスで遊んでいるところなので、
それで使っている 74HC595 シフトレジスタの操作をライブラリにしてみたいと思います。

ライブラリの作成には以下のサイトを参考にしました。
arduinoIDEの使い方:自作ライブラリの作り方

ファイル構成
今回のライブラリ名は ShiftRegister とします。
構成は以下のように、任意フォルダの下に、ヘッダー・ソース・キーワードファイルを作ります。
[ShiftRegister]
|- lib74hc595.h
|- lib74hc595.cpp
|- keywords.txt
(ディレクトリ名とソースファイル名は異なっていても問題ありません。)

ヘッダー

#ifndef lib74hc595_H_
#define lib74hc595_H_
#include "arduino.h"

class ShiftRegister
{
public:
 ShiftRegister(int latch, int clock, int data);
 
public:
 void Begin(void);
 void Output(int mode, byte data);
 void Output16(int mode, int data);
 void End(void);
 
private:
 int latchPin, clockPin, dataPin;
};

#endif

Arduino の標準関数などは ardunino.h を include することで使用できます。

ソース

#include "arduino.h"
#include "lib74hc595.h"

ShiftRegister::ShiftRegister(int latch, int clock, int data)
: latchPin(latch), clockPin(clock), dataPin(data)
{
 pinMode(latchPin, OUTPUT);
 pinMode(clockPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
}

void ShiftRegister::Begin(void)
{
    digitalWrite(latchPin, LOW);
}

void ShiftRegister::Output(int mode, byte data)
{
    shiftOut(dataPin, clockPin, mode, data);
}
void ShiftRegister::Output16(int mode, int data)
{
    if( mode == LSBFIRST )
    {
        shiftOut(dataPin, clockPin, mode, (data   )&0xFF);
        shiftOut(dataPin, clockPin, mode, (data>>8)&0xFF);
    }
    else
    {
        shiftOut(dataPin, clockPin, mode, (data>>8)&0xFF);
        shiftOut(dataPin, clockPin, mode, (data   )&0xFF);
    }
}

void ShiftRegister::End(void)
{
    digitalWrite(latchPin, HIGH);
}


特に気にすることなく C++ のコードを書きます。
ピン操作などは標準で用意されていますので、ただ呼ぶだけです。

キーワード
キーワードファイルを設定することで文字に色を付けることができます。
今回は以下のように設定しました。

ShiftRegister KEYWORD1
Begin KEYWORD2
End KEYWORD2
Output KEYWORD2

セットアップ
ライブラリが書けたら、Arduino IDE に認識してもらえるようにセットアップします。
と、いってもやることは先ほど作成したライブラリをディレクトリごとコピーするだけです。

コピー先はこちら > %ProgramFiles%\Arduino\libraries

コピーしたら次は使ってみましょう。

使う
作成したライブラリを使うには IDE のメニューの「スケッチ」の「ライブラリの使用」にライブラリリストが表示されるので、その中から追加した「ShiftRegister」を選択します。(名前はディレクトリ名になります。)

すると、コードにライブラリのヘッダーが include されます。

使い方も C++ とほぼ一緒です。
#include <lib74hc595.h>

int latchPin = 8;  // 74HC595のST_CPへ
int clockPin = 12; // 74HC595のSH_CPへ
int dataPin = 11;  // 74HC595のDSへ
int ledPin = 13;

ShiftRegister sr(latchPin, clockPin, dataPin);

void setup() {
  pinMode(ledPin, OUTPUT);
}
 
void loop() {
  for (int j = 0; j < 16; j++) {
    sr.Begin();
    // シフト演算を使って点灯するLEDを選択しています
    sr.Output(LSBFIRST, (1<<j)>>8);
    sr.Output(LSBFIRST, 1<<j);
    if( j % 2 == 0 ) {
      digitalWrite(ledPin, LOW);
    } else {
      digitalWrite(ledPin, HIGH);
    }
    // 送信終了後latchPinをHIGHにする
    sr.End();
//    delay(100);
  }
}

ライブラリを使用したライブラリ
別のライブラリを使用して、新しいライブラリを作ることもできます。
その場合は、普通に使用したいライブラリのヘッダーファイルを include して、
後は普通にライブラリを書くだけです。

#ifndef ledmatrix_H_
#define ledmatrix_H_
#include "arduino.h"
#include "lib74hc595.h"

class LedMatrix
{
public:
    enum {
          RED
        , GREEN
        , ORANGE
    };
    enum {
        MODE_NORMAL
        , MODE_INVERT
    };
public:
    LedMatrix(int latch, int clock, int data
    , int latch_r, int clock_r, int data_r
    , int latch_g, int clock_g, int data_g);

public:
    void setmode(int mode);
public:
    void bitblt(const uint16_t red[16], const uint16_t green[16]);
    void bitblt(const uint16_t data[16], int color);
    
    void slideout_h(const uint16_t red[][16], const uint16_t green[][16]
                      , int num, int delay_n);
    void slideout_h(const uint16_t data[][16], int num, int delay_n, int color);
    void flashout(const uint16_t array[][16], int num, int delay_n, int color);
    
private:
    void setcol(uint16_t red, uint16_t green);
    uint16_t getclearbit();
    
public:
    ShiftRegister m_raw;
    ShiftRegister m_red;
    ShiftRegister m_grn;
    
    int m_mode;
};

#endif

まとめ
まとまったコードをライブラリにすることで、メインのコードをコンパクトに書けるようになりました。
また、使い慣れた言語で書ける点も良い所です。

さて、この LED マトリックスの納期まで残り一週間ほどになってしまいました(汗
ライブラリを使ってコードの使いましができるようにはなったので、ラストスパート頑張ります。
では。

0 件のコメント:

コメントを投稿