--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/README.rst Sun Oct 13 13:14:35 2013 +0900
+See chukmote.fzz or `chuckmote_bb.svg
+<https://bitbucket.org/engored/chukmote/raw/tip/chukmote_bb.svg>`_.
+- WiiChuck Adapter for Arduino: https://dx.com/p/147094
+- L298N Motor Board: https://dx.com/p/120542
+- Bluetooth Serial Port Module: https://dx.com/p/104299
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/car2wd_bt/car2wd_bt.ino Sun Oct 13 13:14:35 2013 +0900
+#include <VirtualWire.h>
+unsigned long lastmsg = 0;
+ if (Serial.available() > 0) {
+ int a = Serial.parseInt();
+ int b = Serial.parseInt();
+ if (Serial.read() == '\n') {
+ unsigned int fade = (millis() - lastmsg) / 1000;
+ analogWrite(IN3, map(lspd, 0, 127, 0, 255));
+ digitalWrite(IN4, LOW);
+ digitalWrite(IN3, LOW);
+ analogWrite(IN4, map(lspd, 0, -128, 0, 255));
+ analogWrite(IN1, map(rspd, 0, 127, 0, 255));
+ digitalWrite(IN2, LOW);
+ digitalWrite(IN1, LOW);
+ analogWrite(IN2, map(rspd, 0, -128, 0, 255));
Binary file chukmote.fzz has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chukmote.py Sun Oct 13 13:14:35 2013 +0900
+ self.stdscr = curses.initscr()
+ self.nubwin = self.stdscr.subwin(9, 17, 2, 4)
+ self.inwin = self.stdscr.subwin(10, 20, 2, 23)
+ self.lthwin = self.stdscr.subwin(9, 4, 2, 45)
+ self.rthwin = self.stdscr.subwin(9, 4, 2, 50)
+ self.outwin = self.stdscr.subwin(10, 20, 2, 56)
+ self.inwin.addstr(0, 1, ' Input ')
+ self.inwin.addstr(2, 4, 'Nub X:')
+ self.inwin.addstr(3, 4, 'Nub Y:')
+ self.inwin.addstr(4, 4, 'Pitch:')
+ self.inwin.addstr(5, 4, 'Roll:')
+ self.inwin.addstr(6, 4, 'C:')
+ self.inwin.addstr(7, 4, 'Z:')
+ self.outwin.addstr(0, 1, ' Output ')
+ self.outwin.addstr(2, 4, 'Left:')
+ self.outwin.addstr(3, 4, 'Right:')
+ def update(self, rawinput, lspd, rspd):
+ self.inwin.addstr(2, 10, '{0:5}'.format(rawinput.x))
+ self.inwin.addstr(3, 10, '{0:5}'.format(rawinput.y))
+ self.inwin.addstr(4, 10, '{0:5}'.format(rawinput.pitch))
+ self.inwin.addstr(5, 10, '{0:5}'.format(rawinput.roll))
+ self.inwin.addstr(6, 8, 'on ' if rawinput.c else 'off')
+ self.inwin.addstr(7, 8, 'on ' if rawinput.z else 'off')
+ self.nubwin.addch(4 - round(rawinput.y / 42), 8 + round(rawinput.x / 21), 'o')
+ llim = 4 - round(lspd / 42)
+ for i in range(min(llim, 4), max(llim, 4) + 1):
+ self.lthwin.addstr(i, 1, ' ', curses.A_REVERSE)
+ rlim = 4 - round(rspd / 42)
+ for i in range(min(rlim, 4), max(rlim, 4) + 1):
+ self.rthwin.addstr(i, 1, ' ', curses.A_REVERSE)
+ self.outwin.addstr(2, 10, '{0:5}'.format(lspd))
+ self.outwin.addstr(3, 10, '{0:5}'.format(rspd))
+ def error(self, error):
+ self.stdscr.addstr(22, 2, error)
+ def update(self, rawinput):
+ if abs(rawinput.y) > self.deadzone:
+ if abs(rawinput.x) > self.deadzone:
+ self.lspd += rawinput.x
+ self.rspd -= rawinput.x
+ if self.lspd < -128: self.lspd = -128
+ if self.lspd > 127: self.lspd = 127
+ if self.rspd < -128: self.rspd = -128
+ if self.rspd > 127: self.rspd = 127
+ def __init__(self, x=0, y=0, pitch=0, roll=0, c=False, z=False):
+ parts = line.strip().split(',')
+ return RawInput(x, y, pitch, roll, c, z)
+def encode_output(lspd, rspd):
+ return '{0},{1}\n'.format(lspd, rspd)
+ tty_in = open(sys.argv[1], 'rb', 0)
+ tty_out = open(sys.argv[2], 'wb', 0)
+ atexit.register(ui.finish)
+ line = tty_in.readline().decode()
+ rawinput = decode_input(line)
+ except (IndexError, ValueError):
+ ui.error('bad line "{0}"'.format(line.strip('\n')))
+ driver.update(rawinput)
+ ui.update(rawinput, driver.lspd, driver.rspd)
+ tty_out.write(encode_output(driver.lspd, driver.rspd).encode())
+if __name__ == '__main__':
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chukmote/WiiChuck.h Sun Oct 13 13:14:35 2013 +0900
+ * Nunchuck -- Use a Wii Nunchuck
+ * Tim Hirzel http://www.growdown.com
+ notes on Wii Nunchuck Behavior.
+ This library provides an improved derivation of rotation angles from the nunchuck accelerometer data.
+ The biggest different over existing libraries (that I know of ) is the full 360 degrees of Roll data
+ from teh combination of the x and z axis accelerometer data using the math library atan2.
+ It is accurate with 360 degrees of roll (rotation around axis coming out of the c button, the front of the wii),
+ and about 180 degrees of pitch (rotation about the axis coming out of the side of the wii). (read more below)
+ In terms of mapping the wii position to angles, its important to note that while the Nunchuck
+ sense Pitch, and Roll, it does not sense Yaw, or the compass direction. This creates an important
+ disparity where the nunchuck only works within one hemisphere. At a result, when the pitch values are
+ less than about 10, and greater than about 170, the Roll data gets very unstable. essentially, the roll
+ data flips over 180 degrees very quickly. To understand this property better, rotate the wii around the
+ axis of the joystick. You see the sensor data stays constant (with noise). Because of this, it cant know
+ the difference between arriving upside via 180 degree Roll, or 180 degree pitch. It just assumes its always
+ * This file is an adaptation of the code by these authors:
+ * Tod E. Kurt, http://todbot.com/blog/
+ * The Wii Nunchuck reading code is taken from Windmeadow Labs
+ * http://www.windmeadow.com/node/42
+ * Conversion to Arduino 1.0 by Danjovic
+ * http://hotbit.blogspot.com
+// these may need to be adjusted for each nunchuck for calibration
+#define RADIUS 210 // probably pretty universal
+#define DEFAULT_ZERO_JOY_X 129
+#define DEFAULT_ZERO_JOY_Y 128
+ uint8_t status[6]; // array to store wiichuck output
+ uint8_t averageCounter;
+ //int accelArray[3][AVERAGE_N]; // X,Y,Z
+ uint8_t zeroJoyX; // these are about where mine are
+ uint8_t zeroJoyY; // use calibrateJoy when the stick is at zero to correct
+ // instead of the common 0x40 -> 0x00 initialization, we
+ // use 0xF0 -> 0x55 followed by 0xFB -> 0x00.
+ // this lets us use 3rd party nunchucks (like cheap $4 ebay ones)
+ // while still letting us use official oness.
+ // only side effect is that we no longer need to decode bytes in _nunchuk_decode_byte
+ // see http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1264805255
+ Wire.beginTransmission(0x52); // device address
+ Wire.endTransmission();
+ Wire.beginTransmission(0x52);
+ Wire.write((uint8_t)0x00);
+ Wire.endTransmission();
+ zeroJoyX = DEFAULT_ZERO_JOY_X;
+ zeroJoyY = DEFAULT_ZERO_JOY_Y;
+ Wire.requestFrom (0x52, 6); // request data from nunchuck
+ while (Wire.available ()) {
+ // receive byte as an integer
+ status[cnt] = _nunchuk_decode_byte (Wire.read()); //
+ //if (averageCounter >= AVERAGE_N)
+ for (i = 0; i < 3; i++)
+ //accelArray[i][averageCounter] = ((int)status[i+2] << 2) + ((status[5] & (B00000011 << ((i+1)*2) ) >> ((i+1)*2)));
+ angles[i] = (status[i+2] << 2) + ((status[5] & (B00000011 << ((i+1)*2) ) >> ((i+1)*2)));
+ //accelYArray[averageCounter] = ((int)status[3] << 2) + ((status[5] & B00110000) >> 4);
+ //accelZArray[averageCounter] = ((int)status[4] << 2) + ((status[5] & B11000000) >> 6);
+ buttonZ = !( status[5] & B00000001);
+ buttonC = !((status[5] & B00000010) >> 1);
+ _send_zero(); // send the request for next bytes
+ // UNCOMMENT FOR DEBUGGING
+ // total = 0; // accelArray[xyz][averageCounter] * FAST_WEIGHT;
+ return (float)angles[0] - ZEROX;
+ // total = 0; // accelArray[xyz][averageCounter] * FAST_WEIGHT;
+ return (float)angles[1] - ZEROY;
+ // total = 0; // accelArray[xyz][averageCounter] * FAST_WEIGHT;
+ return (float)angles[2] - ZEROZ;
+ return (buttonZ && ! lastZ);
+ return (buttonC && ! lastC);
+ // for using the joystick like a directional button
+ bool rightJoy(int thresh=60) {
+ return (readJoyX() > thresh and lastJoyX <= thresh);
+ // for using the joystick like a directional button
+ bool leftJoy(int thresh=60) {
+ return (readJoyX() < -thresh and lastJoyX >= -thresh);
+ return (int) joyX - zeroJoyX;
+ return (int)joyY - zeroJoyY;
+ // R, the radius, generally hovers around 210 (at least it does with mine)
+ // return sqrt(readAccelX() * readAccelX() +readAccelY() * readAccelY() + readAccelZ() * readAccelZ());
+ // returns roll degrees
+ return (int)(atan2(readAccelX(),readAccelZ())/ M_PI * 180.0);
+ // returns pitch in degrees
+ return (int) (acos(readAccelY()/RADIUS)/ M_PI * 180.0); // optionally swap 'RADIUS' for 'R()'
+ uint8_t _nunchuk_decode_byte (uint8_t x)
+ //decode is only necessary with certain initializations
+ //x = (x ^ 0x17) + 0x17;
+ Wire.beginTransmission (0x52); // transmit to device 0x52
+ Wire.write ((uint8_t)0x00); // sends one byte
+ Wire.endTransmission (); // stop transmitting
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chukmote/chukmote.ino Sun Oct 13 13:14:35 2013 +0900
+WiiChuck chuck = WiiChuck();
+ //chuck.calibrateJoy();
+ int jx = chuck.readJoyX(), jy = chuck.readJoyY();
+ int pitch = chuck.readPitch(), roll = chuck.readRoll();