はじめに
freeRTOSの勉強のため、STM32F103をArduinoでは無くSTM32CubeIDEを使用していろいろ動作させる。
今回はI2Cデバイスの操作として家に転がっていたWiiのヌンチャクを動作させた。
使用した環境
-
ハードウェア
-
マイコン :STM32F103C8T6 (別名Black Pill) 300円ぐらい
-
デバッガ :ST-LinkV2-1 (NUCLEO付属のものを使用) 1500円ぐらい
-
Wiiヌンチャク (白、Wii本体の発売日に購入)
-
USBシリアル変換 (こんなの)
-
ソフトウェア
-
STM32CubeIDE (ST社公式からダウンロード)
-
freeRTOS (上記CubeIDEに内包されている)
ハードウェアの準備
- ヌンチャクとマイコンを接続するため、ヌンチャクのケーブルをバラし4本の線
- 白:GND
- 赤:3.3V
- 緑:SDA
- 黄:SCL
を出します。
-
I2C用のプルアップ抵抗の接続
2本の抵抗(2~3KΩ程度)を使用し、SDA,SCLと3.3Vを抵抗でつなぐ。 -
マイコンとの接続
4線を下記のように接続します。
マイコン側 | --- | ヌンチャク側 |
---|---|---|
GND | --- | 白:GND |
V3 | --- | 赤:3.3V |
PB7 | --- | 緑:SDA |
PB6 | --- | 黄:SCL |
(SDA,SCLはプルアップ抵抗経由で3.3Vにも接続されています) |
I2C仕様
arduinoのライブラリなどから以下のことが分かった。
基本情報
- デバイスID : 0x52@7bit
- 初期化 : 2Byteライト[0x40,0x00]
- データ読み出し : 0x00をライト後6Byteリードする
動作波形
リードデータ仕様
暗号化について
データは暗号化されているため以下の数式を使用して複合する
result = (input ^ 0x17) + 0x17
リードデータ内部
リードデータ | bit割付 | 説明 | 備考 |
---|---|---|---|
1Byte目 | [7:0] | ジョイスティックX軸 | センター値130、左に傾けると減少 |
2Byte目 | [7:0] | ジョイスティックY軸 | センター値130、下に傾けると減少 |
3Byte目 | [7:0] | 加速度センサX軸 | [9:2]bitの値(下位2bitは6Byte目に存在) |
4Byte目 | [7:0] | 加速度センサY軸 | [9:2]bitの値(下位2bitは6Byte目に存在) |
5Byte目 | [7:0] | 加速度センサZ軸 | [9:2]bitの値(下位2bitは6Byte目に存在) |
6Byte目 | [7:6] [5:4] [3:2] [1] [0] |
加速度センサZ軸 加速度センサY軸 加速度センサX軸 Cボタン Zボタン |
[1:0]bit目 [1:0]bit目 [1:0]bit目 押下時 0 押下時 0 |
ソースコード
ライブラリ以外の部分のソースは以下のようになる
// ヌンチャク構造体宣言
typedef struct {
uint8_t joy_x;
uint8_t joy_y;
uint8_t button_c;
uint8_t button_z;
uint16_t accel_x;
uint16_t accel_y;
uint16_t accel_z;
}wiiNunchuck;
// HALライブラリでは7bitアドレスを左シフトして設定する
# define WII_NUNCHUCK_DEV_ID ((0x52)<<1)
// ディレイ関数、置き換えやすいように関数化
static void userDelay(uint32_t millisec)
{
osDelay(millisec);
}
// データリード前に0x00をライト
static void send_request(I2C_HandleTypeDef *hi2c)
{
uint8_t pData[2] = {0x00, 0x00};
HAL_I2C_Master_Transmit(hi2c, WII_NUNCHUCK_DEV_ID, pData, 1, 3000);
}
// 複合
static uint8_t decode_byte(uint8_t x)
{
return ((x ^ 0x17) + 0x17);
}
// データリード
void WiiNunchuck_getKey(I2C_HandleTypeDef *hi2c, wiiNunchuck *keyStatus)
{
int cnt=0;
uint8_t rxData[6],decData[6];
send_request(hi2c);
userDelay(2);
// 6Byteリード
HAL_I2C_Master_Receive(hi2c, WII_NUNCHUCK_DEV_ID|0x01 , rxData, 6, 3000);
// データ複合
for(cnt=0; cnt<6; cnt++){
decData[cnt] = decode_byte(rxData[cnt]);
}
// 構造体へ代入
keyStatus->joy_x = decData[0];
keyStatus->joy_y = decData[1];
keyStatus->button_c = (decData[5]>>1) & 0x01;
keyStatus->button_z = (decData[5]>>0) & 0x01;
keyStatus->accel_x = (((uint16_t)decData[2])<<2) | ((decData[5]>>2) & 0x03);
keyStatus->accel_y = (((uint16_t)decData[3])<<2) | ((decData[5]>>4) & 0x03);
keyStatus->accel_z = (((uint16_t)decData[4])<<2) | ((decData[5]>>6) & 0x03);
}
// ヌンチャク初期化
void WiiNunchuck_init(I2C_HandleTypeDef *hi2c)
{
uint8_t pData[2] = {0x40, 0x00};
HAL_I2C_Master_Transmit(hi2c, WII_NUNCHUCK_DEV_ID, pData, 2, 3000);
}
動作結果
出力例
メンバ名 | 値 |
---|---|
joy_x | 131 |
joy_y | 131 |
button_c | 1 |
button_z | 1 |
accel_x | 696 |
accel_y | 509 |
accel_z | 543 |
総評
ボタンとスティックの情報は正常に取得できたが、
加速センサの値が正しいかどうか判断できない。
(傾けると重力加速度の方向の値が変わることは確認できるが…)