In this article by Kassandra Perch, the author of Learning JavaScript Robotics, we will learn how to wire up servos and motors, how to create a project with a motor and using the REPL, and how to create a project with a servo and a sensor
(For more resources related to this topic, see here.)
Wiring up servos will look similar to wiring up sensors, except the signal maps to an output. Wiring up a motor is similar to wiring an LED.
To wire up a servo, you'll have to use a setup similar to the following figure:
A servo wiring diagram
The wire colors may vary for your servo. If your wires are red, brown, and orange, red is 5V, brown is GND, and orange is signal. When in doubt, check the data sheet that came with your servo.
After wiring up the servo, plug the board in and listen to your servo. If you hear a clicking noise, quickly unplug the board—this means your servo is trying to place itself in a position it cannot reach. Usually, there is a small screw at the bottom of most servos that you can use to calibrate them. Use a small screwdriver to rotate this until it stops clicking when the power is turned on.
This procedure is the same for continuous servos—the diagram does not change much either. Just replace the regular servo with a continuous one and you're good to go.
Wiring up motors looks like the following diagram:
A motor wiring diagram
Again, you'll want the signal pin to go to a PWM pin. As there are only two pins, it can be confusing where the power pin goes—it goes to a PWM pin because, similar to our LED getting its power from the PWM pin, the same pin will provide the power to run the motor.
Now that we know how to wire these up, let's work on a project involving a motor and Johnny-Five's REPL.
Grab your motor and board, and follow the diagram in the previous section to wire a motor. Let's use pin 6 for the signal pin, as shown in the preceding diagram.
What we're going to do in our code is create a Motor object and inject it into the REPL, so we can play around with it in the command line. Create a motor.js file and put in the following code:
var five = require('johnny-five');
var board = new five.Board();
board.on('ready', function(){
var motor = new five.Motor({
pin: 6
});
this.repl.inject({
motor: motor
});
});
Then, plug in your board and use the motor.js node to start the program.
If we take a look at the documentation on the Johnny-Five website, there are few things we can try here. First, let's turn our motor on at about half speed:
> motor.start(125);
The .start() method takes a value between 0 and 255. Sounds familiar? That's because these are the values we can assign to a PWM pin! Okay, let's tell our motor to coast to a stop:
> motor.stop();
Note that while this function will cause the motor to coast to a stop, there is a dedicated .brake() method. However, this requires a dedicated break pin, which can be available using shields and certain motors.
If you happen to have a directional motor, you can tell the motor to run in reverse using .reverse() with a value between 0 and 255:
> motor.reverse(125);
This will cause a directional motor to run in reverse at half speed. Note that this requires a shield.
And that's about it. Operating motors isn't difficult and Johnny-Five makes it even easier. Now that we've learned how this operates, let's try a servo.
Let's start with just a servo and the REPL, then we can add in a sensor. Use the diagram from the previous section as a reference to wire up a servo, and use pin 6 for signal.
Before we write our program, let's take a look at some of the options the Servo object constructor gives us. You can set an arbitrary range by passing [min, max] to the range property. This is great for low quality servos that have trouble at very low and very high values.
The type property is also important. We'll be using a standard servo, but you'll need to set this to continuous if you're using a continuous servo. Since standard is the default, we can leave this out for now.
The offset property is important for calibration. If your servo is set too far in one direction, you can change the offset to make sure it can programmatically reach every angle it was meant to. If you hear clicking at very high or low values, try adjusting the offset.
You can invert the direction of the servo with the invert property or initialize the servo at the center with center. Centering the servo helps you to know whether you need to calibrate it. If you center it and the arm isn't centered, try adjusting the offset property.
Now that we've got a good grasp on the constructor, let's write some code. Create a file called servo-repl.js and enter the following:
var five = require('johnny-five');
var board = new five.Board();
board.on('ready', function(){
var servo = new five.Servo({
pin: 6
});
this.repl.inject({
servo: servo
});
});
This code simply constructs a standard servo object for pin 6 and injects it into the REPL.
Then, run it using the following command line:
> node servo-repl.js
Your servo should jump to its initialization point. Now, let's figure out how to write the code that makes the servo move.
The most basic thing we can do with a servo is set it to a specific angle. We do this by calling the .to() function with a degree, as follows:
> servo.to(90);
This should center the servo. You can also set a time on the .to() function, which can take a certain amount of time:
> servo.to(20, 500);
This will move the servo from 90 degrees to 20 degrees in over 500 ms.
You can even determine how many steps the servo takes to get to the new angle, as follows:
> servo.to(120, 500, 10);
This will move the servo to 120 degrees in over 500 ms in 10 discreet steps.
The .to() function is very powerful and will be used in a majority of your Servo objects. However, there are many useful functions. For instance, checking whether a servo is calibrated correctly is easier when you can see all angles quickly. For this, we can use the .sweep() function, as follows:
> servo.sweep();
This will sweep the servo back and forth between its minimum and maximum values, which are 0 and 180, unless set in the constructor via the range property. You can also specify a range to sweep, as follows:
> servo.sweep({ range: [20, 120] });
This will sweep the servo from 20 to 120 repeatedly. You can also set the interval property, which will change how long the sweep takes, and a step property, which sets the number of discreet steps taken, as follows:
> servo.sweep({ range: [20, 120], interval: 1000, step: 10 });
This will cause the servo to sweep from 20 to 120 every second in 10 discreet steps.
You can stop a servo's movement with the .stop() method, as follows:
> servo.stop();
For continuous servos, you can use .cw() and .ccw() with a speed between 0 and 255 to move the continuous servo back and forth.
Now that we've seen the Servo object API at work, let's hook our servo up to a sensor. In this case, we'll use a photocell. This code is a good example for a few reasons: it shows off Johnny-Five's event API, allows us to use a servo with an event, and gets us used to wiring inputs to outputs using events.
First, let's add a photocell to our project using the following diagram:
A servo and photoresistor wiring diagram
Then, create a photoresistor-servo.js file, and add the following.
var five = require('johnny-five');
var board = new five.Board();
board.on('ready', function(){
var servo = new five.Servo({
pin: 6
});
var photoresistor = new five.Sensor({
pin: "A0",
freq: 250
});
photoresistor.scale(0, 180).on('change', function(){
servo.to(this.value);
});
});
How this works is as follows. During the data event, we tell our servo to move to the correct position based on the scaled data from our photoresistor.
Now, run the following command line:
> node photoresistor-servo.js
Then, try turning the light on and covering up your photoresistor and watch the servo move!
We now know how to use servos and motors that helps to move small robots. Wheeled robots are good to go! But what about more complex projects, such as the hexapod? Walking takes timing. As we mentioned in the .to() function, we can time the servo movement, thanks to the Animation library.
Further resources on this subject: