IoT POV Fidget Spinner

A WiFi fidget spinner, taken from concept to ordering parts in one weekend

Similar projects worth following
What do you get, when you combine an urge to distract yourself from disappointing events in your personal life with two recent Hackaday posts?
An internet connected fidget spinner! Or at least concept, planning, PCB design and ordering parts.

This addresses multiple challenges at once: How do you improve fidget spinners? How do you combine them with electronics? Can you turn them into useful IoT devices? Can you add more buzz words (most challenging - Arduino?)?

First of all, it allows you to display messages and maybe pictures on your fidget spinner. That's should already be world changing enough on its own. But wait! That's not all! You also gain the ability to compete with the spinning ability of others by comparing your stats (rpm, duration). And you even get to see how balanced your spinner is using the integrated accelerometer and possibly find out how to improve the balance (using the accelerometer is somewhere further down the priority list, though).

Unless otherwise noted, everything is GPLv3. The git repository comes with a license file.


Aluminum part

sla - 1.46 MB - 06/13/2017 at 16:11


Zip Archive - 108.25 kB - 06/13/2017 at 16:09



Schematic (CC BY-SA 4.0)

application/pdf - 127.24 kB - 06/13/2017 at 16:10


  • 32 × APA102-2020 RGB LEDs with SPI interface
  • 1 × ESP8285 (It's running this show)
  • 1 × LIS2DE Accelerometer
  • 1 × TLV4946-2K Hall effect sensor for index signal
  • 1 × MCP73831 LiPo charger

View all 13 components

  • Purple PCBs :) Also: Assembly

    Matthias06/27/2017 at 00:46 5 comments

    Today, a package with my PCBs arrived. Actually, it was two packages, because I messed up the orders (as you probably read in my previous log).

    Armed with almost all the required parts, I started assembly. First, I cut out a stencil on my vinyl cutter. While my vinyl cutter produces fairly low quality stencils which don't work reliably work with .5mm pitch QFNs, these stencils are almost free for me. So for a single PCB, that's fine.

    [I will add a video of the stencil cutting right here...]

    The finished stencil applied to a PCB:

    Next, I added some solder paste and all the parts. Placing 32 LEDs tends to be a bit tedious, but I got through it just fine. After touching it up a bi, the PCB now looks like this:

    Since I need electrical contact on the outer bearings (they will be used for charging), I used the battery contacts I described in one of the earlier logs. They fit really well and are even able to hold the bearings in place.

    Tomorrow, I plan to finally mill the back cover, upload the videos (both of stencil cutting and milling), put everything together and finally do a smoke test. Hopefully, the magic smoke will stay inside...

  • A big thanks to OSH Park

    Matthias06/15/2017 at 23:44 3 comments

    As some of you remember, I already ordered my PCBs. And I totally messed up. I didn't check which version I uploaded (although I always put the git hash in the name of gerber-zip. Shortly after my last log, Drew from OSH contacted me and upgraded everything - shipping, fast service, etc. I was very impressed by them and happy about getting the PCB really soon.

    So later today, I got the message that my board had been sent to the fab. And as I read that mail, it hit me - I had sent them the first version of the board, not the newest one. So I asked them if they could still change it, on the off chance that they could. If they couldn't I would still have a working PCB, but not with all the bells and whistles that I had added later on. Of course my assumption was correct - once the design hits the fab, it will be produced that way.

    However, after they had sent me a coupon for my first order, they sent me a new one. This time enough to cover fast shipping, and express service right from the start. This is not what I expected. I mean - I messed up, yet they are willing to make up for my mistake. They went above and beyond any expectation I had. It's seldom that you experience this kind of customer service from a company.

    Because of this, I want to express my deepest thanks to OSH Park! You guys rock! Thank you!!!

  • Hackaday, ordering parts, locking in the design

    Matthias06/14/2017 at 08:38 2 comments

    So a lot has happened since the last update. First of all, I have been featured on the main site. That probably wouldn't have been possible without all of you, who followed and liked my project. So to thank you all, I decided to step up the speed a bit:

    I already ordered all the parts so they'll be here by the weekend. For the ESP8285 and APA102-2020, this meant ordering assembled boards with the parts on them as availability of those is otherwise very bad in Germany. Sadly, I won't be here to try assemble everything, as I'm going to London from Friday to Tuesday.

    As some of you might have noted, there has been a last minute change on the design - the center hole is now sized for an 608 bearing. That way I can use 608 bearings with a greater availability for the center. Especially, when it comes to ceramic bearings and the like, they are simply cheaper.


    Thank you, followers and likers! I'm doing my best to show some results very soon.

    Quick update: I just ordered the PCB.

  • Power management

    Matthias06/13/2017 at 10:39 0 comments

    As mentioned in my last log, I wanted a way to wake the spinner up by moving it. Also, I want to be able to have the ESP8266 "completely" turn off power until the spinner is woken again. Last but not least, I wanted some kind of relatively fail safe under voltage lockout.

    My solution to these problems comes in the form of a little chip made by Silego, the SLG46140. It is a very useful little programmable chip - more or less a mixed signal PLD. I could have chosen a smaller version, but the SLG46140 is the smallest one that is also supported by open source tools, so I thought that would be nice. Even though I am currently using the Silego tools, that is the only proprietary software I use(d) while designing this project.

    So back to the fun stuff:

    What you see here is my design for this chip. As it handles all the stuff described above, here is a little breakdown:

    Most importantly, I use an analog comparator (CMP0) to make sure the battery voltage is above 3.0V. The hysteresis is configure to make sure that the voltage reaches at least 3.2V before setting UVLOn again after it dropped below 3.0V.

    Next, I use P DLY to detect falling edges coming from the hall sensor. This signal is - together with a roughly 109Hz clock - fed into CNT2. CNT2 is a counter that counts up to a value of 43, which takes about 400ms at 109Hz. When it reaches this value, it does not automatically reset, but stays there and turns the output on until it is reset. By inverting this signal, I get a signal that is high for 400ms and then turns low if the hall effect sensor does not encounter a new magnet within those 400ms.

    The LDO is controlled by the pin labeled "LDO". It is configured as a push-pull output. To control this signal, I used LUT0. This LUT is configured as UVLOn && (!CNT2 || LDO1). Therefore, if the battery voltage is above 3.0V, the LDO is on for 400ms after every turn or longer, if the CPU wants it that way.

    So here, we already have the whole wake up by spinning, go to sleep from CPU stuff solved.

    The remaining circuitry is relatively uninteresting. It only makes sure that the LED regulators can only be turned on if the LDO is on and also, that the CPU can not mess up the index signal when it is turned off. Since the CPU is running at 3.3V, while the PLD could have up to 4.2V running through it, IDX_OUT is configured as open collector and the CPU has to enable an internal pull up to 3.3V.

  • Low Power and Index sensing

    Matthias06/13/2017 at 03:16 0 comments

    After some careful consideration, I went back into KiCad and replaced the VCNT2020 by a TLV4946-2K. This means that I will use a hall effect latch instead of the optical sensor I initially planned to use. I did not plan to use this sensor as I got tired after sifting through a few pages of hall effect latches on mouser only to find them relatively huge or slow.

    The size is an issue as I want to keep a total thickness of about 8mm and I am already stuck with a 1mm wall supporting the battery. Of course, I could go a little thinner, but I would rather not. Thus, all through hole parts are instantly out of the question, while a lot of regular SMD parts are as well.

    Slow sensors are also not an option since a sensor with 50Hz or 3000rpm means I would have no room to spare. Since I would really love everything to work even with compressed air, that's not really an option either.

    These considerations initially lead me to select a very thin optical sensor and call it a day. However, there was on issue that kept me thinking: optical sensors draw quite a bit of current. That also means that my dream of using the index sensor to wake everything up would not have been possible.

    So today, I went back and sifted through a few more pages of datasheets until I found a sensor that fit my bill. At up to 15kHz it's a lot better than the ones meant for detecting a closed display. I might even be able to use multiple magnets as described by [hyperneurone] in the comments.

    I already updated the files on github and will now try to come up with a circuit that allows me to disable the LDO from software until the spinner is spun. That way I could get great standby times.

    P.S.: I already ordered the parts that take longer because they are not available at Mouser. In this case, that's the two most important parts: ESP8285 and APA102-2020.

  • Mechanical stuff

    Matthias06/11/2017 at 02:03 0 comments

    I finally got around to designing the part that will hold everything together. As you can see, there is one hole for the battery at the bottom and the outer bearing holes also have some free space for the charging contacts. They will be mounted on the bottom of the PCB and be used to get power through those bearings. This way, there is no disassembly required for charging. And given that I can only fit a 240mAh LiPo in there, it won't last very long if you use it at the highest brightness. The LEDs can draw up to 3*150mA@5V while the ESP will probably be in the 100-150mA range. So you will get less than 20 minutes at full blast. Under normal conditions, I estimate more like 1 hour of use with pictures or a few hours if you display messages inside. And even with an empty battery, you can still use it as a "dumb" spinner.

    So here is the part that keeps everything together:

    And here it is with the PCB "mounted": (I was too lazy to get everything into FreeCAD just for rendering)

  • PCB "done"

    Matthias06/10/2017 at 15:15 0 comments

    The PCB layout is finally done. There are a few things that can be improved, but I'll probably leave them for later. It's very likely that some minor fixes will be required, so the improvements can be done at the same time as those fixes. One thing I had completely forgotten was the fact, that the reverse voltage protection is not needed - it's already integrated in the charger IC.

    Since I read the email that [OSH Park] started following me while I was mostly done, I decided to make the PCB purple. I also added the jolly wrencher.

    All current files are on Github.

  • APA102

    Matthias06/09/2017 at 16:31 1 comment

    As I was just asked about the ability to hit a sufficient refresh rate with the LEDs, here are my thoughts on the matter: With WS2812 and similar ones, it would be impossible, but apparently not with the APA102. From the information I gathered, the APA102 can be controlled with a clock of at least 8MHz. With 32 LEDs, I get at least 8(Mb/s)/(32b/w)/(32+2w/l)=7353l/s. That's well below the 19.2 kHz PWM frequency, so no worries there.

    At 3000rpm (which should be close to the maximum you can reach by hand), you have 50 revolutions per second. That leaves you with at least 7353/50 = 147 lines per revolution. In other words, you get a angular resolution of about 2.5°. And that's assuming you cannot fit in more updates. For the outermost LED, we get a resolution of about 2mm. Measuring from the center, the LEDs are about 2.5mm apart.

    Looking at, they are driving the LEDs at up to 24 MHz. So at least in theory, it should be possible to have a higher resolution, even though that only makes sense if you get to higher rotational speeds. 24MHz would give you the same resolution at 9000rpm. And 2.5mm on the outermost LED should be enough, so you could - at least theoretically - get up to 11250rpm.

    There is one big caveat: I never used the APA102. For my last project involving addressable LEDs, I used the SK6812 mini LEDs. Before that were the WS6812. In a way, I am moving to smaller and smaller LEDs. But in this case, they are not only smaller, but also easier to control (I can just set the I2S of the ESP8285 to output 32 bit frames from RAM via DMA which are perfectly sized for the APA102). Compared to the way [cnlohr] developed for the WS2812, I only need 1/4 of the RAM. So assuming everything works as advertised - when does it every, though... - I should be able to have a "high" resolution at up to almost 12000rpm. That would be more than sufficient. My goal for this project is to get a "high" resolution up to at least 3000rpm.

    One more thought I had was, that I could store a higher resolution image in RAM and then skip lines depending on the speed.

    Btw: converting data from cartesian to polar will be done on the client in javascript. My requirement for this project is to get at least a single color on/off POV. RGB will be the next step (probably even after low power consumption).

  • Current Status

    Matthias06/09/2017 at 14:29 0 comments

    Now that I wrote up everything I did earlier today, here is the current status:

    As you can see, the PCB outline is already done and I placed all LEDs, the optical sensor (upper left wing), the ESP8285 and supporting parts (bottom) and the LiPo charger.

    I will now upload my current KiCad files to Github.

  • Schematic

    Matthias06/09/2017 at 14:19 1 comment

    The schematic is already done. It is attached to this project as a PDF file. You can also find it here:

    I release this schematic as CC BY-SA 4.0.

    In the top left corner, you find the LiPo circuitry. The cell can be charged by a MCP73831. This is an IC, I used previously. It works very well in cases like this.

    The 3-4.2V from the LiPo go through a TLV70033 LDO to power everything except for the LEDs. The LEDs are in two strings of 11 and (due to space restrictions) one of 10. These are each powered by a TPS60150 (at the bottom). Since this chip can only provide 140mA, the LEDs should be driven with only half the maximum brightness or less. Since there are a lot of LEDs in a small area, that should still be plenty. I don't want to blind the user!

    In the top center, you find the ESP8285. The LEDs are connected to the I2S pins, the battery voltage can be measured using a voltage divider (R11 and R12). The HSPI port is connected to the accelerometer, which you find on the top right. Last but not least, there is a VCNT2020 optical sensor. I intend to use this to get an index signal.

    This index signal will allow both the proper operation of the POV display, but also gives me the ability to measure the time per revolution. Due to this, the users will be able to compare how fast they can spin their device.

View all 12 project logs

Enjoy this project?



Matthew Sylvester wrote 06/26/2017 at 07:55 point

Quick question: are you interleaving your apa102 LEDs? I wasn't planning to, but now that I'm looking at the form factor for the pcba I can't pack in quite as many as I'd hoped despite how tiny they are. I'm considering interleaving them by offsetting their radial distances by a half pitch on the other arm (mine is planned to be a 2-arm spinner). However the actual led locations are not the center of the package so some thought might need to go into placement. 

  Are you sure? yes | no

Matthias wrote 06/26/2017 at 10:06 point

The current design has them not interleaved, so it's only 11 LEDs. However, they are offset to the side, so they should appear closer than they would in the center. Also, the center line would have given me less space for LEDs.

  Are you sure? yes | no

Maksim Surguy wrote 06/16/2017 at 19:25 point

This project really hit a nerve and it seems like we'll see only more of these popping up here and overseas. I really like how you are using 3 sides of the spinner to get higher refresh rate. Very clever!

I had an idea about a month ago to make a similar device but with only 1 row of LEDs, and hall sensor to detect rotation. Not sure if it would display as nicely: 

Not sure about using LiPos in a spinner though as these things slip out of kids hands quite a lot and can potentially catch fire from damage. I was thinking of using 2 AA batteries that also double as weights instead of bearings. 

