Here's another fun way to use your animatronic hand -- it can count up to the number 15 (and say the numbers out loud)! How's this possible with only four active fingers? By using a modified finger binary counting method.
Finger binary is a counting method where each finger is assigned a 0 (down) and 1 (up) state, each with a different power of two.
These will be the powers of two and values of each finger of our modified, four-finger binary counting system:
- Index is 20, in binary
0001
, or a value of 1 - Middle is 21, in binary
0010
, or a value of 2 - Ring is 22, in binary
0100
, or a value of 4 - Pinky is 23, in binary
1000
, or a value of 8
By holding up the Index (1) and Middle (2) fingers, the binary representation is 0011
. We add their values, 1 + 2, therefore we indicate the number 3.
Here's another one: Pinky(8) + Ring(4) is 1100
in binary, or a value of 12.
So, here's the pattern for counting from 1 to 15 on four fingers:
- 1 = Index
0001
- 2 = Middle
0010
- 3 = Index, Middle
0011
- 4 = Ring
0100
- 5 = Ring, Index
0101
- 6 = Ring, Middle
0110
- 7 = Ring, Middle, Index
0111
- 8 = Pinky
1000
- 9 = Pinky, Index
1001
- 10 = Pinky, Middle
1010
- 11 = Pinky, Middle, Index
1011
- 12 = Pinky, Ring
1100
- 13 = Pinky, Ring, Index
1101
- 14 = Pinky, Ring, Middle
1110
- 15 = Pinky, Ring, Middle, Index
1111
CPX Setup
Below is the CircuitPython code we'll use to count in binary on the fingers.
You'll still want all 4 servos attached. But now you'll also want a speaker on the speaker port!
Audio Files
The CRICKIT is a terrific board for animatronics projects, particularly audio-animatronics projects, because it can play back audio as well as control servos and motors. Download this .zip file and uncompress it to get a collection of audio .wav files we'll use during number counting.
We'll use an external speaker to hear things loud an clear. Screw the leads of your 4Ω or 8Ω speaker to the two speaker terminals on the CRICKIT -- orientation does not matter, so either wire can go to either terminal.
Once you've uncompressed the .zip file, drag the .wav files onto your CIRCUITPY drive. The files can live at the root level of the CPX.
For more on audio playback with CRICKIT, check out this guide.
CircuitPython Code
Download this code and paste it into Mu. Then, save the file as main.py or code.py to your Circuit Playground Express. Make sure the CPX switch is to the left and sit back to watch and listen as your CRICKIT-powered animatronic hand counts in binary!
# SPDX-FileCopyrightText: 2018 John Edgar Park for Adafruit Industries # # SPDX-License-Identifier: MIT # Animatronic Hand # Binary Counting on four fingers up to 15 import time from digitalio import DigitalInOut, Direction, Pull import audioio import audiocore import board from adafruit_crickit import crickit #################### CPX switch # use the CPX onboard switch to turn on/off (helps calibrate) switch = DigitalInOut(board.SLIDE_SWITCH) switch.direction = Direction.INPUT switch.pull = Pull.UP #################### Audio setup print("Let's count in binary.") wavfiles = ("one.wav", "two.wav", "three.wav", "four.wav", "five.wav", "six.wav", "seven.wav", "eight.wav", "nine.wav", "ten.wav", "eleven.wav", "twelve.wav", "thirteen.wav", "fourteen.wav", "fifteen.wav") introfile = "intro.wav" cpx_audio = audioio.AudioOut(board.A0) def play_file(wavfile): with open(wavfile, "rb") as f: wav = audiocore.WaveFile(f) cpx_audio.play(wav) while cpx_audio.playing: pass #################### 4 Servos! servos = (crickit.servo_1, crickit.servo_2, crickit.servo_3, crickit.servo_4) for servo in servos: servo.angle = 180 # starting angle, open hand # Which servos to actuate for each number counting = ( [3], [2], [3, 2], [1], [1, 3], [1, 2], [3, 2, 1], [0], [0, 3], [0, 2], [0, 3, 2], [0, 1], [0, 3, 1], [0, 2, 1], [0, 3, 2, 1] ) play_file(introfile) while True: if not switch.value: continue # the CPX switch is on, so do things for servo in servos: # close the fist servo.angle = 0 # close the fingers print("Servo %d angle = 0" % (servos.index(servo)+1) ) time.sleep(.2) time.sleep(1) # pause a moment for i in range(len(counting)): # close all the counting fingers between numbers for servo in servos: servo.angle = 0 # close print("\t\tServo #%d angle 0" % (servos.index(servo)+1)) time.sleep(0.3) print("Number #%d \tfingers: %s" % (i+1, counting[i])) # open just the indicated fingers when counting for finger in counting[i]: servos[finger].angle = 180 # open print("\t\tServo #%d angle 180" % (finger+1)) time.sleep(0.3) # say it! play_file(wavfiles[i]) # hold for a bit of time time.sleep(0.3) print("...")
Code Explainer
Take a look at the code to get a sense of how it works. After importing libraries and setting up the CPX switch, we have an audio setup section.
First, we create a variable list called wavfiles
that stores the names of all the counting audio files we'll use. We also make a variable called introfile
that has the filename of the intro audio wav file.
Then, we instantiate the audioio
command and define a process called play_file
to open, play, and close the audio files specified.
#################### Audio setup print("Let's count in binary.") wavfiles = ["one.wav", "two.wav", "three.wav", "four.wav", "five.wav", "six.wav", "seven.wav", "eight.wav", "nine.wav", "ten.wav", "eleven.wav", "twelve.wav", "thirteen.wav", "fourteen.wav", "fifteen.wav"] introfile = "intro.wav" cpx_audio = audioio.AudioOut(board.A0) def play_file(wavfile): with open(wavfile, "rb") as f: wav = audiocore.WaveFile(f) cpx_audio.play(wav) while cpx_audio.playing: pass
Servo Counting
Next, we set up the four servos, and create a variable list of lists called counting
. This specifies which finger or set of fingers is to be raised up for each number that we're counting. You can see, for example, that the number 1 raises the index finger only, while 15 raises all four fingers.
#################### 4 Servos servos = (crickit.servo_1, crickit.servo_2, crickit.servo_3, crickit.servo_4) for servo in servos: servo.angle = 180 # starting angle, open hand # Which servos to actuate for each number counting = [ [3], [2], [3, 2], [1], [1, 3], [1, 2], [3, 2, 1], [0], [0, 3], [0, 2], [0, 3, 2], [0, 1], [0, 3, 1], [0, 2, 1], [0, 3, 2, 1] ]
Counting Time
The final bit of setup is to play the intro wav file and then get into the main loop. Here we check the CPX switch and only proceed if it is set to the left position.
Then, we close all the fingers down into a fist and pause a moment.
play_file(introfile) while True: if not switch.value: continue # the CPX switch is on, so do things for servo in servos: # close the fist servo.angle = 0 # close the fingers print("Servo %d angle = 0" % (servos.index(servo)+1) ) time.sleep(.2) time.sleep(1) # pause a moment
Finally, we run through the counting
list one item at a time and open only the fingers specified per entry in that list.
After all of the fingers needed for a particular number have been raise, we play back the appropriate wav file so the audio-animatronic can speak!
for i in range(len(counting)): # close all the counting fingers between numbers for servo in servos: servo.angle = 0 # close print("\t\tServo #%d angle 0" % (servos.index(servo)+1)) time.sleep(0.3) print("Number #%d \tfingers: %s" % (i+1, counting[i])) # open just the indicated fingers when counting for finger in counting[i]: servos[finger].angle = 180 # open print("\t\tServo #%d angle 180" % (finger+1)) time.sleep(0.3) # say it! play_file(wavfiles[i]) # hold for a bit of time time.sleep(0.3) print("...")
Page last edited January 21, 2025
Text editor powered by tinymce.