这是一个通过 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
}