Really curious how APA102 perform on a POV display, as I am getting more and more into those myself. Not totally related, but I am working on RGB seven segment display that could soon be made smaller with those (currently uses WS2812B): I have a supplier for APA102 2020s if you need a contact. 15 cents a piece if you buy 500 pcs.

Not to disappoint you in any way, shortly after I started creating my version of the same device, I came upon this product from Banggood:

I think the open source nature of your project and possibility of connecting spinners via WiFi (and gamification effort that follows) can give an entirely new spin on these spinners. Fidget spinners unite!

  Are you sure? yes | no

Matthias wrote 06/18/2017 at 00:00 point

Thanks for your comment!

Once the first prototype is running, I will be able to gather more data about power consumption and be able to consider other power sources.

Also, when everything works smoothly, the contact info of your supplier would probably be very helpful - There's 32 in 1 spinner, so even at 100 devices, that's 3.2k LEDs.

Regarding that banggood device, I can only say that just as you, I hope to differentiate my device enough to make up for the difference in price.

  Are you sure? yes | no

overflo wrote 06/14/2017 at 21:19 point

This is a very nice project.

Some time ago the MagicShifter 3000 launched.

It also features an ESP8266 an Accelerometer and APA102 leds.

You might be able to reuse a lot of the source code.

check out:

PS: Every time you make something, someone on the internet will tell you it makes no sense to waste your time on this, because there is some gadget in china that is basically the same thing for less bucks.
These people are wrong on multiple instances. Don't follow their advice.
Do what you love! Stay awesome.

  Are you sure? yes | no

Matthias wrote 06/15/2017 at 07:49 point

Thanks for the hint. I'll have a look at their code. Although from a first glance, they seem to have the LEDs connected to the SPI and the accelerometer to the I2C interface, while I am using I2S for the LEDs and SPI for the accelerometer. But that's just the interface layer, so there is probably still some useful code.

Yeah, I already had my fair share of those (not so much on this project), but I learned to just push through and do what makes me happy. Your advice is exactly the same I would give to anyone else. Thank you!

  Are you sure? yes | no


[this comment has been deleted]

Matthias wrote 06/13/2017 at 07:00 point

The three blades allow for a good picture at slow rates. So if your chinese POV spinner stops to work properly at x rpm, this spinner should be able to show a good picture at x/3 rpm. Since all the lines are stored in an array, it's a simple matter of having three pointers to a single array, spaced 1/3 of the length apart.

Since the curved line is the same on all three blades, It can be accounted for in the software that produces the lines. As I described in one of my earlier logs, this will be done on the client, so it absolutely doesn't make much of a difference.

Regarding your remark about the Chinese POV spinners: I didn't find them before, but now tried to search for them in a more "Chinese-friendly" way: "LED message fidget spinner". That was close enough to "LED Message Hand Spinner". From what I can tell, those come with one or more pre-programmed pattern(s) or messages (depending on the model). On this one, you can display arbitrary data and update it while the thing is spinning. So I think it's not a fair comparison.

  Are you sure? yes | no

Youlian Troyanov wrote 06/14/2017 at 06:49 point

plz share a link to that chinese product

  Are you sure? yes | no

Richard Hogben wrote 06/13/2017 at 00:45 point


  Are you sure? yes | no

Matthias wrote 06/13/2017 at 01:55 point

I know. I don't know how we could live without it, but I'm here to fix that. It will absolutely be the best thing since sliced bread 

  Are you sure? yes | no

Matthew Sylvester wrote 06/11/2017 at 19:10 point

I've actually been planning  a similar project for awhile now! interested to see how yours comes out. How are you planning to sync the display each revolution? the accelerometer wont give you that, is there a pulse per revolution to allow things to sync up each cycle? I'm planning to use a neat hall effect based solution I found that offers even better resolution.
EDIT: I see theres an optical sensor for that. I'm planning to include the same accelerometer as well, maybe for "shake to wake" or for some sort of user interaction. not sure yet.

  Are you sure? yes | no

Matthias wrote 06/11/2017 at 19:13 point

Copied this from my reply to Werner below ;)

My index signal comes from an optical sensor, as described in my second log:

My next log will probably be about this as it is a fairly frequent question.

Edit: Damn Ninja edit. I can play that game as well ;) Yup. Things like that are why I added it.

  Are you sure? yes | no

Matthew Sylvester wrote 06/11/2017 at 19:22 point

Anyway, cool project, looks like great minds think alike ;)

I should post mine up here as well, you're considerably further along than me!

  Are you sure? yes | no

Matthias wrote 06/11/2017 at 19:15 point

How far along are you with your project? What are the chips you want to use? We might be able to collaborate.

  Are you sure? yes | no

Matthew Sylvester wrote 06/11/2017 at 19:28 point

planning to use allegro 1262 with some small magnets for full quadrature output. Already tested this with eitght magnets just as a proof of concept, works great. and originally planned to use SAM D 21 cortex m0+ with separate bluetooth LE module but am thinking more along the lines of an NRF52832 module containing a cortex M4F and bluetooth all-in-one. especially since it has a built in quadrature accumulator. Plus its much faster at dual core 240MHZ, and sleep current of only 1.2uA, and a built in RTCC for use as a spinner pocketwatch!  FastLED doesn't support it quite yet but is planned to in the near future. Just using the SPI interface on the chip ought to be enough to get things working though I think. 

  Are you sure? yes | no

Boris van Galvin wrote 06/11/2017 at 02:57 point

I got a little board at work a couple of weeks back and after machining some nice ALU batman spinners decided to see how cast i could crank it up :)

May have to try it out on one of these ones as well :)

  Are you sure? yes | no

Matthias wrote 06/11/2017 at 03:32 point

That's definitely an impressive speed! Most likely, the POV won't work properly at that speed, but once the software gets to that stage it can still be used as RPM counter.

Regardless, a maximum speed test will be done, once I have received all the parts! I'll have to see how fast ~10bar will get me :)

  Are you sure? yes | no

werner wrote 06/10/2017 at 16:56 point

Nice job! - But I'm worried about using an accelerometer for this use case. Two issues that speak against this:

- if you hold the spinner exactly horizontally, all three accelerometer axis will give you a constant output. Only if you tilt the spinner, you'll see the sine wave in the output data that tells you about the absolute position of the spinner legs.

- the position of the sensors is not exactly in the center of the spinner but slightly offset. This will give you a hign centrifugal acceleration which may max out the sensors range. E.g. if the sensor is located 10 mm from the center and spinning at 3900 RPM, you'll already reach ~16G from the centrifugal acceleration.

So I think the more appropriate sensor for this would we a gyro sensor. It will not give you the "absolute" position but the speed of rotation and has issues like zero-level drift but I think those are easier to manage than the problems resulting from using an accelerometer. 

Having said all of this - I still believe it's possible to get some good results with an accelerometer also.

  Are you sure? yes | no

Matthias wrote 06/11/2017 at 01:47 point

Hi Werner,


I'm totally aware of all those limitations. The accelerometer is only meant for "nice to have" features. I will probably not use it in the beginning.

When I use it, it will be for stuff like finding the floor with a tilted spinner and hopefully to measure vibrations. All those are non-essential functions, though.

My index signal comes from an optical sensor, as described in my second log:

  Are you sure? yes | no

K.C. Lee wrote 06/09/2017 at 21:00 point

PCB is a bit too thin for mounting the bearings.  Might also want to think about the weight distribution and how to tune the balance so that it would spin smoothly.

  Are you sure? yes | no

Matthias wrote 06/09/2017 at 21:43 point

Yeah. I should have made that clear in my project logs. My plan is to have a aluminum "case" on the back of the PCB and a frosted part on the front. The aluminum is for the structure, the PCB only for electronics. That's also why the holes on the PCB are a bit bigger than what's needed for the bearing. Additionally, the battery will have a hole machined in the back part to be properly seated. It would be rather complicated to mount it on the back of the PCB and still balance everything.

Regarding balance: that's what I want to figure out with the accelerometer. I want to know if this can help with fine tuning. Rough tuning can be done by resting the center bearing on a rod supported by two pillars on opposite ends.

TL;DR: I don't intend to use the PCB as mechanical part. My posts didn't touch that subject yet and the picture is misleading.

  Are you sure? yes | no

K.C. Lee wrote 06/10/2017 at 01:52 point

A rotator is balanced by supporting shaft horizontally to see if one side is heavier than the other.  It is well balanced if it rests in any position.  Holes are then drilled for fine adjustments.

I would assume that this trick would work for the spinner.  Holes could be hidden by drilling on the aluminium side facing the PCB.

  Are you sure? yes | no

Jon Thomasson wrote 06/09/2017 at 19:37 point

Cool project! Neat idea to make it internet connected. I recently had a similar idea, although my version is with the 2 sided fidget spinner and the AtTiny85 micro:

  Are you sure? yes | no

benkokes wrote 06/09/2017 at 16:57 point

Lookin' good.. Its definitely possible. As for if its been done yet, yes!

  Are you sure? yes | no

Matthias wrote 06/09/2017 at 19:48 point

That's awesome! Which parts did you use? What features did you implement? Do you have a photo with long exposure?

  Are you sure? yes | no

zakqwy wrote 06/09/2017 at 14:54 point

Ah yes, the bane of high school teachers everywhere. Glad to see a POV fidget spinner project here -- I've been mulling a design over for a bit but currently lack the time. Are you confident you'll be able to hit the needed LED refresh rate using APA102s? I figured addressable LEDs wouldn't be up to the task.

Cool project!

  Are you sure? yes | no

Matthias wrote 06/09/2017 at 16:14 point


I'd say I'm about 90% confident. I just wrote a fairly lengthy response. It was long enough that I decided to put it into a project log instead ;) That one should go up in a few minutes.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates