IOエクスパンダを使ったプログラム例2

ドットマトリクスLEDライブラリの変更

それでは、STEP10で作成したドットマトリクスLEDライブラリdotmatrixled.cppをIOエクスパンダ用に修正し、プログラム例10-4のように「A」をダイナミック点灯してみましょう。

既存のコードですが、完全に削除してしまうのはもったいないので、まずはこれをマクロでコメントアウトしましょう。

dotmatrixled.cpp 既存コードのコメントアウト

/**********************************************************
  製作者  アドウィン
  解説   ドットマトリクス LED の制御用の関数類
**********************************************************/
#include <Arduino.h> // Arduino.h の読み込み

// IOエクスパンダ使用(使わない場合はこの行をコメントアウト)
#define IOEXPANDER

#ifdef IOEXPANDER

/* ここにIOエクスパンダ用コードを記載 */

#else

// ドットマトリクスLEDアノード側ピンの配列
int ledAnodePins[8] = {0, 2, 4, 5, 16, 17, 18, 19};
// ドットマトリクスLEDカソード側ピンの配列
int ledCathodePins[8] = {21, 22, 23, 25, 26, 27, 32, 33};

/*
 * ドットマトリクスLED初期設定関数
 */
void initLed() {

  // 各アノード・カソード端子の設定
  for(int i=0; i<8; i++) {

    // 入出力設定
    pinMode(ledAnodePins[i], OUTPUT);
    pinMode(ledCathodePins[i], OUTPUT);

    // 出力レベル設定(全消灯)
    digitalWrite(ledAnodePins[i], LOW);
    digitalWrite(ledCathodePins[i], HIGH);
  }
}

/*
 * ドットマトリクスLED点灯パターン設定関数
 * 引数: patternAnode 表示するパターン( アノード側)
 *       patternCathode 表示するパターン( カソード側)
 */
void setLed(byte patternAnode, byte patternCathode) {

  // カソード側のパターンを反転
  patternCathode = ~patternCathode;

  // 列および行の点灯設定
  for(int i=0; i<8; i++) {
    // i 列目に patternAnod の i ビット目の値を設定
    digitalWrite(ledAnodePins[i], bitRead(patternAnode, i));
    // i 行目に patternCathode の i ビット目の値を設定
    digitalWrite(ledCathodePins[i], bitRead(patternCathode, i));
  }
}
#endif
Code language: Arduino (arduino)

なお、ここで用いたマクロは、ヘッダファイルのインクルードガードで使った「#ifndef」〜「#endif」と類似した以下のようなものです。

// 「定義値」が設定されている時は「#ifdef」〜「#else」を処理に含め,
// 「#else」〜「#endif」を処理に含めない(定義されていない時は逆)
#ifdef 定義値#else#endifCode language: Arduino (arduino)

IOエクスパンダ用のコードとしては、まずは空の関数を準備しましょう。

dotmatrixled.cpp 空の関数の準備

#ifdef IOEXPANDER

/*
 * ドットマトリクスLED初期設定関数
 */
void initLed() {
}

/*
 * ドットマトリクスLED点灯パターン設定関数
 * 引数: patternAnode 表示するパターン(アノード側)
 *       patternCathode 表示するパターン(カソード側)
 */
void setLed(byte patternAnode, byte patternCathode) {
}

#else
(以下略)
Code language: Arduino (arduino)

プログラム例11-1を参考に、initLed関数の実装を行いましょう。IOエクスパンダのピンを出力に設定し、全消灯します。また、関数外でWire.hの読み込みやIOエクスパンダのアドレスの設定も必要になります。

dotmatrixled.cpp initLed関数の実装

#ifdef IOEXPANDER

#include <Wire.h> // Wire.h の読み込み

// IOエクスパンダのI2C上でのアドレス
int ioxAdr = 0x27;

/*
 * ドットマトリクスLED初期設定関数
 */
void initLed() {

  // I2Cの初期化
  Wire.begin();

  // IOエクスパンダの初期設定
  Wire.beginTransmission(ioxAdr); // IOエクスパンダとの通信の開始
  Wire.write(0x00); // レジスタのアドレスの設定(0x00=GPIOA入出力設定レジスタ)
  Wire.write(0x00); // GPIOAのピンを出力に設定(0x00=GPIOA入出力設定レジスタに0x00を書き込み)
  Wire.write(0x00); // GPIOBのピンを出力に設定(0x01=GPIOB入出力設定レジスタに0x00を書き込み)
  Wire.endTransmission(); // データを送信し通信を完了

  // IOエクスパンダのピンの初期値の設定
  Wire.beginTransmission(ioxAdr); // IOエクスパンダとの通信の開始
  Wire.write(0x12); // レジスタのアドレスの設定(0x12=GPIOA出力レベル設定レジスタ)
  Wire.write(0b00000000); // GPIOAのピンの出力レベルの設定(0x12=GPIOA出力レベル設定レジスタ)
  Wire.write(0b11111111); // GPIOBのピンの出力レベルの設定(0x13=GPIOB出力レベル設定レジスタ)
  Wire.endTransmission(); // データを送信し通信を完了
}

/*
 * ドットマトリクスLED点灯パターン設定関数
 * 引数: patternAnode 表示するパターン(アノード側)
 *       patternCathode 表示するパターン(カソード側)
 */
void setLed(byte patternAnode, byte patternCathode) {
}

#else
(以下略)
Code language: Arduino (arduino)

プログラム例11-1を参考に、setLed関数を実装しましょう。以前と同じ動作になるよう、カソード側は引数の値をビット反転させて出力レベルに設定しています。

dotmatrixled.cpp setLed関数の実装

/*
 * ドットマトリクスLED点灯パターン設定関数
 * 引数: patternAnode 表示するパターン(アノード側)
 *       patternCathode 表示するパターン(カソード側)
 */
void setLed(byte patternAnode, byte patternCathode) {
  Wire.beginTransmission(ioxAdr); // IOエクスパンダとの通信の開始
  Wire.write(0x12); // レジスタのアドレスの設定(0x12=GPIOA出力レベル設定レジスタ)
  Wire.write(patternAnode); // アノード側の出力レベルの設定(0x12=GPIOA出力レベル設定レジスタ)
  Wire.write(~patternCathode); // カソード側の出力レベルの設定(0x13=GPIOB出力レベル設定レジスタ)
  Wire.endTransmission(); // 送信の完了
}
Code language: Arduino (arduino)

それでは、main.cppをSTEP10のプログラム例10-4に戻してみましょう。

プログラム例 (main.cpp) 10-4(再掲)

#include <Arduino.h> // Arduino.h の読み込み
#include "char8x8.h" // char8x8.h の読み込み
#include "dotmatrixled.h" // dotmatrixled.h の読み込み

/*
 * setup 関数
 */
void setup() {
  /* ここにプログラムの最初に1回だけ実行したい処理を上から順に記述していきます */

  // シリアル通信を115200bpsで開始
  Serial.begin(115200);

  Serial.println("初期設定の開始");

  // ドットマトリクスLED初期設定
  initLed();

  Serial.println("初期設定の完了");
}

/*
 * loop 関数
 */
void loop() {
  /* ここにプログラム中で繰り返し実行したい処理を上から順に記述していきます */

  for(int i=0; i<8; i++) {

    // ドットマトリクスLEDのi行目を表示
    setLed(ledPatternA[i], ledCathodePattern[i]);
    // 時間待ち
    delay(1);
  }
}
Code language: Arduino (arduino)

ドットマトリクスLEDは「A」を表示しましたか?

一応表示はしていますが、多少文字が滲んで見えるかもしれません。

文字が滲んでしまったのは何故でしょうか? 解消するにはどうすれば良いでしょうか? 原因と対策を考え、コードを修正してみましょう。対策例を次に示します。

前の記事

I2C通信の関数

次の記事

I2Cの速度の設定