8x8 BiColor LED Matrix
使用デバイス
今回はAdafruitの8x8 BiColor LED Matrix(https://www.adafruit.com/product/902)の制御を行ってみます。
https://learn.adafruit.com/adafruit-led-backpack/bi-color-8x8-matrix
8x8ドットで各2色のLEDを個別に制御できるので、消灯、緑、赤、黄色の4つの状態を表現できます
これはいろいろなステータス表示を行えそうです。
デバイスの入手について
日本での購入:
スイッチサイエンス
https://www.switch-science.com/catalog/1498/
アマゾン
単色版は手頃な値段です(下記のコードで、LED_YELLOWを指定すれば、必ず点灯します)。
アマゾン
デバイスの制御
Adafruitのサンプルコードはこちら。https://github.com/adafruit/Adafruit_LED_Backpack
Displayのメモリについては少しトリッキーです。
上記表の意味をサンプルを例に説明します。これは、Addressの0x00はgreenのLEDマトリクスの1列目、Addressの0x01はredのLEDマトリクスの1列名を表します。
従って、Address 0x00から次のようなデータを16バイト書き込むと、全てグリーンになります。
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00
全てをレッドにするためには次のようにAddress 0x00から16バイトを書き込みます。
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF
次のものは、1列目をGreenに点灯します。
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
LED8x8bi.c
#define LED_ON 1
#define LED_OFF 0
#define LED_RED 1
#define LED_YELLOW 2
#define LED_GREEN 3
#define HT16K33_BLINK_CMD 0x80
#define HT16K33_BLINK_DISPLAYON 0x01
#define HT16K33_BLINK_OFF 0
#define HT16K33_BLINK_2HZ 1
#define HT16K33_BLINK_1HZ 2
#define HT16K33_BLINK_HALFHZ 3
#define HT16K33_CMD_BRIGHTNESS 0xE0
#define SEVENSEG_DIGITS 5
#define ADAFRUIT_LEDBACKPACK_DEFAULT_ADDR 0x70 //b'1110000
uint8_t LED8x8bi_i2c_addr = ADAFRUIT_LEDBACKPACK_DEFAULT_ADDR;
uint16_t LED8x8bi_displaybuffer[8];
uint8_t LED8x8bi_rotation = 1;
#define swap(a, b) { int16_t t = a; a = b; b = t; }
#define _BV(bit) (1<<(bit))
void LED8x8bi_setBrightness(uint8_t b)
{
if (b > 15) b = 15;
I2CDev_writeCommand(LED8x8bi_i2c_addr, HT16K33_CMD_BRIGHTNESS | b);
}
void LED8x8bi_blinkRate(uint8_t b)
{
if (b > 3) b = 0; // turn off if not sure
I2CDev_writeCommand(LED8x8bi_i2c_addr, HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1));
}
void LED8x8bi_begin(uint8_t _addr)
{
LED8x8bi_i2c_addr = _addr;
I2CDev_writeCommand(LED8x8bi_i2c_addr, 0x21); // turn on oscillator
LED8x8bi_blinkRate(HT16K33_BLINK_OFF);
LED8x8bi_setBrightness(15); // max brightness
}
void LED8x8bi_writeDisplay(void)
{
uint8_t buffer[16];
uint8_t i,j;
j=0;
for (i=0;i<8;i++)
{
buffer[j++] = LED8x8bi_displaybuffer[i] & 0xFF;
buffer[j++] = (LED8x8bi_displaybuffer[i & 0xF] >> 8) & 0xFF;
}
I2CDev_writeBytes(LED8x8bi_i2c_addr, 0, buffer, 16);
}
void LED8x8bi_clear(void)
{
for (uint8_t i=0; i<8; i++) {
LED8x8bi_displaybuffer[i] = 0;
}
}
void LED8x8bi_all_yellow(void)
{
for (uint8_t i=0; i<8; i++) {
LED8x8bi_displaybuffer[i] = 0xFFFF;
}
}
void LED8x8bi_all_yellow_1(void)
{
for (uint8_t i=0; i<8; i++) {
LED8x8bi_displaybuffer[i] = 0x0101;
}
}
void LED8x8bi_all_red(void)
{
for (uint8_t i=0; i<8; i++) {
LED8x8bi_displaybuffer[i] = 0xFF00;
}
}
void LED8x8bi_all_red_1(void)
{
for (uint8_t i=0; i<8; i++) {
LED8x8bi_displaybuffer[i] = 0x0100;
}
}
void LED8x8bi_all_green(void)
{
for (uint8_t i=0; i<8; i++) {
LED8x8bi_displaybuffer[i] = 0x00FF;
}
}
void LED8x8bi_all_green_1(void)
{
for (uint8_t i=0; i<8; i++) {
LED8x8bi_displaybuffer[i] = 0x0001;
}
}
uint8_t LED8x8bi_getRotation(void)
{
return LED8x8bi_rotation;
}
void LED8x8bi_drawPixel(int16_t x, int16_t y, uint16_t color)
{
if ((y < 0) || (y >= 8)) return;
if ((x < 0) || (x >= 8)) return;
switch (LED8x8bi_getRotation()) {
case 1:
swap(x, y);
x = 8 - x - 1;
break;
case 2:
x = 8 - x - 1;
y = 8 - y - 1;
break;
case 3:
swap(x, y);
y = 8 - y - 1;
break;
}
if (color == LED_GREEN) {
// Turn on green LED.
LED8x8bi_displaybuffer[y] |= 1 << x;
// Turn off red LED.
LED8x8bi_displaybuffer[y] &= ~(1 << (x+8));
} else if (color == LED_RED) {
// Turn on red LED.
LED8x8bi_displaybuffer[y] |= 1 << (x+8);
// Turn off green LED.
LED8x8bi_displaybuffer[y] &= ~(1 << x);
} else if (color == LED_YELLOW) {
// Turn on green and red LED.
LED8x8bi_displaybuffer[y] |= (1 << (x+8)) | (1 << x);
} else if (color == LED_OFF) {
// Turn off green and red LED.
LED8x8bi_displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8));
}
}