Detecting input from the Joystick

According to a page that sells a device similar to the one I’ve got, the joystick consists of 4 directional buttons with one selection button. These are connected to pins FLATH, RSET, D5, D6, and D7.

In theory, we should be able to read a digital input from each of those pins to detect key presses, but the RSET pin seems to reset the device whenever you push the joystick left.

Right: pin D3

Left: pin D4 (resets the device so we shouldn’t use this)

Push down: pin D5

Down: pin D6

Up: pin D7

The following code continuously polls to see the state of these pins, displaying them as a binary string to the serial port

#include <OLEDDisplay.h>
#include <SSD1306.h>

// connect to display using pins D1, D2 for I2C on address 0x3c
SSD1306  display(0x3c, D1, D2);

int y;

unsigned char joystick_pins[] = {D3, D4, D5, D6, D7};
byte joystick_buttons[] = {0, 0, 0, 0, 0};

void setup() {
  
  // init serial port
  Serial.begin(115200);
 
  // set the builtin LED pin to work as an output
  pinMode(LED_BUILTIN, OUTPUT);

  for(int i = 0; i < sizeof(joystick_pins); i++) {
    pinMode(joystick_pins[i], INPUT);
  }
 
  // init the display
  display.init();
  
  // set text y coordinate to start at 0
  y = 0;
}

void pollJoyStick() {
  Serial.print("Joystick buttons: ");
  for(int i = 0; i < sizeof(joystick_pins); i++) {
    joystick_buttons[i] = digitalRead(joystick_pins[i]);
    Serial.print(joystick_buttons[i]);
  }
  Serial.println();
  for(int i = 0; i < sizeof(joystick_pins); i++) {
    pinMode(joystick_pins[i], OUTPUT);
    digitalWrite(joystick_pins[i], HIGH);
    pinMode(joystick_pins[i], INPUT);
  }
}

void loop() {
  // turn off the LED
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);

  // clear the screen
  display.clear();
  
  // display text on the screen
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.setFont(ArialMT_Plain_10);
  display.drawString(0, y%64, "The screen is working!");
  
  // move text down 1 pixel next time
  y++;

  // update the display
  display.display(); 

  // turn on the LED
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);

  pollJoyStick();
}

A better way of detecting key presses would be to trigger an interrupt whenever a pin changes value. This would mean that the code wouldn’t have to keep polling to set the value.

The following code sample will display (0,0) in the top left corner of the screen but you can use the joystick to move the text left, right, up and down, updating the coordinates as it moves:

#include <OLEDDisplay.h>
#include <SSD1306.h>

// connect to display using pins D1, D2 for I2C on address 0x3c
SSD1306  display(0x3c, D1, D2);

int x,y;

byte joystick_pins[] = {D3, D5, D6, D7};
byte joystick_buttons[] = {0, 0, 0, 0};

const byte JOY_RIGHT = 0;
const byte JOY_PUSH = 1;
const byte JOY_DOWN = 2;
const byte JOY_UP = 3;
void onJoystickChange() {
  Serial.print("Joystick: ");
  for(int i = 0; i < sizeof(joystick_pins); i++) {
    joystick_buttons[i] = !digitalRead(joystick_pins[i]);
    Serial.print(joystick_buttons[i]);
  }
  Serial.println();
}

void setup() {
  
  // init serial port
  Serial.begin(115200);
 
  // set the builtin LED pin to work as an output
  pinMode(LED_BUILTIN, OUTPUT);

  for(int i = 0; i < sizeof(joystick_pins); i++) {
    pinMode(joystick_pins[i], INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(joystick_pins[i]), onJoystickChange, CHANGE);
  }
 
  // init the display
  display.init();
  
  // set text x and y coordinate to start at 0
  x = 0;
  y = 0;
}


void loop() {
  // clear the screen
  display.clear();
  
  // display text on the screen
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.setFont(ArialMT_Plain_10);

  // create string containing coordinates
  String coords = "(";
  coords += x;
  coords += ",";
  coords += y;
  coords += ")";
  display.drawString(x, y, coords);
  
  // update coordinates based on joystick movement
  if(joystick_buttons[JOY_RIGHT]) x++;
  if(joystick_buttons[JOY_DOWN]) y++; 
  if(joystick_buttons[JOY_UP]) y--;
  if(joystick_buttons[JOY_PUSH]) x--;
 
  // make sure x and y are valid numbers
  if(x > 128) x = 128;
  if(x < 0) x = 0;
  if(y > 64) y = 64;
  if(y < 0) y = 0;
   
  // update the display
  display.display(); 

  // slow down loop
  delay(10);

}