pdf-icon

Arduino入門

2. デバイス&サンプル

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

アクセサリー

6. アプリケーション

Unit ChainBus Arduino チュートリアル

1. 準備作業

2. 注意事項

ピン互換性
各ホストのピン配置が異なるため、ご使用前に製品ドキュメントのピン互換表を参照し、実際の配線に合わせてサンプルプログラムを修正してください。

3. コンパイルと書き込み

  • 1. ダウンロードモードに入る:CoreS3-SE のリセットボタンを長押し(約 2 秒間)して、内部の緑色 LED が点灯するまで押し続け、その後ボタンを離します。デバイスはダウンロードモードに入り、プログラミングを待機しています。
説明
異なるデバイスではプログラムのアップロード前にダウンロードモードに入る必要があり、メインコントローラの種類によってこの手順が異なる場合があります。詳細については、Arduino IDE 入門ガイドページの下部にあるデバイスプログラムダウンロードチュートリアルリストを参照して、具体的な操作方法をご確認ください。
  • 2. デバイスポートを選択し、Arduino IDE の左上隅にあるコンパイルおよびアップロードボタンをクリックします。プログラムのコンパイル完了とデバイスへのアップロード完了を待ちます。

4. サンプルプログラム

  • 本チュートリアルで使用するメインコントローラは CoreS3-SE です。Base M5GO Bottom3 ベースから給電し、PORT.C を使用して、Unit ChainBus および他のモジュールと組み合わせて動作させます。本モジュールは UART 通信を採用しています。実際の配線に合わせてプログラム内のピン定義を修正してください。接続後の対応 UART IO は G17 (RX)G18 (TX)
説明
ホストを電源断せずに再起動した場合、Unit ChainBus の GPIO の動作モードは前回設定した状態が保持されます。例えば GPIO2 を入力モードに設定していると、ホストを電源断せずに再起動して GPIO2 の動作モードを再設定しなくても、GPIO2 は引き続き入力モードのままになります。

4.1 I2C モード

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 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
#include "M5Chain.h"
#include "M5Unified.h"

#define TXD_PIN GPIO_NUM_17  // Tx
#define RXD_PIN GPIO_NUM_18  // Rx

Chain M5Chain;

device_list_t *devices_list = NULL;
chain_status_t chain_status;
uint16_t device_nums     = 0;
uint8_t operation_status = 0;
work_status_t gpio1;
work_status_t gpio2;

void printWorkStatus(String gpio_num, work_status_t gpio_status);
bool sht3x_update(UnitChainBus& chain, uint8_t chainId, uint8_t sht3xAddr, float& cTemp, float& fTemp, float& humidity);

/* ---------- SHT3X STRUCT ---------- */
typedef struct {
    UnitChainBus* chain;
    uint8_t uart_id;
    uint8_t i2c_addr;

    float cTemp;
    float fTemp;
    float humidity;

    bool update()
    {
        if (chain == nullptr) return false;
        return sht3x_update(*chain, uart_id, i2c_addr,
                                     cTemp, fTemp, humidity);
    }
} SHT3X_t;

SHT3X_t sht3x;

void setup()
{
    M5.begin();
    M5.Display.clear();
    M5.Display.setFont(&FreeMonoBold12pt7b);
    M5.Display.setTextDatum(middle_center);
    M5.Display.drawCenterString("Unit ChainBus Test", 160, 120);

    Serial.begin(115200);
    Serial.println("Unit ChainBus Test");
    M5Chain.begin(&Serial2, 115200, RXD_PIN, TXD_PIN);

    // Check whether any Unit Chain device is connected
    if (M5Chain.isDeviceConnected()) {
        Serial.println("devices is connected");
        chain_status = M5Chain.getDeviceNum(&device_nums);
        if (chain_status == CHAIN_OK) {
            devices_list          = (device_list_t *)malloc(sizeof(device_list_t));
            devices_list->count   = device_nums;
            devices_list->devices = (device_info_t *)malloc(sizeof(device_info_t) * device_nums);
            // Get detailed device list
            if (M5Chain.getDeviceList(devices_list)) {
                Serial.println("devices list get success");
            } else {
                Serial.println("devices list get failed");
            }
        } else {
            Serial.printf("error status:%d \r\n", chain_status);
            Serial.printf("devices num get failed.\r\n");
        }
    } else {
        Serial.println("devices is not connected.");
    }

    if (devices_list->devices[0].device_type == UNIT_CHAIN_BUS_TYPE_CODE) {
        Serial.println("ID[1] is Unit ChainBus\n");
        chain_status = M5Chain.setChainBusI2cMode(devices_list->devices[0].id, CHAIN_I2C_HIGH_SPEED_400KHZ, &operation_status);// set i2c mode
        if (chain_status == CHAIN_OK && operation_status == 1) {
            Serial.printf("Unit ChainBus ID[%d] set i2c mode success \r\n", devices_list->devices[0].id);
            M5Chain.getChainBusWorkMode(devices_list->devices[0].id, &gpio1, &gpio2);// Read Unit ChainBus GPIO working status
            printWorkStatus("GPIO_1", (work_status_t)gpio1);
            printWorkStatus("GPIO_2", (work_status_t)gpio2);
        } else {
            Serial.printf("Unit ChainBus ID[%d] set i2c mode fail, chain_status:%d  operation_status:%d \r\n", devices_list->devices[0].id, chain_status, operation_status);
        }
        delay(500);

        // Bind SHT3X to this ChainBus
        sht3x.chain    = &M5Chain;
        sht3x.uart_id  = devices_list->devices[0].id;
        sht3x.i2c_addr = 0x44;  // SHT3X I2C address, can get from getChainBusI2cScanAddr

        Serial.printf("\nUnit ENV-III SHT3X bind to ChainBus ID[%d]\r\n", sht3x.uart_id);
    } else {
        Serial.println("ID[1] is NOT Unit ChainBus\n");
        return;
    }

    delay(5);
}

void loop()
{
    if (sht3x.update()) {
        Serial.println("-----SHT3X-----");
        Serial.print("Temperature: ");
        Serial.print(sht3x.cTemp);
        Serial.println(" 'C");
        Serial.print("Humidity: ");
        Serial.print(sht3x.humidity);
        Serial.println("% rH");
        Serial.println("--------------\r\n");

        M5.Display.fillRect(0, 0, 320, 240, TFT_BLACK);
        M5.Display.setCursor(0, 20);
        M5.Display.println("-----SHT3X-----");
        M5.Display.print("Temperature: ");
        M5.Display.print(sht3x.cTemp);
        M5.Display.println(" 'C");
        M5.Display.print("Humidity: ");
        M5.Display.print(sht3x.humidity);
        M5.Display.println("% rH");
        M5.Display.println("---------------\r\n");
    }

    delay(1000);
}

void printWorkStatus(String gpio_num, work_status_t gpio_status)
{
    Serial.print("  >>> " + gpio_num + ": ");
    switch (gpio_status) {
        case CHAIN_NOT_WORK_STATUS:
            Serial.println("Not configured working status");
            break;
        case CHAIN_OUTPUT_WORK_STATUS:
            Serial.println("Output status");
            break;
        case CHAIN_INPUT_WORK_STATUS:
            Serial.println("Input status");
            break;
        case CHAIN_NVIC_WORK_STATUS:
            Serial.println("External interrupt working status");
            break;
        case CHAIN_ADC_WORK_STATUS:
            Serial.println("ADC working status");
            break;
        case CHAIN_I2C_WORK_STATUS:
            Serial.println("I2C working status");
            break;
        default:
            Serial.println("Unrecognized work status");
            break;
    }
}

