Pages: [1]   Go Down
Author Topic: Nintendo Controller / NES Controller for Arduino  (Read 8544 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Sr. Member
****
Karma: 4
Posts: 310
Posts: 40382
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This code uses an old-school 1980's NES controller to control a servo and an LED with the Arduino.  
With this code, the 'up' pad turns a servo to 180 degrees, 'right' turns it to 90, and 'down' turns it to 0 degrees.  Also, the A and B buttons turn a LED on and off.  
You can get a NES controller from ebay for less than $10.00
Here is a crude drawing of the controller plug, four holes on one side, three holes on the other.
                      _____
                     /
                    /       0     --0v (ground)
        +5V  ---0      0     --CLOCK
 nothing  ---  0      0     --LATCH
 nothing  ---  0      0     --SERIAL OUT
                    _______

You can just stick wires into the controller plug holes for prototyping.  
The +5 is connected to the Arduino +5
Ground to Arduino Ground
Latch goes to Pin 2 (with this code)
Clock to Pin 3
Serial Out to Pin 4

The servo data line is connected to Pin 10, and the LED is on Pin 11.

If you want to see the controller input on the serial monitor then just open up the serial monitor.  It will show you the binary numbers that are coming in from the controller.  
Each button has its own binary number.  'Up' is 11110111, for example.  
I included a //hidden Serial.println code that will display "Button has been pressed" if you press down the start button.  Just erase the '//' if you want to use that.  
The SNES plug is different, you're interested in that you will have to look elsewhere for the clock,latch,serial out info.


Quote
/* INITIALIZATION */
#include <ServoTimer1.h>
ServoTimer1 servo1;

int latch = 2; // set the latch pin
int clock = 3; // set the clock pin
int datin = 4;// set the data in pin
byte controller_data = 0;
int ledpin = 11;


/* SETUP */
void setup() {
Serial.begin(57600);
pinMode(latch,OUTPUT);
pinMode(clock,OUTPUT);
pinMode(datin,INPUT);
pinMode(ledpin, OUTPUT);

digitalWrite(latch,HIGH);
digitalWrite(clock,HIGH);

servo1.attach(10);

}

/* THIS READS DATA FROM THE CONTROLLER */
void controllerRead() {
controller_data = 0;
digitalWrite(latch,LOW);
digitalWrite(clock,LOW);

digitalWrite(latch,HIGH);
delayMicroseconds(2);
digitalWrite(latch,LOW);

controller_data = digitalRead(datin);

for (int i = 1; i <= 7; i ++) {
digitalWrite(clock,HIGH);
delayMicroseconds(2);
controller_data = controller_data << 1;
controller_data = controller_data + digitalRead(datin) ;
delayMicroseconds(4);
digitalWrite(clock,LOW);
}

}

/* THE LED, SERVO, AND SERIAL MONITOR PROGRAM */
void loop() {
controllerRead();
Serial.println(controller_data, BIN);

 // if (controller_data==B11101111){
   // Serial.println("Button has been Pressed");  
    //}  else {
    //Serial.println("Button not pressed");
    //}

//for REFERENCE:  
//UP = 11110111
//DOWN=11111011
//LEFT=11111101
//RIGHT=11111110
//SELECT=11011111
//START=11101111
//A=01111111
//B=10111111

if (controller_data==B01111111){
  digitalWrite(ledpin, HIGH);  
  }
  
if (controller_data==B10111111){
  digitalWrite(ledpin, LOW);
 }
  
if (controller_data==B11110111){
  servo1.write(180);
 }  

if (controller_data==B11111011){
  servo1.write(0);
}

if (controller_data==B11111110){
  servo1.write(90);
}

 delay(100);
}

« Last Edit: October 07, 2009, 08:19:49 pm by Big_Oil » Logged

New York
Offline Offline
Edison Member
*
Karma: 1
Posts: 1023
E != m*c^2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can we have some pics please?  smiley
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I made a simple class for a NES controller. It has functions like isDown, isPressed, isReleased. Just to make it easier to work with. Can use words like 'START' 'RIGHT' and stuff...

Not really commented or anything, but useful. Only made it to use it myself,.


Controller.h
Code:
#ifndef Controller_h
#define Controller_h

#include "WProgram.h"

const int A = 0;
const int B = 1;
const int SELECT = 2;
const int START = 3;
const int UP = 4;
const int DOWN = 5;
const int LEFT = 6;
const int RIGHT = 7;

class Controller
{
      public:
            int clockPin;// set the clock pin   RED
            int latchPin;// set the latch pin   ORANGE
            int datinPin;// set the data in pin YELLOW

            Controller(int clock, int latch, int datin);
            void update();
            boolean isDown(int button);
            boolean isPressed(int button);
            boolean isReleased(int button);
      
      private:
            byte buttons[8];
            byte buttonsOld[8];
};

#endif


Controller.cpp
Code:
#include "WProgram.h"
#include "Controller.h"

Controller::Controller(int clock, int latch, int datin)
{
      clockPin = clock;
      latchPin = latch;
      datinPin = datin;

      pinMode(latchPin,OUTPUT);
      pinMode(clockPin,OUTPUT);
      pinMode(datinPin,INPUT);
      digitalWrite(latchPin,HIGH);
      digitalWrite(clockPin,HIGH);
      
      //set arrays to all false;
      for (int i = 0; i<8; i++)
      {
            buttons[i] = false;
            buttonsOld[i] = false;
      }
}

void Controller::update()
{

      //set old buttons to current buttons
      for (int i = 0; i<8; i++)
      {
            buttonsOld[i] = buttons[i];
      }
      
      
      digitalWrite(latchPin,LOW);
      digitalWrite(clockPin,LOW);

      digitalWrite(latchPin,HIGH);
      delayMicroseconds(2);
      digitalWrite(latchPin,LOW);
      
      buttons[0] = !digitalRead(datinPin);

      for (int i = 1; i <= 7; i ++)
      {
            digitalWrite(clockPin,HIGH);
            delayMicroseconds(2);

            buttons[i] = !digitalRead(datinPin);

            delayMicroseconds(4);
            digitalWrite(clockPin,LOW);
      }
}
boolean Controller::isDown(int button)
{
    if (button >= 0 && button < 8)
            return (buttons[button]);
    else
            return false;
}
boolean Controller::isPressed(int button)
{
    if (button >= 0 && button < 8)
            return (buttons[button] && !buttonsOld[button]);
    else
            return false;
}
boolean Controller::isReleased(int button)
{
    if (button >= 0 && button < 8)
            return (!buttons[button] && buttonsOld[button]);
    else
            return false;
}
Logged

0
Offline Offline
Sr. Member
****
Karma: 4
Posts: 310
Posts: 40382
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

CONTRA CODE CONTROLLER
I have added to the original program.  Now, the servo will work only if you first enter the classic Contra Code.  (Up,Up,Down,Down,Left,Right,Left,Right,B,A,Start).  note- you don't hold down B and A with this code, you just press them separately.  
Pressing the 'select' button will reset the code and the servo won't work.
The program works by incrementing a variable Var every time you press a correct button in the sequence.  When Var gets up to 11 then an LED lights up and the servo can be controlled.  The servo and controller wiring is the same as my original post.  
I included a couple of "Tripwires" in the code.  When you get to that point, if an incorrect button is pushed it sends Var back to 0.  The trip wire ignores the last button pushed, the next button to be pushed, and the neutral 11111111 no buttons pushed.  Other than that, if a wrong button is hit the process resets.
If there is a simpler way to program this process I would be interested in seeing it.  

Quote
/* CONTRA CODE CONTROLLER */
/* INITIALIZATION */
#include <ServoTimer1.h>
ServoTimer1 servo1;

int latch = 2; // set the latch pin
int clock = 3; // set the clock pin
int datin = 4;// set the data in pin
byte controller_data = 0;
int ledpin = 11;

int var;

/* SETUP */
void setup() {
Serial.begin(57600);         //Make sure to set your
pinMode(latch,OUTPUT);       //serial port to 57600
pinMode(clock,OUTPUT);       //if you want to use it
pinMode(datin,INPUT);
pinMode(ledpin, OUTPUT);

digitalWrite(latch,HIGH);
digitalWrite(clock,HIGH);

servo1.attach(10);

var=0;

}

/* THIS READS THE CONTROLLER DATA */
void controllerRead() {
controller_data = 0;
digitalWrite(latch,LOW);
digitalWrite(clock,LOW);

digitalWrite(latch,HIGH);
delayMicroseconds(2);
digitalWrite(latch,LOW);

controller_data = digitalRead(datin);

for (int i = 1; i <= 7; i ++) {
digitalWrite(clock,HIGH);
delayMicroseconds(2);
controller_data = controller_data << 1;
controller_data = controller_data + digitalRead(datin) ;
delayMicroseconds(4);
digitalWrite(clock,LOW);
}

}

/* CONTRA CODE PROGRAM */
void loop() {
controllerRead();
//Serial.println(controller_data, BIN);

Serial.println(var);

if (controller_data==B11110111) //UP, var has become 1
  if (var==0){
    var=1;
  }
  
if (var==1){
  if (controller_data==B11110111) //UP
  var++;
}

if (var==2){
  if(controller_data==B11111011) //DOWN
  var++;
}


if (var==3){
  if(controller_data==B11111011) //DOWN
  var++;
}

if (var==4){
  if(controller_data==B11111101) //LEFT
  var++;
}

if (var==5){
  if(controller_data==B11111110) //RIGHT
  var++;
}

if (var==6){
  if(controller_data==B11111101) //LEFT
  var++;
}

if (var==7){
  if(controller_data==B11111110) //RIGHT
  var++;
}


if (controller_data==B10111111){         //B
  if (var==8){
  var=9;
}
}

if (var==9){                             //Tripwire 1
  if (controller_data!=B11111111){   //no buttons pressed
    if (controller_data!=B01111111){ //A
      if(controller_data!=B10111111){ //B
    var=0;
  }
}
  }
}

if (var==9){
  if (controller_data==B01111111){       //A
    var=10;
    } 
}
 
if (var==10){                             //Tripwire 2
  if (controller_data!=B11111111){   //no buttons pressed
    if (controller_data!=B11101111){ //start
      if(controller_data!=B01111111){ //A
    var=0;     //If you enter something wrong, like UP,  
  }            // var will go back to 0
}
  }
}

if (var==10){
  if (controller_data==B11101111){        //START
  var=11;
  }
}
 
  
if (controller_data==B11011111){ //SELECT, OFF
  var=0;
  digitalWrite(ledpin, LOW);
 }
  
if (var==11){  //If the code has been entered correctly var=11
  digitalWrite(ledpin, HIGH); //LED is on, and motors work
  if (controller_data==B11110111){   //UP
    servo1.write(178);
  } else {
  if (controller_data==B11111011){  //DOWN
  servo1.write(0);
  }else {
    if (controller_data==B11111110){  //RIGHT
    servo1.write(90);  
}
  }
  }
}


 delay(100);


« Last Edit: October 14, 2009, 03:17:52 pm by Big_Oil » Logged

Vallejo, CA
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I used this code to make a usb game controller with ppjoy. I figured out that if you use bitread it can see multipupal button presses.
Quote
byte ud = 127;
byte lr = 127;
byte st = 0;
byte sl = 0;
byte a = 0;
byte b = 0;
int latch = 2; // set the latch pin
int clock = 3; // set the clock pin
int datin = 4;// set the data in pin
byte controller_data = 0;
void setup() {

  Serial.begin(9600);
  pinMode(latch,OUTPUT);
  pinMode(clock,OUTPUT);
  pinMode(datin,INPUT);

  digitalWrite(latch,HIGH);
  digitalWrite(clock,HIGH);
  
}

/* THIS READS DATA FROM THE CONTROLLER */
void controllerRead() {
  controller_data = 0;
  digitalWrite(latch,LOW);
  digitalWrite(clock,LOW);

  digitalWrite(latch,HIGH);
  delayMicroseconds(2);
  digitalWrite(latch,LOW);

  controller_data = digitalRead(datin);

  for (int i = 1; i <= 7; i ++) {
    digitalWrite(clock,HIGH);
    delayMicroseconds(2);
    controller_data = controller_data << 1;
    controller_data = controller_data + digitalRead(datin) ;
    delayMicroseconds(4);
    digitalWrite(clock,LOW);
  }

}


void loop() {
  
  controllerRead();
  // if (controller_data==B11101111){
    // Serial.println("Button has been Pressed");  
     //}  else {
     //Serial.println("Button not pressed");
     //}

  //for REFERENCE:  
  //UP = 11110111 bit3
  //DOWN=11111011 bit2
  //LEFT=11111101 bit1
  //RIGHT=11111110 bit0
  //SELECT=11011111 bit5
  //START=11101111 bit4
  //A=01111111 bit7
  //B=10111111 bit6
  
  if (bitRead(controller_data,3)==0){
    ud = 235;
    //Serial.println("up"); //Debug test
  }

  if (bitRead(controller_data,2)==0){
    ud = 1;
    //Serial.println("down"); //Debug test
  }

  if (bitRead(controller_data,1)==0){
    lr = 235;
    //Serial.println("left"); //Debug test
  }
  if (bitRead(controller_data,0)==0){
    lr = 1;
    //Serial.println("right"); //Debug test
  }
  
  if (bitRead(controller_data,4)==0){
    st = 235;
    //Serial.println("start"); //Debug test
  }
  if (bitRead(controller_data,5)==0){
    sl = 235;
    //Serial.println("select"); //Debug test
  }
  if (bitRead(controller_data,7)==0){
    a = 235;
    //Serial.println("a"); //Debug test
  }  
  if (bitRead(controller_data,6)==0){
    b = 235;
    //Serial.println("b"); //Debug test
  }
  
  Serial.print(246,BYTE); // 240 plus the number of channels
  Serial.print(0,BYTE);   // button presses
  Serial.print(ud,BYTE);
  Serial.print(lr,BYTE);
  Serial.print(st,BYTE);
  Serial.print(sl,BYTE);
  Serial.print(a,BYTE);
  Serial.print(b,BYTE);
  delay(100);
  
  ud = 127;
  lr = 127;
  st = 127;
  sl = 127;
  a = 127;
  b = 127;

}



« Last Edit: October 07, 2010, 03:00:17 am by beast_C_A_T » Logged

Pages: [1]   Go Up
Jump to: