Team: Yu Jiang & Max Kornyev

Maze Frame 3D Design

We created a CAD rendering of our basic maze design, which will be ready to be laser cut and assembled next week.

Handsfree Controller

We also refined our sensor input to create a responsive handsfree control of a 20 degree tilt on the two maze axes. We employ a simple filter to scale the value to our desired range, and implemented incremental movement of our servo mechanism.

The input is relatively faultless, but a low pass filter could also be implemented to avoid the occasional erroneous reading.

Code Artifacts

#include <Servo.h&gt;
bool DEBUG = true; // Print output


// CONSTANTS
const int X_SERVO_PIN = 6;
const int Y_SERVO_PIN = 7;

const int L_ECHO_PIN = 13;
const int L_TRIGGER_PIN = 12;
const int R_ECHO_PIN = 11;
const int R_TRIGGER_PIN = 10;

// Change the following as needed
const int MAX_ANGLE = 20;  // Max angle that the servo will rotate in either direction
const int START_ANGLE = 15; // Starting angle for a servo

const int MAX_DISTANCE = 30; // cm
const int MIN_DISTANCE = 0;

// GLOBALS
Servo xServo;
Servo yServo;
float leftDistance; // Hand distance in cm
float rightDistance;
int lAngle; // Corresponding servo angle
int rAngle;

void setup()
{
 Serial.begin(9600);
 xServo.attach(X_SERVO_PIN);
 yServo.attach(Y_SERVO_PIN);
 pinMode(X_SERVO_PIN, OUTPUT);
 pinMode(Y_SERVO_PIN, OUTPUT);
 xServo.write(START_ANGLE);
 yServo.write(START_ANGLE);
}

void loop()
{
 // Get hardware input
 leftDistance = 0.01723 * handDistance(L_TRIGGER_PIN, L_ECHO_PIN);
 lAngle = map(leftDistance, 0, MAX_DISTANCE, -MAX_ANGLE, MAX_ANGLE);

 rightDistance = 0.01723 * handDistance(R_TRIGGER_PIN, R_ECHO_PIN);
 rAngle = map(rightDistance, 0, MAX_DISTANCE, -MAX_ANGLE, MAX_ANGLE);

 // Sanitize input
 sanitizeAngles();

 if (DEBUG) {
   Serial.print("L: ");
   Serial.print(leftDistance);
   Serial.print(" --&gt; ");
   Serial.println(lAngle);

   Serial.print("R: ");
   Serial.print(rightDistance);
   Serial.print(" --&gt; ");
   Serial.println(rAngle);
 }

 // Smooth motion 
 moveServo(yServo, START_ANGLE + lAngle); // L 
 moveServo(xServo, START_ANGLE + rAngle); // R

 // Naive Motion 
 //yServo.write(START_ANGLE + lAngle); // L
 //xServo.write(START_ANGLE + rAngle); // R

 delay(100);
}

long handDistance(int TRIGGER_PIN, int ECHO_PIN)
{
 pinMode(TRIGGER_PIN, OUTPUT);
 digitalWrite(TRIGGER_PIN, LOW);
 delayMicroseconds(2);
 digitalWrite(TRIGGER_PIN, HIGH);
 delayMicroseconds(10);
 digitalWrite(TRIGGER_PIN, LOW);
 pinMode(ECHO_PIN, INPUT);
 return pulseIn(ECHO_PIN, HIGH);
}

// Prepares the input for parsing
void sanitizeAngles() {
 if (lAngle &gt; MAX_ANGLE) { // Left
   lAngle = MAX_ANGLE;
 }
 if (lAngle < -MAX_ANGLE) {
   lAngle = -MAX_ANGLE;
 }
 if (rAngle &gt; MAX_ANGLE) { // Right
   rAngle = MAX_ANGLE;
 }
 if (rAngle < -MAX_ANGLE) {
   rAngle = -MAX_ANGLE;
 }
}

// Smooth/incremented servo movement
void moveServo(Servo &amp;s, int angle) { // pass servo by reference 
 int previousAngle = s.read();

 if (angle &gt; previousAngle)
 {
   for (int i = previousAngle; i <= angle; i++)
   {
     s.write(i);
     delay(10);
   }
 }

 if (angle < previousAngle)
 {
   for (int i = previousAngle; i &gt;= angle; i--)
   {
     s.write(i);
     delay(10);
   }
 }
}