這是一個透過 I2C 將 Wii Nunchuk 與 ESP32 結合使用的函式庫。它可以與 Arduino IDE 一起使用,也可以直接與使用 ESP-IDF 的程式碼一起使用。要在 Arduino IDE 草圖中使用該庫,只需將檔案wii_i2c.c
和wii_i2c.h
複製到草圖目錄中。
該庫使用 ESP-IDF I2C API,因為 Arduino Wire 庫在具有 Wii 控制器的 ESP32 中無法可靠運作。
該庫支援Wii Nunchuk和Wii Classic 控制器。根據 Wiibrew 項目中提供的信息,使其能夠與插入 Wiimote 的其他 I2C 設備(如 Classic Controller Pro、Wii Motion Plus 等)配合使用應該不難,但我沒有這些設備所以我不確定。
ESP32 的 Arduino Wire 庫(來自Wire.h
)使用 I2C 連接埠 0 作為Wire
對象,並使用連接埠 1 作為Wire1
對象。因此,如果在此庫中使用 I2C 連接埠 0,請不要使用Wire
如果使用 I2C 連接埠 1,請不要使用Wire1
。
這是一個使用 Wii Nunchuk 的簡單範例。有關檢測和處理多種控制器類型的更完整範例,請參閱esp32-wii-nunchuk.ino
。
# include " wii_i2c.h "
// pins connected to the Nunchuk:
# define PIN_SDA 32
# define PIN_SCL 33
// ESP32 I2C port (0 or 1):
# define WII_I2C_PORT 0
void setup ()
{
Serial. begin ( 115200 );
if ( wii_i2c_init (WII_I2C_PORT, PIN_SDA, PIN_SCL) != 0 ) {
Serial. printf ( " Error initializing nunchuk :( " );
return ;
}
wii_i2c_request_state ();
}
void loop ()
{
const unsigned char *data = wii_i2c_read_state ();
wii_i2c_request_state ();
if (! data) {
Serial. printf ( " no data available :( " )
} else {
wii_i2c_nunchuk_state state;
wii_i2c_decode_nunchuk (data, &state);
Serial. printf ( " Stick position: (%d,%d) n " , state. x , state. y );
Serial. printf ( " C button is %s n " , (state. c ) ? " pressed " : " not pressed " );
Serial. printf ( " Z button is %s n " , (state. z ) ? " pressed " : " not pressed " );
}
delay ( 1000 );
}
如果您的程式碼對時間敏感,無法等待控制器回應,請使用 API 函數來產生讀取不同核心中控制器狀態的任務。例如:
# include " wii_i2c.h "
// pins connected to the controller:
# define PIN_SDA 32
# define PIN_SCL 33
// ESP32 I2C port (0 or 1):
# define WII_I2C_PORT 0
// CPU id where the task will run (1=the core
// where your code usually runs, 0=the other core):
# define READ_TASK_CPU 0
// delay in milliseconds between controller reads:
# define READ_DELAY 30
static unsigned int controller_type;
void setup ()
{
Serial. begin ( 115200 );
if ( wii_i2c_init (WII_I2C_PORT, PIN_SDA, PIN_SCL) != 0 ) {
Serial. printf ( " Error initializing nunchuk :( " );
return ;
}
// if you want to read the controller identity,
// do it BEFORE starting the read task:
const unsigned char *ident = wii_i2c_read_ident ();
controller_type = wii_i2c_decode_ident (ident);
// start the a task that reads the controller state in a different CPU:
if ( wii_i2c_start_read_task (READ_TASK_CPU, READ_DELAY) != 0 ) {
Serial. printf ( " Error creating task to read controller state " );
return ;
}
}
void loop ()
{
// this function always returns quickly, either
// with new data or NULL if data isn't ready:
const unsigned char *data = wii_i2c_read_data_from_task ();
if (data) {
// decode data according to controller_type:
// wii_i2c_decode_nunchuk(data, &nunchuk_state);
// wii_i2c_decode_classic(data, &classic_state);
}
// do other timing-sensitive stuff
}