Arduino & Motor-Party

 

Remember that you can use a single motor to create more interesting movements by designing linkages. In fact, "Linkage" is a piece of free Windows software that can help you design such mechanisms. If you'd like to make the servo-powered slider above, check this tutorial.

Overview of Your Electronics Kit

You have been provided with the following equipment. (You are welcome to go foraging for different motors if you want, but the Professor will not be supporting alternatives types of components for this assignment.)

Adafruit METRO 328 - Arduino Compatible - ATmega328
Motor Shield v2 Party add-on pack for Arduino
Stepper motor - NEMA-17 size - 200 steps/rev, 12V 350mA
Small stepper motor
 Standard size servo
 Micro size servo
 6 VDC hobby motor
IR distance sensor includes cable (10cm-80cm) - GP2Y0A21YK0F
9 VDC 1000mA regulated switching power adapter
 2x Servo Extension Cable - 30cm / 12" long
 Micro-USB cable
 4-Pin Terminal Block

Key Reference Materials:

Getting Started

Installing Arduino etc.; Verifying and Uploading Sketches
    1. Download and install the Arduino IDE for your computer, here (180MB).
    2. We are using the Adafruit Metro, an Arduino clone. Download and install the CP2014 VCP drivers from SiLabs in order to help the Metro connect correctly via USB. Note that you will need Administrator privileges on your computer to install these drivers. I've uploaded copies here (Win/Mac). If installing these drivers is a problem, I may have a spare "regular" Arduino you can borrow.
    3. Connect your Metro to your computer with the provided micro-USB cable. Note that this must be a "data/charge" USB cable and not just a "charge" cable.
    4. Launch the Arduino IDE (integrated development environment)
    5. Test your Metro Arduino:
      1. In the Arduino IDE, select the menu: Tools>Board. The IDE should report that you are connected to a Board: "Arduino/Genuino UNO".
      2. In the Arduino IDE, select the menu: Tools>Port. You may have to select one of the ports. On my Mac, the board works with a port called: /dev/cu.
      3. Open the example sketch: File>Examples>01.Basics>Blink.
      4. Click the Check button (") in the upper left of the IDE to "Verify" the sketch.
      5. Click the Right-Arrow button (') in the upper left to "Upload" the sketch to the Metro. The device should flash green momentarily, and then the red built-in LED should blink every second.
      6. If you change the numbers of milliseconds in lines 34 and 36 of the Blink sketch, and repeat the Verify/Upload steps, you can change the LED's blink frequency.
    6. Open the menu: Sketch>Include Library>Manage Libraries...
    7. Search for Adafruit Motor Shield v2 Library and install it. Some illustrated instructions are here.
    8. Now that this library is installed, test it to make sure it uploads without errors. Open the sketch: File>Examples>Adafruit Motor Shield V2 Library>MotorParty. Verify and Upload this sketch. Since your Metro doesn't have the Motor Shield or any motors attached (yet), nothing will happen.

Building your Arduino + Motor Shield

Wiring up the IR Distance Sensor.

HEY, pay attention and read carefully! The IR Distance Sensor has three wires: 5v power (red), ground (black), and the data signal (white). These should be connected to the pins labeled 5v, Gnd, and A0 (analog pin #zero) on the Adafruit Motor Shield, respectively.

NOTE! your Motor Shield Board may have been provided to you with a pre-soldered 3-wire pigtail. The wires on that pigtail are probably not colored correctly! IGNORE the pigtail colors and make sure that the IR sensor is wired exactly as described above.

Also, you may need to do a bit of soldering to get the sensor wires to connect to the Motor Shield. Look in your bag for a small bundle of pluggy wires. You can chop these up and solder them to your sensor.

Wiring up the large (4-wire) stepper motor.

You have been provided with an Adafruit 4-wire NEMA-17 stepper motor, with 200 steps per revolution. For information on controlling steppers in general, please see this article. Your stepper should get wired into one of the two blue terminal blocks on the Motor Shield. From left to right, the wires should be connected as follows, and as pictured below:

  1. Gray
  2. Bluish-Green
  3. -- Skip! No wire here.
  4. Yellow
  5. Red

Wiring the smaller (5-wire) stepper

You have been provided with an Adafruit 5-Wire Small Stepper Motor, which effectively has 513 steps per revolution. That's less than 1° per step. You'll need to use some intermediate wires to connect it to one of the terminal blocks. Pay attention to colors! In the lists below, I am referring to the motor's own wire colors, not the colors of my short jumper wires.

  • Motor Blue -- position 1 (leftmost on terminal block)
  • Motor Pink -- position 5 (rightmost on terminal block)
  • Motor Yellow -- position 2 (2nd from left on terminal block)
  • Motor Orange -- position 4 (2nd from right on terminal block)
  • Motor Red -- position 3 (middle of terminal block)

Alternatively, from left to right on the blue terminal block:

  1. Motor Blue
  2. Motor Yellow
  3. Motor Red
  4. Motor Orange
  5. Motor Pink

Wiring the Servo Motors

Your two servo motors use the same common 3-wire connector that all hobby servos do. The key for connecting these is to make sure that the dark wire is nearest to the outside edge of the board. This is super important -- if you get it wrong you may fry something.

You've also been provided with a couple of servo extender cables. Make sure you connect them so that the dark wire is closest to the outside edge, too. See the illustration below; it's the 3-wire cable on the left:

Wiring the DC Motor

Hey, you have a little DC motor that can spin really fast. It uses 2 out of the 5 connections on the blue terminal block. (The terminal block can support up to 2 DC motors). Here you can see the DC motor's two wires (red and white) in the center foreground. Note that the Motor Shield contains some circuitry (called an "H-Bridge") that allows you to control a DC motor in both directions.  (By the way, you could use a PC fan instead of a regular DC motor, if you wanted to blow some air around!)

Making the Shield+Arduino Sandwich

It should be pretty obvious, but the shield clips onto the Arduino...


Starter Code Template

Here's our Arduino code starter template:

CmuemsMotorShieldParty (zip file with Arduino code!)

// Library Reference for Motor Shield:
//    https://learn.adafruit.com/adafruit-motor-shield-v2-for-arduino/library-reference
// Motor Shield Overview:
//    https://learn.adafruit.com/adafruit-motor-shield-v2-for-arduino/overview

// To include the Motor Shield library,
// 1. Open "Sketch>Include Library>Manage Libraries..."
// 2. Search for Adafruit Motor Shield v2 Library and add it
// Also, there's more example sketches in:
//    "File>Examples>Adafruit Motor Shield V2 Library"

// MOTOR PARTY:
// A /distance sensor/ that checks whether you're close enough to have a party
// A /stepper motor /  that spins in a different direction every time you start a party
// A /dc motor/ that spins around for an extra 2 seconds after the party is over
// A /big servo/ that spins 180 degrees, and then starts back at the beginning
// A /little servo/ that spins according to value from the distance sensor

#include <Wire.h>
#include <Servo.h>
#include <Adafruit_MotorShield.h>

// Pin A0 is the analog pin #0, which should be connected to 
// the white wire from your IR Distance Sensor. 
#define distanceSensorPin A0

//------------------------------------------------------
// Is a party happening currently?
bool bPartyHappening = false;

// Expected extrema for sensor values. 
// This is empirically determined; your mileage may vary!
int maxRawSensorValue = 650; // values more than this will be ignored
int minRawSensorValue =  50; // values less than this will be ignored

// Timestamp when we were most recently partying
unsigned long mostRecentPartyTime;

// In our (particular) demo, the DC motor continues to spin 
// for a couple seconds after the sensor stops receiving input. 
// For how long should we spin the DC motor (in milliseconds)
// after the last party has concluded?
int motorSpinTime = 2000;

// What degree the servo is rotated to.
float servo2Degree = 0;

// What direction the stepper is spinning, either -1 or +1
int stepperStep = -1;

// Running average to smooth distance servo
float runningAvgServo = 90.0;

//------------------------------------------------------
// create the motor shield object
Adafruit_MotorShield AFMS = Adafruit_MotorShield();

// connect a stepper motor to motor port #2 (M3 and M4) with 200 steps per revolution (3.6 degrees)
Adafruit_StepperMotor *stepper = AFMS.getStepper(6000, 2);

// connect a DC motor to port M1
Adafruit_DCMotor *motor = AFMS.getMotor(1);

// connect a servo to servo 1 and servo 2
Servo servo1;
Servo servo2;

//------------------------------------------------------
void setup() {
  // Start the serial port.
  // We need this in order to print debugging info.
  Serial.begin(9600);

  // Initialize the AdaFruit Motor Shield
  AFMS.begin();

  // attach servo1 to pin #10
  servo1.attach(10);

  // attach servo2 to pin #9
  servo2.attach(9);

  // setup motor M1
  motor->setSpeed(80);
  motor->run(RELEASE);

  // set up the stepper
  stepper->setSpeed(10);
}


//---------------------------------------------------------
void loop() {

  // Update our world (sensors & motors) every 3 milliseconds
  delay(3);

  // Fetch  values from the IR distance sensor.
  int rawSensorValue = analogRead(distanceSensorPin);
  Serial.println(rawSensorValue);

  // If the sensor value is within an acceptable range
  if ((rawSensorValue < maxRawSensorValue) &&
      (rawSensorValue > minRawSensorValue)) {

    // Store the current time. 
    // It's the most recent interaction timestamp.
    mostRecentPartyTime = millis();

    // If we've *just* entered the acceptable distance zone,
    // flip the stepper direction, and update our bookkeeping.
    if (bPartyHappening == false) {
      Serial.println("Start the party!!!!");
      stepperStep = stepperStep * -1;
      bPartyHappening = true;
    }

    // Spin the stepper 5 little turns at a time.
    if (stepperStep == 1) {
      stepper->step(5, FORWARD, INTERLEAVE);
    } else {
      stepper->step(5, BACKWARD, INTERLEAVE);
    }

    // Set servo #1 proportional to the sensor distance.
    float newServoAngle = map(rawSensorValue, minRawSensorValue, maxRawSensorValue,  0.0, 180.0);
    runningAvgServo = (0.9 * runningAvgServo) + (0.1 * newServoAngle);
    servo1.write (runningAvgServo);

    // Spin servo #2: forward, then quickly back
    servo2Degree = servo2Degree + 2;
    if (servo2Degree > 180) {
      servo2Degree = 0;
    }
    servo2.write(servo2Degree);

  } else {
    // Stop the motor
    motor->run(RELEASE);
    bPartyHappening = false;
  }

  // Run the motor if we're partying, or if we're within the extra time
  if ((millis() - mostRecentPartyTime) < motorSpinTime) {
    motor->run(FORWARD);
  }
}

Hot Tips

You may be able to get your stepper motors to move more quickly by changing the clock frequency of the Arduino's I2C bus. See this note.

If your motors cut out or skip, there may be electrical noise in your system. Try installing a teeny capacitor as described in this note.