🕒 3 min read

The Arduino Joystick shield could be used as a user interface, be it as a remote control to wireless send commands to control a robot, or as a game controller interface, etc. In this tutorial, we’ll be exploring how to interface the shield with the arduino, and using a 0.96″ OLED display to display the readings of the buttons and joystick.

Overview

The Arduino Joystick Shield is a convinient shield that could be used to turn your Arduino Uno into a controller! Featuring a 2 axis joystick + 7 buttons, it could be used to easily control either a robot via a wireless module, or an interface to a game. A Nokia 5110 Display and a RF module could be attached to the Arduino Shield, but this may be covered in future post.

  • 2 Axis joystick + 1 Push button (Can be pressed)
  • 4 Momentary Button (Larger Push button)
  • 2 Select Buttons (Smaller Push buttons)

Components

The components used are as follows:

  • Arduino Uno
  • Arduino Joystick Shield
  • OLED 0.96″ Display, I2C
  • Jumper Wires x 4

Schematics

The shield could be easily attached onto the Arduino Uno, and the OLED Display is connected via 4 jumper wires.

Demo

Code

Pre-requisite

For the interfacing, we would be using the u8g2 library to display a User interface, in which the interface would respond according to the sensor readings read. The library could be downloaded here: https://github.com/olikraus/u8g2

Basic User Interface

The buttons are labelled, the circles would become larger when the buttons are pressed. The joystick location shown on the left side of the screen.

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

const uint8_t PROGMEM a_btn{2};
const uint8_t PROGMEM c_btn{4};
const uint8_t PROGMEM d_btn{5};
const uint8_t PROGMEM b_btn{3};
const uint8_t PROGMEM e_btn{6};
const uint8_t PROGMEM f_btn{7};
const uint8_t PROGMEM k_btn{8};
const uint8_t PROGMEM x_joystick = A0;
const uint8_t PROGMEM y_joystick = A1;

// keep state of all btns
boolean prev_a_btn = false;
boolean prev_c_btn = false;
boolean prev_d_btn = false;
boolean prev_b_btn = false;
boolean prev_e_btn = false;
boolean prev_f_btn = false;
boolean prev_k_btn = false;

void setup() {
  // initialise the digital pins
  pinMode(a_btn, INPUT);
  pinMode(c_btn, INPUT);
  pinMode(d_btn, INPUT);
  pinMode(b_btn, INPUT);
  pinMode(e_btn, INPUT);
  pinMode(f_btn, INPUT);
  pinMode(k_btn, INPUT);

  //Setup display
  u8g2.begin();
  Serial.begin(9600);

  u8g2.setFont(u8g2_font_6x10_tf);

}

void btn_cb(bool new_val, bool &old_val)
{
  // if there is no change in state, don't generate events
  if (new_val == old_val)
    return;
  // update the previous value so changes in state can be registered
  old_val = new_val;
}

const int PROGMEM l_len{20};
const int PROGMEM cir_x{25};
const int PROGMEM cir_y{32};
const int PROGMEM cir_r{13};

const int PROGMEM txt_x{4};
const int PROGMEM txt_y{2};

void drawBtn(int x, int y, int r, int off_x, int off_y, int btn, char* txt) {
  u8g2.drawStr(x - r / 2 + off_x, y + cir_r / 2 - off_y, txt);
  u8g2.drawCircle(x, y, !digitalRead(btn) ? 3 * r / 4 : r / 2);
}

void loop()
{
  u8g2.clearBuffer();
  // handle normal buttons, the state will be true on LOW, when the
  // button is pressed (low resistance on button press)
  btn_cb(digitalRead(a_btn) == LOW, prev_a_btn);
  btn_cb(digitalRead(b_btn) == LOW, prev_b_btn);
  btn_cb(digitalRead(c_btn) == LOW, prev_c_btn);
  btn_cb(digitalRead(d_btn) == LOW, prev_d_btn);
  btn_cb(digitalRead(e_btn) == LOW, prev_e_btn);
  btn_cb(digitalRead(f_btn) == LOW, prev_f_btn);

  // to parse analog sensors to digital ones, we first read them and
  // map them to a value in [-1, 0, 1]
  int new_x_joystick = map(analogRead(x_joystick), 0, 1000, -1 * cir_r, cir_r);
  int new_y_joystick = map(analogRead(y_joystick), 0, 1000, -1 * cir_r, cir_r);
  Serial.print(cir_x + new_x_joystick);
  Serial.print("\t");
  Serial.print( cir_y + new_x_joystick);
  Serial.print("\n");

  //draw grid
  u8g2.drawLine(cir_x, cir_y - l_len, cir_x, cir_y + l_len);
  u8g2.drawLine(cir_x - l_len, cir_y , cir_x + l_len, cir_y);

  //draw circle
  u8g2.drawStr(cir_x + new_x_joystick, cir_y - new_y_joystick, "K");
  u8g2.drawCircle(cir_x + new_x_joystick, cir_y - new_y_joystick, !digitalRead(k_btn) ? 3 * cir_r / 2 : cir_r);

  //draw Btn
  //A
  drawBtn(100, 20, cir_r, txt_x, txt_y, a_btn, "A");
  //D
  drawBtn(85, 35, cir_r, txt_x, txt_y, d_btn, "D");
  //C
  drawBtn(100, 50, cir_r, txt_x, txt_y, c_btn, "C");
  //B
  drawBtn(115, 35, cir_r, txt_x, txt_y, b_btn, "B");
  //F
  drawBtn(55, 55, cir_r, txt_x, txt_y, f_btn, "F");
  //E
  drawBtn(75, 55, cir_r, txt_x, txt_y, e_btn, "E");

  u8g2.sendBuffer();

  //delay(5);
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *