Wednesday, 9 January 2013

Working Word Clock update

This was supposed to have been a simple one-night project but trying to get to grips with these crazy, massive, 8x8 LED matrices has been more difficult than we first thought.
But, having finally finished our custom alarm clocks project, and waved family farefare for another Christmas, we eventually found time to get the soldering iron out and write some PIC micro code.

The first thing to do is confirm that we're able to correctly address each column in an 8x16 matrix. If we can't do that properly, debugging in future is going to be a nightmare. So we put together a simple routine which lights up a sequence of on-off-on-off LEDs on each column, and had the PIC light each column in turn (in time we'll just speed this up and use persistance-of-vision to make each individual LED look like it's continuously lit up).



Once we were happy that we could address each column and send it a single byte figure to get different LEDs to light up, we hacked together some code to make the "correct" LEDs light up, according to the current time. We've discussed the method on how to do this in an earlier post.

And the code is starting to look good. So far, we've got our clock lighting up the correct LEDs! Here are some examples of hard-coded times and the resulting LED output:


(it has just gone twenty minutes past eight)



(it is twenty five past seven)



(it is nearly ten o'clock)


Compared to the word grid, everything appears to line up correctly for the random sample times we've chosen:


We're currently using the 20Mhz operational clock crystal for our time-base, and an internal counter to keep track of the milliseconds and seconds. We'll have to leave the "clock" running for quite some time to see what kind of drift we get, and how accurate the clock stays to the true time.
(we're hoping that any drift will be disguised long enough to be un-noticeable, since the clock is only actually accurate to about two minutes anyway!)

All that remains now is to fire up the laser-cutter and make a nice fancy etched front for it....

Thursday, 3 January 2013

Happy New Year!

Christmas has been and gone and while we had lots of exciting geeky presents here at Nerd Towers, we've not actually had much time for nerding around (though plenty of time to scoff mince pies and leftover turkey). Some people say they prefer New Year to Christmas (Xmas is a time for family, New Year a time for friends and all that). So how did you see in the New Year?

Did you get away to an amazing all night party before walking home with just one shoe in at 4am? Or perhaps you had a quiet night in with Jools Holland's Hootenanny? Or maybe you were up until the wee small hours soldering about 50 audio player pcbs for an alarm clock project that's already running past the delivery deadline? Yup, we were too.

 
The Daily Mirror was left behind by a relative after Xmas. Please don't judge us!

Check out that festive tablecloth!

Saturday, 29 December 2012

Rope making machine at BuildBrighton

With Xmas and New Year occupying so much of everyone's time, there's not really been much time for nerding about lately. Well, not for some of us. But thankfully Stephen Cropp from BuildBrighton hasn't been so pre-occupied, and set about 3D-printing this awesome rope-making machine.


It's really quite simple in design. At one end of the table is clamped a central cog, which drives three outer cogs (each spaced 60 degrees apart). By turning the central cog with a handle, all the outer cogs turn the same way and at the same rate.

Steve threads his twine through hooks on these outer cogs to a weighted clip at the other end of the table then cranks the handle...



Sunday, 23 December 2012

Wiegand26 protocol RFID reader

We recently received an RFID reader from eBay for a door tagging/entry system project due to start in the New Year. This one was going to stay on hold for a while, but with a few hours to spare one evening at a BuildBrighton Thursday night, it seemed like the perfect opportunity to have a play about and see what this thing could do.



Firstly, it uses some weird protocol called Wiegand26 rather than the slightly more straight-forward serial/TTL level communications. But the protocol itself seems quite straightforward: the device consists of two data lines - when a zero is transmitted, one line goes low for a few microseconds, while the other stays high and when a one is transmitted, the other line goes low, keeping the first line high.

This seems easy enough. We simply monitor both lines and when one goes low, wait for it to come high again, and add a zero or a one to a binary buffer value. The tricky part comes in detecting the end of the binary stream:

Now the "official" Wiegand26 protocol involves 26 bits of data (that must be where it gets the -26 part of it's name from!). But some RFID cards and tags use much longer data for better security. Since we don't know much about the tags/cards we're going to use with this reader, we're going to have to assume there could be more or fewer bits of data coming down the wire(s).

So here's the approach:
We're going to set a flag to say whether or not we've started receiving some data.
As soon as one of the data lines changes, we start a timer running to time out after about 500ms.
Every time one of the data lines changes, we reset the timer.
When the timer times out (no activity for 500ms) we see what data we've got in the buffer and spit it out over serial.

We've doing this project in SourceBoost - not because we've fallen out with Oshonsoft, but because the first chip we picked up was one of the 16F1825s we've been using in our earlier audio project, so we stuck with it for ease of use.

This is the bulk of our program:
void main(){
   init();
   timer1Init();
   delay_ms(50);
   startTimer();
   while(1){
      checkforinput();
   }
}

The init routine simply sets up the input/output pins, and for debugging, starts the UART for writing data out over serial so we can debug what's actually going on inside the magic black box:


void init(){
   
   osccon           = 0b11110000;   //32 MHz clock   
   intcon           = 0b11000000;   //global/peripheral ints enabled
   apfcon0          = 0b01000000;   //MOSI on RA4
   option_reg         = 0b10000000; //no weak pull-ups, timer0 at OSC/4/2 = osc/ 8   

   UARTInit();
   ansela            = 0;         //no analog inputs
   anselc            = 0;         //no analog inputs
   trisa=00000000b;
   trisc=00000110b;
   
   porta=0;
   portc=0;
   tmp=0;   
   bitCount=0;
   bufferPointer=0;
   
   // now we pull pins low to activate the beeper and the lights
   // so force them high by default
   porta.2=1;
   portc.0=1;
   
   msCount=0;
   isReading=0;
   empty_buffer();
}

We couldn't be bothered to work out the values/pre-scalers for a 500ms timer, so just copied and pasted some code from another project which kept a 1ms timer, and used that with a counter to decide when 500ms had passed:


void preloadTimer1(){
   //------------------------------------
   // pre-load timer1 with 65172 (0xFE94)
   //------------------------------------
   // 1/22050 = 0.00004535147
   // at 32mhz, fosc=8,000,000
   // and 8m/22050 = 362.812
   // so we want our timer1 to only count up to 363
   // timer1 is a 16-bit timer (0-65535) so we need to
   // preload it with 65535-363 = 65172

   tmr1h=0xfe;
   tmr1l=0x94;
}   

void timer1Init(){
   //-------------------------------------------
   // interrupt on timer1 22050 times per second
   // ------------------------------------------
   pie1.0=1;   // timer1 rollover interrupt on bit zero
   intcon.7=1;   // global interrupts
   intcon.6=1;   // peripheral interrupts
   preloadTimer1();   
}

void startTimer(){   
   t1con.0=1;
}

void stopTimer(){
   // turn off the timer1 T1ON bit
   t1con.0=0;
}

void resumeTimer(){
   // turn on the timer1 T1ON bit
   t1con.0=1;
}

And in our timer interrupt:

void interrupt(void){
   
   // bit zero of pir1 is tmr1 overflow interrupt
   if(pir1.0==1){
      // clear the timer1 interrupt flag
      pir1.0=0;
      // preload timer1 to get the next interrupt to occur in a timely manner
      preloadTimer1();
      msCount++;   
      
      if(msCount>500){
         if(isReading==1){
            flushBuffer();
         }
         msCount=0;
      }         
   }
}


Now every time one of the data lines goes low, we wait for it to come back high, then add a one or a zero to the end of a stream of bits.

void checkforinput(){
   if(portc.2==0){
      // reset the timer if this is the start of a read
      if(isReading==0){msCount=0;}
      // set the flag to say we're reading some data
      isReading=1;
      //data1 has gone low: this is a one
      while(portc.2==0){
         // wait for the line to return high
         tmpBit=1;         
      }
      add_bit();
   }
   
   if(portc.1==0){   
      // reset the timer if this is the start of a read
      if(isReading==0){msCount=0;}
      // set the flag to say we're reading some data
      isReading=1;   
      //data1 has gone low: this is a one
      while(portc.1==0){
         // wait for the line to return high
         tmpBit=0;   
      }
      add_bit();
   }
   
}


To add a bit to the right-most end of the temporary value, we bit-shift all the data in the variable one place to the left, and simply OR the value (1 or zero) to the final result.
Here's an example:

Let's say we've already got the value 001101 in our buffer and we receive a one. First we bit-shift the value one place to the left. This gives us 011010. Now we OR this value with the number one (000001) and the result is 011011. This is the same as just tacking a one onto the end of the bit stream!

void add_bit(){
   tmp=tmp << 1;
   tmp=tmp | tmpBit;
   bitCount++;
   if(bitCount>=8){
      // this is a full byte
      // add it to the buffer
      porta.4=1;
      buffer[bufferPointer]=tmp;
      bufferPointer++;      
      tmp=0;
      bitCount=0;
   }   
}


So all that's left to do now is spit the data out so we can interrogate it:

void empty_buffer(){
   unsigned char i;
   for(i=0; i<=12; i++){
      buffer[i]=0;
   }
   bufferPointer=0;
}

void flushBuffer(){
   unsigned char i;
   
   // send out whatever's in the buffer
   // (first four bytes for a 26-bit protocol)
   isReading=0;
   UARTPrintLn("Buffer contents:");
   for(i=0; i<4; i++){
      tmp=buffer[i];
      UARTPrintNumber(tmp);
      UARTPrintLn(" ");
   }
   
   // reset the buffer for the next read
   tmp=0;
   bitCount=0;   
   empty_buffer();      
}

The reader we're working with has the following pinout:

power
ground
data0
data1
buzzer (low to activate)
led (low = green, high = blue)

So we wired the whole lot up to our PIC 16F1825 microcontroller, dumped some code onto it and read back what came out:


Amazingly, everything worked pretty much the first time out, with the results as follows:


Amazingly, the RFID reader could read a variety of RFID tags. We tried it with some of the phonics owl cards from an earlier BuildBrighton project, as well as the key fobs from the BuildBrighton door entry system, along with some other RFID tags from other people's various places of work. The RFID reader simply read them all and reported back the tag contents!

Now it'd be easy to call it a day and say we can read RFID tags successfully, but there's still the nagging doubt that we're not actually reading data, and just reporting a load of junk. What we needed was some way of confirming the data being read with a known value.
Luckily, the phonics owl cards (and a lot of RFID cards for that matter) have a Wiegand26 value printed onto them. If you have an RFID card with two sets of values, it's the second value (the one with the comma in it) that we're interested in:


What we need to do is compare our read-in value(s) against the Wiegand26 values printed onto the cards. So let's take a look at the actual bitstream from each of the card reads:

card no: 0006304068 096,12612
0000000048
0000000024
0000000162
0000000000
b00110000000110001010001000 (first 26 bits)

card no: 0012225140 186,35444
0000000093
0000000069
0000000058
0000000000
b01011101010001010011101000 (first 26 bits)

card no: 0006348080 096,56624
0000000176
0000000110
0000000152
0000000000
b10110000011011101001100000 (first 26 bits)

We've reported four bytes of data, because 26 bits is just over 3 bytes (3x8 = 24 bits).
In this case, all our fourth bytes are zero, but there's no guarantee that this will always be the case. So let's convert each decimal value to binary  and squash them all together (truncating once we get to 26 bits). Looking at it now, we could have created a single 32-bit value and simply bit-shifted the data 26 times, but then our code wouldn't work with 64-bit (or longer) cards. So by handling the data one byte at a time, we've got more work to do at this end (for validating) but it does mean we've a much more flexible system for future use.

Here's how the Wiegand26 protocol works, with 26 bits of data:



Let's look at the first set of values.
Splitting the byte stream up into groups of bits, we've got

0 01100000 0011000101000100 0

At the minute we're ignoring the parity bits, and are only interested in the "middle" section of the data stream. But already it's looking quite encouraging....

01100000 in decimal is 96
We've a couple of cards that begin with 096 followed by a comma.....
Taking the next group of 16-bits and converting to a single decimal gives us - 12612

That means we've correctly read the RFID data from the top-most card! Yay!
Comparing the values from the other cards, and we find we're accurately reading all the cards using the Wiegand26 protocol. We're not just reading junk, we're actually reading data.

With this in mind, we don't actually have to decode the bit-stream back to Wiegand values every time - we can simply report back the groups of bytes from the different cards, fobs and tags, confident that if we're reading them correctly (we are), the data from each will decode to the actual value on the card (if we need it to) but the parity bits will always give us the same groups of bytes for each card. As long as we have consistency each time a card is presented (i.e. we're not reading junk, we know we're reading the data correctly) we can simply compare the clumps of bytes to a look-up table to make the cards usable.

So to use this RFID reader for a door entry system, for example, it doesn't matter if we record a card as having the Wiegand26 value of 096,12612 or whether it's stored as 48,24,162,0 - each time the card with 096,12612 is presented to the card reader, we should expect to get back the bytes 48,24,162,0.
It's much easier to work with byte rather than splitting them up into bits, so we could just put these four bytes into our look-up table instead of converting back and forth between crazy 26-bit values!

In short, our first quick success for a long time.
After just a few hours of messing about, we've got a fully working RFID reading system.
In future posts, we'll look at writing our lookup table to an SD card and logging each time a card is swiped by writing a log file back to the card, making a completely PC-independent, embedded system!

Thursday, 20 December 2012

Working word clock pcb at last!

Having created a pcb from our earlier design, we've finally had time to sit and work out the pinout. And this time we're delighted to report that it actually works. Each pin on the 24-pin connector performs just one task and the correct combination of power and ground onto the pins causes just one LED to light up at a time. Result!

Here's the pin-out from the earlier pcb. The pins along the bottom need to be pulled to ground, while the pins along the edge should have power applied to them:


So if, for example, we put power onto pin2 and pull pin 23 low (to ground) the single LED in the top left corner of the matrix should light up. Repeat as necessary for each individual pin and we've finally got a fully working, individually addressable LED matrix. Yay!

Source code for the word clock to follow.....

Tuesday, 18 December 2012

Some SD cards don't like SPI mode and low voltages

It's a sad fact that some SD cards work differently to others.
Although there's a set of "standards" that all (most?) SD cards are supposed to adhere to, the degree of variance between cards is huge.

And we've just wasted about a month trying to fix a problem "properly" instead of doing the pragmatic thing and just hacking a solution together.

A while ago we started adapting some noise-playing alarm clocks. We completely replaced the onboard sound chip with one of our own design, which plays uncompressed wavs from an SD card. It took a lot of working out to get the SD card actually readable and when we thought we'd cracked it, put the audio player board back inside the alarm clock and gave it a try.

Incredibly, it worked first time!
And second time.
And third. But not the fourth.
In fact, after just a few plays, the SD card refused to initialise properly.

It all came down to the supply voltage. At 5v, we put the supply through a voltage regulator to give a steady 3.3v out. Everything worked fine. We put the boards into the alarm clocks and ran them off the 3v that 2xAA batteries created. In truth this was sometimes as high as 3.2v.

After just a few plays, the tiny voltage drop in the batteries was enough to stop the SD card from working.
But that's not where the story ends. Because we've spent about a month trying to use different triggering mechanisms, DC-to-DC converters, opto-isolators, PNP transistors and more yet all the time we had a working prototype on the desk. The circuit was exactly the same, we kept going back to the same (rough-and-ready) firmware. But all the time the prototype worked while every new version didn't.

And then we spotted the difference.
The prototype was using a genuine SanDisk micro sd card. The newer boards were using another brand. And that was enough to make a difference! SanDisk cards are pretty robust and can handle a wide range of supply voltages - cheaper, inferior brands can't.

So after a month of trying to build a circuit which is 100% compatible with all brands of SD cards, we've finally given up. And decided to only support a small sub-set of available cards on the market. It's not ideal. But it'll let us get these bloody clocks made up and shipped, hopefully this time of Christmas!!


Monday, 17 December 2012

Another word clock update

Anyone who has tried making a word clock from our previous designs is likely to be as disappointed as we were - they still don't work! This despite us actually reading the datasheet and laying out the pcb accordingly.

The problem this time wasn't that we'd connected the wrong pins (earlier assuming that all the "row" pins were on the top and all the "column" pins were on the bottom) but more that we hadn't identified which pins were which!

The datasheet we found suggested that the pin layout was a little peculiar:


So our latest pcb followed this layout. Without further information, we'd assumed that the pins were numbered

 1   2   3   4   5   6   7   8


 9  10  11  12  13  14  15  16 

None of the pins caused the right LED to light up. Putting power and ground to various pins was lighting up lights, just not the ones we expected. Then something peculiar happened:


Now at no point should putting a single power source onto a single pin cause more than one LED at a time to light up. Something was obviously very wrong! And so began the painful, laborious task of applying 5v power to one pin (through a 220ohm resistor of course) and ground to another, and charting which combinations caused which LEDs to light up.


Our final chart didn't resemble the datasheet in any way - we were grounding pins which the datasheet said were LED anodes, and putting power onto pins that the datasheet said should be pulled to ground. 
Once we'd identified which pin caused which "row" to light up, and done the same to find which pin to ground caused the LEDs in a specific column to light, we stopped filling in the grid and just did some random sample testing to prove our theory. Each test worked fine, so we were confident that we'd correctly identified the row and column pins.

There was no denying the hand-written grids - they were what we'd actually witnessed, datasheet or not. But they just didn't match with the datasheet at all. Just before we binned the datasheet and presumed it belonged to another module, we tried changing the presumed layout of the pins on the board.

We'd assumed they were numbered 

 1   2   3   4   5   6   7   8
 9  10  11  12  13  14  15  16 


when - after much messing about -  it turns out that they're, in fact, numbered 

16  15  14  13  12  11  10   9 
 1   2   3   4   5   6   7   8

Following this layout, suddenly the datasheet made sense!
We could read the pins on the datasheet, work out which LED should light by putting power and ground onto the appropriate pins and then proving this to be correct.

(note the LED module spread over two breadboards: it was simply too large to fit onto a single breadboard for testing!)

This time, everything matched up. We'd finally worked out how to make the LEDs light up in the correct way. But one thing remained - the pcb was, once again, wrong!
A bit of re-work in ExpressPCB and we came up with this:
Word Clock v2

Hopefully, a working PCB. To keep the overall final dimensions small, we're going to connect this to the 40-pin PIC mcirocontroller using a simple ribbon cable (off an IDE hard drive). For now we'll keep the connector in place, to make it easier to breadboard the whole thing up during testing: