micro:bit キャラクタ表示LCDの接続

micro:bitは、LEDやボタン、加速度センサ、地磁気センサがついていて面白いのですが、ちょっとした表示をしてみたいこともあります。I2C接続AQMシリーズのキャラクタ表示LCDを接続してみます。

秋月電子で購入した安価なI2C接続小型LCDモジュール(8×2行)ピッチ変換キット[AE-AQM0802]を使います。本当は、Raspberry piで使用するつもりで購入しておいたのですが、このような問題がありバス・リピータが必要なようです。代わりにmicro:bitで使うことにします。

micro:bitには加速度センサと地磁気センサが搭載されています。せっかくLCDを接続するので、加速度センサの値を表示できるようにします。さらに、こちらを参考にLEDマトリックスで加速度センサの値を表示するようにします。

■Arduino IDE インストール
開発環境は。Arduino IDEを利用します。こちらの本家サイトからArduino 1.8.12(2020年4月12日時点)をダウンロードしてインストールします。

■Arduino設定
メニューから
 ファイル > 環境設定 > 設定
追加のボードマネージャーのURLに
 https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json
を入力してOKを押します。

 ツール > ボード > ボードマネージャ
検索欄に「nRF」を入力。[Nordic Semiconductor nRF5 Boards by Sandeep Mistry」を選択、インストール。

 ツール > ボード > ボードマネージャ
使用するボードをBBC micro:bitにします。

 ツール > Softdevice
「S110」を選択します。

 ツール > シリアルポート
micro:bitで使用する仮想COMポートを選択します。

次のテストコードを入力して書き込みます。
成功すると、1つのLEDが1秒ごとに点滅します。

const int COL1 = 3;
const int LED = 27;

void setup(){
  Serial.begin(9600);

  pinMode(COL1, OUTPUT);
  digitalWrite(COL1, LOW);

  pinMode(LED, OUTPUT);
}

void loop(){
  digitalWrite(LED, HIGH);
  delay(1000);
  digitalWrite(LED, LOW);
  delay(1000);
}

■LCDの接続
micro:bitのピン配置を参考に接続します。micro:bitの+3V3、SCL(P19)、SDA(P20)とGNDをLCDに接続します。

■加速度センサの確認とライブラリのインストール
micro:bitボードは製造された時期によって2種類あるようです。
こちらを参考にどちらのセンサが搭載されているか確認します。
センサが2つなら
 ・地磁気センサ= MAG3110
 ・加速度センサ = MMA8653
センサが一つなら
 ・地磁気/加速度センサ= LSM303AGR
だそうです。今回使用するのはセンサ2つのタイプですので、MMA8653のライブラリをインストールします。

Arduino IDEにライブラリをインストールします。こちらを参考に加速度センサのライブラリをzipからインストールします。zipファイルを同サイトからダウンロードして、Arduino IDEから
 スケッチ > ライブラリをインクルード > Zip形式のライブラリをインクルード
で、ダウンロードしたZipファイルを選択・インクルードします。

また、簡単にLEDマトリックスを使用するために、こちらを参考にAdafruit Librariesをインストールします。

■実行
下記のコードをスケッチに記述しmicro:bitに書き込みます。ボードの傾き程度に応じてLCDに表示される加速度センサの値が変化し、LEDマトリックスの店頭位置が変化します。また、
 ツール > シリアルモニタ
でシリアルモニタを表示させておくと、加速度センサXYZの値を連続して表示し続けます。

#include <Wire.h>
#include "MMA8653.h"
#include <Adafruit_Microbit.h>
MMA8653 accel;
Adafruit_Microbit_Matrix microbit;

unsigned char lcd_address = 0x3e; // LCD slave
int n = 0;
 
int i2cwritecmd(byte cmd) {
    Wire.beginTransmission(lcd_address);
    Wire.write((byte)0x00); 
    Wire.write(cmd);
    return Wire.endTransmission();
}
 
int i2cwritedata(byte data) {
    Wire.beginTransmission(lcd_address);
    Wire.write(0x40);
    Wire.write(data);
    return Wire.endTransmission();
}
 
void lcdcu_set(int x, int y) {
    byte ca = (x + y * 0x40) | (0x80); i2cwritecmd(ca);
}
 
void lcdclear() {
    i2cwritecmd(0x01);
}
 
void lcdhome() {
    i2cwritecmd(0x02);
}
 
void dsift_l() {
 i2cwritecmd(0x1C);
}
 
void dsift_r() {
    i2cwritecmd(0x18);
}
 
void i2cprint( String pdata) {
    int n = pdata.length();
    for (int i = 0; i < n; i = i + 1) {
        i2cwritedata(pdata.charAt(i));
        delay(1);
    }
}
 
void init_lcd() {
    delay(145);
    i2cwritecmd(0x38);delay(1);
    i2cwritecmd(0x39);delay(1);
    i2cwritecmd(0x14);delay(1);
    i2cwritecmd(0x73);delay(1);
    i2cwritecmd(0x56); //3.3V
    delay(1);
    i2cwritecmd(0x6c);delay(300);
    i2cwritecmd(0x38);delay(1);
    i2cwritecmd(0x01);delay(2);
    i2cwritecmd(0x0C);delay(2);
}
 
int sensorPin = A0;
int sensorValue = 0;
 
void setup() {
    Wire.begin();
    init_lcd();
    Serial.begin(9600);
    Serial.println("microbit accel test");
    microbit.begin();
    accel.begin(false, 2); // 8-bit mode, 2g range
}
 
void loop() {
    lcdclear();
    accel.update();
    int px = accel.getX();
    int py = accel.getY();
    int pz = accel.getZ();
    Serial.print(px);    Serial.print(" , ");
    Serial.print(py);    Serial.print(" , ");
    Serial.println(pz);

    i2cprint(String(px));i2cprint(String(", "));
    i2cprint(String(py));i2cprint(String("")); 
    
    for (int x = 0; x < 5; ++x) {
      for (int y = 0; y < 5; ++y) {
        if (x == px && y == py)
          microbit.drawPixel(x, y, LED_ON);
        else
          microbit.drawPixel(x, y, LED_OFF);
      }
    }
    delay(1000);
}