Nintendo 64 controller + Servos

Hello I am relatively new to Arduinos and programming in general. I recently ran across a tutorial online to connect a Nintendo 64 controller to an Arduino. http://www.instructables.com/id/Use-an-Arduino-with-an-N64-controller/ Everything is working but I would really like to increase the functionality of the controller by hooking up two parallax servos. I have the servos connected but I am stuck on how to implement code to actually control them with the different buttons on the controller. This is the link to the download of the code used in the instructables I mentioned above. http://www.instructables.com/files/orig/F54/ZDHF/G3TDVKWH/F54ZDHFG3TDVKWH.zip

Any help or incite would be appreciated!

Thanks,

Matt

I am stuck on how to implement code to actually control them with the different buttons on the controller.

You need to define which button(s) you want to control the servos, and how the servo should move when each button is pressed.

I would like to control both servos with the joystick on the controller. The left to right motion on the joystick would allow one of the servos to rotate 180 degrees. The up and down motion on the joystick would allow the second servo to rotate 180 degrees as well. My hope is to mount the two servos so that I can control both horizontal and vertical movements using the joystick. I will probably use the servos to control a webcam of some sort. I hope this makes a little more sense.

I hope this makes a little more sense.

It does, since it says that you want to control the servos based on the joystick, not the buttons. It was the buttons that made no sense.

The code shows that there are joystick values, x and y, in the data structure. Do those change (properly) as you move the joystick left and right? Forward and backwards?

If so, what range of values do you get?

Yes when I use the serial monitor there are two values (x and y) corresponding with the joystick movements. When the joystick is in the middle it stays 0 and 0 for both the x and y values. When the joystick is pushed far left the x value ranges from about -75 to -85. When pushed right the x value ranges from 65 to 80. When pushed down the y value ranges from -75 to -90. When pushed up the y value ranges from 75 to 85.

When the joystick is pushed far left the x value ranges from about -75 to -85. When pushed right the x value ranges from 65 to 80. When pushed down the y value ranges from -75 to -90. When pushed up the y value ranges from 75 to 85.

So, you can map() the values from the range -90 to +90 to the range of your servos, and make the servo move to the map output.

I attempted to map the values but I believe I am missing something because the servo is not responding to joystick movement. (I am trying to get one servo working before I add the second) I am pretty confident that I mapped the values correctly but I think the problem might be that I am incorrectly reading the data with the analogRead function. Here is the code…

I added the following code before the void setup():

#include <Servo.h>

Servo myservo;

int val;

int stickx = N64_status.stick_x;

Here is the void setup():

void setup()
{
  Serial.begin(115200);



  // Communication with gamecube controller on this pin
  // Don't remove these lines, we don't want to push +5V to the controller
  digitalWrite(N64_PIN, LOW);  
  pinMode(N64_PIN, INPUT);


  // Initialize the gamecube controller by sending it a null byte.
  // This is unnecessary for a standard controller, but is required for the
  // Wavebird.
  unsigned char initialize = 0x00;
  noInterrupts();
  N64_send(&initialize, 1);

  // Stupid routine to wait for the gamecube controller to stop
  // sending its response. We don't care what it is, but we
  // can't start asking for status if it's still responding
  int x;
  for (x=0; x<64; x++) {
      // make sure the line is idle for 64 iterations, should
      // be plenty.
      if (!N64_QUERY)
          x = 0;
  }

  // Query for the gamecube controller's status. We do this
  // to get the 0 point for the control stick.
  unsigned char command[] = {0x01};
  N64_send(command, 1);
  // read in data and dump it to N64_raw_dump
  N64_get();
  interrupts();
  translate_raw_data(); 
 
  myservo.attach(9); 
}

And here is the void loop():

