Lachlan's avatar@lachlanjc/edu
All Physical Computing

Week 4 – Interactive Object project

Group members: Kline Gareth, Lachlan Campbell

Kline & I are looking to make a Halloween-themed musical chairs game.

3 players join for gameplay:

  1. We press buttons on both systems to start music. Turn Off the Light by Kim Petras is playing. All LEDs are on.
  2. 10-ish seconds go by where the players are moving
  3. The music stops, players must sit down. Last FSR to be triggered flashes its chair’s LED until it goes out.
  4. The music starts again for another duration.
  5. This repeats until there’s one winner.

2022-09-27: Project plan

System

Materials

Parts

  • Arduino for powering FSR/LED interactions
  • Wires (from the shop/our personal collections)
  • Raspberry Pi (Kline’s) + Speaker (Lachlan’s)
  • Button (from the shop)
  • 3 FSRs
  • 3 large LEDs

There’s a few components we need to de-risk immediately, as they could require additional materials/planning to fix:

  • Sitting on a chair doesn’t trigger FSR reliably; we might need more of them or to spread out the force of the sitting somehow
  • Ease of playing music to speaker via the Raspberry Pi setup. We’re thinking Raspberry Pi instead of the Arduino since the Pi has an integrated SD card, whereas Arduino can’t store the song data.
  • Speaker is loud enough/sounds good enough to contribute vibe.
  • A bunch of wires are involved, to connect each chair setup. Not sure how well we can store/scale this with stiff wires.

Installation plan

We haven’t figured out whether we’ll use chairs on the floor, in the classroom, or in the hallway, but we’re expecting the physical installation to be flexible, though with the difficulty of wires/attachment to the chosen chairs.

2022-09-28: Early prototyping

Kline & I assembled a basic circuit, with few of the complexity of the finished project’s features, to test FSRs & LEDs. Our afternoon felt deeply unfulfilling, as we encountered numerous technical issues with the Arduino & FSRs not working. Here’s to tomorrow!

Prototype

2022-09-29: Will it sit?

Circuit

Today our primary goal was to de-risk our first risk: does sitting down reliably trigger the FSR? After today’s testing, we concluded yes, & decided it could be made more reliable with a cushion/cardboard board to spread out the pressure from the sitter.

Chair seat

The path, as ever, was not smooth. Wiring the FSR to the breadboard turned out unexpectedly challenging; the Shop didn’t have electrical tape, so we inserted the FSR ledes in a terminal block (itself a challenge), then wired that into a secondary breadboard taped under a chair. The breadboard setup was fragile, finicky, & frustrating, plus it required a breadboard per chair, so figuring out a better connection/mounting mechanism is paramount. Having even 2 of the 12 long wires our design calls for proved the wire management concern is anything but unfounded.

View under chair

In addition to preliminary physical logistics, we got started on the coding. Both coming from higher-level programming environments like JavaScript/TypeScript, we found it challenging adjusting to the limited control flow & helper functions available in the Arduino environment. Not being afraid to write more un-scalable/basic code, with a dash of GitHub Copilot, proved the way.

Code at this stage
int led1 = 2;
int led2 = 3;
int led3 = 4;
int activeChairs = 3;
int currentStage = 2;
bool chair1Active = false;
bool chair2Active = false;
bool chair3Active = false;
/*
stages:
0 button pressed to start game
1 playing music (no sitting detected)
2 music pauses/sit-down mode becomes active
3 loser declared with LEDs
*/
void setup() {
Serial.begin(9600);
pinMode(A1, INPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
}
void loop() {
// Sit-down race
if (currentStage == 2) {
int sensor1State = analogRead(A2);
chair1Active = sensor1State > 32;
int sensor2State = analogRead(A1);
chair2Active = sensor2State > 32;
int sensor3State = analogRead(A0);
chair3Active = sensor3State > 32;
Serial.print("1: ");
Serial.print(chair1Active);
Serial.print("\t");
Serial.print("2: ");
Serial.print(chair2Active);
Serial.print("\t");
Serial.print("3: ");
Serial.print(chair3Active);
Serial.println();
if ((chair1Active && chair2Active) || (chair2Active && chair3Active) || (chair1Active && chair3Active)) {
Serial.println("2 CHAIRS SAT ON");
// advance stage
currentStage = 3;
// declare winner
if (!chair1Active) {
Serial.println("CHAIR 1 IS LOSER");
digitalWrite(led1, HIGH);
} else if (!chair2Active) {
Serial.println("CHAIR 2 IS LOSER");
digitalWrite(led2, HIGH);
} else if (!chair3Active) {
Serial.println("CHAIR 3 IS LOSER");
digitalWrite(led3, HIGH);
}
}
}
}

Ending our work today, we got the most basic implementation of the game working. With the FSRs & red LEDs on the breadboard for simplicity, pressing two FSRs together makes the light next to the third illuminate & the verdict displays in the console.

2022-10-04

This morning I fixed last week’s incorrect LED wiring, plus I implemented an exponential fading blink-out on the LED marking the out chair, which involved writing my first custom function in Arduino code that accepts a parameter.

Code at this stage
int led1 = 2;
int led2 = 3;
int led3 = 4;
int activeChairs = 3;
int currentStage = 2;
bool chair1Active = false;
bool chair2Active = false;
bool chair3Active = false;
/*
stages:
0 button pressed to start game
1 playing music (no sitting detected)
2 music pauses/sit-down mode becomes active
3 loser declared with LEDs
*/
void setup() {
Serial.begin(9600);
pinMode(A1, INPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
}
void loop() {
// Sit-down race
if (currentStage == 2) {
int chair1Signal = analogRead(A2);
chair1Active = chair1Signal > 32;
int chair2Signal = analogRead(A1);
chair2Active = chair2Signal > 32;
int chair3Signal = analogRead(A0);
chair3Active = chair3Signal > 32;
Serial.print("1: " + String(chair1Active) + "\t");
Serial.print("2: " + String(chair2Active) + "\t");
Serial.print("3: " + String(chair3Active) + "\t");
Serial.println();
if ((chair1Active && chair2Active) || (chair2Active && chair3Active) || (chair1Active && chair3Active)) {
Serial.println("2 CHAIRS SAT ON");
// advance stage
currentStage = 3;
// declare winner
if (!chair1Active) {
// chair 1 is the loser
Serial.println("CHAIR 1 IS LOSER");
blinkToOff(led1);
} else if (!chair2Active) {
// chair 2 is the loser
Serial.println("CHAIR 2 IS LOSER");
blinkToOff(led2);
} else if (!chair3Active) {
// chair 3 is the loser
Serial.println("CHAIR 3 IS LOSER");
blinkToOff(led3);
}
// reset game
currentStage = 2;
}
}
}
void blinkToOff(int led) {
digitalWrite(led, HIGH);
// blink LED for 2 seconds, exponentially decreasing speed
for (int i = 0; i < 10; i++) {
digitalWrite(led, LOW);
delay(500 / pow(2, i));
digitalWrite(led, HIGH);
delay(500 / pow(2, i));
}
// turn off LED & wait 5 seconds
digitalWrite(led, LOW);
delay(5000);
}

After the terminal blocks caused much hassle last week, I’ve simplified the system by inserting the FSRs directly into them, then soldering long wires onto the terminal blocks for insertion into the central breadboard. This eliminates the per-chair breadboards we’d prototyped last week. The wires can be much shorter than the previous design by arranging the chair backs to form a triangle, with the “brain” in the middle.

Triangle

Following a tip from an ITP student, I soldered a 220 resistor directly between the extension wire & the positive lede of the each LED, simplifying hardware needed on the breadboard. In total: 27 wires soldered today! All mediocre, but they work, & I became way more confident with the soldering iron.

Heatshrink

With that, here’s the final configuration. For installation, the masking tape proved unreliable with the wires’ desires to slither toward the ground.

Setup

I play-tested without the music with two nearby Shop-pers: