Project showcase
Footpad game controller

Footpad game controller © CC0

In order to achieve more indoor physical exercise while there is a threat of SARS-COV-2 outdoors, I worked on this simple game controller.

  • 499 views
  • 0 comments
  • 3 respects

Components and supplies

Necessary tools and machines

Apps and online services

About this project

Project Background

We have been thinking of building a more physical game controller to use it with Scratch or any other Blockly implementation. The overall idea is that the footpad works as a keyboard emulator so it easy to integrate with Scratch. This project is just an initial feasibility study using an Arduino-Uno rather than the Arduino-Leonardo we will use in the future. The Arduino-Leonardo can become a keyboard emulator while the Arduino-Uno can not do this,

Principle

Mechanically it is just two squares of sturdy plywood with a pivot point in the middle of the square to make the whole board wobble. In principle, not more than two corners should be pressed together at the same time.

Electronically we use piezoelectric elements to measure the pressure which we convert to a simple yes or no for each corner that is pressed. So we get four values.

The piezo elements here are used to detect pressure. Their principle is explained in detail here. When they are compressed they will release a voltage that can go up to 20 volts, However, the power/current they can release is limited. Never the less they could damage the Analog-Digital Converters ports of the Arduino. A resistor of 1 Mega Ohm in Parallel reduces this risk. There is more elaborate circuitry that eliminates such risk but so far a simple resistor is cheap easy and proves to work very well.

Hardware assembly

To keep the top part of the plywood on the bottom one we will use L profiles which we cut to hold both parts together. I made one larger to guide cables through as shown below.

They should be mounted as shown below with screws to the board.

Below the screws I used, flat embedded once for the bottom and rounded ones for the sides. The sizes were those that I had and fitted the building of the board.

Mark the places where you want to drill prior to drilling.

All the electronics will be mounted on the upper plate but we need a cut-out to allow space for the Arduino µ-processor board as shown below.

Below is shown how the two parts fit together.

Notice the resistor mounted in parallel with the piezo-crystal below. The value is around 1 Mega Ohm with 1/4W or even less is required. The wiring is shown on Figure 2.

Notice also the screw in the middle of the board to make the board pivot. There is such a screw on the other board. Some washers are probably required to get a suitable height for the pivot point.

Once all is connected add some foam between the piezo and the bottom board. I glued it all to the bottom of the upper board as you can see below.

Above you see a view of the bottom view of the top board (left-bottom) and the top of the bottom board (right top corner).

I used some candle wax at the areas where there is friction between the aluminum and the wood to reduce the friction.

Below is a view from the bottom where the Arduino is visible including some patches to protect the floor.

Software explained

This is not the firmware for the pad yet but just a simple code to test the functioning of the pad. We added a very simple running game to explore the pad which is the default setting in the attached code.

Pre-compiler information

// Threshold levels with higher up and lower down threshold "Schmitt-trigger" approach
#define ThresholdUp 500 // value becomes high if reading becomes equal or higher than this value
#define ThresholdLow 50 // value becomes low if reading becomes lower than this value

The Arduino-NO has a 10-bit ADC allowing values from 0 to 1023. When the signal is low or O it will only go to high or one once the value is above a value of 500 which is roughly equivalent to 2.5 volts. The signal will remain high until the signal drops under a value of 50 or 0.25 volts. This simulates the behavior of a Schmitt trigger making the readings more reliable.

// Code inclusion excludion settings
#define Debug 0 // to test the code
#define Logic 0 // to have the logic printed out, best when not the running game counter
#define Game 1 // running game

There are three settings. One is 'Debug' for debugging which was left in the code as it might help to understand the code. 'Logic' is the first attempt just to send the sensor data as zeros and ones as shown below. Only a change in state is sent out as can be seen below. In the left column are the four current values and in the right column the 4 former (old values).

0,  0,  0,  0, || 0,  1,  0,  0
1, 0, 0, 0, || 0, 0, 0, 0
0, 0, 0, 0, || 1, 0, 0, 0
0, 0, 1, 0, || 0, 0, 0, 0
0, 0, 0, 0, || 0, 0, 1, 0
1, 0, 0, 0, || 0, 0, 0, 0
0, 0, 0, 0, || 1, 0, 0, 0
0, 1, 0, 0, || 0, 0, 0, 0
0, 0, 0, 0, || 0, 1, 0, 0
1, 0, 0, 0, || 0, 0, 0, 0
0, 0, 0, 0, || 1, 0, 0, 0
0, 0, 1, 0, || 0, 0, 0, 0
0, 0, 0, 0, || 0, 0, 1, 0
1, 0, 0, 0, || 0, 0, 0, 0
0, 0, 0, 0, || 1, 0, 0, 0
0, 1, 0, 0, || 0, 0, 0, 0
0, 0, 0, 0, || 0, 1, 0, 0

