Digital Sandbox Arduino Companion

Pages
Contributors: jimblom
Favorited Favorite 3

15. Serial Motoring (Addon)

Motors make the world go round. Well, not literally, but they make a lot things we use every day spin and actuate. There are tiny vibration motors in cell phones, speedy motors that spin CDs and Blu-Ray discs, and of course, massive engine motors that help propel our cars. In this experiment we'll explore one of the most fundamental motor types out there - DC motors - and we'll tell the Sandbox precisely how fast we want the motor to spin.

Note: This experiment requires the Digital Sandbox Add-On Kit, purchased separately.

Background Information

A DC motor turns electrical energy into a rotational, mechanical energy. DC motors are popular because they're very simple to control: Give them some voltage and they spin. You can control the speed of a motor much as you might control the intensity of an LED - with PWM - so in this experiment, we'll be using the analog output block to control the motor's speed.

This experiment also introduces serial input. Up to this point our conversations with the Sandbox have been very one-sided - the Sandbox has been outputting data to the serial monitor. Serial input allows us to send data to the Sandbox via the serial monitor.

Active Parts

alt text

Code Components

There are a couple new serial-related functions to discuss in this example. In addition to printing out to the Serial Monitor, we'll be reading from it. Two-way communication!

Reading In Serial Data

To begin, we need to know if any data has been sent from the Serial Monitor. We can use the Serial.available() function to find out how many, if any, characters are waiting for us. There's a good chance Serial.available() returns 0, which means there's no data to be read, but it could also return 1, 2, 3, or more. Here's how we usually use this function:

language:c
if (Serial.available() > 0)
{
    // do something with the Serial data, 
    // like Serial.read() or Serial.parseInt();
}

There are a few functions that can be used to read data in from the Serial Monitor. Serial.read() is one of the more common functions -- it reads in a single character at a time. In this experiment we'll be using Serial.parseInt(), which can be used to read in an integer value. This will be handy for our experiment because we want to read in values containing anywhere between 1 and 3 digits.

Here's an example using Serial.parseInt():

language:c
if (Serial.available() > 0)
{
    // Read a value in from Serial and store it in serial_in:
    int serial_in = Serial.parseInt();
}

When you do a Serial.parseInt() (or Serial.read()) the value of Serial.available() decreases by however many characters you read in. So you'll only be able to read a serially-sent value once.

Sketch and Experiment

Here's the Sandbox_15_SerialMotoring.ino sketch. You know the drill: read the comments and upload.

language:c
    // Sandbox 15: Serial Motoring

/* Motors make the world go round. Well, not literally, but they make a lot 
   things we use every day spin and actuate. There are tiny vibration motors in 
   cell phones, speedy motors that spin CDs and Blu-Ray discs, and of course, 
   massive engine motors that help propel our cars. In this experiment we’ll 
   explore one of the most fundamental motor types out there - DC motors - and 
   we’ll tell the Sandbox precisely how fast we want the motor to spin.

   In this experiment we'll use analog output to control a motor. We can PWM 
   them just like we do to dim LEDs.

   We'll also be exploring the subject of Serial input. In addition to Serial
   printing out to the serial monitor, we'll be reading data in from it too. To
   do that we'll use Serial.available() to check if any data is there, and
   Serial.parseInt() to read it in.
*/

const int slidePin = A3;    // Slide pot is connected to A3
const int motorPin = 3;     // DC motor is connected to pin 3
const int buttonPin = 12;   // Button is connected to pin 12

void setup()
{
    pinMode(slidePin, INPUT);   // Set the slide pot as an input
    pinMode(buttonPin, INPUT);  // Set the button as an input

    pinMode(motorPin, OUTPUT);      // Set the motor as an output
    digitalWrite(motorPin, LOW);    // Turn the motor off.

    Serial.begin(9600); // Initialize serial, set the baud rate to 9600
}

void loop()
{
    // Serial.available() will return 0 if nothing has been sent to the serial
    // monitor.
    // If one or more characters have been sent to the Serial Monitor, the
    // Serial.available() function will return that number (1 or greater).
    if (Serial.available()) // If data has been sent to the serial monitor
    {
        // Create a varaible, speed, and read the data from the serial monitor
        // into it. parseInt() reads in a number of characters and turns them
        // into a single integer value.
        int speed = Serial.parseInt();

        // Since we're using speed with analogWrite, we need to constrain its 
        // value between 0 and 255. The constrain function will do that for us!
        speed = constrain(speed, 0, 255);   // Constrain speed between 0 and 255

        // Print a message, tell us what we just told the Serial Monitor:
        Serial.print("Setting speed to: ");
        Serial.println(speed);

        // We can set the speed of the motor with the analogWrite function. It's
        // just like dimming an LED, but this time we're dimming the speed
        // of a motor.
        analogWrite(motorPin, speed);
    }

    // If the button is pressed, we'll halt the motor
    if (digitalRead(buttonPin))
    {
        // Set the motor output to LOW (off):
        digitalWrite(motorPin, LOW);

        Serial.println("Stopping!");    // Let us know through the serial monitor

        delay(250); // "Debounce" the switch, by delaying for a short moment
    }
}

After uploading, connect the motor’s black wire (GND) to the GND pin on the Sandbox’s add-on header. Then, connect the motor’s red wire to the OUT pin on the Sandbox’s add-on header. Your motor should now be connected to the Sandbox as shown in this picture:

alt text

Now open the Serial Monitor, type a number between zero and 255 into the box next to "Send," and then click that button. The Sandbox should respond with a message, and the motor should start spinning.

What happens when you send 255? How about zero? What happens when you send a number greater than 255 or less than zero (a negative)? Can you spot a block in the code that is restricting those values?

As a "safety mechanism," if you ever need to stop the motor from spinning, press the button to bring it to a halt.

Your Turn!

  • Try connecting something mechanical to the motor. Perhaps tape a narrow piece of paper to create a spinner and play Twister. Or add a few pieces of paper to create a fan. What else can you connect to the axle to take advantage of the rotational motion?
  • As a programming challenge, can you make the motor smoothly speed up or down when a new serial value is received?