Gizmo

Innovation Design Engineering

The goal of this project was to create a machine that effectively integrates machine elements, sensors and actuators and code to perform an iterative interaction. Create an interaction in which the user experiences the machine’s b initial response, and takes more action, in a continued loop. Since I was more familiar with coding, I wanted to step outside my comfort zone by challenging myself to play around more with physical mechanics. With budget and time limits, I had to get creative to achieve the effect I wanted.

Inspiration

I wanted to recreate the soothing cascade of panels from the Design Museum’s “User Maker Designer” installation and add an interactive element. However, the installation uses individual motors that control each panel, which I simply don’t have the budget for. The majority of the time was spent looking at different physical mechanisms to identify which ones could be modified to serve my needs.

Prototyping

I started with simple cardboard models to test and validate designs before investing in the components. This project more than the others required good time management and timing as I had to take into consideration shipping time for components. Some components arrived and were broken, forcing me to make last minute functions from scratch to carry out the design. Originally, I had ordered a gesture sensor from a third party distributor, but when it arrived, it seemed the infrared sensors were broken. As a result, I had to quickly make my own gesture sensor by detecting the timing differences in light change between two light theremins. The end result was far from perfect, but I believe given more time, I could have a more polished gizmo. I learned that although I was confident in the electrical/coding component of the project, I should still take care to calculate errors and mishaps into the scheduling.

#include <AccelStepper.h>
#define HALFSTEP 8

// Motor pin definitions
#define motorPin1  10     // IN1 on the ULN2003 driver 1
#define motorPin2  9     // IN2 on the ULN2003 driver 1
#define motorPin3  6     // IN3 on the ULN2003 driver 1
#define motorPin4  5     // IN4 on the ULN2003 driver 1

//Time Variables
unsigned long startMillis;
unsigned long timing1; //time variable for left sensor
unsigned long timing2; //time variable for right sensor

//Sensor Variables
int sensorValue1; //left sensor
int sensorValue2; //right sensor
int sensorLow = 1023;
int sensorHigh = 0;

//Interaction Variables
boolean right = false;
boolean left = false;
boolean interaction = false;

// LED pin
const int ledPin = 13;

// Initialize with pin sequence IN1-IN3-IN2-IN4 for using the AccelStepper with 28BYJ-48
AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);


//***Main Code***

void setup() {
  // Make the LED pin an output and turn it on
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
  startMillis = millis();  //Initial start time
  
  // Calibrate for the first five seconds after program runs
  while (millis() < 5000) {
    //Set sensor values to read from the corresponding analog pins
    sensorValue1 = analogRead(A4);
    sensorValue2 = analogRead(A5);

    // record the maximum sensor value for sensor1
    if (sensorValue1 > sensorHigh) {
      sensorHigh = sensorValue1;
    }
    // record the minimum sensor value for sensor1
    if (sensorValue1 < sensorLow) {
      sensorLow = sensorValue1;
    }
    // record the maximum sensor value for sensor2
    if (sensorValue2 > sensorHigh) {
      sensorHigh = sensorValue2;
    }
    // record the minimum sensor value for sensor2
    if (sensorValue2 < sensorLow) {
      sensorLow = sensorValue2;
    }
  
  //Initialize motor settings
  stepper1.setMaxSpeed(1500.0);
  stepper1.setAcceleration(1000.0);
  stepper1.setSpeed(1000);
  stepper1.setCurrentPosition(0);
  
  digitalWrite(ledPin, LOW); // turn the LED off, signaling the end of the calibration period
  Serial.begin(9600); //Starts Serial communication
  }
}

void loop() {
//  //read the input from A0 and store it in a variable
//  sensorValue1 = analogRead(A5);
//  sensorValue2 = analogRead(A4);

  // map the sensor values to a wide range of pitches
  int reading1 = map(sensorValue1, sensorLow, sensorHigh, 50, 4000);
  int reading2 = map(sensorValue2, sensorLow, sensorHigh, 50, 4000);


  //Detect if valid interaction happened, if so, set interaction to TRUE
  if (stepper1.distanceToGo() == 0){ //check to see if stepper motor has reached the destination, if so, begin new loop and receive input, otherwise, continue moving the motor
    stepper1.setCurrentPosition(0); //if so, set the current location to be the new starting point
    if (reading1 < 0){ //if sensor1 detects negative light change, take the current running time of program and put it in timing1
      timing1 = millis();
      if (reading2 < 0){ //if sensor2 detects negative light change, take the current running time of program and put it in timing2
        timing2 = millis();
        if (timing1 - timing2 <= 100){ //if the time difference between timing1 and timing2 is less than 1 second, it means an interaction has happened
          interaction = true;
        }
      }
    }
    if (reading2 < 0){ //if sensor2 detects negative light change, take the current running time of program and put it in timing2
      timing2 = millis();
      if (reading1 < 0){ //if sensor1 detects negative light change, take the current running time of program and put it in timing1
        timing1 = millis();
        if (timing2 - timing1 <= 100){ //if the time difference between timing1 and timing2 is less than 1 second, it means an interaction has happened
          interaction = true;
        }
      }
    }

    //If an interaction has happened, check to see which timing came first to determine the direction of hand gesture
    if (interaction){
      if (timing1 < timing2){ //if the time sensor1 was triggered is earlier than time for sensor2, it means the interaction started from the left and moved to the right
        Serial.println("Right");
        stepper1.moveTo(-20000); //set the new motor destination 20000 units in the counter-clockwise direction, so the panels get turned starting from the left side, going to the right
        interaction = false; //reset the interaction boolean to false so the motor doesn't get accidentally triggered in the next iteration if no interaction was detected
        delay(400); //wait 4 seconds
      }
      if (timing2 < timing1){ //if the time sensor2 was triggered is earlier than time for sensor1, it means the interaction started from the right and moved to the left
        Serial.println("Left");
        stepper1.moveTo(20000); //set the new motor destination 20000 units in the clockwise direction, so the panels get turned starting from the right side, going to the left
        interaction = false; //reset the interaction boolean to false so the motor doesn't get accidentally triggered in the next iteration if no interaction was detected
        delay(400); //wait 4 seconds
      }
    }
  }
  stepper1.run(); //run the stepper motor
}