Monday, 10 December 2012

Updated word clock PCBs

After making a complete cock-up of the earlier 16x8 word clock (made from two massive 8x8 LED matrices), we've had to revise the layout.

Here's the PCB for the LED face.
Since we're going to be connecting the 40-pin PIC microcontroller via some IDE ribbon cable, joining which pins on the connector to which pins on the LED board(s) isn't really that important - we just need to make sure all the pins from the boards are routed to some kind of ribbon connector:

Clock 8x8 v2

But since the pins for the rows and columns are all over the place, and we've just connected them any-old-how to the ribbon connector, we need some kind of look-up table:


The PCB for the PIC simply puts all the output pins to 0.1" pitched holes on the board.
So all we need to do is wire up the pins on the 24-way clock board connector to the appropriate pins on the PIC, following the table above.

That's the theory anyway.
Whether or not it actually works is another question.......

There's no getting away from it, we screwed up

In this earlier post, we designed a schematic and PCB for our 8x8 LED matrix and didn't really pay attention to the data sheet. Like a bunch of idiots, we just assumed that the pins along one edge were for the "rows" and the other set of pins were for "columns".

So it's no wonder that by sticking voltage across the pins resulting in some really peculiar behaviour. Where we expected the top-left corner LED to come on, one somewhere in the middle near the bottom lit up! The next pin along didn't light the next LED in the row, but one about three places along.


To get the top-left LED to light, we don't simply put power onto the first pin at the top, and ground the first pin on the bottom set - that won't actually light any LED!
Assuming our pins are labelled 1-8 across the top, and 9-16 along the bottom, connecting power to pin 1 and ground to pin 9 doesn't pass through any of the LEDs. If we put power onto pin 1, we need to ground one of either pins 3,4,6,11,13,15 or 16.

With this in mind, we've had to re-draw our schematic (and make a new PCB using a similar layout):

clock_8x8


Friday, 7 December 2012

A quick Xmas-themed project with flashing LEDs!

Here's an idea for an Xmas themed project, using up a few components most people are likely to have floating around. At the heart of it is a 555 timer, which creates a regular "pulse".
We're using this on/off behaviour to drive two transistors - one NPN and one PNP

Xmas Tree Sch

When the 555 timer output goes high, the NPN transistor allows current to flow lighting up LEDs 1-4. At hte same time, the PNP blocks current and LEDs 5-8 go out. When the output goes low, the NPN stops the current flow, making LEDs 1-4 go out, while the PNP makes LEDs 5.8 light up.


Play about with the values of the two resistors, R1+R2, between pins 6+7 on the 555 timer, and the value of the capacitor to create different flashing frequencies.

The 555 timer can sink/source up to 200mA. As this is an untested design, and depending on the voltage of the battery used, a resistor between power and the common LED anodes may be required. The value of this resistor will depend on the power source used

Xmas Tree Pcb

Create two of these PCBs. Cut a slot from the top of the first board, to about the mid-point, and from the bottom to the same point on the second board. The common power supply to the LEDs makes a complete circuit around the outside of the board, so it shouldn't matter if it's cut at the top or the bottom (just not both!)

On the first board only, mount the 555 timer and associated discrete components. On the second board, simply populate with LEDs.

Slot the two boards together. Every LED has two holes alongside it. These are for connecting wires to the corresponding hole(s) on the other board. This creates a complete circuit between all the LEDs.
Don't use straight bits of bare wire - use coloured wire (coloured sleeves) and bend them slightly to make "loops" going across the branches. For a real Xmas feeling, cover in glitter or bits of tinsel.

Connect up a battery and see if it works.
(this design, at the time of writing, is untested!)
Here's the silkscreen/layout:



Wednesday, 5 December 2012

There's no room for the pedantic Grammar Police

Try as I might, I can't bring myself to be happy with a word clock which potentially reads "it is just gone five minutes past six".

The sentence should read "it has just gone five minutes past six". But at the same time, we also need to be able to say "it is nearly quarter to seven", for example. A possible work-around (though still slightly clumsy) is "it's....." which could then be read as it is or it has depending on what follows. But that's still a bit nasty.

