8×8 LED Matrix シールドを自作した後、たまたまガリレオ7さんのオリジナルの基板を入手しました。

2つの8x8 LED Matrixシールド

2つの8x8 LED Matrixシールド

期せずして8×8 LED Matrix シールドが2つになったのですが、自作とオリジナルとはピンアサインが違うだけで、同じスケッチで動作します。そこで使い回し出来るようプリプロセッサ命令文をスケッチに書き足しました。

/*
 * ガリレオ7さんのサンプルが元です。
 */

// ここを書き足し
#define GALILEO_SHIELD
#ifdef GALILEO_SHIELD
  int col[] = {2, 3, 4, 5, 6, 7, 8, 9};
  int row[] = {10, 11, 12, 14, 15, 16, 17, 18};
#else
  int col[] = {8, 10, 5, 9, 3, 6, 4, 7};
  int row[] = {13, 18, 19, 11, 2, 12, 17, 16};
#endif

int c = 0;
int bct = 0;
int cnt = 0;

char* dat[8] = {
  "----------***-------*---*-----------*******-------",
  "---------*---*------*---*-----------*******-------",
  "---------*----------*---*---------------**--------",
  "---------*------*---*-*-*--**---**-----**---------",
  "---------*--**-*-*--*---*-*--*-*--*----**---------",
  "---------*---*-*-*--*-*-*-***--*--*---**----------",
  "---------*---*-*-*--*-*-*-*----*--*---**----------",
  "----------***---*-*-*-*-*--***--**----**----------"
};

void setup(void)
{
    for (int i = 0; i < 8; i++)
    {
        pinMode(col[i], OUTPUT);
        digitalWrite(col[i], LOW);
        pinMode(row[i], OUTPUT);
        digitalWrite(row[i], HIGH);
    }
}

void loop(void)
{
    digitalWrite(row, HIGH);
    if (c++ >= 7)  c = 0;

    for (int i = 0; i < 8; i++)
    {
        if (dat[7-c][bct+i] == '*')
        {
            digitalWrite(col[i], HIGH);
        }
        else
        {
            digitalWrite(col[i], LOW);
        }
    }

    digitalWrite(row, LOW);
    delayMicroseconds(2500);
    if (cnt++ >= 80)
    {
        cnt = 0;
        if (bct++ > 41) bct = 0;
    }
}

上記のスケッチなら問題なくコンパイルが通りますが、GALILEO_SHIELDの宣言を外してコンパイルすると奇妙なエラーが出ます。

奇妙なエラー

奇妙なエラー

そこでArduino IDEが作成したC++のソースを確認したところ、以下のような状況。

/*
 * \u30ac\u30ea\u30ec\u30aa\uff17\u306e\u30b5\u30f3\u30d7\u30eb\u304c\u5143\u3067\u3059\u3002
 */

//#define GALILEO_SHIELD
#ifdef GALILEO_SHIELD
  #include "WProgram.h"
void setup(void);
void loop(void);
int col[] = {2, 3, 4, 5, 6, 7, 8, 9};
  int row[] = {10, 11, 12, 14, 15, 16, 17, 18};
#else
  int col[] = {8, 10, 5, 9, 3, 6, 4, 7};
  int row[] = {13, 18, 19, 11, 2, 12, 17, 16};
#endif

int c = 0;
int bct = 0;
int cnt = 0;

char* dat[8] = {
  "----------***-------*---*-----------*******-------",
  "---------*---*------*---*-----------*******-------",
  "---------*----------*---*---------------**--------",
  "---------*------*---*-*-*--**---**-----**---------",
  "---------*--**-*-*--*---*-*--*-*--*----**---------",
  "---------*---*-*-*--*-*-*-***--*--*---**----------",
  "---------*---*-*-*--*-*-*-*----*--*---**----------",
  "----------***---*-*-*-*-*--***--**----**----------"
};

/*以下省略*/

プリプロセッサ命令の条件の中に、WProgram.hのインクルードとかsetup関数の宣言とか入ってしまってます。プリプロセッサ命令なんか気にせずにソースを寄せ集めるらしいです。そらぁ、奇妙なエラーも納得です。

で、この寄せ集めの癖を考慮してソースを書き直しました。

/*
 * ガリレオ7のサンプルが元です。
 */

int c = 0;
int bct = 0;
int cnt = 0;

char* dat[8] = {
  "----------***-------*---*-----------*******-------",
  "---------*---*------*---*-----------*******-------",
  "---------*----------*---*---------------**--------",
  "---------*------*---*-*-*--**---**-----**---------",
  "---------*--**-*-*--*---*-*--*-*--*----**---------",
  "---------*---*-*-*--*-*-*-***--*--*---**----------",
  "---------*---*-*-*--*-*-*-*----*--*---**----------",
  "----------***---*-*-*-*-*--***--**----**----------"
};

//#define GALILEO_SHIELD
#ifdef GALILEO_SHIELD
  int col[] = {2, 3, 4, 5, 6, 7, 8, 9};
  int row[] = {10, 11, 12, 14, 15, 16, 17, 18};
#else
  int col[] = {8, 10, 5, 9, 3, 6, 4, 7};
  int row[] = {13, 18, 19, 11, 2, 12, 17, 16};
#endif

void setup(void)
{
    for (int i = 0; i < 8; i++)
    {
        pinMode(col[i], OUTPUT);
        digitalWrite(col[i], LOW);
        pinMode(row[i], OUTPUT);
        digitalWrite(row[i], HIGH);
    }
}

void loop(void)
{
    digitalWrite(row, HIGH);
    if (c++ >= 7)  c = 0;

    for (int i = 0; i < 8; i++)
    {
        if (dat[7-c][bct+i] == '*')
        {
            digitalWrite(col[i], HIGH);
        }
        else
        {
            digitalWrite(col[i], LOW);
        }
    }

    digitalWrite(row, LOW);
    delayMicroseconds(2500);
    if (cnt++ >= 80)
    {
        cnt = 0;
        if (bct++ > 41) bct = 0;
    }
}

このように何かの変数の宣言後、プリプロセッサ命令文を書けば問題は顕著化しません。

で教訓、

Arduino のスケッチでは、いきなりプリプロセッサ命令文を書いてはイケナイ