In the 'Game' setting the board will ask how long you want to run. Once ready to record one wants to push and release the left sensor and consequently the same with the right sensor which will be counted as on step. The information as shown in the serial monitor is shown below.

Give a one digit number of minutes you want to exercise: 4
Your chosen exercise time is 4 minutes or 43392 microseconds.
We are ready to record your race ;-)
Start running!
1
2
3
4
5
6
7
8
9
You did it !
You have done 8 steps. Well done!
You had around 2 steps per minute!

The rest, we hope, is well documented in the code itself.

Future development

  • Make a python game in which the pad can be used.
  • Make another pad but this time with an Arduino Leonardo so it can work as a keyboard wedge. This would allow use with for example Scratch.
  • Connect the above (UNO( pad over serial communication with the Leonardo so two pad can be used in the same game through the Leonardo
  • Write a python program that runs video a the speed of the pad so people get a feeling that they are running outside.

Code

Testing Software for Floor Pad Game ControllerC/C++
This is a very simple allows for testing the hardware in the Arduino serial monitor
/*
 * By Eye4Tech.info
 * Released under Creative Common Zero License
 * This code reads 4 analog signals from Piezo Electric Crystal elements and convert the signal into pressed yes=no.
 * Although set as a game controler for future use we made a small running game in which steps made in a set time are counted
 * Debug set to 1 prints additional information to the serial monitor is used to write the programme
 * Logic set to 1 gives the values of four sensors
 * Game  set to 1 counts the steps in a set time.
 */

// Treshold levels with higher up and lower down treshold "schmitt-trigger" approach
#define ThresholdUp  500           // value becomes high if reading becommes equal or higher than this value
#define ThresholdLow  50           // value becomes low  if reading becommes lower than this value

// Code inclusion excludion settings
#define Debug          0           // to test the code
#define Logic          0           // to have the logic printed out, best when not the running game counter
#define Game           1           // running game

// constant values 
const uint8_t PIEZO_0  =    A0;    // piezo output left
const uint8_t PIEZO_1  =    A1;    // piezo output back
const uint8_t PIEZO_2  =    A2;    // piezo output right
const uint8_t PIEZO_3  =    A3;    // piezo output front
bool Reading[4]    = {0,0,0,0};
bool OldReading[4] = {0,0,0,0};
bool change        =         0;
uint16_t EndTime   =         0;    // time to end of exercise
uint16_t ExerTime  =         0;    // duration of exercise in microseconds
int  StepCounter   =         0;

void setup() 
{
  Serial.begin(9600);
  // When game is set above this will ask for the time the person wants to race
  #if Game
    { 
      Serial.print  ("Give a one digit number of minutes you want to exercise: ");
      while (!ExerTime)
      {
        if (Serial.available() > 0)
        {
          char Minutes = Serial.read();
          if (isDigit(Minutes))
          { 
            Serial.print  (Minutes);
            ExerTime = 60000*(int(Minutes )-48);    // 1 is ASCII 49
            Serial.print  ("\nYour chosen exercise time is ");
            Serial.print  ( Minutes        );
            Serial.print  (" minutes or "  );
            Serial.print  ( ExerTime       );
            Serial.println(" microseconds.");
            Serial.println("We are ready to record your race ;-)");
          }
        }
      }
    }
  #endif
}

void loop() 
{
  // read Piezo ADC values
  int piezoADC0 = analogRead(PIEZO_0);
  int piezoADC1 = analogRead(PIEZO_1);
  int piezoADC2 = analogRead(PIEZO_2);
  int piezoADC3 = analogRead(PIEZO_3);
  
  // Use a schmitt trigger approach with higher up and lower down treshold to set yes no values.
  if (piezoADC0 >= ThresholdUp  & !Reading[0]) Reading[0] =1;
  if (piezoADC0 <  ThresholdLow &  Reading[0]) Reading[0] =0;
  if (piezoADC1 >= ThresholdUp  & !Reading[1]) Reading[1] =1;
  if (piezoADC1 <  ThresholdLow &  Reading[1]) Reading[1] =0;
  if (piezoADC2 >= ThresholdUp  & !Reading[2]) Reading[2] =1;
  if (piezoADC2 <  ThresholdLow &  Reading[2]) Reading[2] =0;
  if (piezoADC3 >= ThresholdUp  & !Reading[3]) Reading[3] =1;
  if (piezoADC3 <  ThresholdLow &  Reading[3]) Reading[3] =0;


  // verify if the reading changed the array values
  if (Logic)
  {
    change = 0;                      // assume no change at the start
    for (int i=0; i < 4; i++)
    {
      if (Reading[i] != OldReading[i])
      {
        change = 1;                  // indicate a change in values
        #if Debug
        {
          Serial.println("The values have been changed");
        }
        #endif
        break;                       // if one value is changed no other check is required
      }
    }
   
  }
  
  // if the value changed and Logic is on print the logic values
  if (change && Logic) 
  {
    Serial.print  (Reading[0]    );
    Serial.print  (",  "         );
    Serial.print  (Reading[1]    );
    Serial.print  (",  "         );
    Serial.print  (Reading[2]    );
    Serial.print  (",  "         );
    Serial.print  (Reading[3]    );
    Serial.print  (", || "       );
    Serial.print  (OldReading[0] );
    Serial.print  (",  "         );
    Serial.print  (OldReading[1] );
    Serial.print  (",  "         );
    Serial.print  (OldReading[2] );
    Serial.print  (",  "         );
    Serial.print  (OldReading[3] );
    Serial.println(""            );
    memcpy(OldReading, Reading, 4);
  }
  if (!change && Debug)
  {
    Serial.println("The values have been NOT been changed");
  }

  // step counter as a simple application for the pad
  if (Game)
  {
    // determine the start of the execise on the left foot when no step was set yet
    if (!EndTime && !StepCounter && Reading[0])
    {
      EndTime = millis() + ExerTime;
      Serial.print  ("Start running!\n");
      /*
      Serial.print  ("Now = "  );
      Serial.print  (millis()  );
      Serial.print  ("\tEnd = ");
      Serial.println(EndTime   );
      */
      OldReading[0]=1;
    }

    // as long as the end time of the exercise is not reached count steps
    // one step is a press left, press right. Counter count on the right step. 
    if (millis() < ExerTime)
    {
      if( OldReading[0] && !Reading[0] && Reading[2] )
      {
        /*
         * L[0] | R[2] | OL[0] | OR[2]
         * 0    | 0    | 0     | 0
         * 1    | 0    | 1     | 0     Conditions         => Set values
         * 0    | 1    | 0     | 1     OL_1 && L_0 && R_1 => OL_0 & OR_1
         * 1    | 0    |               OR_1 && L_1 && R_0 => OL_1 & OR_0
         */
        OldReading[0]= 0 ;
        OldReading[2]= 1 ;
        StepCounter += 1 ;
        Serial.println(StepCounter);
        
      }
      if( OldReading[2] && Reading[0] && !Reading[2] )
      {
        OldReading[0]= 1 ;
        OldReading[2]= 0 ;
      }
    }
    else
    {
      Serial.println("\nYou did it !"    ) ;
      Serial.print  ("You have done "    ) ;
      Serial.print  ( StepCounter        ) ;
      Serial.println(" steps. Well done!") ;
      Serial.print  ("You had around "   ) ;
      Serial.print  (StepCounter/(ExerTime/60000));
      Serial.println(" steps per minute!"          ) ;
      
      while (true)
      {
        // do nothing in a continious look to stop the program
      } 
    }
  }
}

Comments

Similar projects you might like

Space Trash Game using Arduino and OLED Display

Project tutorial by Pi BOTS MakerHub

  • 168 views
  • 0 comments
  • 3 respects

LCD Game

Project showcase by Team Iron_SalsaStudio

  • 17,785 views
  • 16 comments
  • 27 respects

Bongo Hero: A Fun and Easy Arduino Game

Project showcase by Etienne Daspe

  • 5,389 views
  • 2 comments
  • 15 respects

Bubble Cannon Interactive Game Controller

Project tutorial by Jimmy Huang

  • 1,467 views
  • 0 comments
  • 1 respect

Ponguino Arduino Pong Game

Project tutorial by 5vdc

  • 1,772 views
  • 0 comments
  • 3 respects

Make an Arduino Memory Game

Project tutorial by Jeremie

  • 23,640 views
  • 40 comments
  • 52 respects
Add projectSign up / Login