Introduction: Lip-Syncing Characters With Micro:bit

About: Dreamer, maker, artist.

Videos, video calls, TikToks, etc. If you are anything like me, you are interested in creating content, but absolutely hate appearing in videos yourself. My solution: to make cute characters that appear in the videos instead. Fortunately, with a little bit of coding and crafting, you can make these characters lip-sync to the sound of your voice to appear as if they are the ones doing the talking/singing.

In this Instructable I'll explain first how the lip-syncing code works, then show you some simple builds first (only one motor and one Micro:Bit), then I'll give a step-by-step of how I made a more elaborate 4 servo motor character (or avatar) using two Micro:bits, an expansion board, and a remote controller.

My hope is that you'll be inspired to make your own or have students make their own. Wouldn't it be great to have a biography report presented by a lip-syncing robot of a famous person? Or an amazing robotic TikTok star singing the latest "it" song?

This Instructable is meant for people who have at least a basic knowledge of how to use a Micro:bit.

Supplies

For the first simple build you need:

  • A Micro:bit V.2 (V.1 will NOT work for this build as we'll be using the integrated sound sensor that comes in the newest version)
  • 3 alligator clips to male jumper wires (or Alligator Clip with Pigtail as they are called sometimes) to connect the servo to the Micro:bit
  • 1 Micro Servo like this one or these cheap ones.
  • USB Micro B to USB A data cord (not just power, although unless you choose the next option you will also be powering the robot with this).
  • Optional: 3AA Battery pack and 2 alligator clips. ---While you can power the Micro:bit and the servo through the USB cord connected to a computer, it's recommended to use external power for the servo, although in my own opinion, at that point you are better off buying an expansion board that will provide power safely and adds functionality.
  • Crafts supplies that you prefer. I like using cardboard as a base and you can either paint it directly or paste paper onto it. Please note that unless you are providing the extra power for the motor, you should keep the materials you use for the mouth movement light or it will be hard for the Micro:bit to move it on its own.


For the second more elaborate build you will need:

  • 2 Micro:bits (at least one of these needs to be a Micro:bit V2 since we'll use the sound sensor)
  • 2 Standard size servos
  • 1 Micro Servo (see above for link)
  • 1 Kitronick Linear actuator kit
  • 1 Micro:bit expansion board. I recommend either a HummingbirdBit or a REKA:Bit, but there are lots of great ones out there. The important part is to make sure they support 4 servo connections.
  • 1 Joystick:bit to use as a remote. There are other alternatives, but I have not personally used those.
  • USB B to USB A data cord (not just power).
  • 2 Servo extension cords. They don't need to be too long, about 6 inches (15 cm) should be fine.
  • Inline switch cable (makes life easier if you want to seal the box)
  • 5V 2A power supply or 4AA battery pack
  • Cardboard cutting tools
  • If you are following the instructions exactly: 6 x 6 x 2.5 in (15 x 15 x 6.5 cm) or deeper box. Several pieces of flat, clean cardboard. The cardboard I use comes from reusing all kinds of boxes. I am not picky as long as it does not have big folds. Especially since I cover most of it anyway.
  • Watercolor paper, paint and brushes.
  • Hot glue gun

Step 1: Lip Syncing Basics

This section is going to be a bit technical, so if you are just interested in making cool things, go to the code link below and you can use that to program your simple creations.

In order to make a robot appear to be "lip-syncing" to your voice, you need a sound sensor (for this project we are using the one integrated into the Micro:Bit v2) to sense the volume of the sounds you are making. With some code, you can tell the Micro:Bit to move the servo to a bigger or smaller angle depending on how loud you are. In the attached video, you can see how the servo needle goes up and down depending on the volume of my voice.

Let's break down the code that is doing that. (You can open it in Makecode here)

The important parts of the code are inside the Forever block, but there are some important things you should know first:

-The sound sensor on the Micro:bit V.2 measures sounds from 0-255, zero being no sound at all, and 255 being VERY loud. That said, when doing a project like this, I ask the Micro:bit to react on measurements 25-180 because I have found sensing anything under 25 makes it too sensitive and jittery because any small sound triggers it. On the opposite end of the scale, it is hard when talking to go above 180 because anything above that has to be VERY loud like I mentioned. So by shortening the scale of the sound sensor, I make the servo move only when there is enough sound and get to the highest setting with a regular loud voice instead of needing to be as loud as a fire alarm.

-Position servos usually go from 0º to 180ºish degrees. For a mouth in a project to look somewhat natural when it opens and closes, I find 0º-55º is more than enough.

With that in mind, looking at the code we see that inside the Forever block we have:

-set 'mouth' to (mouth, in this case, is the name of the variable I created)

-map 'sound level' (sound level is an Input block that is measuring what the sound sensor on the Micro:bit v2 is sensing) from low 25 high 180 to low 0 high 55 (the first two numbers are my modified scale of the sound sensing as I explained previously, and it is "mapped" to the second set of numbers that represent what will be the servo angles. What that does is automatically calculate the equivalent number for what you are sensing, so for example the lowest volume it is sensing, "25", is equivalent to having the servo at 0 degrees, and if the sensor is picking a number like 100, the math is done automatically to get the number that corresponds to in a scale of 0-55 which is roughly 30 - there is a reason I need the calculations to be automatic 😅)

-The next block says servo write pin P0 to "mouth" which tells the servo connected to P0 to use the variable "mouth" to determine what position to be in. The value of "mouth" is determined by the math in the previous block.

-Those blocks inside the Forever block make it so the Micro:bit is constantly doing the math and setting the servo to the correct position.


The blocks inside the "On Start" block are optional and do not affect the function of the project. They are a personal preference.


This code is all you need to make a basic lip-syncing robot. The way you make the mouth can vary and maybe the angles will be different when you make yours, but these are the basics.

Note that the servos are usually pretty noisy; it is better to not have the sensor (i.e. Micro:bit v2) super close to the motor or it'll pick up the noise from that. Also, if you want to take a video or use these characters for video conferencing, it is advisable to use a separate headset or microphone because otherwise, the computer's or camera's integrated microphone will pick up the noise of the motors more than your voice.

Step 2: Simple Build - Examples

Now that I explained how the coding works, I am going to show you some examples of the simple build that consists of just one servo to move the mouth. There are several ways to make a mouth for a robot, but for these examples, I am just focusing on a simple up and down where the top of the head is glued to a servo horn.

Please note that if you are powering the motor straight from the Micro:bit v2 you should try to make the mouth as light as possible so it is not a strain on the Micro:bit. The sample build with the skeleton mariachi I have is too heavy to be very good with the lip-syncing because of the big hat and everything being mounted on cardboard; in that case, it's better to either power the motor separately or have a separate add-on or expansion board powering the project.

In the video of the skeleton mariachi, I show how I:

  1. Make a drawing of the character on a piece of paper
  2. Trace it to the surface I'll use for crafting (in this case I used colored paper, but I usually trace the characters onto watercolor paper) making sure the lower layer (i.e. the body and lower jaw) continues higher than it would if I just cut the head in half, that way when the character opens the mouth, it will look more natural.
  3. Mount the body and lower jaw to a surface (cardboard)
  4. Make a hole for the servo to poke through
  5. Calculate where I want the top of the head to sit so I can...
  6. Hot glue the servo horn in the correct spot
  7. Connect the servo horn to the servo
  8. Plug the alligator to male header cords to the servo cord
  9. Clip the alligator clips to the Micro:bit
  10. Connect the Micro:bit to the computer to download the code
  11. Talk and have the character "talk" as well

That same basic process is what I used to create the Crocodile Rocking that I'm showing as well. The main difference is that the mouth of the crocodile is small and light, so the movements are faster and more pronounced without having to provide separate power. The music sounds good because my own singing was replaced by the music track, so think in terms of TikTok where you record the video lip-syncing to the song, except with the robots you actually need to sing yourself to activate the movements of the mouth (you would use headphones to listen to the song so the music does not activate the robot). No one will hear your actual singing, so you can just have at it!

Step 3: Elaborate Build - Making the Character

Now that I covered the simple build, I will take you step-by-step on how I made my little avatar which has 4 servo motors: one moving the left arm up and down, one moving the mouth, and two controlling the neck up and down and side to side motions.

First up is to make your character. One of the most important things is to pick a size. For my project, I wanted it to be as portable as possible, but big enough to fit the mouth mechanism. I made several small sketches until I decided on which I wanted. I made the character in "chibi" proportions to make it that much cuter, but feel free to do what works for you. I scaled up my drawing and separated the head from the body on the computer, but if working to the size you want is easy for you, you might want to just draw it that size.

I'm providing a rough template based on my own character if you want to use it. You can print it, customize and then trace it onto the surface you want to use. I did NOT include the mouth piece in the template because it was more trial and error than accurate measurements.

The way I make most of my projects is by combining watercolor paintings with cardboard builds because cardboard is extremely easy to work with and cheap, and the watercolor paintings make the project more my style. If you like that approach then you:

  • Trace the character onto the watercolor paper
  • Paint it
  • Cut it
  • Glue it to flat cardboard (I like to use this glue and let it set by setting the pieces aside with books on top of them)
  • Cut the pieces again and get ready to use them in the next step.

If you want to paint your character directly on the cardboard, I recommend craft acrylics on thin layers (not blobs of paint) so it doesn't get too wet and warp.

The essential parts you need to make are: the head (with a hole for the mouth), the mouth (which needs to be separate and longer than you need), the body, and the left arm.

In my case, I also made it so I could change out the right arm depending on the position I wanted, plus I wanted to be able to change the left hand so the character could be pointing or waving. This was achieved with magnets glued to the end of the arm and on the hands.

You might also notice I made two heads and several mouths. That is because I wanted to make sure I did not ruin one and ended up having to make a new one. When you work in watercolor it is harder to match colors if you have to make the pieces at a later date.

Step 4: Elaborate Build - Body

Once you have the character all painted and on cardboard or a similar sturdy surface, you need to start putting it together.

Since I wanted to hide the electronics and provide a solid base for everything, I used a 6 x 6 x 2.5 inch box so that the 2.5 inches is the depth of the project. It can be deeper if you prefer, and it can be wider than 6 inches as it does not make a big difference. But if you are using the template I provided, the 6 inches of height of the box are important. You might actually need it to be deeper depending on which Microbit expansion board you are using. For this build I used the HummingbirdBit, so everything fit inside the box I used. I painted the box black, but that is a personal preference.

The first thing I did was to trace one of the standard servos onto the middle of the box with the motor being as close to the edge towards the front as possible (see photos) taking into account the extra width of the mounting holes. I then cut the hole for the motor.

By planning where that motor will be, you get an idea of where the middle of the body should be, or where the neck should end up since that motor will be controlling the side to side movement of the head.

Next up is to figure out where the motor for the arm will be. While holding the body in the middle as I mentioned previously, you note where the best spot for the arm movement will be, then you make the hole for the motor. Since I want the arm to stick out as little as possible, but to have a sturdy connection, I glued the motor with only the top third sticking through (it's clearer in the photos and videos).

The reason to try to have the arm sticking out as little as possible is that the body has to go in front of it. In order to achieve that, I mounted the body on a 3 layered cardboard piece to get it to stick out the correct amount. You might need to check the number of layers needed by trial and error. Notice how my body base does not have the arm on the left (aka the right arm) included, and that is because like I mentioned before, I want to be able to swap out the arm (I put a small piece of velcro to do that). You do not need to do this unless that is also your preference.

For the arm on the right (aka the left arm) I made sure that I measured everything with it being on the lowest position by manually moving the servo gears as far down as they went. That way I know for sure that it is as far as it needs to go and I can adjust the body base in case it bumps the arm.

Now that you made sure everything is going to be in the right spot, you can start gluing the body base, the painted body, etc. to the box.

Step 5: Elaborate Build - Mouth

At the center of this build is the Kitronick Linear Actuator Kit that converts the movement of the servo into a linear movement so I can have an up and down of the mouth behind the face. You can look at how that works in the attached video. The servo can move 0-180º and that makes the acrylic piece go up and down from one point to the other.

The servo is mounted on enough layers of cardboard to make it even with the mouth which is glued to the acrylic arm. I wish I had taken a better picture of that, but I put a quick drawing that will hopefully give you an idea of what I am talking about.

The trickiest part is to have the mouth piece be the correct size; it has to have the drawing of the open mouth, plus enough "skin" underneath to be able to cover the mouth hole when the mouth is closed. It also needs enough material for the acrylic arm to be well glued to it. In addition to all that, you have to make sure when the mouth opens, nothing sticks out below the chin.

I made several tests to make sure I had things in the position I liked. In the video, you can see how I am using a HummingbirdBit connected to my phone via Bluetooth using an app called Birdblox. That lets me make tests in real-time of the angles that will make the mouth open the way I want it.

When I figure out the correct position, I hot glue the servo (previously mounted on layers of cardboard) to the face. I then test again to make sure everything is working the way I want, then move on to the next steps.

Step 6: Elaborate Build - the Neck and Head

You have the body glued to the base, and the mouth glued to the face. Now it's time for the neck.

The neck goes side to side, and up and down. That is achieved by having a servo mounted/glued on top of another servo. You can either just hot glue a servo horn onto another servo, or you can use the provided file to 3D print the piece I used. It is still basically gluing the servos together, but it provides a sturdier connection. Please note that I used this kind of servo and do not know if the 3D printed file would fit others because I had it designed specifically for these parts.

Notice how I mounted the servos off-center. That is because I want the top servo, which will control the up and down, to stick out from the edge of the box because the body, as seen previously, also sticks out.

To mount the head on the neck, I glued cardboard that sticks out on the back of the head. The cardboard behind the head has to reach back far enough to be able to reach the servo and provide enough room for the mouth mechanism and the other motors. I wish I could give you exact measurements, but it was mainly trial and error for this project, mine is a bit less than 3 inches deep. You can see I had to add a couple of layers of cardboard on the side to center the head better before I glued everything to the servo horn.

At this point make sure that you can insert the cords of the motors into the box by making any necessary holes. Some of the cords might be too short and not have a comfortable slack. If so, you can add servo extension cords.

Step 7: Connecting Everything and Coding

For my project, I used a HummingbirdBit to connect and control the motors. If you use a different board, make sure it has at least 4 servo connections. I will be describing how I connected and coded everything using the HummingbirdBit and then added the joystick:bit. The coding of the HummingbirdBit is a bit different than other boards, but I hope by showing you how I did it will guide you to how you can do it with your board.

I made a hole on the side of the box so the Inline switch cable can connect to the Hummingbird Bit. Then I connected the cords as follows:

  • Left Arm - Servo 1
  • Head Side to side - Servo 2
  • Head Up and Down - Servo 3
  • Mouth - Servo 4

Using the BirdBlox app, I slowly decided on what the angle limits of each motor will be (see attached video) and I wrote them down on my rough schematic so I can use that information to code the robot and controller with Makecode.

The reason I switch between BirdBlox and Makecode is that with BirdBlox I get the immediate feedback of controlling the robot through a Bluetooth connection and do not need to download the code or even make it into completed code. I can just drag the block for a Servo and tap on it to make the servo move. It is a quick way to prototype. The downside of using Birdblox is that the code stays on the iPad and you can't download it to the Micro:Bit to make it independent of the iPad. That's where Makecode comes into play. With Makecode, you can code the robot, download the code to the Micro:Bit, and have the robot work without any connection to the computer or iPad. If you pair that with a battery pack, you can take your robot anywhere and still have it work. The only downside to using Makecode is that downloading and testing your code can become tedious with the unplugging and plugging of the Micro:bit each time you want to change something. That is why I use both coding platforms for their different strengths. I figure out the parameters of the code with Birdblox, then switch to Makecode where I refine it and make it independent.

Once I know the values of the angles of how far I want each part to move, I start coding the remote control on Makecode. I am using a Joystick:Bit. You can open the code here and I'll try my best to explain it as well.

The way the remote works is that it will be sending radio signals from the Micro:bit V.2 (#1) connected to the remote to the second Micro:bit(#2) connected to the HummingbirdBit. Those radio signals will tell #2 to move the robotic character accordingly.

Code for the remote (#1):

  • Add the extension for the JoystickBit by clicking Advanced and then Extensions. Search for Joystickbit then click on one with the correct picture.
  • Inside the On Start add a initialization joystick:bit block
  • I like adding a show icon, but it's not necessary.
  • Add a radio set group with the number you want from 0-255. It has to match the code for the #2 Micro:bit, but if you have more than one Micro:bit using radio signals around you (like in a classroom) it has to be different from those.
  • For my project, I determined that I wanted the left arm to move between 3 set positions, but also be able to wave, so I linked the code for those to Joystickbit's on button " " is pressed and added a radio send string " ". What this does is when you press each of the buttons on the right side of the controller, they send specific messages to Micro:bit #2. It is important that if you send strings, numbers, and/or values, they match what the code for Micro:bit #2 has exactly because if you accidentally capitalize a word in one code and not the other, they will be interpreted as different things.
  • Button C (which is the one on the left in the cluster of buttons) in my project sends a number instead of a string so I could have a separate line of code in the #2's code. I'll explain why later.
  • Inside the Forever block, you need to add 3 different radio send value " " = " " blocks.
  • The first radio send value " " = " " will be sending value "x" and you will add a map block (found under Advanced > Pins) that allows you to enter several values. The first will be to add a block from the Joystickbit next to map called "rocker value of X". This is telling the code to use the information the Micro:bit gets from moving the joystick (or rocker) left and right and do some quick math. The first set of numbers from low 0 and from high 1023 is saying to use the whole range of values from the rocker (0-1023, 0 being all the way to the right and 1023 all the way to the left). The second set of numbers to low 105 and to high 65 comes from the servo angles (that I determined previously using Birdblox) that you want the servo to go to. In this case 65º was what I determined should be the furthest to the left the head of the character should turn and 105º the furthest to the left. So what that means is the block is mapping the values to say the lowest value of the first number (the rocker all the way to the right) corresponds to 105 (the servo angle furthest to the right) and sending that number via radio to the second Micro:bit so the servo knows to go to that number angle.
  • Very similarly to the previous block, the second radio send value " " = " " will be "y" and will use the rocker value of Y to use the values of moving the joystick (or rocker) up and down (0-1023, 0 being all the way down and 1023 all the way up) and map them to the numbers of the neck moving up and down (80-55, 80 being all the furthest down that you want the neck to go and 55 the highest) which were determined by my Birdblox test.
  • The third radio send value " " = " " will be "talk" and will map the sound level (found under Input) which is the volume of your voice and use a modified scale. While the sound sensor can sense sound values between 0-255, I have found that my usually quiet voice and the extra noisy servo used for the mouth, I rather it only map the values between 30-150, which will correspond to the scale of 0-120 (0 being closed and 120 all the way open) that are the angles of the servo as I determined earlier.
  • The last block is a pause (ms) 100 because when you are sending so many signals, it makes things smoother if there are small pauses.

Next, the code for the #2 Micro:bit that actually moves the motors when it receives the radio signals from the remote control can be found here. And here's a rough explanation/walkthrough:

  • Add the Hummingbird extension by going to Advanced > Extensions and searching for it.
  • Inside the On Start block, you need to add a Start Hummingbird block.
  • Then add a radio set group " " this number HAS to match the number you entered for the remote control.
  • The rest of the blocks inside On Start are just a preference of making the robot character start by having all the servos be in a "neutral" position by adding Hummingbird Position Servo " " " " blocks for each of the four servos. The values inside each one were determined by the Birdblox test.
  • Next, you will have an on radio received name value block. Inside you'll add an if "true" else " " block. To add else if "true" options to that block, you can press the plus sign at the end. And you can delete any by pressing the minus sign next to it.
  • Next you need to replace the "true" in the if "true" and else if "true" blocks with a comparison " " = " " block.
  • You need to drag the "name" block from the on radio received name value block into the first value in each of the comparison " " = " " blocks.
  • The second value of the comparison blocks needs to be the name of the radio signal sent by the remote. It has to match the name exactly.
  • Then inside each of those blocks, you need to add the corresponding Hummingbird Position Servo "number" " " blocks and drag the value block inside. So for example the first if name = x then Hummingbird Position Servo 2value means that if the name of the radio signal received is "x" (you moved the joystick side to side) then the servo 2 (the side to side servo in my case) will then move to the position determined by the value the radio signal sent.
  • You have to do that for all 3 of the name value signals, so you will be controlling each servo with the corresponding value signal from the remote.
  • Next, you need an on radio received receivedNumber block (if you are following along exactly). In my project this blocks will make a quick wave with the arm. So inside you add an if "true" block where you'll replace the "true" with a comparison "0" = "0" block (since we're using numbers this time). You'll drag the receivedNumber block that is on the block to the first position in the comparison block and you'll write the number that is expected from the radio signal (1 in my case). So when I press the left button in the remote control, it sends the radio signal number 1, which tells the robot to move the servo controlling the arm (1) back and forth quickly a couple of times to make a little wave. The reason I have this separated from the other arm positions is that the wave and little pauses seemed to interfere with the rest of the code.
  • The last blocks of code are a on radio received receivedString that will house an if "true" else if "true" else if "true" blocks, much like the ones controlling the neck and the mouth. This will have "true" replaced by a comparison " " = " " blocks that will have receivedString in the first position and the different messages determined by the remote in each of the second positions. So when Micro:bit #2 receives the string "up" it will move the arm to the up position which for my project is 90º with the block Hummingbird Position Servo 1 "90º"and so on.

I hope all this made sense. Coding the radio signals with the Micro:bit takes some practice.

Step 8: Conclusion

There you have it. Now the character is responding to the sound of my voice, and the commands from the controller. You can make silly videos to your heart's content.

Please note again that the servos, especially the one attached to the Kitronick Kit, are very loud. To make the best videos of your character, you need to be using a different microphone than the default one of your camera, so that is not too close to the robot to avoid it picking up the sound of the servo more than your own voice.

Micro:bit Contest

Grand Prize in the
Micro:bit Contest