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
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.
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?
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);
}
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.
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.
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: