Introduction: Spell Out Affection for Your Valentine With Chocolates, LEDs, Attiny13 and Arduino IDE

About: Just a guy tinkering away in a lab ...
Well, sure, you could have put a post-it note with the same message inside that chocolate box :)  but it won't be nearly as cool, especially if your Valentine has a sweet spot for nerds. Come to think of it: of course she does, otherwise what is she doing still hanging out with you?

If you are still reading this, I have to assume that the matter of "why-oh-why?!" has already been settled and you have decided to go a slightly harder but much cooler way of delivering the message: you will build a POV (Persistence Of Vision) display  inside that chocolate box which will spell “I HEART U”  when shaken (not stirred!).

I would estimate start-to-finish time when you have all the parts ready to be about 1.5-2 hours.

Here are the parts you will need:
  1. A box of chocolates with a transparent cover. I used the 2012 vintage Ferrero Rocher chocolate box. They failed me in 2013 - their Valentine's Day gift boxes were neither plastic nor did they have a transparent cover this year
  2. Atmel ATtiny13 MCU
  3. 6 x red LEDs
  4. 1 x tilt switch (a.k.a. ball switch, a.k.a. shake sensor)
  5. 1 x 14-pin IC socket
  6. 3 x 22 Ohm resistors
  7. 1 x 470K Ohm resistor
  8. CR2032 or similar 3V battery
  9. a holder for the above mentioned battery
  10. about 3' of thin red hookup wire (30AWG is perfect size)



Please see the image with parts that I marked up below and I also have a more extensive explanation of the parts that have been chosen for the project on the POV display post on my blog

Step 1: How Does This Work?


POV displays use the LEDs uncanny ability to go from OFF to full brightness in a matter of microseconds (try that, incandescent bulb!) coupled to the human beings' pathetic slowness in reacting to the world changing around us. Visual events happening within approximately 1/30th to 1/20th of a second (33 ms - 50 ms) from one another are all jumbled together in our slow brains and we "see" (i.e. perceive) them as one. So, next time someone says: " it's all a big blur to me",  don't ridicule them. It's exactly how you waddle through your life, too, even on the clearest of days!

So, the big goal is to light the LEDs 102 times in a  very particular sequence while your hand moves the chocolate box and provides the so called mechanical scanning of the columns of the dots that the image is comprised of. Why 102? I decided to base the design on the smallest and cheapest of the Atmel AVR microcontrollers - ATtiny13 and the amount of program storage is already pushing the memory limits of the little chip. After some experimentation I have settled on the pattern that involves 17 columns of 6 dots  (LED flashes) - hence 17x6=102 individual flashes that have to be completed in 50ms. This is the very basic calculation which you start any POV display project with: how many events you can "jam" into the time window of one smallest human timeframe - 50ms.

Unlike many (most?) POV displays you've come across, our little POV display has another limitation because ATtiny13 has only 5 input/output lines (well, OK, it does have 6 but the last one is used as Reset and if we take is as an I/O, we won't be able to re-write the program without a high-voltage programmer).  Since we cannot have one LED per one output and light all 6 LEDs that make one column at once, we need to scan LEDs over time, i.e. light them one by one but still so quickly that all 102 flashes fit within the mandatory 50ms timeframe. This is why  timing becomes very critical in this project and it's very important to use the brightest red LEDs you can find - certainly go for 5000mcd+ brightness - because each LED only has 1/102 of the frame time to shine and still register in your brain.

There's also another feature of this project that made it particularly interesting to me. Again, unlike most POV displays out there,  mechanical scanning for this Valentine's POV display is severely limited by our limbs' construction ( humans are just NOT very well suited to interface with electronics, I tell ya!). Since we don't have joints that rotate 360º (wouldn't that be something!), all we can muster is a reciprocal movement back and forth, However, the message we are trying to write should be read only left-to-right. In other words, the message should be only shown on the movement of your (or your Valentine's) hand from left to right and not  on the way back. I guess, "U HEART I" is also kinda sweet but not grammatically correct.

By the way, I keep spelling HEART as a word but I'm sure you understand I actually mean the symbol in the shape of a stylized heart which is possible to show on the screen of your browser but Instructables' editor is preventing me from using HTML characters, such as ❤ which is what I actually need to show the heart symbol. I am telling you this because, unlike the word "HEART"  the actual heart symbol is symmetrical on its vertical axis and it would look OK as a mirror image, and so would the letters "I" and "U". However, I was thinking of using this display for other messages, too, such as "I HEART NYC" for example and in that case it would have been even more important to eliminate mirroring of the message on the way back.

Ball tilt switch to the rescue! This cheap and simple little device has a dual use in this project.  We use it to wake the ATtiny13 from the battery-saving sleep and we also position it just the right way so that it closes contact every time your hand starts decelerating from the way back (right-to-left) and into accelerating on the way forward (left-to-right)


OK, I think it's just about enough theory for a simple project like that.

Step 2: Building It - LEDs

If ATtiny13 is the heart of the project, then the LEDs must be its face. I don't know about other holidays but on a Valentine's Day the right presentation is 75% of success, so I would advise to start with LEDs.

For POV displays it is very important that all the dots (i.e. LED flashes) look the same to your eye - same brightness, shape and size as well as distance between them. Big differences with either of those parameters will ruin the effect and that's not something you want on a day like this!

Our goal is to conceal the LEDs inside the chocolate box by locating them underneath the plastic insert which the individual chocolates are put into, and that presents a particular challenge. First of all, the LEDs have to shine through the insert and they will lose part of their brightness because of that. Second, they are projecting their light onto the back of the insert and the further from the surface of the insert they are, the larger the light spot and the dimmer it will become.   

I decided to make a separate PCB just for the LEDs (the rest of the circuit is built free-hand around a 14-in IC socket) to better control the depth at which each LED is positioned as well as the distance between the LEDs themselves.

Start by finding a spot in the box where you can have approx 2.5" of linear space that's deep enough to receive the LEDs and the board. Depending on the actual design of the box, it may not be that easy! I only found two such places in the box I used, both towards the top portion of the box. Then measure the contour of the peaks and valleys in the plastic insert using either the contour gauge tool (see pic below) or if you don't have one (I didn't) use just a number of thin sticks held between two planks. The tool is much easier, trust me, so next time you're at your favorite tool store, pick one up, will save a lot of aggravation.

Transfer the contour onto a piece of paper and form the leads of LEDs using the PCB, which I cut from a larger perforated breadboard, as a guide. I started by laying the board flat and LEDs on their sides while soldering. In retrospect, it would probably be a little easier to solder the LEDs standing up, like they should be in the finished state (second photo) .

The PCB makes is easier to position the current limiting 22 Ohm resistors, so use the remaining holes on the board to solder them in and wire the LEDs to the resistors and between themselves according to the schematics diagram on the previous page.

Step 3: Building It - Wire ATtiny13 MCU, Shake Sensor and Battery

The rest of the circuit is built around the 14-pin IC socket which makes for a very convenient carrier for the ATtiny13 MCU as well as the rest of the components. It will be a little easier to see the positioning of the ball tilt switch on the photo on the next step page but suffice is to say here that I've soldered it standing straight up in the MCU socket in the unused two contacts on one side of the socket. Although sockets are not designed to be soldered from the top, with good amount of flux they solder just fine.

Other than the ball tilt switch, the only other component soldered to the circuit is the 470K Ohm pull-up resistor, so there's space for everything and it's not even all that crammed.

Be careful with polarity of the battery wires. This is why I used color different from the rest of the red wires in this project - the blue wire here signifies connection to the negative terminal of the battery. The battery holder I used has negative and positive sides clearly marked, so follow that through to the IC socket - reversing polarity would be pretty bad.

Do not solder the MCU in - we need to program it first! Until you insert the programmed  Attiny13 into the circuit, do not insert the battery into its holder either.

Step 4: Building It - Program the ATtiny13 MCU and Give It a Test Run.

I have used Arduino IDE for the software development in this project - my IDE of choice when it comes to MCU programming in C. Since programming an ATtiny13 microcontroller, which is not covered by Arduino IDE by default but can be relatively easily added to the list of MCUs it works with, may be considered an instructable in its own right (and indeed, I have seen a few separate instructables on the subject) I would like to refer you to a post I wrote some time ago on the subject: How to use ATtiny13 with Arduino IDE please check it and a related forum thread   on the finer details of setting up the Arduino IDE for programming smaller chips, such as ATtiny13.

Without blowing this particular intructable out of proportions, suffice it to say that you won't need any non-free software and, other than an Arduino board, you won't need much extra hardware either - some wires and perhaps an extra 8-pin IC socket or just simply a solderless breadboard to mount the  ATtiny13 you are programming. The end goal is to make sure ATtiny13 is one of the boards that come up in Arduino IDE when you open Tools->Board (see picture below) before compiling the sketch with the program (see ZIP file below). Then you upload the compiled binary  to ATtiny using either an Arduino board as a programmer or a specialized AVR programmer if you have one.

I have tried to mark up the Arduino sketch with as much commentary as possible for your editing pleasure :) The actual message is recorder in this  part of the code:

PROGMEM byte column[17]   = {

  33,    // --X----X // 0
  63,    // --XXXXXX // 1
  33,    // --X----X // 2
  0,     // -------- // 3
  24,    // ---XX--- // 4
  60,    // --XXXX-- // 5
  30,    // ---XXXX- // 6
  15,    // ----XXXX // 7
  30,    // ---XXXX- // 8
  60,    // --XXXX-- // 9
  24,    // ---XX--- // 10
  0,     // -------- // 11
  62,    // --XXXXX- // 12
  1,     // -------X // 13
  1,     // -------X // 14
  62,    // --XXXXX- // 15
  0      // -------- // 16

};

Unfortunately, I'm not sure how to save the proper formatting in Instructables page editing tool, but if you were looking at the piece of code using a monospace font, you would immediately recognize the shape of the symbols in the commented out parts of the lines. The actual column is encoded with integer representation of the binary version to the right where "-" is actually "0" and "X" is "1". I hope it makes sense and you won't have much difficulty changing "I HEART U" to "I HEART BEER" for the upcoming St. Patty's festivities. Enjoy responsibly and be sure to increase the amount of scanned columns since "BEER" is quite a bit longer than "U", obviously :)

Anyway, I hope you pardon my chickening out of creating an instructable within the instructable on setting up the Arduino IDE and refer to the blog post instead and at this point in time you have burned the software into the ATtiny13 chip.

Insert the ATtiny13 into the IC socket you've prepared on the previous step, then insert the battery and shake the socket several times to close the ball tilt switch. The LEDs will start flashing in some sort of random fashion which of course is only random until you start moving the LEDs in space thus providing the mechanical scanning of the columns.

A small note on troubleshooting which may be required at this stage: while developing this project, I did have a couple of wiring mishaps. Charlieplexing is usually associated with complicated wiring and things can get switched around accidentally. I have written a small sketch (which I cannot find right now, incidentally) which was lighting the LEDs not in the pseudo-random
but in very orderly fashion from 1 to 6 and back, just to see that I got the sequence of LEDs right. It simply modified the same part of code you would modify for changing the message and used 1,2,4,8,16 and 32 for the codes of the LED patten to light just one LED per column. If it does not make sense while reading this, write these integers in binary form and you'll see right away. "0" - LED OFF, "1" - LED ON.

Step 5: Building It -position Parts in Place and Glue Them In

This is the part where it all comes together!

I hope the picture below is pretty much self-explanatory but basically all you need to do is to flip the plastic insert upside down, position the LED strip into the valley that you've taken the contour of earlier so each LED ends up touching the plastic of the insert. Then place each of the two remaining separate modules that comprise the full circuit - the battery holder with the battery and the IC socket with MCU - into any crevice that's large enough to receive them.

Then use low temperature glue stick gun to glue the parts in their places. Low temp so as to not melt the plastic underneath. I would advise for obvious reasons to be careful with not gluing shut the battery (in case you need to change it even though it will last several months) and also leaving the MCUfree to come out of the socket just in case you need to re-deploy it in the future. As for the rest of parts, use as much glue as your heart desires heaping in mind of course that the insert has to go into the box which will have to close when you're done - so no very large lumps of glue please :) 

A special important note on positioning the tilt ball switch.

The battery life of this circuit very much depends on the MCU going to sleep after it no longer senses any movement for longer than 5 seconds. For that the ball switch should stop changing its ON/OFF status. In other words, the ball has to come to rest. This will happen regardless of which position it stopped in - ON or OFF but consider that if it stopped in the ON position, there's current flowing from the positive 3V terminal to the negative terminal via the 470K Ohm current limiting resistor. It's a meager 6.3 µA of course but keep in mind that it's unnecessarily wasted and the MCU itself draws even less - 2µA  . In other words, in the interest of prolonging battery life you want the ball to stop in the OFF position - i.e. the ball has to roll down into the top of the cylinder, away from the switch'es leads. It may be a little hard to see on the picture but the switch is facing slightly up, and of course, when we flip the insert right side up, it will face down - that's what we need to keep it always in OFF when not in use (and laying on the flat leveled surface).

Yet another note on the ball switch position - the ball flies back and forth when you shake the box, so it has to be positioned so that it goes into ON position when you swing to the right. So, it's rather important that it faces to the left when the insert is upside down (as on the picture) . If you modify the  design and your parts are facing a different way, don't forget to also change the position of the sensor.

Step 6: Using It.

Well, I seriously considered skipping this step because there are probably  not too many electronic devices easier to use than this - just take the box in your hand and start shaking it back and forth making sure the box moves at least a foot in each direction. But one observation of note for the future users - the software tries to time the beginning of each cycle of showing the message to 1/8th of the duration of one swing. Perhaps I horribly over-engineered it, but this looked like the easiest way to center the message in relation to the size of the swing.  Trust me, it will be easier to understand once you start swinging it ! :) There could be (several) better ways of doing this but I literally ran out of programming space in ATtiny13 - it can only hold 1024 bytes and I used something like 1006. As a result, the message starts showing in the right place only after 3-4 swings (during which time it gathers time data to come up with the proper average).

So, yes, there's more to it that meets the eye (pun totally intended) and I would be glad to see brilliant inventive minds of instructables users take the concept of the oscillating POV display and take is further, both in terms of programming and hardware.

And a parting thought for today: if you are interested in the oscillating POV display concept but don't want to mess with all the wiring, I created a PCB (some SMT soldering will be needed) and BatchPCB had already sent me a couple. If you're interested, let me know or check my blog here , I'll post updates on the status of the PCB.

Thanks for sticking with me to the end of this Instructables, I hope your Valentine will appreciate all your efforts!

Valentine's Day Contest

Second Prize in the
Valentine's Day Contest

UP! Contest

Participated in the
UP! Contest