The problem is, wherever there's a possibility that one word could be immediately followed (light up) by another, we've had to leave a space (notice how there's a space between "it" and "is" on the earlier example, and between "minutes" and "past" - but not between "half" and "minutes"). Well, if we allow for both "it is" and "it has" there simply aren't enough squares left to spell out all the required times.

Unless we fudge it some other way:


We've had to spell out the word "ten" vertically rather than horizontally. It's a bit of a kludge and I'm still not 100% happy with it. But a bit happier than the nails-on-a-blackboard-sounding "it is just gone....x o'clock".

With this in mind, here's how we're going to write the time, at each of 0-59 minutes past each hour:


Bit-shifting. Shift over.

As part of our word clock made from two 8x8 LED matrix modules, we're trying to work out a way of quickly lighting up columns of 8 LEDs at a time.


Here's how it works: we set (and unset) any number of 8 different pins (connected to the "rows" line). Then we pull one of the 16 columns low, leaving the other column pins high, thus lighting up to eight LEDs in a single column. After a short delay, we then change the eight "row" pins and move along to the next column.

One way of achieving this is to have one single byte variable for the rows data, and a two byte (16-bit) variable for the columns data. If we start by lighting the first column, the two byte variable value would be 0111-1111-1111-1111 (in binary). After changing the row data, we need to make the two-byte variable value 1011-1111-1111-1111

In short, we need to make the zero value "move along" one space to the right.
A really easy way to do this is bit shifting.

We're going to simplify things (although not immediately obvious) by bit-shifting the (binary) value 1000-0000-0000-0000 one place to the right, then sending the inverse value to the column pins (so every 1 becomes a zero and every 0 becomes a one).

The reason for this is because bit-shifting isn't necessarily "circular". When a bit "drops off the end" it doesn't necessarily appear back at the start of the value. Consider a simpler example, the number 0110.
If we bit-shift one place to the right, the number becomes 0011. But if we bit-shift one more place to the right, the number becomes 0001. The trailing one has "dropped off the end" and disappeared - it doesn't appear back at the start of the value.

If we had the initial value 01111111 etc. and bit-shift one place to the right, we end up with 00111111 and not 10111111 (which is what we need). Whereas taking the value 10000000 and bit-shifting one place to the right gives us 01000000 which - when inverted - gives us the value we're after.

Right, that's that cleared up.
First we declare our variable:

unsigned short colData;  (SourceBoost)
Dim colData As Word (Oshonsoft)


Why unsigned rather than signed?
A two-byte signed value is simply a 15-bit value and the very first (leading) bit determines whether the value is positive (leading bit zero) or negative (leading bit one). If we used signed values, the leading bit would need to be toggled from zero to one depending on the position of the zero in the rest of the string. This is more hassle than just inverting an unsigned value (where the leading bit actually makes up part of the value represented by the binary pattern).

Then give our variable an initial value
colData=0x8000;
or
colData=32768;

The hex value 0x8000 is the same as binary value 1000-0000-0000-0000
Now when we need to move onto the next column, we bit-shift the colData value one place to the right:

colData = colData >> 1

This means that the value now becomes 0100-0000-0000-0000
And bit-shifting again:

colData = colData >> 1

returns the value 0010-0000-0000-0000
And so on and son on.

When the column is all the way over to the right, 0000-0000-0000-0001, and we bit-shift once more, we end up with 0000-0000-0000-0000 whereas we want the one to wrap around to the start again.
A simple if statement takes care of this:

If colData = 0 Then colData = 32768 (Oshonsoft)
if (colData==0){ colData = 0x8000;} (Sourceboost)

But as we've already stated, our colData is inverted to what we actually want. We don't want to pull 15 of the 16 columns low, we want only one column low at any one time. So we need to invert the value in the colData variable and put this value onto the output port(s):

tmp = colData XOR 0xFFFF

XOR is an exclusive OR statement:


If either of the bit patterns BUT NOT BOTH are one, the result is a one, otherwise it's zero. So simply XOR-ing our colData value with a load of ones 0xFFFF is binary 1111-1111-1111-1111 inverts the value, turning all the ones to zeros and all the zeros to ones.

Now we put the first (most significant) byte of the two byte variable onto PORTB and the second (least significant) onto PORTD:

Oshonsoft
Dim H As Byte
Dim L as Byte
H = colData.HB
L = colData.LB
PORTB = H
PORTD = L



SourceBoost
unsigned short b;
b=colData;
PORTD=b;  // only the lower 8-bits are put onto the output pins
b = b >> 8;  // move the upper 8-bits eight places to the right
PORTB=b;


The end result is that only one pin is pulled low at any one time.
Every time we use the bit-shift operator, the low pin "moves along" one place to the right, effectively lighting up the next column of LEDs in our matrix.

Heres's a quick guide to bit-shifting and unsigned/signed variables:
http://stackoverflow.com/questions/141525/absolute-beginners-guide-to-bit-shifting

Tuesday, 4 December 2012

Word clock PCBs

These massive 16-pin 8x8 LED matrix modules are easy enough to work with - each row of LEDs has a common pin (so all 8 LEDs in a single row are potentially connected to the power supply) and you simply ground one of eight "column" pins to make the appropriate LED light up.



Although there are load of different driver chips for these display blocks, or we could use shift-registers and the like, we're going to do with the really simple direct-drive method. Basically this means choosing a microcontroller with loads of pins and connecting them directly to the pins on the LED matrix.

Word Clock Sch

To keep our final clock dimensions quite small, we're going to put the microcontroller on the back on the LEDs and use some IDE cable (which conveniently is 0.1" pitch spaced anyway) to connect the two boards:


Word Clock Pcb

Since these modules have a common anode, and you drive the appropriate pin(s) low to make the LEDs switch on, we've connected all the anodes on each "row" together. So each "row" output pin activates up to 16 LEDs at once.

This isn't an ideal way of driving these boards - using something like a Maxim MAX7219 constant current LED matrix driver would be better but two of those at a tenner each and the project starts to get a bit spend-y. Since we're only likely to actually light 3 or 4 LEDs (from a maximum of eight) at any one time, direct drive gives us a cheaper alternative to try out the design and check that everything works properly before committing to some rather expensive components.

We've gone for the PIC 16F877A chip, just because we've a few left over from years and years ago - they're the typical "starter" chip for people getting into PIC programming; loads of pins (it's a 40-pin DIP) and loads of peripherals (UART, SPI, I2C etc). It's probably a bit overkill, and there may be other, cheaper chips out there, but we're just using up what we've got.

We're going to be running the chip off a crystal and use this to keep time as well as provide the instruction clock cycle. We've some 4Mhz and some 20Mhz crystals knocking around - either will do. The idea is to keep an array of values representing the output state of each of the 16 vertical columns in the LED matrix. We'll create a timer interrupt every 1ms and use this for timekeeping (increase a seconds counter every second, when this rolls over to 60, increase a minute counter, when this rolls over to 60, incease an hours counter) as well as to drive the next column of LEDs.

By strobing all 16 columns once every millisecond, we're hoping to create an illusion of an always on display; depending on the results of this, we may strobe the columns every few milliseconds and try to find the optimum balance between the length of time each column remains lit and the "refresh rate": as each column stays on for longer, the LEDs may appear brighter, but the refresh rate (the number of times each column is "drawn" per second) reduces.

Monday, 3 December 2012

More Christmas clocks

Last year we made some clocks for Xmas. This was because of an earlier ill-fated attempt to charlie-plex a load of LEDs (a 9x10 matrix) in order to create a word clock (which failed) and a bingo machine (which later worked, but using shift registers instead of charlie-plexing).

This year, since we've got a cheap audio playing device and having seen Jason's awesome digital led MatrixFaces, we thought that some digital caricatures of friends and family would make great stocking filling gifts. So promptly ordered a load of 8x8 LED matrices and waited until they arrived...


They're supposed to be two-colour (red and green) 3mm matrix blocks but the ones that arrived are massive! They're also single colour, with just 16 pins - one set of 8 pins for the "rows" and one set of 8 pins for the "columns". By driving the appropriate pins high/low you can activate any single LED in the matrix. Drive each of them quickly enough, and using POV (persistance of vision) you create the illusion of many LEDs being lit at the same time.

Which got us thinking back to our (failed) word clock project about a year ago.
Instead of a home-made 9x10 matrix, perhaps there's some way we could squeeze a word clock into an 8x8 matrix and use these ridiculously large (in LED matrix terms) modules to create a ridiculously small (in wall clock terms) erm wall clock...

No matter how we tried to spell out all the words required, we couldn't quite get them all to fit into an 8x8 grid. So what if we put two of these side-by-side?


Well now, a 16x8 LED matrix not only gives us more than enough letters to spell out all the words needed for our word clock, but also solves a little niggling issue we'd previously tried to ignore:

Word clocks with five minute increments are accurate to the last five minute segment. Between five to, and o'clock, say, the clock will always read "it is five minutes to x". Then at the o'clock position, it read "it is x o'clock" until it's five past.

By having a larger matrix (albeit by accident than design) we've got extra lights to add in some extra words. So we've added "nearly" and "just gone". This should make our clock accurate to about two minutes at worst.

  • At 2 minutes to six o'clock, it would read "it is nearly six o'clock".
  • At six o'clock, it would obviously read "it is six o'clock" 
  • At 2 minutes past six, it would read "it is just gone six o'clock"
  • And at 4 minutes past six, it would read "it is nearly five past six"
  • At five past, it reads "it is five past six" 

and so on - each two minute segment before a five/ten/quarter past would have "nearly" at the front, and each two minute segment after a five/ten/quarter past time would have "just gone" added to it. This means that you should be able to work out to within two minutes the actual time on the clock.

It's not millisecond accuracy, but it's a bit better than most word clocks manage!

To make the clock, we're planning a laser-cut face over the LED matrix with the letters as laid out in the spreadsheet above. We may even coat some glass with semi-opaque paint to give a smoked effect, and laser this off. The exact finish has yet to be decided.

Since the two LEDs matrices side-by-side give us a 16x8 grid, we can simply keep track of the current time and convert this into an array of single-byte values, each sent out over a full output port (PORTB for example) on a PIC microcontroller, while pulling the appropriate cathode "column" low to make the corresponding LED(s) light up:


In the above example, we want to light up the words to spell out "it is five minutes past six".
If we highlight the letters required, and at the bottom of every column add up the values of all the "lit" characters, we can see the array of value(s) required to make the LED matrix light up.