使用Wii nunchuk手柄连接Arduino控制伺服电机的方法

描述

  简介

  偶然在箱子里发现一个旧的Wii Nunchuk手柄,又叫“双节棍”手柄,我想它是否可以用来控制Arduino,查阅了相关资料,确定Nunchuk手柄支持I2C方式连接到Arduino, 通过不断地研究深入,最后从todbot.com等网站上找到了相关的控制Will nunchuk的代码,于是就将代码移植过来,实现了 Will nunchuk 对伺服电机的控制!

  Wii Nunchuk接口定义

  把Wii Nunchuk和Arduino连接起来有几种方法,我们可以买一个Wii nunchuk的适配器,或者像剪断连接线,确保手柄再不需要和Wii连接使用了。本文采用了剪断线的方法,剪线之后再焊接了插针到nunchuk的连线,这样就可以和面包板更好的连接了。下图是Wii Nunchuk的接口定义 。

Arduino

  Wii Nunchuk手柄接口定义

  Wii Nunchuk连接Arduino

  手柄白线 (GND) –》 Arduino GND

  手柄红线 ( +5V ) –》 Arduino 5V

  手柄绿线 (SDA) –》 模拟引脚 4 或者 专用的 SDA pin

  手柄黄线 (SCL) –》 模拟引脚 5 或者 专用的 SCL pin

  连接伺服电机到Arduino

Arduino

  双轴舵机云台

  Servo 1 (x-axis)

  舵机棕线 (GND) –》 Arduino GND

  舵机红线 (5V) –》 Arduino 5V

  舵机黄线 (data/Signal) –》 Arduino Pin 10

  Servo 2 (y-axis)

  舵机棕线 (GND) –》 Arduino GND

  舵机红线 (5V) –》 Arduino 5V

  舵机黄线 (data/Signal) –》 Arduino Pin 9

Arduino

  舵机云台连接Arduino UNO

  连接全部组件

Arduino

  代码部分

  使用Arduino IDE上传代码前,需要两个标准库: Wire.h 、 Servo.h 。

  代码的执行顺序如下:

  初始化Nunchuk手柄的I2C接口;

  初始化伺服系统 ;

  读取Nunchuk手柄的数据;

  根据读取得 Nunchuk 手柄的实时数据控制伺服电机运动。

  完整代码如下:

/*

* NunchuckPrint

* 2007 Tod E. Kurt, http://todbot.com/blog/

* Change log:

*

* Mark Tashiro - Changed Wire.read to Wire.write

* Changed Wire.receive to Wire.read

* Added code for servos

*/

#include

#include

Servo servoLeft; // Define left servo

Servo servoRight; // Define right servo

static uint8_t nunchuck_buf[6]; // array to store nunchuck data,

void setup()

{

Serial.begin(19200);

servoLeft.attach(10); // Set left servo to digital pin 10

servoRight.attach(9); // Set right servo to digital pin 9

nunchuck_setpowerpins(); // use analog pins 2&3 as fake gnd & pwr

nunchuck_init(); // send the initilization handshake

Serial.print ("Finished setup\n");

}

void loop()

{

nunchuck_get_data();

// map nunchuk data to a servo data point

int x_axis = map(nunchuck_buf[0], 23, 222, 180, 0);

int y_axis = map(nunchuck_buf[1], 32, 231, 0, 180);

//move servo to desired position based on Wii nunchuk reading

servoLeft.write(x_axis);

servoRight.write(y_axis);

// un-comment next line to print data to serial monitor

// nunchuck_print_data();

}

//

// Nunchuck functions

//

// Uses port C (analog in) pins as power & ground for Nunchuck

static void nunchuck_setpowerpins()

{

#define pwrpin PORTC3

#define gndpin PORTC2

DDRC |= _BV(pwrpin) | _BV(gndpin);

PORTC &=~ _BV(gndpin);

PORTC |= _BV(pwrpin);

delay(100); // wait for things to stabilize

}

// initialize the I2C system, join the I2C bus,

// and tell the nunchuck we're talking to it

void nunchuck_init()

{

Wire.begin(); // join i2c bus as master

Wire.beginTransmission(0x52); // transmit to device 0x52

Wire.write(0x40); // sends memory address

Wire.write(0x00); // sends sent a zero.

Wire.endTransmission(); // stop transmitting

}

// Send a request for data to the nunchuck

// was "send_zero()"

void nunchuck_send_request()

{

Wire.beginTransmission(0x52); // transmit to device 0x52

Wire.write(0x00); // sends one byte

Wire.endTransmission(); // stop transmitting

}

// Receive data back from the nunchuck,

int nunchuck_get_data()

{

int cnt=0;

Wire.requestFrom (0x52, 6); // request data from nunchuck

while (Wire.available ()) {

// receive byte as an integer

nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.read());

cnt++;

}

nunchuck_send_request(); // send request for next data payload

// If we recieved the 6 bytes, then go print them

if (cnt >= 5) {

return 1; // success

}

return 0; //failure

}

// Print the input data we have recieved

// accel data is 10 bits long

// so we read 8 bits, then we have to add

// on the last 2 bits. That is why I

// multiply them by 2 * 2

void nunchuck_print_data()

{

static int i=0;

int joy_x_axis = nunchuck_buf[0];

int joy_y_axis = nunchuck_buf[1];

int accel_x_axis = nunchuck_buf[2]; // * 2 * 2;

int accel_y_axis = nunchuck_buf[3]; // * 2 * 2;

int accel_z_axis = nunchuck_buf[4]; // * 2 * 2;

int z_button = 0;

int c_button = 0;

// byte nunchuck_buf[5] contains bits for z and c buttons

// it also contains the least significant bits for the accelerometer data

// so we have to check each bit of byte outbuf[5]

if ((nunchuck_buf[5] >> 0) & 1)

z_button = 1;

if ((nunchuck_buf[5] >> 1) & 1)

c_button = 1;

if ((nunchuck_buf[5] >> 2) & 1)

accel_x_axis += 2;

if ((nunchuck_buf[5] >> 3) & 1)

accel_x_axis += 1;

if ((nunchuck_buf[5] >> 4) & 1)

accel_y_axis += 2;

if ((nunchuck_buf[5] >> 5) & 1)

accel_y_axis += 1;

if ((nunchuck_buf[5] >> 6) & 1)

accel_z_axis += 2;

if ((nunchuck_buf[5] >> 7) & 1)

accel_z_axis += 1;

Serial.print(i,DEC);

Serial.print("\t");

Serial.print("joy:");

Serial.print(joy_x_axis,DEC);

Serial.print(",");

Serial.print(joy_y_axis, DEC);

Serial.print(" \t");

Serial.print("acc:");

Serial.print(accel_x_axis, DEC);

Serial.print(",");

Serial.print(accel_y_axis, DEC);

Serial.print(",");

Serial.print(accel_z_axis, DEC);

Serial.print("\t");

Serial.print("but:");

Serial.print(z_button, DEC);

Serial.print(",");

Serial.print(c_button, DEC);

Serial.print("\r\n"); // newline

i++;

}

// Encode data to format that most wiimote drivers except

// only needed if you use one of the regular wiimote drivers

char nunchuk_decode_byte (char x)

{

x = (x ^ 0x17) + 0x17;

return x;

}

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分