Help with Nunchuck Code

Hello,

I've been working on my first project for a little while now and I recently purchased the nunchuck adapter from todbot. I have it up and running because I can do the serial stuff and get all the values, however, I can't seem to get the code right. I have played with it for a couple days now and nothing ever works. What I would like to do is get my 4 servos to be controlled by the joystick (forward sends them all forward, left sends 2 in one direction and 2 in the other, ect). I am using continuous rotation servo's and the ServoTimer2 library for that one was easiest to learn with for me. I looked at this code in this thread and it seems so simple: http://forums.ladyada.net/viewtopic.php?f=25&t=8262

I have all those libraries and stuff but could someone just give me a hint as ot how to get started? I can figure most of it out on my own, I just need a general idea as to how to get the code going for the nunchuck part. Thank you.

I have written my code and it seems to compile fine, it just doesnt work as I would like it to. The servos go in random directions for a split second then stop on their own. Could someone experienced check this over?

#include <math.h>
#include <ServoTimer2.h>
#include "Wire.h"
#include "WiiChuck.h"
//#include "nunchuck_funcs.h"

WiiChuck chuck = WiiChuck();

ServoTimer2 a;    // defines the servo names
ServoTimer2 b;
ServoTimer2 c;
ServoTimer2 d;

int joyThreshold = 10; // So it hopefully won't pick up little movements of the joystick

void setup() {
  //nunchuck_init();
  chuck.begin();
  chuck.update();
  chuck.calibrateJoy();
 
  a.attach(12);    // attaches all the servos to their proper pins
  b.attach(11);
  c.attach(10);
  d.attach(9);
}
 
void loop() {
  chuck.begin();
  chuck.update(); // Read the data from the nunchuck
   if( chuck.readJoyY() < joyThreshold ){ // Stick is being pushed down
      a.write(750);     // makes all servos go backward
      b.write(2250);
      c.write(750);
      d.write(2250);
     
   }
   else { // Stick is not being pushed down
      a.write(1500);   // all servos stop
      b.write(1500);
      c.write(1500);
      d.write(1500);
   }

   if( chuck.readJoyY() > joyThreshold ){ // Stick is being pushed up
      a.write(2250);    // all servos go forward
      b.write(750);
      c.write(2250);
      d.write(750);
   }
   else { // Stick is not being pushed up
      a.write(1500);   // all servos stop
      b.write(1500);
      c.write(1500);
      d.write(1500);
   }

   if( chuck.readJoyX() < joyThreshold ){ // Stick is being pushed left
      a.write(750);     // values to make the left servos go backward, and the right servos go forward
      b.write(2250);
      c.write(2250);
      d.write(750);
   }
   else {  // Stick is not being pushed down
      a.write(1500);   // servos are stopped
      b.write(1500);
      c.write(1500);
      d.write(1500);
   }

   if( chuck.readJoyX() > joyThreshold ){ // Stick is being pushed right
      a.write(2250);     // values to make the left servos go forward, and the right servos go backward
      b.write(750);
      c.write(750);
      d.write(2250);
   }
   else {  // Stick is not being pushed right
      a.write(1500);   //servos are stopped
      b.write(1500);
      c.write(1500);
      d.write(1500);
   }
}

You need a better understanding of what values of X & Y the controller is returning when you move the stick around.

I can see some obvious problems with your code.

First I suggest you simply loop and output the values of X & Y to the Arduino console (via serial). That will show you the sort of values you need to test for to decide when to move and in which direction.

Once you have done that you will know what values of X & Y the controller returns when it is centred (I expect the value to be about 128), left (expect X=0), right (expect X=255), forward (expect Y=0) and back (expect Y=255). You can use your "threshold", but not in the manner you are currently doing. Try testing for < 100 and > 160:

if (x < 100){ "left" }
else if (x > 160) { "right"}
else "stop"

similar for Y. You need to make sure that if you don't completely separate the tests for X and Y as in that case your code (as it stands now) will for instance if X = 200 and Y = 128 (ie joystick is right), your code will test X and command a right turn but then immediately test Y and stop the servos. This means you really need to test both X & Y at the same time and have cases for stop, left, right, forward, back, left-forward, left-back, right-forward and right-back. Once you have determined which of these 9 cases you are in, you can command the servos to move.

Also I suggest you replace the calls to the servos inside your "if" statements with calls to output text (via serial) to the Arduino IDE console, for instance inside your first "if" you should print "backwards". This will let you know whether your code is working without making your servos go crazy.

Thanks for the help, I understand what you mean and that does make a lot more sense :slight_smile: however, I'm new to all this stuff and I don't know how to implement that code you gave me. I understand the serial stuff and I can do that to get my values and test things, but I don't get how to do the nunchuck stuff. Once I have a basic idea of it in front of me I know I can pull it off but this code:

void loop() {
  chuck.begin();
  chuck.update(); // Read the data from the nunchuck
  chuck.readJoyX();
  if (X < 100){ "left" }
    a.write(2250);
    b.write(750);
    c.write(750);
    d.write(2250);
   }
   else if (X > 160) { "right" } // Stick is not being pushed right
      a.write(750);   // all servos stop
      b.write(2250);
      c.write(2250);
      d.write(750);
   }
   else "stop"
   a.write(1500);
   b.write(1500);
   c.write(1500);
   d.write(1500);
}

won't even compile, and I don't know how to get it working. Could someone please help write just that one section or drop another hint?

That wasn't code, it was pseudo-code to illustrate the point. That's why it won't compile. Braces are mismatched for a start.

Try this first - it should give you left & right turn behaviour.

void loop() {
  chuck.begin();
  chuck.update(); // Read the data from the nunchuck
  x = chuck.readJoyX(); // need to first assign X
  if (x < 100){ // Move one direction
    a.write(2250);
    b.write(750);
    c.write(750);
    d.write(2250);
   }
   else if (x > 160) {// move another direction
      a.write(750);   
      b.write(2250);
      c.write(2250);
      d.write(750);
   }
   else { // i.e. 100 <= x <= 160
   a.write(1500);
   b.write(1500);
   c.write(1500);
   d.write(1500);
   }
}

Make sure you declare x above the functions (before setup())

int x;

Thank you very much! Alright I get how to do it now. The code is still buggy so I think I gotta do more with the servo code. I can figure that out on my own though hopefully :slight_smile: