This project uses the TM014: Feetech Servo FS90R, 360 degrees as basic hardware and makes fun controlling of it, by using Micro:bit's built-in button, and the tilting gesture. This project contains extra learning for debugging, codes structure and architectural optimizations, good practices and mindset of designing and testing in engineering. Goals:
Fun experience with Micro:bit + servo motor, inspire future explorations
Practice Variables and Functions, understand why and how they are used
Build mindset of serious engineering and attention on details investigations, optimizations
START A BIT > Projects Library > This page
A demo of the result, by the tutor
This project uses only 1 continuous servo motor, and the wiring is straightforward. Wire the servo motor's signal control (orange) to Micro:bit's PIN 1. Some other PINs are also available, but let's say this as easy start.
Stay still when powering up.
Button controlling:
Press button A to make the servo motor to spin more (and more) in A-direction (say, clockwise), this also means to spin less and less (and less) in B-direction (say, anticlockwise)
Press button B to make the servo motor to spin more (and more) in B-direction (say, anticlockwise), this also means to spin less and less (and less) in A-direction (say, clockwise)
When reaching max speed in that direction, warn a beep sound
Press button A+B to immediately reset to speed 0, with a sound hint
Gesture controlling:
Gesture tilting-left does exactly the same thing as pressing button A
Gesture tilting-right does exactly the same thing as pressing button B
Gesture shaking does exactly the same thing as pressing button A+B
Optional visualization of current speed and spinning direction, this is not a must, but a challenging exploration
[ ] Simple: 30-60 minutes
[ ] Moderate: 1-2 hours
[x] Challenging: more than 2 hours
The estimation bases on average situation without unexpected troubleshooting, assuming that the student meets prerequisites. It only indicates rough time needed to complete this project, but not about technical difficulty, not covering discussion and sharing time. Here is a possible breakdown:
5 minutes: Understand requirement and solution, collect materials
5-10 minutes: Hardware wiring
45-60 minutes: Programming for button controlling part, make it work
15-30 minutes: Add debugging, optimize code structure using Variables/Functions, test and keep it working
30-45 minutes: Programming for gesture controlling part, download and test
15-30 minutes: Experience test, find out improvement points, try out different solutions
45-60 minutes: Optional challenge of visualization of speed
One should have prior knowledge
Micro:bit V2 board: Know what they are, better to have prior experience with it
MakeCode by Microsoft, the programming tool, better to have prior experience using it with Micro:bit
Basic knowledge of Variables, Functions
1x Micro:bit V2 board , with USB cable
A few jumping wires
Find out the wire layout of servo motor from TM014: Feetech Servo FS90R, 360 degrees, build the connections like the picture.
Suggest to follow the same here using Micro:bit's PIN1 for signaling.
Goal: Make it spin for fun, learn how to control the servo motor, try the speed parameter -100~0~100
Click "Extensions", search "Servo", add it.
Since it's confusing to say direction as "clockwise" or "anticlockwise", because you can observe the servo motor from the top-down or bottom-up, the perspective leads different answers.
Let's say "direction+" or "direction-" instead from now on.
"direction+" is when speed is 0~100%
"direction-" is when speed is -100~0%
Servos -> Continuous ->
Parameters:
Signal pin: P0/P1/P2
Speed: -100~100, which means percentage of the max speed, the "+/-" sign means rotation direction.
Goal: Change speed with buttons, make it work
You need a variable to help storing and changing the current speed.
Good practices of variable:
Readable and understandable name
Initialize it before use it! Good with on-start
Typically 2 types of using:
Reader/Viewer/Consumer
Fetch and consume it as soon, since the value could be updated quickly by writer on the other hand
Writer/Changer/Producer
To change/update the value of variable, good to handle this job as accountable complete within a clear logical block of codes, avoid doing the change at different places where mixing other jobs or logic.
Be careful of conflict parallel handling of the same variable.
Create variable
Initialize variable
If you don't know how to start, a straightforward idea like this will work to prove the concept, try it out, test it with the servo motor, can you change the speed and even rotation direction now?
Be noticed that, we say this is "prototype", because it's not such simple as a good work yet.
Writer user of variable
Reader user of variable
Goal: Add debugging using serial write, optimize the button controlling feature with Functions, and better using Variable, ensure the speed value not out of valid range
From Task 2, it seems things can work, let's look into it closer and check if it really does correctly or not.
This is very useful block for debugging to send real time data back to PC when the Micro:bit board is executing the program.
Advanced -> Serial ->
Reader user of variable
From the debug information via "serial write", it's seen that the variable value could be bigger than 100, less than -100, which are invalid for the servo motor controlling block's parameter.
In this case, it doesn't bring obvious harm, but it could be serious sequence in other cases. As accountable program, we should take care of this, secure the right interfacing.
Here we list some common solutions from our students, please take a serious and good engineering mindset to handle this, keep things as neat and efficient!
NOT good example#1 ☹️
It let things be wrong first and correct afterwards, waste of actions, and redundant logic
NOT good example#2 ☹️
It lets things be wrong here, but correct it later elsewhere, besides the drawbacks from example#1, it also creates a mess for variable being changed here and there, confusing logic to follow and maintain.
Use function to group the codes blocks into clearer logical structure and purpose.
Good practices of Functions:
Readable and understandable name
Clear purpose, be complete and accountable for that
Advanced -> Functions
As fun and useful interaction with the user, let's add some warning sounds when
reached max speed in direction+
reached max speed in direction-
resetting speed to 0
Goal: Get it work with gesture controlling added, but not breaking existed buttong controlling
There are 2 relevant blocks, either will work, but a little different, feel free to try out!
To trigger the speed up functions, just reuse the similar "call function" blocks.
Goal: Continuously triggering the speed change when keeping tilting
On-event v.s. On-status
If you use the "on-tilt" block, which is on-event triggering, it only triggers one time of the same event, but not trigger the same event even if you keep the same gesture.
Try out the on-status blocks, test and feel the difference!
"On-event" triggering
"On-status" triggering
By using "on-status" blocks, it's possible to continuously triggering the speed changing actions, the logic doesn't seem wrong, however, what does it feel in real world?
It's almost not a useful feature if we see it quickly hits the max speed when we keep the tilting just for a second!
Luckily, a small "pause" improve the user experience a lot!
Using the handy looping block also works
Another working solution by our student
Goal: Find out the possible conflict from different controlling source, try out the technique of "lock" to solve it
What happens when doing some simultaneous actions like this
Tilting-left and pressing button B or button A+B
Tilting-right and pressing button B or button A+B
Shaking and press button A or button B
The conflict of using the same critical resource is called "synchronization issue", this happens in parallel way of jobs handling (multi processing/threading). There are several solutions to the embarrassment, the "lock" technique is one of the effective methods.
Create a new variable, we will use it as boolean type, remember to initialize variable before anything.
Always check the availability before using the resource, if it's busy, you can decide to give up, or wait. Here, we simply give up.
"Lock" the resource by setting the variable as True
Now your are safe to use the resource.
"Unlock" the resource by setting the variable as False
We use "on event" gesture block here as a simple example
As an optional exercise, a more professional way is to create 2 functions to simplify the "check-lock-unlock" actions for every user.
An easier way to understand this technique is like this
"Can I use it now"
"I'm done, others can use it now"
Now, looks at this in a professional view:
"Fetch lock"
= "Can I use it now"
Successful = Check and is available + Lock
Failed = Check and is unavailable
"Return lock"
= "I'm done, others can use it now"
= "Unlock"
As seen from above, it's still redundant codes for gesture and button controlling parts, we can even optimize it, e.g. like this, finally, a satisfying work! 😁
Goal: Develop a nice visualization to indicate the speed and rotation direction using the LED screen
The speed/direction is represented as -100~100 number range. So just map this number range to a range of levels to display.
There is ready-made bar plot, but it's only possible to map number range to a bar level.
Try it out, find out the limitations.
Led->
The speed/direction is represented as -100~100 number range.
Stand in front of the class, share with your group what you have made, please cover important points
Tell what it is your product
Demonstrate how it works
Explain how it works
Share with your group about
What troubles you met
How you analyze
How you get help
How you solve it
What you have learnt
Find out working copy as a MakeCode shared project.
Used as main project across 2 sessions in LP2435: 2 Weeks Extended Focus on Variables & Functions Basic, 24w35
Used as demo for LP2517: Special Onboarding Workshop, 25w17