Arduino softpot potentiometer game


Made a cave-navigation game using a Spectra Symbol softpot. The resistance of the softpot changes depending on where you press it, so you can do an Arduino analogRead() on the voltage output to determine where the circle goes on the screen. You have to make sure to add a resistor (I think I used a 100k resistor) going from the middle pin to ground (or power), or else the output floats.

Code available in the full post.

Here’s the Arduino code. The middle pin of the softpot should go to analog input pin 2:

int analogPin = 2;

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println(analogRead(analogPin));
  delay(100);
}

And here’s the Processing code. First, create a file named “score.dat” in the folder, and put a number on the first line. Sorry for the lack of commenting.

import processing.serial.*;

///////////////
// Constants //
///////////////

// High score data file
PrintWriter file;
String FILE_NAME = "score.dat";

// Serial input setup
String PORT_NAME = "COM3";   // Change this
int BAUD_RATE = 9600;
int SERIAL_IN_MAX = 1023;

// Font setup
PFont font;
String FONT_NAME = "Arial";
int FONT_SIZE = 20;

// Graphics setup constants
int FPS = 60;
int SCREEN_SIZE[] = {550,400};
int BG_COLOR = #000000;
int LINE_COLOR = #00FF00;
int TEXT_COLOR = #FFFFFF;
int CENTER_X = SCREEN_SIZE[0]/2;
int CENTER_Y = SCREEN_SIZE[1]/2;

// Player information constants
int PLAYER_SIZE = 6;
int HALF_PLAYER_SIZE = PLAYER_SIZE/2;

// Difficulty constants
int VERTICAL_RATE_RANGE[] = {2, 7};
int VERTICAL_RATE_CHANGE = 500;
int GAP_SIZE_RANGE[] = {25, 50};
int GAP_SIZE_CHANGE = 500;

int OBSTACLE_UPPER_BOUND = 100;
int OBSTACLE_LOWER_BOUND = SCREEN_SIZE[1]-100;

// Circular buffer constants
int SCROLL_SPEED = 2;
int BUFFER_SIZE = SCREEN_SIZE[0]/SCROLL_SPEED;

///////////////
// Variables //
///////////////

Serial arduino;

String serialString = "";
char byteReceived = 0;
int serialValue = 512;
int serialValueBuffer = serialValue;

float playerY = CENTER_Y;
int playerX = SCREEN_SIZE[0]/10;
int score, highScore, verticalRate, gapSize = 0;

int[] buffer = new int[BUFFER_SIZE];
int bufferWritePos = 0;
int bufferWritePosPrev = BUFFER_SIZE-1;
int bufferReadPos = 0;
int bufferCheckIndex = 0;

//////////////////////////
// Function definitions //
//////////////////////////

void setup() {
  size(SCREEN_SIZE[0],SCREEN_SIZE[1]);

  font = createFont(FONT_NAME, FONT_SIZE);  // Initialize font
  textFont(font);

  arduino = new Serial(this, PORT_NAME, BAUD_RATE);

  rectMode(CENTER);
  frameRate(FPS);

  reset();

  highScore = int(loadStrings(FILE_NAME)[0]);
  file = createWriter(FILE_NAME);
}

void draw() {
  if (arduino.available() > 0) {
    getData();
  }
  clearScreen();
  updateBackground();
  drawPlayer();
  scoreUpdate();
  difficultyCheck();
  checkDeath();
}

void reset() {
  score = 0;

  for (int i = 0; i  buffer[bufferCheckIndex]+gapSize ||
      playerY - HALF_PLAYER_SIZE  highScore) {
    highScore = score;
  }

  fill(LINE_COLOR);
  stroke(TEXT_COLOR);
  textAlign(RIGHT, TOP);
  text("High Score:", SCREEN_SIZE[0]-70, 0);
  text("Score:", SCREEN_SIZE[0]-70, FONT_SIZE);

  text(nfc(highScore), SCREEN_SIZE[0], 0);
  text(nfc(score), SCREEN_SIZE[0], FONT_SIZE);
}

void difficultyCheck() {
  score ++;
  gapSize = max(GAP_SIZE_RANGE[1]-score/GAP_SIZE_CHANGE, GAP_SIZE_RANGE[0]);
  verticalRate = min(VERTICAL_RATE_RANGE[0]+score/VERTICAL_RATE_CHANGE, VERTICAL_RATE_RANGE[1]);
}

void clearScreen() {
  background(BG_COLOR);
}

void drawPlayer() {
  playerY = map(serialValue, 0, 1023, 0, SCREEN_SIZE[1]);
  fill(LINE_COLOR);
  ellipse(playerX, playerY, PLAYER_SIZE, PLAYER_SIZE);
}

void getData() {
  byteReceived = char(arduino.read());
  if (byteReceived != '¥n') {
    serialString += byteReceived;
  } else {
    serialString = serialString.substring(0,serialString.length()-1);

    if (int(serialString) != 0) {
      serialValueBuffer = int(serialString);
    }
    serialValue = (3*serialValue+serialValueBuffer)/4;
    serialString = "";
  }
}

void updateBackground() {
  buffer[bufferWritePos] = buffer[bufferWritePosPrev] + int(random(-verticalRate,verticalRate));

  if (buffer[bufferWritePos] > OBSTACLE_LOWER_BOUND) {
    buffer[bufferWritePos] = OBSTACLE_LOWER_BOUND;
  }
  if (buffer[bufferWritePos] < OBSTACLE_UPPER_BOUND) {
    buffer[bufferWritePos] = OBSTACLE_UPPER_BOUND;
  }

  bufferWritePosPrev = bufferWritePos;
  bufferWritePos ++;
  bufferWritePos %= BUFFER_SIZE;

  drawObstacles(-gapSize);
  drawObstacles(gapSize);
}

void drawObstacles(int offset) {
  bufferReadPos = bufferWritePos;

  stroke(LINE_COLOR);
  noFill();

  int x, y;
  beginShape();
  for (int i = 0; i < BUFFER_SIZE; i++) {
    x = i*SCROLL_SPEED;
    y = buffer[bufferReadPos]+offset;
    vertex(x,y);

    bufferReadPos ++;
    bufferReadPos %= BUFFER_SIZE;
  }
  endShape();
}

void stop() {
  file.println(highScore);
  file.flush();
  file.close();
  exit();
}