pdf-icon

Arduino入門

2. デバイス&サンプル

5. 拡張モジュール&サンプル

アクセサリー

6. アプリケーション

Chain RGB 使用チュートリアル

1.準備作業

  • 環境設定:Arduino IDE クイックスタートを参照して IDE のインストールを完了し、実際に使用する開発ボードに応じて対応するボードマネージャと必要なドライバライブラリをインストールしてください。

  • 使用するドライバライブラリ:

  • 使用するハードウェア製品:

2.サンプルプログラム

実際の接続は以下の通りです:

コンパイル要件
M5Stack ボードマネージャ バージョン >= 3.2.4
M5Chain ライブラリ バージョン >= 1.0.5

ピクセルモード

単一ピクセル制御と一括書き込み

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
#include "M5Chain.h"
#include "M5Unified.h"

#define TXD_PIN GPIO_NUM_2
#define RXD_PIN GPIO_NUM_1

Chain M5Chain;

chain_status_t chain_status = CHAIN_OK;
uint8_t rgb_id           = 0;
uint8_t operation_status = 0;

const uint16_t colors[] = {
    0xF800,  // Red
    0x07E0,  // Green
    0x001F,  // Blue
    0xFFE0,  // Yellow
    0xF81F,  // Magenta
    0x07FF   // Cyan
};

bool findFirstRGBDevice()
{
    // Enumerate devices and use the first RGB node
    uint16_t device_nums = 0;
    if (M5Chain.getDeviceNum(&device_nums) != CHAIN_OK || device_nums == 0) {
        Serial.println("No Chain devices found");
        return false;
    }

    device_info_t *infos = (device_info_t *)malloc(sizeof(device_info_t) * device_nums);
    if (infos == nullptr) {
        return false;
    }

    device_list_t devices;
    devices.count   = device_nums;
    devices.devices = infos;

    bool found = false;
    if (M5Chain.getDeviceList(&devices)) {
        for (uint8_t i = 0; i < devices.count; i++) {
            if (devices.devices[i].device_type == CHAIN_RGB_TYPE_CODE) {
                rgb_id = devices.devices[i].id;
                found  = true;
                break;
            }
        }
    }

    free(infos);
    if (found) {
        Serial.printf("RGB device found, id=%d\r\n", rgb_id);
    } else {
        Serial.println("No RGB device found");
    }
    return found;
}

bool prepareRGB()
{
    // Initialize pixel mode, rotation, and brightness
    if (!findFirstRGBDevice()) {
        return false;
    }

    if (M5Chain.setRGBMode(rgb_id, RGB_PIXEL_MODE, &operation_status) != CHAIN_OK || operation_status != 1) {
        return false;
    }

    M5Chain.setRGBRotation(rgb_id, RGB_ROTATION_0, &operation_status);
    M5Chain.setRGBBrightness(rgb_id, 50, &operation_status);
    M5Chain.setRGBClear(rgb_id, &operation_status);
    return true;
}

void setup()
{
    M5.begin();
    Serial.begin(115200);
    Serial.println("RGB pixel demo");
    M5Chain.begin(&Serial2, 115200, RXD_PIN, TXD_PIN);

    if (!prepareRGB()) {
        Serial.println("Chain RGB init failed");
        while (1) {
            delay(100);
        }
    } else {
        Serial.println("Chain RGB init success");
    }
}

void loop()
{
    static bool single_phase = true;
    static uint8_t single_x  = 0;
    static uint8_t single_y  = 0;
    static uint8_t block_x   = 0;
    static uint8_t block_y   = 4;
    static uint8_t color_i   = 0;

    if (single_phase) {
        // Walk through the first 4 rows with one RGB pixel
        M5Chain.setRGBClear(rgb_id, &operation_status);
        chain_status = M5Chain.setRGBPixel(rgb_id, single_x, single_y, colors[color_i], &operation_status);
        if (chain_status == CHAIN_OK && operation_status == 1) {
            Serial.printf("Single pixel: x=%d, y=%d, color=0x%04X\r\n", single_x, single_y, colors[color_i]);
        }

        delay(160);

        single_x++;
        color_i = (color_i + 1) % (sizeof(colors) / sizeof(colors[0]));
        if (single_x >= 8) {
            single_x = 0;
            single_y++;
        }

        if (single_y >= 4) {
            single_phase = false;
            block_x      = 0;
            block_y      = 4;
        }
    } else {
        // Walk through the last 4 rows with a 2x2 RGB block
        RGBPixelInfo pixels[] = {
            {block_x, block_y, colors[color_i]},
            {(uint8_t)(block_x + 1), block_y, colors[(color_i + 1) % 6]},
            {block_x, (uint8_t)(block_y + 1), colors[(color_i + 2) % 6]},
            {(uint8_t)(block_x + 1), (uint8_t)(block_y + 1), colors[(color_i + 3) % 6]}};

        M5Chain.setRGBClear(rgb_id, &operation_status);
        chain_status = M5Chain.setRGBPixel(rgb_id, pixels, sizeof(pixels) / sizeof(pixels[0]), &operation_status);
        if (chain_status == CHAIN_OK && operation_status == 1) {
            Serial.printf("RGB block: x=%d, y=%d\r\n", block_x, block_y);
        }

        delay(160);

        block_x++;
        color_i = (color_i + 1) % (sizeof(colors) / sizeof(colors[0]));
        if (block_x >= 7) {
            block_x = 0;
            block_y += 2;
        }

        if (block_y >= 8) {
            single_phase = true;
            single_x     = 0;
            single_y     = 0;
        }
    }
}

サンプルの表示効果は以下の通りです:

文字表示

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
#include "M5Chain.h"
#include "M5Unified.h"

#define TXD_PIN GPIO_NUM_2
#define RXD_PIN GPIO_NUM_1

Chain M5Chain;

uint8_t rgb_id           = 0;
uint8_t operation_status = 0;
const char text[]        = "I'mChainRGB";
const uint16_t colors[]  = {0xFFE0, 0xF800, 0x07E0, 0x001F, 0xFD20, 0x07FF, 0xF81F};

bool findFirstRGBDevice()
{
    // Enumerate devices and use the first RGB node
    uint16_t device_nums = 0;
    if (M5Chain.getDeviceNum(&device_nums) != CHAIN_OK || device_nums == 0) {
        Serial.println("No Chain devices found");
        return false;
    }

    device_info_t *infos = (device_info_t *)malloc(sizeof(device_info_t) * device_nums);
    if (infos == nullptr) {
        return false;
    }

    device_list_t devices;
    devices.count   = device_nums;
    devices.devices = infos;

    bool found = false;
    if (M5Chain.getDeviceList(&devices)) {
        for (uint8_t i = 0; i < devices.count; i++) {
            if (devices.devices[i].device_type == CHAIN_RGB_TYPE_CODE) {
                rgb_id = devices.devices[i].id;
                found  = true;
                break;
            }
        }
    }

    free(infos);
    if (found) {
        Serial.printf("RGB device found, id=%d\r\n", rgb_id);
    } else {
        Serial.println("No RGB device found");
    }
    return found;
}

bool prepareRGB()
{
    // Initialize pixel mode, rotation, and brightness
    if (!findFirstRGBDevice()) {
        return false;
    }

    if (M5Chain.setRGBMode(rgb_id, RGB_PIXEL_MODE, &operation_status) != CHAIN_OK || operation_status != 1) {
        return false;
    }

    M5Chain.setRGBRotation(rgb_id, RGB_ROTATION_0, &operation_status);
    M5Chain.setRGBBrightness(rgb_id, 50, &operation_status);
    M5Chain.setRGBClear(rgb_id, &operation_status);
    return true;
}

void setup()
{
    M5.begin();
    Serial.begin(115200);
    Serial.println("RGB character demo");
    M5Chain.begin(&Serial2, 115200, RXD_PIN, TXD_PIN);

    if (!prepareRGB()) {
        Serial.println("Chain RGB init failed");
        while (1) {
            delay(100);
        }
    } else {
        Serial.println("Chain RGB init success");
    }
}

void loop()
{
    static uint8_t index = 0;
    char c               = text[index];
    uint16_t color       = colors[index % (sizeof(colors) / sizeof(colors[0]))];

    // Show characters one by one with changing colors
    M5Chain.setRGBClear(rgb_id, &operation_status);
    M5Chain.setRGBPrintChar(rgb_id, c, 1, 1, color, &operation_status);
    Serial.printf("Character shown: %c, color=0x%04X\r\n", c, color);

    delay(400);

    index++;
    if (index >= sizeof(text) - 1) {
        index = 0;
    }
}

サンプルの表示効果は以下の通りです:

カスタムパターン表示と回転

説明
ここでの回転は、描画前に表示方向を設定することを指します。設定後に行う描画はすべて、その方向を基準として表示されます。すでに描画済みの内容を直接回転変換するものではありません。
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
#include "M5Chain.h"
#include "M5Unified.h"

#define TXD_PIN GPIO_NUM_2
#define RXD_PIN GPIO_NUM_1

Chain M5Chain;

uint8_t rgb_id           = 0;
uint8_t operation_status = 0;

// 8x8 green arrow pattern
uint16_t arrow[64] = {
    0x0000, 0x0000, 0x0000, 0x07E0, 0x07E0, 0x0000, 0x0000, 0x0000,  //    ■■   
    0x0000, 0x0000, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x0000, 0x0000,  //   ■■■■  
    0x0000, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x0000,  //  ■■■■■■ 
    0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0,  // ■■■■■■■■
    0x0000, 0x0000, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x0000, 0x0000,  //   ■■■■  
    0x0000, 0x0000, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x0000, 0x0000,  //   ■■■■  
    0x0000, 0x0000, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x0000, 0x0000,  //   ■■■■  
    0x0000, 0x0000, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x0000, 0x0000   //   ■■■■  
};

bool findFirstRGBDevice()
{
    // Enumerate devices and use the first RGB node
    uint16_t device_nums = 0;
    if (M5Chain.getDeviceNum(&device_nums) != CHAIN_OK || device_nums == 0) {
        Serial.println("No Chain devices found");
        return false;
    }

    device_info_t *infos = (device_info_t *)malloc(sizeof(device_info_t) * device_nums);
    if (infos == nullptr) {
        return false;
    }

    device_list_t devices;
    devices.count   = device_nums;
    devices.devices = infos;

    bool found = false;
    if (M5Chain.getDeviceList(&devices)) {
        for (uint8_t i = 0; i < devices.count; i++) {
            if (devices.devices[i].device_type == CHAIN_RGB_TYPE_CODE) {
                rgb_id = devices.devices[i].id;
                found  = true;
                break;
            }
        }
    }

    free(infos);
    if (found) {
        Serial.printf("RGB device found, id=%d\r\n", rgb_id);
    } else {
        Serial.println("No RGB device found");
    }
    return found;
}

bool prepareRGB()
{
    // Initialize pixel mode and brightness
    if (!findFirstRGBDevice()) {
        return false;
    }

    if (M5Chain.setRGBMode(rgb_id, RGB_PIXEL_MODE, &operation_status) != CHAIN_OK || operation_status != 1) {
        return false;
    }

    M5Chain.setRGBBrightness(rgb_id, 50, &operation_status);
    M5Chain.setRGBClear(rgb_id, &operation_status);
    return true;
}

void setup()
{
    M5.begin();
    Serial.begin(115200);
    Serial.println("RGB custom pattern rotation demo");
    M5Chain.begin(&Serial2, 115200, RXD_PIN, TXD_PIN);

    if (!prepareRGB()) {
        Serial.println("Chain RGB init failed");
        while (1) {
            delay(100);
        }
    } else {
        Serial.println("Chain RGB init success");
    }
}

void loop()
{
    // Rotate through 0/90/180/270 degree display states
    for (uint8_t rotation = RGB_ROTATION_0; rotation <= RGB_ROTATION_270; rotation++) {
        M5Chain.setRGBRotation(rgb_id, (rgb_rotation_t)rotation, &operation_status);
        M5Chain.setRGBBufferRefresh(rgb_id, arrow, &operation_status);
        Serial.printf("Rotation set to: %d°\r\n", rotation * 90);
        delay(800);
    }
}

サンプルの表示効果は以下の通りです:

ダイナミックカラーフォール

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
#include "M5Chain.h"
#include "M5Unified.h"

#define TXD_PIN GPIO_NUM_2
#define RXD_PIN GPIO_NUM_1

Chain M5Chain;

uint8_t rgb_id           = 0;
uint8_t operation_status = 0;
uint16_t frame[64]       = {0};
uint8_t color_offset     = 0;

uint16_t color565(uint8_t r, uint8_t g, uint8_t b)
{
    return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

uint16_t wheel(uint8_t pos)
{
    if (pos < 85) {
        return color565(255 - pos * 3, pos * 3, 0);
    }
    if (pos < 170) {
        pos -= 85;
        return color565(0, 255 - pos * 3, pos * 3);
    }

    pos -= 170;
    return color565(pos * 3, 0, 255 - pos * 3);
}

bool findFirstRGBDevice()
{
    // Enumerate devices and use the first RGB node
    uint16_t device_nums = 0;
    if (M5Chain.getDeviceNum(&device_nums) != CHAIN_OK || device_nums == 0) {
        Serial.println("No Chain devices found");
        return false;
    }

    device_info_t *infos = (device_info_t *)malloc(sizeof(device_info_t) * device_nums);
    if (infos == nullptr) {
        return false;
    }

    device_list_t devices;
    devices.count   = device_nums;
    devices.devices = infos;

    bool found = false;
    if (M5Chain.getDeviceList(&devices)) {
        for (uint8_t i = 0; i < devices.count; i++) {
            if (devices.devices[i].device_type == CHAIN_RGB_TYPE_CODE) {
                rgb_id = devices.devices[i].id;
                found  = true;
                break;
            }
        }
    }

    free(infos);
    if (found) {
        Serial.printf("RGB device found, id=%d\r\n", rgb_id);
    } else {
        Serial.println("No RGB device found");
    }
    return found;
}

bool prepareRGB()
{
    // Initialize pixel mode, rotation, and brightness
    if (!findFirstRGBDevice()) {
        return false;
    }

    if (M5Chain.setRGBMode(rgb_id, RGB_PIXEL_MODE, &operation_status) != CHAIN_OK || operation_status != 1) {
        return false;
    }

    M5Chain.setRGBRotation(rgb_id, RGB_ROTATION_0, &operation_status);
    M5Chain.setRGBBrightness(rgb_id, 50, &operation_status);
    M5Chain.setRGBClear(rgb_id, &operation_status);
    return true;
}

void setup()
{
    M5.begin();
    Serial.begin(115200);
    Serial.println("RGB color waterfall demo");
    M5Chain.begin(&Serial2, 115200, RXD_PIN, TXD_PIN);

    if (!prepareRGB()) {
        Serial.println("Chain RGB init failed");
        while (1) {
            delay(100);
        }
    } else {
        Serial.println("Chain RGB init success");
    }
}

void loop()
{
    // Move old rows down by one row
    for (int y = 7; y > 0; y--) {
        for (int x = 0; x < 8; x++) {
            frame[y * 8 + x] = frame[(y - 1) * 8 + x];
        }
    }

    // Generate a new color row at the top
    for (int x = 0; x < 8; x++) {
        frame[x] = wheel(color_offset + x * 16);
    }

    M5Chain.setRGBBufferRefresh(rgb_id, frame, &operation_status);
    Serial.printf("Waterfall frame offset: %d\r\n", color_offset);

    color_offset += 4;
    delay(80);
}

サンプルの表示効果は以下の通りです:

文字列スクロールモード

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
#include "M5Chain.h"
#include "M5Unified.h"

#define TXD_PIN GPIO_NUM_2
#define RXD_PIN GPIO_NUM_1

Chain M5Chain;

chain_status_t chain_status = CHAIN_OK;
uint8_t rgb_id           = 0;
uint8_t operation_status = 0;
const char text[]        = "Hi I'm Chain RGB! ";

bool findFirstRGBDevice()
{
    // Enumerate devices and use the first RGB node
    uint16_t device_nums = 0;
    if (M5Chain.getDeviceNum(&device_nums) != CHAIN_OK || device_nums == 0) {
        Serial.println("No Chain devices found");
        return false;
    }

    device_info_t *infos = (device_info_t *)malloc(sizeof(device_info_t) * device_nums);
    if (infos == nullptr) {
        return false;
    }

    device_list_t devices;
    devices.count   = device_nums;
    devices.devices = infos;

    bool found = false;
    if (M5Chain.getDeviceList(&devices)) {
        for (uint8_t i = 0; i < devices.count; i++) {
            if (devices.devices[i].device_type == CHAIN_RGB_TYPE_CODE) {
                rgb_id = devices.devices[i].id;
                found  = true;
                break;
            }
        }
    }

    free(infos);
    if (found) {
        Serial.printf("RGB device found, id=%d\r\n", rgb_id);
    } else {
        Serial.println("No RGB device found");
    }
    return found;
}

bool prepareRGB()
{
    // Switch to string scroll mode and set basic parameters
    if (!findFirstRGBDevice()) {
        return false;
    }

    if (M5Chain.setRGBMode(rgb_id, RGB_STRING_SCROLL_MODE, &operation_status) != CHAIN_OK ||
        operation_status != 1) {
        return false;
    }

    M5Chain.setRGBRotation(rgb_id, RGB_ROTATION_0, &operation_status);
    M5Chain.setRGBBrightness(rgb_id, 30, &operation_status);
    return true;
}

void setup()
{
    M5.begin();
    Serial.begin(115200);
    Serial.println("RGB string scroll demo");
    M5Chain.begin(&Serial2, 115200, RXD_PIN, TXD_PIN);

    if (!prepareRGB()) {
        Serial.println("Chain RGB init failed");
        while (1) {
            delay(100);
        }
    } else {
        Serial.println("Chain RGB init success");
    }

    chain_status = M5Chain.setRGBStringScroll(rgb_id, text, RGB_SCROLL_LEFT, RGB_SCROLL_MODE_LOOP, 100,
                                              RGB_SCROLL_COLOR_GRADIENT, &operation_status);
    if(chain_status == CHAIN_OK && operation_status == 1) {
        Serial.printf("String scroll started: %s\r\n", text);
    }
}

void loop()
{
    delay(1000);
} 

サンプルの表示効果は以下の通りです:

On This Page