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.
|
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 quantization |
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.
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 |
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 |
Comments
Post a Comment