I've wanted to make a “globe POV” for a while after seeing a totally amazing hi-res one on YouTube a while back. The mechanical side of it (motor drive and power supply) always put me off a bit – while I think I can design a PCB and feel pretty confident it's going to work, motors, gears and bearings are still a matter of kludge and guesswork for me.
I decided to make a 24
LED proof of concept project using the largest size board my free
version of EAGLE would let me work to. I originally intended to use
0805 SMT LEDs mounted on their sides but when I realised what a bitch
they are to solder like that I decided to go with good 'ole 3mm thru
holes of which I have – ahem – about 3,000 blue ones (don't ask).
The electronics was
pretty straightforward – since I have made a few similar things
before (basically this was an Arduino project with a custom designed
PCB) The 24 LEDs are driven by 3 x 74HC595D shift registers through
100 ohm 0805 resistors. I used an Atmega328 in QPF32 package with a
miniature (Nano styley) resonator.
I usually use an FTDI
USB-TTL serial lead for in circuit programming, so I simply added
pads for the the six ICSP connections I needed for burning the
bootloader and temporarily soldered wires to them. In the past I have
routed in a proper 2x3 ICSP header but I don't think I'll bother any
more - after all, burning the bootloader is a one-off procedure and
routing in the header is a pain.
The board is single
sided FR4. After etching and drilling it I tinplated the tracks (I do
this with all my boards now as it makes soldering easier, looks
cooler, doesn't take long, and isn't so expensive). After adding the
wire jumpers to the back I worked in stages to add the components and
test things.
I think its always a
good idea to test at each stage in case you need to junk the board
due to a design problem. First I soldered in the Atmega and the
resonator and burned the bootloader. When that worked I added the
serial programming header, diagnostic LED and resistor and made sure
I could get sketches to run on the Atmega. Only then did I add all
the other components when was confident the brain was alive. I
soldered all the components with an iron, with the exception of the
resonator where I put solder and flux on the pads and used a hot air
tool make the joints.
The rest of it I made
up as I went along, convinced it might go wrong at any moment. I
shaped the board to a disk with a stanley knife, steel rule, pliers
(for snapping) and sandpaper (for smoothing). Then I added in the
slots, top and bottom, to accept a 2mm drive shaft using my new
diamond edge cutting disk on my Proxxon table saw (in retrospect this
blade is fricking awesome and I should have used it to cut out the
circular PCB... you live and learn).
Aligning the 2mm drive
shafts top and bottom was pure guesswork. I both soldered them and
used copious quanitites of cyanoacrylate superglue (with activator
spray) to hold them in place, with the help of a couple of plastic
hub wheels from a model kit supplier.
The drive shafts go
through miniature model bearings in my crudely fashioned frame (made
from MDF I salvaged from an old CD rack, cut with a plain old Bosch
jigsaw) and at the bottom there is a simple reduction gear from a DC
motor to drive it. There is a crude joinery job holding it all
together - I am not proud of it,
What I am more pleased
with was the electrical transfer method I used. In a previous project
I
“borrowed” (saw it on a Youtube video) the idea of using an axially mounted, graphite-lubricated, 3.5mm jack plug/socket connection to take power to the rotating LED board while also acting as a bearing. This time I used some chunky graphite brushes (intended for drill equipment I think) and drilled a 2.5mm hole in each and passed the 2mm drive shafts through them, then crudely superglued the end of the brush springs to my frame. And it worked! In fact it works rather well and I think I will be using this approach again.
“borrowed” (saw it on a Youtube video) the idea of using an axially mounted, graphite-lubricated, 3.5mm jack plug/socket connection to take power to the rotating LED board while also acting as a bearing. This time I used some chunky graphite brushes (intended for drill equipment I think) and drilled a 2.5mm hole in each and passed the 2mm drive shafts through them, then crudely superglued the end of the brush springs to my frame. And it worked! In fact it works rather well and I think I will be using this approach again.
As I expected, some
balancing was needed. I superglued a couple of nuts to the back of
the board to counterbalance the LEDs on the opposite edge. Its not
perfect but it was a big improvement.
I saved soldering the
Hall Sensor until the board was mounted in the frame, so I could make
sure I cut the legs to the right length. A small Neodymium magnet
triggers the sensor.
In hindsight it might
have been better to somehow mount the magnet on the front of the
frame (opposite the vertical part of the frame, so 180 degrees around
the axis from where it is now). The reason is that when the sensor
passes the magnet, a new drawing cycle starts. So this is the point
where the previous draw cycle might be ended early or overrun
(depending on rounding errors due to the timer resolution and
variations in spin speed). With the position of the magnet in my
design these display “glitches” happen right at the front of the
globe and are quite easy to see – it would be better to hide them
around the back by moving the trigger point through 180 degrees, or
by placing the Hall sensor on the same edge as the LEDs rather than
opposite them.
There is a voltage
regulator on the board and I power the motor and board from a common
supply of about 10 volts. Something that surprised me was that when
plugged the USB lead in to the programming header on the board, the
motor received power and span up. I didn't think the current could
cross the regulator in the opposite direction so it was a bit of a
nasty suprise (and presumably it does the regulator no good either).
A 1N4001 rectifier diode on the +10V supply going to the board brush
solved the problem. I was very glad I found this issue before the
motor was attached to the frame or I could have smashed the board.
When it was all fitted
together I tested it out with a simple set of vertical and horizontal
lines, rendering as a wireframe globe, and it looked great. Next I
wanted to display a pixellated map of the world... to get this done I
found a suitable Mercator projection image on Google images and
resized down to the target 24 x 64 pixels in PaintShop Pro (still my
drawing tool of choice for its easy work with small bitmaps). Quite a
bit of manual tweaking was then needed to get a decent recognisable
monochrome image.
I usually use a
spreadsheet to do this kind of thing (OpenOffice). I wondered how I
might import the mono bitmap image data directly into the
spreadsheet, but as I was in a hurry and the image was small I just
retyped it manually. To help keep track I divided the image into 8x8
squares and highlighted them chessboard fashion in yellow. This meant
I could work one square at a time and it only took 15 minutes or so
to enter the data into the spreadsheet and use formulas to calculate
the bitmap values I needed.
I copy/pasted the
values from the spreadsheet into the Arduino sketch, programmed the
globe and fired it up – and it worked first time! The Pacific
looked a bit empty though, so I went back and added Hawaii.
I put a 32kbit I2C
EEPROM on the board so that I can store a decent set of image data to
make animations possible. I haven't done anything with it yet.
Here is a brief
description of how the code works. Almost all the POV projects I've
made work in this way...
The sketch sets up the
Atmega328's internal timers 1 and 2 to run at the same rate (1/64 of
full clock speed). This means they are counting at a very high rate
(I think it works out as 62500 counts a second).
The sketch uses
“interrupts” – an interrupt is a way for a specific hardware
event (like a pin changing value or an internal timer reaching a
certain threshold) to cause a specific piece of program code (called
a “service routine”) to be run immediately. This means the
program does not need to keep “polling” things like inputs and
timers, which would not be very accurate at these timescales.
Interrupts are really the only way to get the consistent timing
accuracy we need.
We use two interrupts,
one is called when the hall sensor fires and the value on pin 2
(Interrupt 0 pin) changes. The service routine for this interrupt
captures the value of timer 1 and resets the timer. This value is the
number of timer ticks in one complete rotation of the board.
Now we divide this up
to get the number of timer ticks in a single “sector” (vertical
scan column width). Although there are 64 columns in the image, I
actually insert an artificial blank column between every pair of
image columns to cleanly seperate the “pixels” rather than
letting them run together into streaks (it just looks nicer) so I
treat the image like it has 128 columns.
So the timer count is
divided by 128 and the result is put into the timer 2 “period
register”. Now when timer 2 reaches the value of the period
register it is automatically reset and another interrupt fires. The
service routine for this interrupt will therefore get regularly
called 128 times on each revolution – perfect! Now we just need to
load values from the image data into the LEDs. We need to keep a
count of how far round the revolution we are and we can add an
incrementing offset to make the image appear to spin. It is also here
that we turn off all the LEDs on every other call to add the gaps
between the pixels.
The LEDs are loaded by
simple shift register stuff (Check the Arduino tutorials if you don't
know what a shift register is) . Speed is of the essence, so the
three shift registers are loaded in parallel using 3 data lines and
common clock lines. I avoid using digitalWrite() to drive the output
pins on anything like this and go direct to the port registers since
it's an order of magnitude faster!
*** Source code, EAGLE files and image data available at
https://github.com/hotchk155/PovGlobe
*** Source code, EAGLE files and image data available at
https://github.com/hotchk155/PovGlobe
Hi Jason,
ReplyDeleteI love it!!
See you one thursday sometime soon if I can ever find time to get down there.
James
Awesome project!
ReplyDeleteKudos
I was thinking that you could power it via resonant energy transfer. Using a coil on a pcb disk set at 90 degrees to your current board and parallel to the ground. Then have the other coil in the base.
ReplyDeleteMaybe throw in some magnetic levitation too.
Anyway good work.
Hi:
ReplyDeleteI actually reached your blog via the library for one dimensional pong project but couldn't find that specific project so I'm asking my question here. I apologize for that. I want to attempt building something similar to the one dimensional pong as my first electronics project. I was wondering if I needed an addressable led strip or using a regular led strip would work just as well. I plan on using an arduino and an lcd to display the score.
Thanks very much!
Hi, yes an addressable strip is definitely required for the 1D pong game. Mine was an SD600 based strip but other controllers (WS2801 etc) should do fine.
ReplyDeleteThanks! Instead of foot switches I think I am going to use FSR's to I can gauge pressure and affect the speed of the light chaser. I, of course, have no clue at this point where to begin but hopefully I'll figure it out :)
DeleteHi:
DeleteI got an addressable strip with the LPD8806 chip from adafruit and have it connected to my arduino pins and power using wires soldered on to the +5V, DI, CI and GND pads on the strip. I downloaded your library and the example arduino code but it doesn't do anything. I'm not sure how the .cpp file in your library should be used/included? Thanks!
Ah. I got the .cpp part. Both the .h and the .cpp files are part of the library that goes into my /libraries folder. Now to figure out why the example doesn't work :)
DeleteThank you!
Ok. Everything is working except the score part coz i'm not sure what logic to use. Does the person have to hit the return switch within a certain time frame or something else? Thanks.
DeleteOh also, aren't the led strips one directional? How did you make it work back and forth? Mine so far does a one direction light chaser when I hit a pressure sensor. I'm sorry about the multiple comment spam.
DeleteOh I think the led's just need to be turned on backwards to look like they are going in the opposite direction :) Now to tackle scoring!
DeleteHey dude, wow lots of posts! you're using LPD8806? mine has sd600 so not sure the protocol is the same. But yeah you need to stomp on the switch just as the light gets to the end. The movement animation has nothing to do with the shift regs on the strip (which are refresh on micro second timescales) but rather you map a memory buffer to the LEDs then program the movement into the buffer, so the shift direction of the strip does not come into it.
DeleteOK for your strip I think you should grab the adafruit LPD8806 library then adapt the strip refresh code in the game to use their lib instead of mine (should port OK I think)
DeleteYep ended up using the adafruit LPD8806 library. I'm not sure I understand what you say about mapping a memory buffer to the LEDs so I'll google and try to figure it out. Thanks and again sorry for the tons of posts.
DeleteDoesn't look like I'm going to make my deadline for tonite :(
DeleteI wasn't able to finish the entire game in time but the led's did travel when someone stepped on the pressure sensor. I was happy with that, being my first ever hardware/electronic project! I'll continue with it in a few weeks to get the real game working.Thanks for all your help!
DeleteWow, I didn't know that was your first project. Very impressive!
DeleteThis comment has been removed by the author.
ReplyDeleteGreetings, I put 32 led, but do not understand how to add the new shift register (number 4) to the software. I appreciate your help and feedback (afaundez@gmail.com)
ReplyDeleteHey – wire it the new shift reg to same shift/store clock lines as the original 3 shift regs. Assign it a new digital out pin for its serial data line. After that you’ll just need to modify the code to add in the new 8 scan rows, where you can just copy the pattern used for the existing 3 shift regs
DeleteHello, thanks for your comments. I achieved to modify your code to enable my shift register number 4 (32 LEDs), but I'm just a beginner in relation to programming. I have placed in my pcb fifth shift register (IC5), with the idea of showing any text (example: time, date, free text), can you help me with the routine that displays text?
DeleteThanks
Here is my Schematic: http://i.imgur.com/TIo2FBg.png
Photos:
http://i.imgur.com/tnTIkaV.jpg
http://i.imgur.com/B72WaHX.jpg
http://i.imgur.com/Dtrg6S1.jpg
http://i.imgur.com/nG6Cvzy.jpg
Video: http://www.youtube.com/watch?v=muGpmjkW7ZE
Hi,
ReplyDeletei decided to build it but i can´t find parts values? Anyone know where they are ? :D
Here you go https://github.com/hotchk155/PovGlobe/wiki/parts
DeleteFun project Jason. How would I change the code to display the globe as lines instead of individual dots?
ReplyDeleteSorry - Never mind. I figured it out.
DeleteSorry for the slow response! quickest method would be to comment out the first half of the conditioni in ISR(TIMER2_COMPA_vect) so that the LEDs are not turned off every other count
DeleteCheers
Jason
Hi Jason, i like your project. Very nice and i like to bould one to. Is it possible to download the source code? Best Regards, Rene
ReplyDeleteHi yes you can find it here
Deletehttps://github.com/hotchk155/PovGlobe/blob/master/PovGlobe.pde
This globe POV looks so cool! Do you think it could be made on a bigger scale? My aunt teaches geography in a middleschool and I think she'd love something like this for her classroom.
ReplyDeleteAimee Hart | http://crisptech.com.au/lumigen/globes
Yeah I am sure you could make a bigger one (the great thing is you can squeeze in more LEDs for higher resolution) but you'd have to make sure it could put up with the forces of spinning,
DeleteI am hopefully going to be able to make a kit based around this project. Watch this space!
Can I make it only with the Atmega and the shift registers?
ReplyDeleteyou can leave the eeprom off, if that is what you mean
DeleteGreat work man.
ReplyDeleteAnd a very clean wiring.
Do you plan to build and RGB one?
Thank you so much
ReplyDeleteolle me podrías ayudar con el circuito e estado buscándolo y todavía no e podido encontrarlo
ReplyDeletePer coloro che sono incerti se hanno un problema e stanno considerando di cercare una terapia per la dipendenza dal sesso, ecco quattro caratteristiche di base della dipendenza. Mentre li leggi, tieni a mente se provi questi sintomi quando guardi la pornografia visita questo
ReplyDeletevisitez ceci youporn video
ReplyDelete