void loop()
{
    int i;
    unsigned char data, addr;

    // Command to send to the gamecube
    // The last bit is rumble, flip it to rumble
    // yes this does need to be inside the loop, the
    // array gets mutilated when it goes through N64_send
    unsigned char command[] = {0x01};

    // don't want interrupts getting in the way
    noInterrupts();
    // send those 3 bytes
    N64_send(command, 1);
    // read in data and dump it to N64_raw_dump
    N64_get();
    // end of time sensitive code
    interrupts();

    // translate the data in N64_raw_dump to something useful
    translate_raw_data();

   for (i=0; i<16; i++) {
       Serial.print(N64_raw_dump[i], DEC);
    }
    Serial.print(' ');
    Serial.print(N64_status.stick_x, DEC);
    Serial.print(' ');
    Serial.print(N64_status.stick_y, DEC);
    Serial.print(" \n");
   //   Serial.print("         Stick X:");
 //   Serial.print(N64_status.stick_x, DEC);
  //  Serial.print("         Stick Y:");
//Serial.println(N64_status.stick_y, DEC);


    // DEBUG: print it
    //print_N64_status();
    delay(25);
    
   val =  analogRead(stickx);
   val = map(val, -90, 90, 0, 180);
   myservo.write(val);
   delay(15);
}

but I think the problem might be that I am incorrectly reading the data with the analogRead function.

Well, yeah.

int stickx = N64_status.stick_x;

Read, one time, the value of the stick_x field of the uninitialized N64_status object.

   val =  analogRead(stickx);

Then, assume that that value represents a pin number (it most certainly does not, being crap), and try to read the value of the pin.

It's no wonder that doesn't work.

    Serial.print(N64_status.stick_x, DEC);

The value to pass to the map function is the one you just printed here.

Okay so I was way off. So I have to read the value of the the x axis of the joystick multiple times and then map this value each time it is read. I am having trouble conceptualizing how this code is going to work. Could you point me in the right direction?

So I have to read the value of the the x axis of the joystick multiple times

Why?

and then map this value each time it is read.

Yes (as long as each time means once).

I am having trouble conceptualizing how this code is going to work. Could you point me in the right direction?

That way -->.

You have a library that is already telling you the x and y joystick values. Use them just as though you had connected a pair of potentiometers to the Arduino and were using analogRead() to get the values. The only difference is that the N64 values are scaled, vs. the analogRead() values, but you want them rescaled anyway, so the fact that the have been scaled once is fine.

What is the name of the library for the joystick values? And so I can follow this http://arduino.cc/it/Tutorial/Knob as a guide?

What is the name of the library for the joystick values?

Beats me. What you were printing here:

    Serial.print(' ');
    Serial.print(N64_status.stick_x, DEC);
    Serial.print(' ');
    Serial.print(N64_status.stick_y, DEC);

You said was accurate, in that the values changed in a reasonable way when you moved the joystick. I assumed, perhaps incorrectly, that N64_status was a library.

And so I can follow this http://arduino.cc/it/Tutorial/Knob as a guide?

Except that you won't be reading the analog value from a potentiometer, yes.

I fixed the code so that the N64_Status library is now after analogRead...

val =  digitalRead(N64_status.stick_x);
   val = map(val, -90, 90, 0, 179);
   myservo.write(val);
   delay(15);

When I run the program the servo just barely twitches when i move the joystick. Not sure what the problem is now.

val =  digitalRead(N64_status.stick_x);

N64_status.stick_x is the value that was read from the x joystick. IT IS NOT A DAMN PIN NUMBER. Quit treating it as one. Just use the value as input to the map function:

val = map(N64_status.stick_x , -90, 90, 0, 179);

Thank you for your help.

-Matt

Hello, nice to see people using the controller. I just updated my N64 controller library which is able to use any PIN. The main aim was to make an easy API. (One missing thing is saving the previous state for comparing.) See here: http://pothos.blogsport.eu/2012/03/26/arduino-n64-controller-library-und-tetris-port/ (code samples inside)

Direct link: http://pothos.blogsport.eu/files/2012/03/N64Controller.zip

Greetings, Kai