Nintendo Controller / NES Controller for Arduino

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.

/* 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);
}

Can we have some pics please? :slight_smile:

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

#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

#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;
}

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.

/* 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);
}

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.

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;

}