Christmas Toy

Over the Christmas holidays, I decided to use my nascent electronics skills to rustle up a little toy for the Christmas tree. I took inspiration from the little Asian waving cat, Maneki-neko, that's often seen at Asian stores and restaurants. I wanted to make a little Santa figurine that would light-up, wave and say "Merry Christmas" when someone came close to it.

I decided to use the Arduino Uno (because I already had one) for the microcontroller (uC), an addressable light strip for the lights, an HC-SRO4 ultrasonic sensor for proximity-based triggering and a tiny 4-ohm 3-watt speaker for the sound to come out of. 

The first thing was to make the setup say something. I found out, initially from this youtube channel, that there is an Arduino PCM library that can play short audio samples. These samples are encoded in the Arduino sketch as an array of numbers. HiLowTech describes the process of converting an audio sample into this series of numbers.

Downsampling the original waveform using Audacity

I recorded a 2-second audio clip of me saying "Merry Christmas" using Apple's Quicktime Player. This was in .m4a format and about 90 KB in size. I loaded this clip up in Audacity and selected the part of the clip I wanted (there was a 0.5 second gap in the front and back that I discarded) and exported a down-sampled version of it with the settings shown in the figure above. Essentially, the sample rate has to be 8 KHz and the encoding has to be 8-bit PCM - which makes it sound tinny and slightly artificial, but makes it small enough to be played through the Arduino.


PCM or Pulse Code Modulation is a standard process of digitizing analog signals. In this case, it is my voice, that is digitized with a quantization bit-rate of 8 - which means that the wave-form is quantized into 8-bits (2^8 = 255 values) and at a sampling rate of 8 KHz. 
Sampling at that frequency retains enough information (frequencies upto half that amount, or 4 KHz - explained below) from the human voice that sounds reasonable to the human ear, which has the capability to detect sound upto 20 KHz (but often much lower for adults).

PCM quantization

I illustrate sampling and quantization, which form part of PCM with the following illustration. The diagram above shows sampling for an example signal (red waveform) of 8 frequency components at [0.2, 2, 10, 44, 80, 100, 150, 200] Hz. These are sampled at a frequency of 50 Hz, and shown as blue dots. Quantization converts the waveform from continuous values to discrete values. In this case, I have selected a bit-rate of 2, which means 2^2 = 4 discrete quantization levels. So the original waveform with infinite continuous values is converted to a squiggly square-wave with 4 quantization levels, sampled at 50 Hz. This is PCM quantization. 


Nyquist cut-off frequency


The other thing to note is that the highest frequency we are able to capture is half of the sampling frequency and we can observe this by taking an FFT (Fast Fourier Transform) of the original signal, which shows all the 8 frequency components and compare that to an FFT of the quantized signal, which shows only the frequency components upto half the sampling frequency = 50/2 = 25 Hz. This is due to the Nyquist-Shannon sampling theorem, another fundamental tenet of Digital Signal Processing.


Ok, back to the original clip and its playback using the uC. 

The Arduino is a small uC with limited memory, and that's why it can only play a short clip. The small speaker we are using is another limiting factor, and that's why we limit the frequency to 8 KHz and a short clip of about 1 second duration.

Audacity converted the audio to a raw binary file of 12 KB, which I then converted into a hexadecimal string using xxd (a linux utility to get a hexadecimal dump of a binary file).

This is the string that I copy-pasted into my arduino code to get it to play it using the PCM library. The PCM library uses two of the timers of the Arduino to create a PWM signal corresponding to the voice sample.


PWM version of PCM-quantized audio signal


PWM or Pulse Width Modulation is a technique used to encode the amplitude of an audio signal with the width of a series of pulse signals. It works by varying the width (duration) of these pulses, while keeping the frequency constant, to represent different signal levels. The duty cycle (the proportion of time the signal is high in each cycle) is altered to correspond to the signal's amplitude. The method is used for controlling the speed of motors, and in digital to analog conversion. A PWM signal (blue) for the quantized audio signal (red) is shown above.

In our case, we have to convert the PCM-encoded digital audio signal back to analog form, and we use PWM to do this.


16 MhZ crystal oscillator on the Arduino

The Arduino Uno, which is based on the ATmega328P uC, has 3 timers: two 8-bit timers and a 16-bit timers. The timers are used for time-keeping functions like delay(), millis() and micros(), which allow a program to wait for a specified period of time and also determine how much time has elapsed since the start of the program. These are implemented using a 16 MHz frequency crystal built into the board that resonates at 16 MHz frequency and is encircled in yellow in the figure above. This is the single clock source on the chip that provides timing signals for uC operations. The 3 timers are driven by this main clock and are configured to divide the main clock frequency to lower frequencies, for creating PWM signals.

The PCM library uses two of the Arduino timers; one timer is used to generate a high-frequency square wave whose duty cycle corresponds to a particular amplitude of the PCM-encoded audio channel and the other timer is used to update this duty cycle at 8 KHz, which is the sampling rate of the audio.

By using these timers and manipulating the duty cycle of the square wave, the library can recreate an approximation of the original audio signal in a form that can be converted back into sound by the speaker. 

This PWM signal is output on pin 11 of the uC and I then amplify it using a transistor and play it through the speaker.


Transistor amplification for Arduino PWM sound signal

The speaker is driven using the 5V output from the Arduino. The transistor acts as a switch and amplifier for the PWM signal from the uC, connected to the base (B) of the transistor. When the Arduino outputs a high on the PWM signal on pin 11, the transistor's base-emitter junction is forward biased, allowing current to flow from the collector (C) to the emitter (E), this driving the speaker. The transistor switches on and off in response to the PWM signal, modulating the power delivered to the speaker, and resulting in the amplitude of the sound from the speaker to match to the width (duty cycle) of the pulses of the PWM signal. This allows the low-power signal from the Arduino to control a higher power load of the speaker. I used a BC337-25 transistor (BC 337 datasheet) for this.

Audio test

I connected it up using a breadboard and was able to hear "Merry Christmas" played on the speaker, corresponding to the voice I had digitally encoded earlier!

However, despite the amplification using the transistor, I had to further amplify the sound digitally a few times to get it to a level that sounded right - and I wrote a small python program to do this.

Now for the lights!

The addressable light strip  is about a metre long and contains 144 RGB LEDs. It is based on the WS2812, and each LED element is individually addressable with 24-bit colour (8 bits each for R, G and B). You can light up any LED on the strip with any colour. I used an Arduino library for playing them in sequence, in a rainbow pattern. I connected Digital pin 6 to the digital input D0 pin of the light strip through a 330 ohm resistor (for current and noise attenuation), with 5V power and ground drawn from the Arduino.

The ultrasonic trigger

The trigger is setup by wiring the HC-SRO4 ultrasonic sensor to the Arduino. The connections are relatively straight forward, and shown here. Apart from 5V power and ground, the sensor has trigger and echo pins, which I connected to Arduino Digital pins 2 and 4. The trigger pin is held low for 2 microseconds, which sends out an 8-cycle sonic burst from the sensor, bounces off the nearest object and comes back to the receiver, connected to the echo pin. This turns the echo pin high for the duration of wave travel. This duration, multiplied by speed gives us the distance the wave traveled, which needs to be further divided by two to account for the back and forth travel.

There we have it! We now have all the components for our Christmas toy. I set the thing to trigger at a distance of 15 cm, and play the LEDs with the rainbow pattern and then say "Merry Christmas".

The final wiring is shown here:

Layout of the circuit on the breadboard

When I get the time, I will print out a PCB version of the same to make the thing more compact.


PCB design for the circuit



3D printed cases for the breadboard and Arduino

I designed and 3D-printed a case for the breadboard and the Arduino and used the snowman tin cover of a chocolate case as the front of the toy. The Arduino code is available here.

                                                               Video of the toy in action


Finally, I tried, but failed in making the snowman hand move like Maneki-neko. I experimented with a servo to do this, but as the PWM audio signal generation already takes up two of the three timers on the Arduino, this is not straight forward. The servo is also controlled using PWM. Additionally, the ultrasonic pulsing, audio signal generation and the rainbow wave light output makes each loop of the single-threaded arduino program very slow. The servo moving the hand was taking several cycles of this already slow loop to move back and forth. I shelved this plan for the current version of the toy, but will explore this further at a future date.







Comments

Popular posts from this blog

SE2 & Forward Kinematics

Unlocking Robotic Grasping: The Fusion of Perception, Mathematics and Control

Teaching Robots to Do the Dishes: A Data-Driven Approach