フェーズ3

E3-01 I2C接続確認:0x68 に対して応答があるか確認する

シリーズ:実験シリーズ(フェーズ3)
対応ロードマップ:フェーズ3 / E3-01
この記事で扱う範囲:E3-00 で確定した配線条件を使い、I2Cアドレス 0x68 に対して応答があることを確認する。まずは「接続できている」を確認するところまでを扱う。

1. 目的

今回は、I2Cで接続した IMU に対して、マイコンから応答があるか を確認します。
前回の E3-00 で、

  • QCIOT-ICM42688P の J1 を評価ボードの Pmod1(J26)へ接続する
  • 評価ボード側は SW4-1 = OFF、SW4-2 = ON にする
  • QCIOT-ICM42688P の J4 にジャンパキャップが付いている
  • その結果、I2Cアドレスは 0x68 になる

という条件を先に固めました。
今回は、その前提で 0x68 に対して通信を試し、IMUとI2Cで接続できているか確認する のが目的です。

今回の段階では、まだ加速度やジャイロの値は読みません。
まずは 「0x68 に応答がある」 と確認できれば十分です。

2. 前提・環境

2-1. 前提

この記事は、次の内容が終わっている前提で進めます。

  • フェーズ0:ビルド / 書き込み / main到達 / UARTログ出力
  • E2-02:1msごとの時刻を作る
  • E2-03:周期処理
  • E2-05:状態で整理(IDLE / RUN / ERROR)
  • E3-00:I2C配線の“詰まりどころ”を先に潰す

2-2. 使用するもの

  • 評価ボード:RTK7EKA8M2S00001BE
  • e² studio + FSP
  • Tera Term
  • IMUモジュール:QCIOT-ICM42688P(PMOD BOARD ICM-42688-P)
  • USB-UART変換ケーブル(またはUSB-UART変換モジュール)
  • ジャンパ線(UART接続用)

2-3. 今回の前提条件

今回は、前回(E3-00)の記事の条件をそのまま使います。

  • 通信方式:I2C
  • 接続方法:QCIOT-ICM42688P の J1 を評価ボードの Pmod1(J26)へ接続
  • 評価ボード側設定:SW4-1 = OFF、SW4-2 = ON
  • AD0:Low(J4 にジャンパキャップあり)
  • I2Cアドレス:0x68

今回は、QCIOT-ICM42688P の J4 にジャンパキャップが付いているため、
AD0 は Low 側となり、I2C アドレスは 0x68 になります。

2-4. 今回の動作イメージ

今回は、起動後に I2C アドレス 0x68 に対して通信を試します。

  • 応答があれば UART に成功ログを出す
  • 応答がなければ UART に失敗ログを出す

今回確認したいのは、
「値を読む」前に、IMUが 0x68 で応答することです。

3. 今回の変更点

3-1. 配線変更

配線は E3-00 と同じです。
今回は新しい配線変更はありません。

  • QCIOT-ICM42688P の J1 を評価ボードの Pmod1(J26)へ接続
  • 評価ボード側は SW4-1 = OFF、SW4-2 = ON
  • J4 にジャンパキャップあり

前回確定した条件で、そのまま接続確認します。

3-2. 設定変更

FSP で I2C Master を1つ追加します。
今回は、接続確認を目的にするため、次の設定で進めます。

  • 通信方式:I2C Master
  • アドレス幅:7bit
  • 通信速度:100kHz
  • Pmod1 を I2C として使うための SDA / SCL ピンを割り当てる

今回は I2C通信速度を 100kHz に設定します。
最初から高速設定にせず、まずは 安定して接続確認できること を優先します。

3-3. コード変更

今回は次の処理を追加します。

  • I2C Master を Open する
  • スレーブアドレスを 0x68 に設定する
  • 0x68 に対して通信を試す
  • 応答があったかどうかを UART に出す

今回はスキャンではなく、既知アドレス 0x68 に対して接続確認する 方針です。
これにより、「なぜこのアドレスを試すのか」が分かりやすくなります。

4. 手順

4-1. E3-00 の条件どおりに接続する

まず、前回の条件どおりに接続します。

  • QCIOT-ICM42688P の J1 を評価ボードの Pmod1(J26)へ接続
  • SW4-1 = OFF
  • SW4-2 = ON
  • J4 にジャンパキャップあり

ここが崩れていると、今回の 0x68 応答確認も通りません。

4-2. プロジェクトを作成する

今回は、UARTログ出力ができる既存のプロジェクトをベースにして進めます。
このプロジェクトに、I2C Master の設定を追加して、IMUへの接続確認を行います。

次の記事の4章手順にて、4-2までの手順まで進めてください。このプロジェクトをベースに進めます。

※上記の記事の「4-3. コードを追加する(Helloを1回送信)」は対応不要です。

4-3. USB-UARTケーブルのUARTと評価ボードを接続する

次の記事の4-4章に従って、USB-UARTケーブルのUARTと評価ボードを接続します。

4-4. FSP で I2C Master を追加する

  1. FSP Configurationを開く
  2. 「Stacks」タブを開く
  3. 「New Stack」を押す
  4. 一覧からConnectivity → I2C Master(r_iic_master)を選び、1インスタンス追加する
    ※今回は、専用IICの端子に繋がっているため、r_iic_masterを選択しています。
r iic master選択
  1. 追加されたg_i2c_master0 I2C Master(r_iic_master)を選択し、プロパティを表示する
  2. 次の設定を行う
    Channel:1
    Rate:Standard ※100kHz
    Slave Address:0x68
    Address Mode:7-Bit
    Callback:i2c_master_callback
r iic master設定

4-5. UARTログを残す

接続確認では、結果を文字で見られた方が分かりやすいです。
今回も UART に

  • I2C check start
  • ACK at 0x68
  • No ACK at 0x68

のようなログを出力する形にします。

5. コード

※下記は考え方を分かりやすくするためのシンプルな例です。
※ I2Cインスタンス名、UART送信関数名、コールバックの有無は、自分のプロジェクトに合わせて置き換えてください。

#include "hal_data.h"
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#define IMU_I2C_ADDR        (0x68U)
#define I2C_TIMEOUT_COUNT   (100000U)

static volatile bool g_i2c_done  = false;
static volatile bool g_i2c_error = false;

static void uart_print(const char * p_text);
static bool imu_check_ack(uint8_t addr);

void i2c_master_callback(i2c_master_callback_args_t * p_args)
{
    if (NULL == p_args)
    {
        return;
    }

    switch (p_args->event)
    {
        case I2C_MASTER_EVENT_ABORTED:
        {
            g_i2c_error = true;
            g_i2c_done  = true;
            break;
        }

        case I2C_MASTER_EVENT_RX_COMPLETE:
        case I2C_MASTER_EVENT_TX_COMPLETE:
        {
            g_i2c_error = false;
            g_i2c_done  = true;
            break;
        }

        default:
        {
            break;
        }
    }
}

void hal_entry(void)
{
    fsp_err_t err;

    /* UART Open */
    err = R_SCI_B_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
    if (FSP_SUCCESS != err)
    {
        while (1)
        {
            ;
        }
    }

    uart_print("I2C check start\r\n");

    err = R_IIC_MASTER_Open(&g_i2c_master0_ctrl, &g_i2c_master0_cfg);
    if (FSP_SUCCESS != err)
    {
        uart_print("I2C open error\r\n");
        while (1)
        {
            ;
        }
    }

    if (imu_check_ack(IMU_I2C_ADDR))
    {
        uart_print("ACK at 0x68\r\n");
    }
    else
    {
        uart_print("No ACK at 0x68\r\n");
    }

    while (1)
    {
        ;
    }
}

static bool imu_check_ack(uint8_t addr)
{
    fsp_err_t err;
    uint8_t dummy = 0x00;
    uint32_t timeout = I2C_TIMEOUT_COUNT;

    g_i2c_done  = false;
    g_i2c_error = false;

    err = R_IIC_MASTER_SlaveAddressSet(&g_i2c_master0_ctrl,
                                       addr,
                                       I2C_MASTER_ADDR_MODE_7BIT);
    if (FSP_SUCCESS != err)
    {
        return false;
    }

    err = R_IIC_MASTER_Write(&g_i2c_master0_ctrl, &dummy, 1U, false);
    if (FSP_SUCCESS != err)
    {
        return false;
    }

    while ((false == g_i2c_done) && (timeout > 0U))
    {
        timeout--;
    }

    if (0U == timeout)
    {
        return false;
    }

    if (true == g_i2c_error)
    {
        return false;
    }

    return true;
}

static void uart_print(const char * p_text)
{
    fsp_err_t err;

    err = R_SCI_B_UART_Write(&g_uart0_ctrl, (uint8_t *) p_text, strlen(p_text));
    if (FSP_SUCCESS != err)
    {
        while (1)
        {
            ;
        }
    }

    for (volatile uint32_t i = 0; i < 1000000U; i++)
    {
        __asm volatile ("nop");
    }
}

6. 実行結果

6-1. 確認したい動き

今回の実験では、次のようなログになればOKです。

I2C check start  
ACK at 0x68

このログが出れば、

  • I2C Master が動いている
  • 0x68 に応答がある
  • IMU と I2C で接続できている

と判断できます。

6-2. 今回確認できればよいこと

今回の段階では、次が確認できれば十分です。

  • 0x68 に対して応答がある
  • I2C の基本配線と基本通信が通っている

7. ハマりポイント/原因と対策

7-1. No ACK at 0x68 になる

原因

  • Pmod1 が I2C モードになっていない
  • J1 が正しく接続できていない
  • J4 の状態が想定と違う
  • I2C ピン設定が違う
  • 3.3V / GND 条件が崩れている

対策

  • SW4-1 = OFF、SW4-2 = ON になっているか確認する
  • QCIOT-ICM42688P の J1 を評価ボード側へ接続しているか確認する
  • J4 にジャンパキャップが付いているか確認する
  • FSP で SDA / SCL ピン割り当てを確認する
  • 必要ならテスターで 3.3V と GND を確認する

7-2. I2C open error になる

原因

  • I2C Master スタック設定が不足している
  • ピン設定が終わっていない
  • Generate Project Content が未実行

対策

  • FSP設定を見直す
  • SDA / SCL が割り当て済みか確認する
  • 生成コードを更新してビルドし直す

7-3. 0x68 で応答しないので、0x69 かもしれないと思って迷う

原因

  • J4 の状態を確認しないまま進めている

対策

  • QCIOT-ICM42688P の J4 を見て、ジャンパキャップが付いているか確認する
  • 今回の記事どおりに進める場合は、J4 にキャップが付いている状態で使う
  • この状態では、I2C アドレスは 0x68 になる
  • 0x69 を疑う前に、まず J4 の状態を確認する

8. 今回わかったこと

今回の実験で大事なのは、
I2C接続確認では、アドレスをあいまいにせず、既知アドレスに対して応答確認した方が初心者には分かりやすい
ということです。
今回は E3-00 で

  • 接続方法
  • SW4 の設定
  • J4 の状態
  • I2Cアドレス

を先に固めたので、E3-01 では「なぜ 0x68 を試すのか」が明確な状態で進められます。

9. 次回やること

E3-02 1レジスタ読み:WHO_AM_I を読んで、相手が ICM-42688-P であることを確認する

10. 関連リンク

  • 実験シリーズ:E2-02 タイマで1ms毎にカウントアップするストップウォッチを作る(リンク)
  • 実験シリーズ:E2-03 タイマで周期処理(リンク)
  • 実験シリーズ:E2-05 状態で整理(IDLE / RUN / ERROR)(リンク)
  • 実験シリーズ:E3-00 I2C配線の“詰まりどころ”を先に潰す(リンク)
  • 基礎シリーズ:電気回路 はじめに読む(リンク)
  • 基礎シリーズ:電子回路 はじめに読む(リンク)
  • 基礎シリーズ:GNDとは?なぜ基準点が必要なのか?(リンク)
  • 基礎シリーズ:マイコン(RA8M2) はじめに読む(リンク)

-フェーズ3