Using an accelerometer to make a circle move around on an OLED screen.

Hello,

I’m trying to adapt using a couple of accelerometers instead of potentiometers to control the paddles in a pong game. The first step was to try and figure out how to control a circular object on an OLED screen, with boundary detection.

I’ve had a go at it, and it works. However, is there a better, or more efficient way of doing this? I’m a complete novice, and want to learn the best ways to approach things.

Code is below, however first some notes:

  1. The accelerometer is a 3 axis ADXL 345.
  2. This is some strange Chinese SPI display that claims to be 128x64, but I don’t think it is. The ball goes out of bounds if the vertical pixel count is more than 32.
  3. I used software SPI because hardware SPI is simply too fast, and the ball is uncontrollable.

Thank you,

N.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SparkFun_ADXL345.h>         // SparkFun ADXL345 Library
ADXL345 adxl = ADXL345();             // USE FOR I2C COMMUNICATION

/* Uncomment this block to use hardware SPI
  #define OLED_DC     9
  #define OLED_CS     0
  #define OLED_RESET  10
  Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);
*/

// Using software SPI because hardware SPI is too fast for this demo
// If using software SPI (the default case):
#define OLED_MOSI  11
#define OLED_CLK   13
#define OLED_DC    9
#define OLED_CS    0
#define OLED_RESET 10
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

// variables for boundary detection of OLED
int a = 64; // initial position of ball on x axis
int b = 16; // initial position of ball on y axis

void setup()   {

  // ADXL345 configurator
 
  Serial.begin(9600);                 // Start the serial terminal

  adxl.powerOn();                     // Power on the ADXL345

  adxl.setRangeSetting(4);           // Give the range settings.  Used 4 after trying the rest
  // Accepted values are 2g, 4g, 8g or 16g
  // Higher Values = Wider Measurement Range
  // Lower Values = Greater Sensitivity

  adxl.setSpiBit(0);                  // Configure the device to be in 4 wire SPI mode when set to '0' or 3 wire SPI mode when set to 1
  // Default: Set to 1
  // SPI pins on the ATMega328: 11, 12 and 13 as reference in SPI Library

  adxl.setActivityXYZ(0, 0, 0);       // Set to activate movement detection in the axes "adxl.setActivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setActivityThreshold(75);      // 62.5mg per increment   // Set activity   // Inactivity thresholds (0-255)

  adxl.setInactivityXYZ(0, 0, 0);     // Set to detect inactivity in all the axes "adxl.setInactivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setInactivityThreshold(75);    // 62.5mg per increment   // Set inactivity // Inactivity thresholds (0-255)
  adxl.setTimeInactivity(10);         // How many seconds of no activity is inactive?

  adxl.setTapDetectionOnXYZ(0, 0, 0); // Detect taps in the directions turned ON "adxl.setTapDetectionOnX(X, Y, Z);" (1 == ON, 0 == OFF)

  // Set values for what is considered a TAP and what is a DOUBLE TAP (0-255)
  adxl.setTapThreshold(50);           // 62.5 mg per increment
  adxl.setTapDuration(15);            // 625 μs per increment
  adxl.setDoubleTapLatency(80);       // 1.25 ms per increment
  adxl.setDoubleTapWindow(200);       // 1.25 ms per increment

  // Set values for what is considered FREE FALL (0-255)
  adxl.setFreeFallThreshold(7);       // (5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(30);       // (20 - 70) recommended - 5ms per increment

  // Setting all interupts to take place on INT1 pin
  //adxl.setImportantInterruptMapping(1, 1, 1, 1, 1);     // Sets "adxl.setEveryInterruptMapping(single tap, double tap, free fall, activity, inactivity);"
  // Accepts only 1 or 2 values for pins INT1 and INT2. This chooses the pin on the ADXL345 to use for Interrupts.
  // This library may have a problem using INT2 pin. Default to INT1 pin.

  // Turn on Interrupts for each mode (1 == ON, 0 == OFF)
  adxl.InactivityINT(0);
  adxl.ActivityINT(0);
  adxl.FreeFallINT(0);
  adxl.doubleTapINT(0);
  adxl.singleTapINT(0);
  //attachInterrupt(digitalPinToInterrupt(interruptPin), ADXL_ISR, RISING);   // Attach Interrupt

  // ADXL345 configurator end

  // begin display
  display.begin(SSD1306_SWITCHCAPVCC);
  display.clearDisplay();
  // begin complete

}

void loop() {

  int x, y, z; // variables for accelerometer 
  adxl.readAccel(&x, &y, &z); // read values.  Tried omitting z, but it didn't work.

  // There are 9 cases of x and y positioning
  
  // Case 1.  x tilt left, y steady
  if (x <= -3 && y > -3 && y < 3 && a > 2) {

    display.fillCircle(a, b, 1, WHITE);
    display.display();
    display.clearDisplay();
    a--;
  }

  // Case 2.  x tilt right, y steady
  if (x >= 3 && y > -3 && y < 3 && a < 126) {

    display.fillCircle(a, b, 1, WHITE);
    display.display();
    display.clearDisplay();
    a++;
  }

  // Case 3.  x steady, y tilt up
  if (y >= 3 && x > -3 && x < 3 && b > 2) {

    display.fillCircle(a, b, 1, WHITE);
    display.display();
    display.clearDisplay();
    b--;
  }

  // Case 4.  x steady, y tilt down
  if (y <= -3 && x > -3 && x < 3 && b < 30) {

    display.fillCircle(a, b, 1, WHITE);
    display.display();
    display.clearDisplay();
    b++;
  }

  // Case 5.  x tilt left, y tilt up
  if (x <= -3 && y >= 3 && a > 2 && b > 2) {

    display.fillCircle(a, b, 1, WHITE);
    display.display();
    display.clearDisplay();
    a--;
    b--;
  }

  // Case 6.  x tilt left, y tilt down
  if (x <= -3 && y <= -3 && a > 2 && b < 30) {

    display.fillCircle(a, b, 1, WHITE);
    display.display();
    display.clearDisplay();
    a--;
    b++;
  }

  // Case 7.  x tilt right, y tilt up
  if (x >= 3 && y >= 3 && a < 126 && b > 2) {

    display.fillCircle(a, b, 1, WHITE);
    display.display();
    display.clearDisplay();
    a++;
    b--;
  }

  // Case 8.  x tilt right, y tilt down
  if (x >= 3 && y <= -3 && a < 126 && b < 30) {

    display.fillCircle(a, b, 1, WHITE);
    display.display();
    display.clearDisplay();
    a++;
    b++;
  }

  // 9.  x steady, y steady
  if (x > -3 && x < 3 && y > -3 && y < 3) {

    display.fillCircle(a, b, 1, WHITE);
    display.display();
  }

}