// Perform one complete SHT3X measurement cycle via Unit ChainBus I2C
bool sht3x_update(UnitChainBus& chain,
                         uint8_t chainId,
                         uint8_t sht3xAddr,
                         float& cTemp,
                         float& fTemp,
                         float& humidity)
{
    uint8_t opStatus = 0;
    chain_status_t status;

    // 1. Send measurement command (high repeatability, clock stretching disabled)
    uint8_t cmd[2] = {0x2C, 0x06};
    status = chain.chainBusI2cWrite(
        chainId,
        sht3xAddr,
        2,
        cmd,
        &opStatus,
        1000
    );

    if (status != CHAIN_OK || opStatus != CHAIN_BUS_OPERATION_SUCCESS) {
        return false;
    }

    // 2. Wait for the measurement to complete
    delay(100);

    // 3. Read 6 bytes of measurement data
    uint8_t data[6] = {0};
    status = chain.chainBusI2cRead(
        chainId,
        sht3xAddr,
        6,
        data,
        &opStatus,
        1000
    );

    if (status != CHAIN_OK || opStatus != CHAIN_BUS_OPERATION_SUCCESS) {
        return false;
    }

    // 4. Convert raw data to temperature and humidity
    cTemp = ((((data[0] * 256.0) + data[1]) * 175.0) / 65535.0) - 45.0;
    fTemp = (cTemp * 1.8) + 32.0;
    humidity = ((((data[3] * 256.0) + data[4]) * 100.0) / 65535.0);

    return true;
}

デバイスの電源投入後、シリアルモニタに接続デバイスの情報が出力されます。さらに、Unit ChainBus のインターフェース経由で、接続された Unit ENV-III の SHT3X センサから温湿度データを読み取ります。

シリアルモニタの出力例:

Unit ChainBus Test
devices is connected
devices list get success
ID[1] is Unit ChainBus

Unit ChainBus ID[1] set i2c mode success 
  >>> GPIO_1: I2C working status
  >>> GPIO_2: I2C working status

Unit ENV-III SHT3X bind to ChainBus ID[1]
-----SHT3X-----
Temperature: 27.19 'C
Humidity: 52.88% rH
--------------

4.2 入力モード

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
#include "M5Chain.h"
#include "M5Unified.h"

#define TXD_PIN GPIO_NUM_17  // Tx
#define RXD_PIN GPIO_NUM_18  // Rx

Chain M5Chain;

device_list_t *devices_list = NULL;
chain_status_t chain_status;
uint16_t device_nums     = 0;
uint8_t operation_status = 0;
work_status_t gpio1;
work_status_t gpio2;

void printWorkStatus(String gpio_num, work_status_t gpio_status);

void setup()
{
    M5.begin();
    M5.Display.clear();
    M5.Display.setFont(&FreeMonoBold12pt7b);
    M5.Display.setTextDatum(middle_center);
    M5.Display.drawCenterString("Unit ChainBus Test", 160, 120);

    Serial.begin(115200);
    Serial.println("Unit ChainBus Test");
    M5Chain.begin(&Serial2, 115200, RXD_PIN, TXD_PIN);

    // Check whether any Unit Chain device is connected
    if (M5Chain.isDeviceConnected()) {
        Serial.println("devices is connected");
        chain_status = M5Chain.getDeviceNum(&device_nums);
        if (chain_status == CHAIN_OK) {
            devices_list          = (device_list_t *)malloc(sizeof(device_list_t));
            devices_list->count   = device_nums;
            devices_list->devices = (device_info_t *)malloc(sizeof(device_info_t) * device_nums);
            // Get detailed device list
            if (M5Chain.getDeviceList(devices_list)) {
                Serial.println("devices list get success");
            } else {
                Serial.println("devices list get failed");
            }
        } else {
            Serial.printf("error status:%d \r\n", chain_status);
            Serial.printf("devices num get failed.\r\n");
        }
    } else {
        Serial.println("devices is not connected.");
    }

    if (devices_list->devices[0].device_type == UNIT_CHAIN_BUS_TYPE_CODE) {
        Serial.println("ID[1] is Unit ChainBus\n");
        chain_status = M5Chain.setChainBusInputMode(devices_list->devices[0].id, CHAIN_GPIO_PIN_1, CHAIN_GPIO_PULL_UP, &operation_status, 3000);// set GPIO1 input mode
        if (chain_status == CHAIN_OK && operation_status == 1) {
            Serial.printf("Unit ChainBus ID[%d] set GPIO1 input mode success \r\n", devices_list->devices[0].id);
            M5Chain.getChainBusWorkMode(devices_list->devices[0].id, &gpio1, &gpio2);// Read Unit ChainBus GPIO working status
            printWorkStatus("GPIO_1", (work_status_t)gpio1);
            printWorkStatus("GPIO_2", (work_status_t)gpio2);
        } else {
            Serial.printf("Unit ChainBus ID[%d] set GPIO1 input mode fail, chain_status:%d  operation_status:%d \r\n", devices_list->devices[0].id, chain_status, operation_status);
        }
        delay(500);
    } else {
        Serial.println("ID[1] is NOT Unit ChainBus\n");
        return;
    }

    delay(5);
}

uint8_t last_button_status = true;

void loop()
{
    uint8_t button_status;
    // Read GPIO1 input level from Unit ChainBus
    chain_status = M5Chain.getChainBusInputLevel(devices_list->devices[0].id, CHAIN_GPIO_PIN_1, &button_status, &operation_status);
    if (chain_status == CHAIN_OK && operation_status == 1) {
        if (button_status != last_button_status) {
            Serial.printf("button status: %d \r\n", button_status);
            last_button_status = button_status;
        }
    } else {
        Serial.printf("get button status failed, chain_status:%d  operation_status:%d \r\n", chain_status,
                      operation_status);
    }

    delay(20);
}

void printWorkStatus(String gpio_num, work_status_t gpio_status)
{
    Serial.print("  >>> " + gpio_num + ": ");
    switch (gpio_status) {
        case CHAIN_NOT_WORK_STATUS:
            Serial.println("Not configured working status");
            break;
        case CHAIN_OUTPUT_WORK_STATUS:
            Serial.println("Output status");
            break;
        case CHAIN_INPUT_WORK_STATUS:
            Serial.println("Input status");
            break;
        case CHAIN_NVIC_WORK_STATUS:
            Serial.println("External interrupt working status");
            break;
        case CHAIN_ADC_WORK_STATUS:
            Serial.println("ADC working status");
            break;
        case CHAIN_I2C_WORK_STATUS:
            Serial.println("I2C working status");
            break;
        default:
            Serial.println("Unrecognized work status");
            break;
    }
}

デバイスの電源投入後、シリアルモニタに接続デバイスの情報が出力されます。さらに、Unit ChainBus のインターフェース経由で、接続された Unit Dual Button の青ボタンの状態変化を読み取ります。

シリアルモニタの出力例:

Unit ChainBus Test
devices is connected
devices list get success
ID[1] is Unit ChainBus

Unit ChainBus ID[1] set GPIO1 input mode success 
  >>> GPIO_1: Input status
  >>> GPIO_2: Not configured working status
button status: 0
button status: 1

4.3 出力モード

以下のプログラムでは、Unit ChainBus の GPIO1 と GPIO2 を同時に制御しています。GPIO1 は 500ms ごとに High/Low を切り替え、GPIO2 は Low レベルに設定します。LED を接続して動作を確認できます。

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
#include "M5Chain.h"
#include "M5Unified.h"

#define TXD_PIN GPIO_NUM_17  // Tx
#define RXD_PIN GPIO_NUM_18  // Rx

Chain M5Chain;

device_list_t *devices_list = NULL;
chain_status_t chain_status;
uint16_t device_nums     = 0;
uint8_t operation_status = 0;
work_status_t gpio1;
work_status_t gpio2;

void printWorkStatus(String gpio_num, work_status_t gpio_status);

void setup()
{
    M5.begin();
    M5.Display.clear();
    M5.Display.setFont(&FreeMonoBold12pt7b);
    M5.Display.setTextDatum(middle_center);
    M5.Display.drawCenterString("Unit ChainBus Test", 160, 120);

    Serial.begin(115200);
    Serial.println("Unit ChainBus Test");
    M5Chain.begin(&Serial2, 115200, RXD_PIN, TXD_PIN);

    if (M5Chain.isDeviceConnected()) {
        Serial.println("devices is connected");
        chain_status = M5Chain.getDeviceNum(&device_nums);
        if (chain_status == CHAIN_OK) {
            devices_list          = (device_list_t *)malloc(sizeof(device_list_t));
            devices_list->count   = device_nums;
            devices_list->devices = (device_info_t *)malloc(sizeof(device_info_t) * device_nums);
            if (M5Chain.getDeviceList(devices_list)) {
                Serial.println("devices list get success");
            } else {
                Serial.println("devices list get failed");
            }
        } else {
            Serial.printf("error status:%d \r\n", chain_status);
            Serial.printf("devices num get failed.\r\n");
        }
    } else {
        Serial.println("devices is not connected.");
    }

    if (devices_list->devices[0].device_type == UNIT_CHAIN_BUS_TYPE_CODE) {
        Serial.println("ID[1] is Unit ChainBus\n");
        chain_status = M5Chain.setChainBusOutputMode(devices_list->devices[0].id, CHAIN_GPIO_PIN_1, CHAIN_GPIO_OUTPUT_PUSHPULL, CHAIN_GPIO_PULL_DOWN, &operation_status, 3000);// set output mode
        chain_status = (chain_status_t)(chain_status &
                    M5Chain.setChainBusOutputMode(devices_list->devices[0].id, CHAIN_GPIO_PIN_2, CHAIN_GPIO_OUTPUT_PUSHPULL, CHAIN_GPIO_PULL_DOWN, &operation_status, 3000));// set output mode
        if (chain_status == CHAIN_OK && operation_status == 1) {
            Serial.printf("Unit ChainBus ID[%d] set output mode success \r\n", devices_list->devices[0].id);
            M5Chain.getChainBusWorkMode(devices_list->devices[0].id, &gpio1, &gpio2);// Read Unit ChainBus GPIO working status
            printWorkStatus("GPIO_1", (work_status_t)gpio1);
            printWorkStatus("GPIO_2", (work_status_t)gpio2);
            M5Chain.setChainBusOutputLevel(devices_list->devices[0].id, CHAIN_GPIO_PIN_2, CHAIN_GPIO_RESET, &operation_status);// set GPIO2 output level - low
        } else {
            Serial.printf("Unit ChainBus ID[%d] set output mode fail, chain_status:%d  operation_status:%d \r\n", devices_list->devices[0].id, chain_status, operation_status);
        }
        delay(500);
    } else {
        Serial.println("ID[1] is NOT Unit ChainBus\n");
        return;
    }

    delay(5);
}

bool flag = false;

void loop()
{
    // change GPIO1 output level
    flag = !flag;
    chain_status = M5Chain.setChainBusOutputLevel(devices_list->devices[0].id, CHAIN_GPIO_PIN_1, flag ? CHAIN_GPIO_SET : CHAIN_GPIO_RESET, &operation_status);
    if (chain_status == CHAIN_OK && operation_status == 1) {
        if (flag) {
            Serial.println("set gpio1 high level");
        } else {
            Serial.println("set gpio1 low level");
        }
    } else {
        Serial.printf("set gpio1 level failed, chain_status:%d  operation_status:%d \r\n", chain_status, operation_status);
    }

    delay(500);
}

void printWorkStatus(String gpio_num, work_status_t gpio_status)
{
    Serial.print("  >>> " + gpio_num + ": ");
    switch (gpio_status) {
        case CHAIN_NOT_WORK_STATUS:
            Serial.println("Not configured working status");
            break;
        case CHAIN_OUTPUT_WORK_STATUS:
            Serial.println("Output status");
            break;
        case CHAIN_INPUT_WORK_STATUS:
            Serial.println("Input status");
            break;
        case CHAIN_NVIC_WORK_STATUS:
            Serial.println("External interrupt working status");
            break;
        case CHAIN_ADC_WORK_STATUS:
            Serial.println("ADC working status");
            break;
        case CHAIN_I2C_WORK_STATUS:
            Serial.println("I2C working status");
            break;
        default:
            Serial.println("Unrecognized work status");
            break;
    }
}

デバイスの電源投入後、シリアルモニタに接続デバイスの情報が出力されます。さらに、Unit ChainBus のインターフェース経由で、接続された LED の点滅を制御します。

シリアルモニタの出力例:

Unit ChainBus Test
devices is connected
devices list get success
ID[1] is Unit ChainBus

Unit ChainBus ID[1] set output mode success 
  >>> GPIO_1: Output status
  >>> GPIO_2: Output status
set gpio1 high level
set gpio1 low level
set gpio1 high level
set gpio1 low level

4.4 割り込みモード

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
#include "M5Chain.h"
#include "M5Unified.h"

#define TXD_PIN GPIO_NUM_17  // Tx
#define RXD_PIN GPIO_NUM_18  // Rx

Chain M5Chain;

device_list_t *devices_list = NULL;
chain_status_t chain_status;
uint16_t device_nums     = 0;
uint8_t operation_status = 0;
work_status_t gpio1;
work_status_t gpio2;

void printWorkStatus(String gpio_num, work_status_t gpio_status);

void setup()
{
    M5.begin();
    M5.Display.clear();
    M5.Display.setFont(&FreeMonoBold12pt7b);
    M5.Display.setTextDatum(middle_center);
    M5.Display.drawCenterString("Unit ChainBus Nvic Test", 160, 120);

    Serial.begin(115200);
    Serial.println("Unit ChainBus Nvic Test");
    M5Chain.begin(&Serial2, 115200, RXD_PIN, TXD_PIN);

    if (M5Chain.isDeviceConnected()) {
        Serial.println("devices is connected");
        chain_status = M5Chain.getDeviceNum(&device_nums);
        if (chain_status == CHAIN_OK) {
            devices_list          = (device_list_t *)malloc(sizeof(device_list_t));
            devices_list->count   = device_nums;
            devices_list->devices = (device_info_t *)malloc(sizeof(device_info_t) * device_nums);
            if (M5Chain.getDeviceList(devices_list)) {
                Serial.println("devices list get success");
            } else {
                Serial.println("devices list get failed");
            }
        } else {
            Serial.printf("error status:%d \r\n", chain_status);
            Serial.printf("devices num get failed.\r\n");
        }
    } else {
        Serial.println("devices is not connected.");
    }

    if (devices_list->devices[0].device_type == UNIT_CHAIN_BUS_TYPE_CODE) {
        Serial.println("ID[1] is Unit ChainBus\n");
        // Configure GPIO1 as NVIC (external interrupt) mode, rising edge trigger
        chain_status = M5Chain.setChainBusNvicMode(devices_list->devices[0].id, CHAIN_GPIO_PIN_1, CHAIN_GPIO_PULL_UP,
                                                    CHAIN_GPIO_MODE_IT_RISING, &operation_status);
        if (chain_status == CHAIN_OK && operation_status == 1) {
            Serial.printf("ChainBus ID[%d] set gpio1 nvic mode RISING success \r\n", devices_list->devices[0].id);
        } else {
            Serial.printf("ChainBus ID[%d] set gpio1 nvic mode RISING fail, chain_status:%d  operation_status:%d \r\n",
                            devices_list->devices[0].id, chain_status, operation_status);
        }

        // Configure GPIO2 as NVIC (external interrupt) mode, rising and falling edge trigger
        chain_status = M5Chain.setChainBusNvicMode(devices_list->devices[0].id, CHAIN_GPIO_PIN_2, CHAIN_GPIO_PULL_UP,
                                                    CHAIN_GPIO_MODE_IT_RISING_FALLING, &operation_status);
        if (chain_status == CHAIN_OK && operation_status == 1) {
            Serial.printf("ChainBus ID[%d] set gpio2 nvic mode RISING_FALLING success \r\n", devices_list->devices[0].id);
        } else {
            Serial.printf("ChainBus ID[%d] set gpio2 mode RISING_FALLING fail, chain_status:%d  operation_status:%d \r\n",
                            devices_list->devices[0].id, chain_status, operation_status);
        }
        M5Chain.getChainBusWorkMode(devices_list->devices[0].id, &gpio1, &gpio2);
        printWorkStatus("GPIO_1", (work_status_t)gpio1);
            printWorkStatus("GPIO_2", (work_status_t)gpio2);
        delay(500);
    } else {
        Serial.println("ID[1] is NOT Unit ChainBus\n");
        return;
    }

    delay(5);
}

void loop()
{
    if (devices_list) {
        if (devices_list->devices[0].device_type == UNIT_CHAIN_BUS_TYPE_CODE) {
            // Check whether GPIO1 or GPIO2 is configured as NVIC mode
            if (gpio1 == CHAIN_NVIC_WORK_STATUS || gpio2 == CHAIN_NVIC_WORK_STATUS) {
                uint16_t nvic_status = 0;
                while (M5Chain.getChainBusNvicTriggerStatus(devices_list->devices[0].id, &nvic_status)) {
                    Serial.println("**********************************");
                    Serial.printf("ChainBus ID[%d] nvic status: 0x%04x \r\n", devices_list->devices[0].id, nvic_status);
                }
            }
        } else {
            Serial.printf("ChainBus ID[%d] get work mode fail, chain_status:%d  operation_status:%d \r\n",
                          devices_list->devices[0].id, chain_status, operation_status);
        }
    }

    delay(40);
}

void printWorkStatus(String gpio_num, work_status_t gpio_status)
{
    Serial.print("  >>> " + gpio_num + ": ");
    switch (gpio_status) {
        case CHAIN_NOT_WORK_STATUS:
            Serial.println("Not configured working status");
            break;
        case CHAIN_OUTPUT_WORK_STATUS:
            Serial.println("Output status");
            break;
        case CHAIN_INPUT_WORK_STATUS:
            Serial.println("Input status");
            break;
        case CHAIN_NVIC_WORK_STATUS:
            Serial.println("External interrupt working status");
            break;
        case CHAIN_ADC_WORK_STATUS:
            Serial.println("ADC working status");
            break;
        case CHAIN_I2C_WORK_STATUS:
            Serial.println("I2C working status");
            break;
        default:
            Serial.println("Unrecognized work status");
            break;
    }
}

デバイスの電源投入後、シリアルモニタに接続デバイスの情報が出力されます。さらに、Unit ChainBus のインターフェース経由で、接続された Unit Dual Button のボタン割り込みトリガ状態を読み取ります。青ボタンを押すと立ち上がりエッジ割り込みが発生し、シリアルに 1 回出力されます。赤ボタンを押すと立ち上がり/立ち下がりエッジ割り込みが発生し、シリアルに 2 回出力されます。返される 16 進数値では、下位バイトが割り込み発生前の GPIO のレベル状態を示し、上位バイトが割り込みを発生させた GPIO 番号を示します。

シリアルモニタの出力例:

Unit ChainBus Nvic Test
devices is connected
devices list get success
ID[1] is Unit ChainBus

ChainBus ID[1] set gpio1 nvic mode RISING success 
ChainBus ID[1] set gpio2 nvic mode RISING_FALLING success 
  >>> GPIO_1: External interrupt working status
  >>> GPIO_2: External interrupt working status
**********************************
ChainBus ID[1] nvic status: 0x0100
**********************************
ChainBus ID[1] nvic status: 0x0201
**********************************
ChainBus ID[1] nvic status: 0x0200

4.5 ADC モード

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
#include "M5Chain.h"
#include "M5Unified.h"

#define TXD_PIN GPIO_NUM_17  // Tx
#define RXD_PIN GPIO_NUM_18  // Rx

Chain M5Chain;

device_list_t *devices_list = NULL;
chain_status_t chain_status;
uint16_t device_nums     = 0;
uint8_t operation_status = 0;
work_status_t gpio1;
work_status_t gpio2;

void printWorkStatus(String gpio_num, work_status_t gpio_status);

void setup()
{
    M5.begin();
    M5.Display.clear();
    M5.Display.setFont(&FreeMonoBold12pt7b);
    M5.Display.setTextDatum(middle_center);
    M5.Display.drawCenterString("Unit ChainBus Test", 160, 120);

    Serial.begin(115200);
    Serial.println("Unit ChainBus Test");
    M5Chain.begin(&Serial2, 115200, RXD_PIN, TXD_PIN);

    if (M5Chain.isDeviceConnected()) {
        Serial.println("devices is connected");
        chain_status = M5Chain.getDeviceNum(&device_nums);
        if (chain_status == CHAIN_OK) {
            devices_list          = (device_list_t *)malloc(sizeof(device_list_t));
            devices_list->count   = device_nums;
            devices_list->devices = (device_info_t *)malloc(sizeof(device_info_t) * device_nums);
            if (M5Chain.getDeviceList(devices_list)) {
                Serial.println("devices list get success");
            } else {
                Serial.println("devices list get failed");
            }
        } else {
            Serial.printf("error status:%d \r\n", chain_status);
            Serial.printf("devices num get failed.\r\n");
        }
    } else {
        Serial.println("devices is not connected.");
    }

    if (devices_list->devices[0].device_type == UNIT_CHAIN_BUS_TYPE_CODE) {
        Serial.println("ID[1] is Unit ChainBus\n");

        // Configure GPIO1 as ADC input mode
        chain_status = M5Chain.setChainBusAdcMode(devices_list->devices[0].id, CHAIN_GPIO_PIN_1, &operation_status, 3000);
        if (chain_status == CHAIN_OK && operation_status == 1) {
            Serial.printf("ChainBus ID[%d] set GPIO1 adc mode success \r\n", devices_list->devices[0].id);
        } else {
            Serial.printf("ChainBus ID[%d] set GPIO1 adc mode fail, chain_status:%d  operation_status:%d \r\n",
                            devices_list->devices[0].id, chain_status, operation_status);
        }

        M5Chain.getChainBusWorkMode(devices_list->devices[0].id, &gpio1, &gpio2);
        printWorkStatus("GPIO_1", (work_status_t)gpio1);
            printWorkStatus("GPIO_2", (work_status_t)gpio2);
        delay(500);
    } else {
        Serial.println("ID[1] is NOT Unit ChainBus\n");
        return;
    }

    delay(5);
}

uint16_t last_adc_value = 0;

void loop()
{
    uint16_t adc_value;
    chain_status = M5Chain.getChainBusAdcValue(devices_list->devices[0].id, CHAIN_GPIO_PIN_1, &adc_value, &operation_status);
    if (chain_status == CHAIN_OK && operation_status == 1) {
        if (abs(adc_value - last_adc_value) > 4) {// Print ADC value only when the change exceeds the threshold
            Serial.printf("\nADC value: %d \r\n", adc_value);
            last_adc_value = adc_value;
        }
    } else {
        Serial.printf("get ADC value failed, chain_status:%d  operation_status:%d \r\n", chain_status, operation_status);
    }

    delay(100);
}

void printWorkStatus(String gpio_num, work_status_t gpio_status)
{
    Serial.print("  >>> " + gpio_num + ": ");
    switch (gpio_status) {
        case CHAIN_NOT_WORK_STATUS:
            Serial.println("Not configured working status");
            break;
        case CHAIN_OUTPUT_WORK_STATUS:
            Serial.println("Output status");
            break;
        case CHAIN_INPUT_WORK_STATUS:
            Serial.println("Input status");
            break;
        case CHAIN_NVIC_WORK_STATUS:
            Serial.println("External interrupt working status");
            break;
        case CHAIN_ADC_WORK_STATUS:
            Serial.println("ADC working status");
            break;
        case CHAIN_I2C_WORK_STATUS:
            Serial.println("I2C working status");
            break;
        default:
            Serial.println("Unrecognized work status");
            break;
    }
}

デバイスの電源投入後、シリアルモニタに接続デバイスの情報が出力されます。さらに、Unit ChainBus のインターフェース経由で、接続された Unit Angle の ADC 値を読み取ります。

シリアルモニタの出力例:

Unit ChainBus Test
devices is connected
devices list get success
ID[1] is Unit ChainBus

ChainBus ID[1] set GPIO1 adc mode success 
  >>> GPIO_1: ADC working status
  >>> GPIO_2: Not configured working status

ADC value: 4095
On This Page