Overview

A fidget box with multiple switches, button, and knobs with a display showing how much the user fidgets, and vibrates and notifies the user to take a break when the user fidgets too much.

Note: final images and videos unavailable due to the pandemic — I do not have access to my project and thus cannot take pictures and videos

Process Images and Review

Decision Point 1 (see below)

Decision point 1: I made a cardboard model to start with, which was 50mm * 50mm * 50mm. As I fitted some electronics in, I realized there was not enough space. As a result, I opted for a larger (70mm) design and chose to only solder the wires instead of using a breadboard.

Following the cardboard model, I made a 3D model on Fusion 360 for laser cutting

The laser-cut pieces to assemble the fidget box

Before wiring and assembling, I tested the electronic parts including the OLED screen

Decision Point 2 (see below)

Decision point 2: When I tried to use the heat gun to heat shrink the wires, I turned it up too hot and it melted the plastic and some solder. It was very frustrating. I took out all parts and wires, and rewired each individual part and fitted them on the box later.

Glueing the last piece together with the box

Discussion

My goal for the fidget box during the ideation process is to make something fidgety to help me deal with stress, and keep track of how much I fidget to prevent from stressing out too much. I am happy with the final product, which more or less reached my initial goal, however the process wasn’t easy.

I spent a lot of time on this project, nearly three or four times more than I did with the last project, but I learned a lot. The initial design of the box was mostly done on paper, and I adjusted each face of the box as I made the cardboard model. Making the cardboard model was surprisingly useful, as I could visualize the product and test how it feels on hand.

I did not have much experience using Fusion 360, so I watched a lot of YouTube tutorials on how to make finger joints and decided to follow one particular video that uses parameters and allows the dimensions to be adjustable. I still had to play around with things as I go, but in the end I succeeded and I believe this process helped me a lot and made me more comfortable with using Fusion.

The hardest and the most time-consuming part was wiring and soldering. Unlike previous homework and the last project, I decided to not use a breadboard to fit the compact size of the box. One of the feedback I got for the final presentation was I like how compact it is, but if it were to be a fidget cube, it should be smaller? Like small enough to hold it with one hand. I know it is hard to put all the wiring in to a box though.” I certainly wished I could make the box smaller, so carrying it would be much easier, but because of the size of the electronics this was the best I could do. The box had to fit all switches/pushbuttons/potentiometers, the OLED screen, the Arduino (the Pro Mini was the only one that fits), battery (coin cells are the smallest), and all the wires. I have had a fair amount of experience with soldering, but the constraint of the space made this process unexpectedly difficult. I ended up tangling all the wires, and since I didn’t utilize the different colors, I was confused as which was connected to which. Eventually I had to pull apart all of them after I overheated with the heat gun and melted the plastic of the wiring and the solder.  But since I already glued together the box the rewiring was also very difficult. This taught me a lesson. So for the next time, I would utilize the colors of the wires efficiently (red for power, black for ground, different colors for each input/output), and then solder and wire individual parts, fit them onto the faces, wire them together, and glue each face together at last.

The idea of quantifying the number of “flips” is interesting because data can be gathered and may reveal interesting things about personal behavior. Maybe making the outer shell of the box a soft surface can make it more stress relieving. It is more comfortable and can be tossed around.This written feedback I received pretty much reflects what I want to do with the project in the future. The texture I used for the box was wood, as it was the most accessible for laser printing, but it doesn’t feel that great on hand. I also didn’t have time to sand down the sides and corners. If I can, I hope I can make it with a softer, and more squeezable material so it adds another way to fidget. I can also attach a flex sensor inside, so it could identify each time the user squeezes. Furthermore, I also wish to use the data of the fidgets to do more, such as uploading it on the Internet, and sending the user a notification of a daily report on fidget habits such as time and frequency.

Technical Information

Schematic:

Code submission:

/*
 * Project 2: Fidget Box
 * Alan Zhu
 * 
 * Description: the code checks each input options (potentiometer, 
 * switches, buttons) from five faces of the fidegt box, and keep
 * count of each fidget, which will be displayed on the OLED as it
 * updates in a set interval. Once the number of fidgets reaches a
 * certain amount, the vibration motor turns on and vibrates the
 * fidget box for 5 seconds, and the OLED displays a message to
 * encourage the user to rest for a while, and then resets count.
 * 
 * Collaboration: none
 * 
 * Pin mapping:
 * pin   | mode   | description
 * ------|--------|------------
 * A0     input     potentiometer
 * A1     input     slide potentiometer
 * 4      input     latching pushbutton 1
 * 5      input     latching pushbutton 2
 * 6      input     SPST switch 1
 * 7      input     SPST switch 2
 * 8      input     rocker switch 1
 * 9      input     rocker switch 2
 * 10     output    vibration motor
 * 
 */

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display(128, 32, &Wire, -1); // 128*32 OLED display

const int POTPIN = A0;
const int SLIDPIN = A1;
const int ROCPIN1 = 7;
const int ROCPIN2 = 6;
const int SWIPIN1 = 9;
const int SWIPIN2 = 8;
const int PUSHPIN1 = 5;
const int PUSHPIN2 = 4;
const int VIBPIN = 10;

unsigned long timer = 0; // internal timer used to update OLEd in set intervals

int roc1, roc2, swi1, swi2, push1, push2; // values of 0 or 1 for the two states of pushbuttons and switches
int potval, slidval; // values between 0 and 1023 for analog readings of potentiometers
int count = 0; // fidget count

const int ANALOG_GAP = 600; // the change in analog reading (0-1023) to be registered as a "fidget"
const int LIMIT = 20; // number of fidget until the box vibrates and sends message
const int WAIT = 500; // milliseconds between each OLED update
const int WARNTIME = 5000; // milliseconds of vibration and message time

// messages to be shown in OLED after reaches fidget limit
String warn_messages[] = {
  "You're spending too much time on this! Find something else to do.",
  "Are you anxious? Consider taking a break.",
  "Put me down, stand up, and go get a drink.",
  "Feeling like your brain isn't working? Maybe you need to rest.",
  "Spending too much time on one thing is not going to be productive.",
  "I think your brain needs to rest. Go talk to someone."
};

void setup() {
  Serial.begin(9600);
  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();

  pinMode(POTPIN, INPUT);
  pinMode(SLIDPIN, INPUT);
  pinMode(ROCPIN1, INPUT);
  pinMode(ROCPIN2, INPUT);
  pinMode(SWIPIN1, INPUT);
  pinMode(SWIPIN2, INPUT);
  pinMode(PUSHPIN1, INPUT);
  pinMode(PUSHPIN2, INPUT);
  pinMode(VIBPIN, OUTPUT);

  // record initial values of each input
  roc1 = digitalRead(ROCPIN1);
  roc2 = digitalRead(ROCPIN2);
  swi1 = digitalRead(SWIPIN1);
  swi2 = digitalRead(SWIPIN2);
  push1 = digitalRead(PUSHPIN1);
  push2 = digitalRead(PUSHPIN2);
  potval = analogRead(POTPIN);
  slidval = analogRead(SLIDPIN);
}

void loop() {
  
  // check all fidgets (digital and analog) and update count
  if (digitalRead(ROCPIN1) != roc1){
    roc1 = abs(roc1 - 1); // if status changes, update local value to match change
    count++; // increase fidget count
  } if (digitalRead(ROCPIN2) != roc2){
    roc2 = abs(roc2 - 1);
    count++;
  } if (digitalRead(SWIPIN1) != swi1){
    swi1 = abs(swi1 - 1);
    count++;
  } if (digitalRead(SWIPIN2) != swi2){
    swi2 = abs(swi2 - 1);
    count++;
  } if (digitalRead(PUSHPIN1) != push1){
    push1 = abs(push1 - 1);
    count++;
  } if (digitalRead(PUSHPIN2) != push2){
    push2 = abs(push2 - 1);
    count++;
  } if (abs(analogRead(POTPIN) - potval) >= ANALOG_GAP){
    potval = analogRead(POTPIN); // if change in analog value is greater than ANALOG_GAP, update local value to match change
    count++;
  } if (abs(analogRead(SLIDPIN) - slidval) >= ANALOG_GAP){
    slidval = analogRead(SLIDPIN);
    count++;
  }

  // fidget count reach limit, send warning
  if (count >= LIMIT) {
    // vibrate
    digitalWrite(VIBPIN, HIGH);
    
    // OLED send message (randomly selected from the group of messages)
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.clearDisplay();
    display.setCursor(0, 0);
    display.println(warn_messages[random(0, 6)]);
    display.display();

    // turns of vibration and message after a while
    delay(WARNTIME);
    digitalWrite(VIBPIN, LOW);
    display.clearDisplay();
    
    // reset fidget count
    count = 0;
  }

  // update OLED every interval of WAIT milliseconds
  if ((millis() - timer) >= WAIT) { 
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);

    // display number of fidgets after last reset
    display.println(F("Total fidget count:"));
    display.print(count, DEC);
    display.display();
    
    timer = millis();
  }
}