Making Things Move
Last updated
Last updated
As you've seen with the robots you've built and many of the embedded systems you interact with daily, it is important to know how to program a system to move objects. For example, in your microwave there is a motor that spins the turn table to evenly cook your food and another one that has fan blades attached to circulate air. Another example would be the circuits in your car, like the servo motors that run your windshield wipers that you turn on with the click of a switch when it is raining.
In this activity we will learn how to use the micro:bit to control motors and servos.
DC Motors take electrical energy and turn it into mechanical energy through putting a current through a coil of wire that creates a magnetic field. This then interacts with magnets in the motor, causing a push / pull effect. If you do that in a proper spacing and timing, then you can spin a shaft.
The hobby motors used with the micro:bot operate in a similar way as mentioned above, but they have a bit of help: a gear box. The ratio of the gearbox is 120:1, which means that for every 120 rotations of the motor shaft you get one rotation at the end of the gear box. This is a good thing because it gives our motor enough strength (torque) to turn wheels. In this case, our gearbox also changes the axis of the shaft so that we can easily use them to drive a robot, etc.
Let's connect the motor to Pin 0 and program it to turn ON. This should be similar to how we turned on an LED or any other output device.
What you'll need:
Breadboard
Wires
1 - DC Motors
Connect a motor as follows:
Program the motor to turn on:
When we do a digital write of a 1 to a pin, it turns that pin ON and outputs a voltage (3 volts).
1. Does the motor turn on? Try connecting an LED. Does the LED turn on?
However, we cannot simply power a motor with the GPIO (programmable) pin because the GPIO pins do not output enough current (and doesn't provide enough power). Thus, we must use the micro:bit's 3v pin to power the motor.
Note: In order to provide enough power to the motors, you sometimes must use the battery pack AND the Micro USB cable connected to the computer. The USB connection may provide too little current to power the motors.
Connect a motor as follows:
DC motors are non-polar, meaning you can connect either one of their wires to the positive and negative sides of your circuit. But, something does change based on how you connect the motor.
Try connecting it this way, switching the wires:
2. What happens as you switch the wires that connect to positive and negative (red and black wires)?
This is due to the change in current flow. Watch this video on how DC motors work:
3. In your own words, explain how a DC Motor works including why reversing the direction of current reveres the rotation of the motor.
OK, but how do we control the motor with a GPIO pin?
For this we need to create a motor controller circuit. We can use a MOSFET (metal-oxide-semiconductor field-effect transistor) to control the motor. MOSFET is essentially an electronic switch that is controlled by applying a voltage.
The MOSFET has “Gate“, “Drain” and “Source” terminals. Only when a voltage is applied at the gate does the MOSFET allows current to flow through the channel between drain and source, activating the switch.
A MOSFET is the most common transistor in digital circuits, as hundreds of thousands or millions of them may be included in a memory chip or microprocessor.
Here is the motor controller circuit that is controlled by Micro:Bit P0
.
What you'll need:
Breadboard
Wires
1 - DC Motors
1 - MOSFET
1 - 1N4001 Diodes
A motor can now be simply turned on and off with a digital write command. Similar to how we have turned LEDs on and off.
Try this code:
4. Create code that turns the motor on when you press button A and off when you press button B. Submit the share URL for your working code.
What if we wanted to change the speed of the motor?
You may have guessed it, we need to use an Analog Write
block instead of digital. But what does that block really do? The answer can be found by looking at a concept called PWM.
Pulse Width Modulation (PWM) is a fancy term for describing a type of digital signal. Pulse width modulation is used in a variety of applications including sophisticated control circuitry. We used it before to control dimming of an LED and change the color value of an RGB LEDs.
We can accomplish a range of results in both applications because pulse width modulation allows us to vary how much time the signal is high in an analog fashion. While the signal can only be high/1 (usually 5V or 3v) or low/0 (ground) at any time, we can change the proportion of time the signal is high compared to when it is low over a consistent time interval.
When the signal is high, we call this “on time”. To describe the amount of “on time”, we use the concept of duty cycle. Duty cycle is measured in percentage. The percentage duty cycle specifically describes the percentage of time a digital signal is on over an interval or period of time. This period is the inverse of the frequency of the waveform. If a digital signal spends half of the time on and the other half off, we would say the digital signal has a duty cycle of 50% and resembles an ideal square wave. If the percentage is higher than 50%, the digital signal spends more time in the high state than the low state and vice versa if the duty cycle is less than 50%. Here is a graph that illustrates these three scenarios:
100% duty cycle would be the same as setting the voltage to 3 Volts (high/1). 0% duty cycle would be the same as grounding the signal (low/0). When you provide a value of 1023 to the Analog Write block you are at a 100% duty cycle. When you provide a value 0 to the Analog Write block you are at a 0% duty cycle. When you provide a value of 511 to the Analog Write block you are at a 50% duty cycle. And so on.
Just like how we controlled the brightness of an LED by adjusting the duty cycle. We can do the same for the speed of the motor.
Try this code:
You can use other electronic components to control the analog write value, like we did in a previous activity. These sensors report back analog values and we can retrieve those values by using Analog Read commands.
We will use a potentiometer to control the motor's speed. Add the potentiometer to your circuit:
5. Create code the uses the potentiometer's value as the motor's analog write (PWM) value to control the motor's speed. Make note of what GPIO pin the potentiometer is connected to vs the motor. Submit the share URL for your working code.
You can now remove the potentiometer from the circuit.
Just as we accelerated (sped up) and decelerated (slowed down) the motor using the turning of a potentiometer, we can to the same with just code. This is important in many applications because electric motors have really good torque. Whenever you have a solution where you do not want the motor to just turn on full blast or turn off immediately, you can have code that accelerates and decelerated the motor. Examples are conveyor belts in manufacturing and robotic vehicles.
Try this acceleration and deceleration code:
Notice how we use two variables: Direction
and Speed
.
Direction
is keeping track of if we are accelerating or decelerating. If Direction
's value is -1
, we decelerate. If Direction
's value is 1
, we accelerate.
Speed
is keeping track of the analog value we write to the motor. When we are in the accelerate section of the code, we continuously add (Speed + 5
) to the Speed
value until it reached 1023
. When we are in the decelerate section of the code, we continuously subtract (Speed - 5
) from the Speed
value until it reaches 0
.
Complete the following code to accelerate the motor when the micro:bit is tilted to the left and decelerate when tilted to the right.
The tilt
events can be found in the "input" section of blocks by changing the shake
event.
Don't forget to pause
during each iteration of the while loop. See the example above and how we paused for 10ms each time.
6. Submit your tilt accelerate decelerate code share URL.
If you want to control two motors, you can simply add another motor to your circuit.
Try this code again:
7. Can you control each motor independently with this circuit? (Turn motor 1 off but motor 2 on) Why or why not?
Many embedded solutions need to control multiple motors separately. For example, a robot needs to independently active the left and right motors to be able to turn or a microwave needs to activate the turntable and fan separately. If we want to control multiple motors, we need multiple motor controller circuits.
What you'll need:
2 - DC Motors
2 - MOSFET
2 - 1N4001 Diodes
Try this code:
8. Submit a picture of your completed and working two motor controller circuit. (Take a picture with your phone and email it to yourself or use the school tablets)
Complete the following code to program the micro:bit as a controller for the motors (like an RC car controller) by having one turn on while you press Button A and the other turn on while you press Button B. Each motor should turn off wh
9. Submit your RC controller code share URL.
Next, we will look at Servo motors.
Servos are a smart motor that you can tell to rotate to a specific angular location. You will program it to rotate to a series of locations, then sweep across its full range of motion, and then repeat.
What is the difference between DC Motors and Servo Motors?
A DC motor has a two wire connection. All drive power is supplied over these two wires—think of an LED light. When you turn on a DC motor, it just starts spinning round and round.
A servo motor is an entirely different story. The servo motor is actually an assembly of four things:
a normal DC motor
a gear reduction unit
a position-sensing device (usually a potentiometer)
a motor control circuit.
The function of the servo is to receive a control signal that represents a desired output position of the servo shaft, and apply power to its DC motor until its shaft turns to that position. It uses the position-sensing device to determine the rotational position of the shaft, so it knows which way the motor must turn to move the shaft to the commanded position. The shaft typically does not rotate freely round and round like a DC motor, but rather can only turn 180 degrees or so back and forth.
A servo does not require a motor control circuit because it is built in.
The servo has a 3 wire connection: power, ground, and control. The power source must be constantly applied; the servo has its own drive electronics that draw current from the power lead to drive the motor.
Servos can have different colors for these wires. Some typical ones are noted below:
Power | Ground | Control / GPIO |
Red | Black | Yellow |
Red | Black | White |
Red | Brown | Orange |
In this exercise, the servo is powered through 3.3 volts on the red wire and ground on the black wire (or brown); the white wire (or orange) is connected to a programmable GPIO pin (in this example P0).
Connect the servo one of the two ways; with or without the breadboard:
OR
Note: In order to provide enough power to the servos, you might need to use the battery pack as power AND the Micro USB cable connected to the computer. The USB connection may provide too little current to power the servos.
To set the position of a servo connected to a micro:bit, MakeCode has a Servo Write block. This block accepts the angle (0-180) that you would like to set the servo to.
Try this code that sets the servo to its one end point, the middle, and the other end point:
Then try this code:
Continue to change the pause time to different values and observe what happens.
10. What is the difference between the two instances of code above? Describe what happens and which is better/more accurate with the desired result (more pause time or less).
We can also gradually change the servo value in a similar manner to how we accelerate and decelerate the motor.
Try this code:
In the on start
block we set the Direction
variable to 1
. This value will be toggled between 1 and -1 to determine the direction we want the servo to sweep.
We use the Servo Write
block to control a servo connected to a specific pin to rotate to a specific angle we pass it in degrees. We use a variable we have labeled as Angle
. You can use this command to just write any angle between 0 and 180 to a servo motor at any time, but do remember to add a small pause to make sure that you give it enough time to respond before moving to the next angle.
In the forever
event we increment or decrement the "Angle" variable by a certain value, the "Direction" variable (1 or -1). This essentially changes the angle by 1 degree each iteration of forever.
To change the direction of the servo once it reaches 0 or 180, we do some fancy math to multiply the direction variable by -1 to toggle it from a positive value to a negative number or a negative number to a positive value. That way when we can properly increment and decrement -- a positive number increases the angle, negative number decreases the angle.
11. In this code, what value would you change to increase the speed the servo is moving (how much it changes angle)?
12. Change the value to move the servo faster. Once you are confident that the code is working, paste share URL of your working code.
You will need to connect 2 servos for this challenge. Connect the servos with or without the breadboard:
OR
We will be creating code that runs in your car when ever you activate the windshield wipers. Attach popsicle sticks to the servos to represent the windshield wipers.
Complete the following code to have Button A turns the windshield wipers on once and Button B keeps them on until Button B is pressed again.
Notice the variable named WipersOn
. This variable should be set to true
and false
to control turning on and off the wipers with Button B.
Notes and Hints:
When windshield wipers are off they return to their normal position (down).
Don't forget to use the pause
blocks.
Button A just moves the servo from one end to the other and back -- one wipe of the wipers. (no need to use WipersOn
)
Button B will set WipersOn
to true
and false
. Forever defines what happens when the wipers are on.
13. Submit your windshield wiper code share URL.
You can even use sensor values to control the servo.
For example, on the back of the micro:bit you can see a number of small chips. One of them is the accelerometer. The micro:bit has an onboard accelerometer that measures gravitational force. Depending on the version that you have, the accelerometer and compass can be on separate ICs or combined into a single IC.
An accelerometer is a sensor that measures the gravitational forces pulling on it in all three dimensions of the chip’s X, Y and Z axes.
Not only can an accelerometer measure the raw forces pulling on the chip and the object that the chip is sitting on, but it can also detect steps, shakes and other motions that have a specific pattern. On top of that, you can use an accelerometer to simply detect the orientation that the device is in. As you know, this is the same sensor that tells your phone's OS when you turn it from portrait to landscape.
Connect one servo to pin0 and try the following code:
The acceleration (mg)
block can be found under the "input" section of blocks. This block returns the force of gravity pulling on a specific axis of the micro:bit (X, Y or Z) and represents that value as a range of numbers between -1023 and 1023. In this case, we measure the X axis, which is the side-to-side tilt of the micro:bit. If you tilt the micro:bit all the way to the left, you will get a -1023 value and all the way to the right is positive 1023.
The map block looks intimidating, but it is one of the most useful blocks in MakeCode and you've seen it before. The map block takes a given variable that has a known range (in this case -1023 to 1023) and “maps” or scales or converts that value range to another given range. The given range we want is 0 to 180, which is the range of possible values for the servo. So, in the end -1023 ends up to equal 0, and 1023 ends up as 180 from the map block.
What You Should See: At the beginning of the program the servo should move to 90 degrees and then react to the orientation of the micro:bit. If you hold the micro:bit flat, the servo will be at 90 degrees. Then if you tilt the servo to the left, it will move less than 90 degrees toward the value of 0. If you move it to the right, the servo will move toward 180.
14. Modify the code so that instead of changing the servo position when the micro:bit moves side-to-side (left and right) it changes when it is moved forward-to-back (up and down). Submit the share URL of your working code.
Hint: Has something to do with the axis being used.
Continuous rotation servos are standard servos that have been modified to offer open-loop speed control instead of their usual closed-loop position control. The modification effectively turns them into motors with integrated motor drivers in a compact, inexpensive package. Just throw on a wheel and you have a drive system for your robot that can be controlled using a analog servo write signal.
The signal specifies speed and direction instead of angle.
Connect the continuous servo the same as a 180 degree servo:
OR
Try this code:
15. Describe what each value does: 180, 90, and 0.
Create code that spins the continuous servo to the left when the Button A is pressed, spins to the right when Button B is pressed, and stops when Button A and B are pressed at the same time.
16. Submit your button controlled servo code share URL.
Similar to the code we created with the 180 degree servo, program the continuous servo to spin left when tilted left and spin right when tilted right.
17. Submit your sensor controlled servo code share URL.
18. Describe the difference between a DC motor, 180 degree servo, and a continuous servo.