Challenge... Accepted!!
When the good people at element14 gave us the challenge of building a present that "shows the most heart", we said: "Challenge... Accepted!!". We said it with so much gusto, that it's hard to describe in simple text, which is why I used bold AND italics at the same time. And we paused in the middle for extra dramatic effect. Make sure you do that too when reading it.
And, because we take things much too literally, we decided to make this project in the shape of a heart, because... what shows more heart than a heart?
We decided it should also be a kind-hearted, feel-good type of project, so we added sounds to really make a person feel good - in fact, we included over 2 dozen compliments in this project!
Say Hello to our little friend
Without further ado then, please welcome... Lolly the LoveBot!
I was once again blessed to have my dear wife SuperArtGirl help out with the design and implementation of the artistic parts of the project, or you'd be staring at a plain box here.
She is also the voice artist for all the sound bites.
Here is a video of Lolly the LoveBot in action.
The Build
For this project, we decided it would be fun to have a cute, fun little creature that gives people compliments as they walk by. Making it fuzzy was just a bonus side-effect of the appropriately coloured fluffy-fuzz material we happened to have in one of the many art-stuff drawers. On an entirely unrelated side note, I'd like to point out that there are far more art-stuff drawers than electronics-stuff drawers in this house.
The enclosure
The enclosure was designed to look like a cute heart, with a box in the centre to house the electronics. I drilled holes for the speaker and the motion sensor, and we left the back open for easy access. There's a little hole at the bottom for the power cord.
We used a little paper/cardboard type box and added heart shapes at the front and back that we cut out of hardboard we bought at the dollar store. To fill the gaps on the rounded sides, the more art-capable part of this duo used crumpled aluminum foil hot-glued into place. The whole thing was then covered with the afore-mentioned fun furry material.
The electronics
For the electronics, I used an Arduino Uno to trigger sounds from a sound module, using a motion sensor to start a random sound bite. We had considered adding a button, but the motion sensor is reliable enough to work on its own. We also considered adding extra lights, but also decided to leave that out of the build as it would be hard to see through the furry material we used to cover it.
In the Arduino code you will notice that I left the code for the button and the lights in place, so those features could be added without having to re-flash the Arduino.
The motion sensor I used for this project is behaving much better than the other smaller units I've tried in the past - keep in mind that continued motion is ignored, and it also takes a moment for it to get settled when starting up, so you'll see a bit of a delay after the first intro sound bite is played while I try to trigger the motion. In general I'm happy with how it's working.
I do wish I was able to hide the motion sensor a little better, but the fur gets in the way so I had to leave it exposed up top.
I used a sound module with built-in memory for this project, which gives plenty of space for this project, but it does mean it needs to be plugged in like a USB drive in order to update files, instead of just using a standard SD card. That does save the cost of the extra SD card too. The sound module has all the smarts to easily play a sound file and amplify the output for a little speaker.
The speaker is something I've had in my parts bin for quite a few years already. I think it came out of an old computer. This one even has the long wires with the plug at the end so it was extra easy to connect to the sound module!
The electronics parts list:
* Arduino Uno
* HC-SR501 PIR motion sensor
* DY-SV17F sound module
* Speaker from an old computer - or possible from a greeting card, old radio, or whatnot. They are probably also cheap and plentiful enough to just purchase.
* Enclosure - really anything you can craft together, as long as it has space for the electronics.
And of course, there's the usual bits of wire, solder, and headers that bring it all together. I also used a breadboard for testing during the circuit development.
Let there be sound...
The first step for me was to check that I could get the sound module working.
A few different but similar sound modules are easily and inexpensively available. For a previous project I used one that takes an SD card, which is very easy to pop out and re-load with new sounds. I bought this particular model of sound module because it actually includes 4MB of memory on the board itself, saving having to dedicate an SD card for the project. I've been upgrading the storage on my Raspberry Pi machines and using the hand-me-downs for this kind of thing, but the space of even an older SD card is ridiculously overkill for a project like this.
As it turns out, the 28 sound bites easily fit within the 4MB of the module. In fact, it only uses about 1/3 of the available space!
To put files onto the sound module, it works like a USB drive - just plug it in using a micro-USB cord and then drag the sound files onto it (I'm on a Mac. Your experience might be more exciting). Note that it expects the sound files to be named 00001.mp3, 00002.mp3 etc, so you can later access them by number to play them. This is what my sound module drive file list looks like:
There are a few ways of triggering the sounds, but for the number of sounds we wanted to include, the serial communication option was the best way. It also requires the least amount of wiring, and no extra parts are needed this way.
I used a library built by Chris Snijder to make the serial communications with the board much easier. You can find it in GitHub: https://github.com/SnijderC/dyplayer
To install the library into your Arduino IDE, download it as a zip file, unzip it, then (for Arduino IDE 1.8 on Mac at least), choose Sketch - Include Library - Add ZIP library, and then choose the dyplayer folder.
Note: I ran into a bug in the dyplayer library that mis-interprets the sound file numbering - they are all seen as odd numbers. To get around that I added a little conversion into the code so that all files can be played. I've added extra comments into the code to describe it. If you're following this build to create your own, you may want to double check that this issue still exists, or if it's even an issue with a different Arduino IDE build. Using the Software Serial example included with that library I was able to spot the numbering issue after having spent a fair bit of time wondering why so many sounds were missing!
You might notice that in these earlier pictures I have connected the sound module via the Uno's standard serial port. This works well, but it meant I had to disconnect the 2 serial wires every time I wanted to upload a new sketch. It also meant that the debug serial console in the Arduino IDE was not available.
That's why I later switched to using Software Serial, for easier sketch updates, and also so that I could debug that odd dyplayer numbering bug. I strongly recommend keeping that built-in serial port free if at all possible - it could save you a lot of trouble later!
Detecting Motion...
After the sound module was working reliably, I added the motion sensor.
That part was fairly easy, as it functions in almost the same way as a button (without the need for a pull-up/down resistor). There are also plenty of examples that use this exact motion sensor with Arduino, making it easy to figure out where the wires go and how to write the code for it.
I then tested it with some placeholder bird sounds.
Note the little portable power supply that looks kind of like a multimeter - that was a gift from element14, and it is SO super useful! In this setup I used the USB power output, limited to something like one Amp just in case I messed something up. And I did - I originally plugged the incoming GND and 5V into the side by side GND and GND spots on the Arduino, shorting them out. The Arduino's 5V was one spot over. Sigh. But hey, that little unit handled it well and nothing blew up! Yay!
Powering the Project...
For a project like this, people would get all weird and judgy if you were to plug the final build into your laptop to power it. And even judgier if you used a big old tower computer. So I had to find a better, and more convenient way. Let's be honest here - people are going to be judgy either way, so that doesn't bother me, but I'm too lazy to pack that old laptop around all the time. That gets tiring. Judge me if you wish.
USB chargers are easily and cheaply acquired almost anywhere you look now, including at dollar stores and even at the grocery store, so I went with the easy option there. This project doesn't draw much power, so a special adapter is just too much effort and cost in this case. To power the Arduino I decided to use a USB charger connected to the Arduino's 5V and GND pins, rather than using the large USB plug the Uno has, as those cables tend to be bulky - and also seem to be harder to get now.
I was able to use a USB power cable with a plug end, and the matching socket, from a Christmas tree kit I bought a while back (the kit can run on batteries so I don't need it there). This has a much smaller plug and cable, and looks a lot better. In a pinch, I could also have just cut the end off a usb cable (also cheap and plentiful everywhere you look), and wired that onto the board. Now that I think about it, that would probably have been just as good, and easier to do, assuming the conductors in the cable are thick enough to solder onto. I'm too lazy to change that now.
One thing that I've always found a bit annoying with these kinds of dev boards is that there are very few power pins available to connect to external fun things. The Arduino Uno I'm using only has the one 5v power pin, and 3 GND pins. So I had to fashion up a fashionable solution to my little situation. One that didn't involve adding a tiny breadboard. I did that for prototyping, but it's uncool to be doing that for a finished project. Unless you then also add some flowers or something shiny onto that breadboard. That might make it ok.
This is how I tackled it: a 1-to-3 power splitter. I used a bit of female header (the type with the extra long pins, bent together, because easier that way) soldered onto a breadboard wire. I made it pretty by giving it some red fingernail polish (yes, Dollar Store for the win again!)
The single pin goes to the Arduino 5v IO pin, and then the Sound Module and Motion Sensor plug into 2 of the 3 female header spots. The 3rd spot is to provide the source power.
I soldered up a similar one to split a GND pin out to 2 spots, although I could've gotten away without it in this case. Ok fine, I admit it - I didn't realize until later that I actually needed 3 spots for the 5v pin and I had created a 1-to-2 splitter to begin with. So I slapped on some black Dollar Store nail polish and called it a GND splitter instead.
Putting it all together...
After getting all the electronics figured out, I loaded up the proper sound files onto the sound module, and removed a bit of test code (that was playing all of the sounds) from the Uno, did a final round of testing, and then I was ready to install it into the enclosure to complete Lolly the LoveBot.
I always test things at various stages like this, to make it easier to fix any issues. Once it's all mounted inside the enclosure it will be a lot harder to make changes!
When mounting the pieces into the enclosure, I made sure to leave enough space to connect a cable to the Arduino Uno in case I need to update the firmware, and I added some spacer foam under the sound board in case I need to upload new files.
I used hot glue to mount everything into the box - just a few drops are enough for a secure hold, and it can easily be peeled off later if things need to be changed.
In the middle picture the motion sensor and its wires are outside of the case, but (after more testing) I routed those through the hole in the top. I had originally hoped to just have it mounted into the top hole of the enclosure box, but that would obscure the sensor too much.
I then tested the assembled setup with the portable power supply. Not shown in the picture, but according to that little power supply, it draws around 70 or 80 milliamps
The Arduino source code is as follows (I'm pretty sure it's also attached to this blog)
#include <Arduino.h> #include "DYPlayerArduino.h" #include <SoftwareSerial.h> // Initialise on software serial port. SoftwareSerial SoftSerial(10, 11); // order is rx, tx => rx = 10, tx = 11 // Initialise the player, it defaults to using Serial, but that means uploading requires wires to be disconnected, and console debug is not available. // Using SoftwareSerial makes things easier for this project (it uses more resources, but that's not important here) DY::Player player(&SoftSerial); #define SOUND_OFF LOW #define SOUND_ON HIGH // The button and lights are optional - this project will function without them. // If you choose to use the button without the motion sensor, you'll need to connect pin 3 to LOW (GND) // For this complimenting heart project, I only use the motion sensor. #define BUTTON 4 // add a button to trigger a sound bite #define MOTION_SENSOR 3 // add a motion sensor to trigger a sound bite #define LIGHTS 13 // This is the built-in LED for the Arduino Uno. Add additional LEDs to pin 13. (use a transistor if there are a lot of them) // on the soundboard (memory or SD card), files must be numbered 00001.mp3, 00002.mp3, etc. in order, up to the count defined on the next line. #define SOUND_BITES_COUNT 27 // adjust to match the number of sound files on the sound board, not counting the intro sound #define INTRO_SOUND 28 // place the intro sound at the end int prevMotionRead = HIGH; void setup() { pinMode(BUTTON, INPUT_PULLUP); // uses internal pull-up resistor to allow a button to be wired directly (connected to GND) without needing an extra resistor. pinMode(MOTION_SENSOR, INPUT); pinMode(LIGHTS, OUTPUT); randomSeed(analogRead(0)); // uses random noise on A0 to help the random() function be more truly random player.begin(); player.setVolume(30); // choose 0-30, 0 is lowest, 30 is highest, 15 = 50% Volume lightsOn(); delay(1000); lightsOff(); // playAllSounds(); // for testing to make sure all sound bites work lightsOn(); playSoundNumber(INTRO_SOUND); // play the introduction sound on startup lightsOff(); } void loop() { int buttonRead = digitalRead(BUTTON); // No need to use debounce because the sound will take long enough to cover it if (buttonRead == LOW) { playComplimentSound(); } int motionRead = digitalRead(MOTION_SENSOR); // only trigger if motion has changed from motion to no-motion or vice-versa, and if motion was sensed. // ie, don't trigger on motion stopping, and don't repeatedly trigger if motion persists longer than the sound being played. // If you want the compliments to continue as long as there is motion, just remove the "if" parts if (motionRead != prevMotionRead) { prevMotionRead = motionRead; if (motionRead == HIGH) { playComplimentSound(); } } delay(200); } void lightsOn() { digitalWrite(LIGHTS, HIGH); } void lightsOff() { digitalWrite(LIGHTS, LOW); } void playComplimentSound() { lightsOn(); playSoundNumber(random(SOUND_BITES_COUNT)); delay(1000); lightsOff(); } void playAllSounds() { for (int i=1; i < SOUND_BITES_COUNT+1; i++) { playSoundNumber(i); } } void playSoundNumber(int soundNumber) { // There is a bug in DYPlayer that interprets files named sequentually 00001, 00002, 00003, 00004, etc as odd file numbers 1, 3, 5, 7, etc // Need to convert it here to match what DYPlayer expects. // For future reference: DYPlayer comes with a sample named "Software Serial", which will print out the sound file numbers as DYPlayer sees them. int convertedSoundNumber = (soundNumber-1) * 2 + 1; player.playSpecified(convertedSoundNumber); // don't do anything else until this sound bite finishes playing. // Note that any extremely long sound file will keep playing until it is finished. // You could add something within the while loop to check for a button press, if desired. // For this complimenting heart project, all sound bites are under 3 seconds. while(player.checkPlayState() == DY::PlayState::Playing) { delay(300); } delay(300); }
The wiring is pretty straight forward:
We hope this fun little project has made your day a little brighter!
May your days be full of love and loving compliments!
-Nico and SuperArtGirl
Top Comments