For Tech Demo 3, Warren and I created a hair brushing machine. A hair brush, attached to a rack and pinion drive, moves back and forth over a user’s head. The machine is activated using an ultrasonic sensor, so the brush will only move if someone’s head is in the correct location.

Here is our code. Much of it is adapted from the course website.


// TECH DEMO 3 HAIR BRUSHING MACHINE

//StepperSweep - move a stepper motor at different rates
//
// Copyright (c) 2016, Garth Zeglin. All rights reserved. Licensed under the
// terms of the BSD 3-clause license as included in LICENSE.
//
// This program assumes that:
//
// 1. A A4988 stepper motor driver is connected to pins 2 and 3.
// 2. A control potentiometer can vary the voltage on A0.
// 3. The serial console on the Arduino IDE is set to 9600 baud communications speed.

// ================================================================================
// Define constant values and global variables.

// Define the pin numbers on which the outputs are generated.
#define DIR_PIN 2 // The direction pin controls the direction of stepper motor rotation.
#define STEP_PIN 3 // Each pulse on the STEP pin moves the stepper motor one angular unit.
#define ENABLE_PIN 4 // Optional control of the driver power.

// Alternate definitions for the Protoneer CNC Shield board X axis.
// #define DIR_PIN 5
// #define STEP_PIN 2
// #define ENABLE_PIN 8

// ================================================================================
// Configure the hardware once after booting up. This runs once after pressing
// reset or powering up the board.

const int TRIG_PIN = 8;
const int ECHO_PIN = 7;

// The rated distance limit of the sensor, in cm.
const int MAX_DISTANCE = 600;

// A typical speed of sound, specified in cm/sec.
const long SOUND_SPEED = 34000;

// Determine the maximum time to wait for an echo. The maximum rated distance is
// 4.5 meters; if no echo is received within the duration representing this
// round-trip distance, stop measuring. The timeout is specified in
// microseconds.
const long TIMEOUT = (2 * MAX_DISTANCE * 1000000)/SOUND_SPEED;
void setup(void)
{
 // Initialize the stepper driver control pins to output drive mode.
 pinMode(DIR_PIN, OUTPUT); 
 pinMode(STEP_PIN, OUTPUT);
 pinMode(ENABLE_PIN, OUTPUT);

// Drive the /ENABLE pin low to keep the motor always energized.
 digitalWrite(ENABLE_PIN, LOW);
 
 // Initialize the serial UART at 9600 bits per second.
 Serial.begin(9600);
 
 pinMode(TRIG_PIN, OUTPUT);
 digitalWrite(TRIG_PIN, LOW);
 
 // Initialize the echo pin for input.
 pinMode(ECHO_PIN, INPUT);
} 
/****************************************************************/

void rotate_stepper(int steps, float speed)
{
 // Configure the direction pin on the stepper motor driver based on the sign
 // of the displacement.
 int dir = (steps > 0)? HIGH:LOW;
 digitalWrite(DIR_PIN, dir);

// Find the positive number of steps pulses to emit.
 int pulses = abs(steps);

// Compute a delay time in microseconds controlling the duration of each half
 // of the step cycle.
 // microseconds/half-step = (1000000 microseconds/second) * (1 step/2 half-steps) / (steps/second)
 unsigned long wait_time = 500000/speed;

// The delayMicroseconds() function cannot wait more than 16.383ms, so the
 // total delay is separated into millisecond and microsecond components. This
 // increases the range of speeds this function can handle.
 unsigned int msec = wait_time / 1000;
 unsigned int usec = wait_time - (1000*msec);
 
 // Loop for the given number of step cycles. The driver will change outputs
 // on the rising edge of the step signal so short pulses would work fine, but
 // this produces a square wave for easier visualization on a scope.
 for(int i = 0; i < pulses; i++) {
 digitalWrite(STEP_PIN, HIGH);
 if (msec > 0) delay(msec);
 if (usec > 0) delayMicroseconds(usec);

digitalWrite(STEP_PIN, LOW); 
 if (msec > 0) delay(msec);
 if (usec > 0) delayMicroseconds(usec);
 }
}
// ================================================================================
// Run one iteration of the main event loop. The Arduino system will call this
// function over and over forever.
void loop(void)
{
 // Begin the motion sequence with a few back-and-forth movements at faster and faster speeds.
 long duration = ping_sonar(); 
 
 
 if (duration < MAX_DISTANCE && duration > 0) {
 
 float distance = (duration * 1e-6 * SOUND_SPEED) / 2;
 
 Serial.print("Ping: ");
 Serial.print(duration);
 Serial.print(" usec Distance: ");
 Serial.print(distance);
 Serial.println(" cm");
 
 // Convert to a distance. Note that the speed of sound is specified in
 // cm/sec, so the duration is scaled from microsecondst o seconds. The
 // factor of 2 accounts for the round-trip doubling the time.
 rotate_stepper( 200, 200);
 rotate_stepper( -200, 200);
 } else {
 // if no pulse detected
 Serial.println(duration);
 }
}
long ping_sonar(void)
{
 // Generate a short trigger pulse.
 digitalWrite(TRIG_PIN, HIGH);
 delayMicroseconds(10);
 digitalWrite(TRIG_PIN, LOW);

// Measure the pulse length
 return pulseIn(ECHO_PIN, HIGH, TIMEOUT);
}

/****************************************************************/

<br data-mce-bogus="1">