Plenty going on over the Xmas period but sadly not a lot of time to post about it, so look out for some updates in the New Year. Most excitingly, we've got a working version of an electronic Blood Bowl board game (well, one that you can download player data onto and it recognises which player you're moving, and can even perform some basic game mechanics).
We've also had quite a bit of interest in the microband miniature instruments so we're hoping to ramp up development on those in the new year too.
But all in all, over Xmas, we've eaten too much, made too little and blogged even less.
It's off to the other side of the country tomorrow for a New Year party so don't expect much for the next few days. In the meantime, have a great weekend, and a Happy New Year!
Friday 30 December 2011
Friday 23 December 2011
Blood Bowl Digital
It's almost Xmas and time to down tools for a while and get all Christmas-y (despite what some people will tell you, tinsels and baubles still lead soldering irons and wire strippers in the Xmas stakes).
But before we wind down for the holiday season, we've been busy working on a website for our Digital Blood Bowl game board. We've called it Blood Bowl Digital.
A preview of the site can be found at http://www.nerdclub.co.uk/bloodbowl
You can create teams and build online rosters and assign attributes and skills to all your players.
The idea behind this is to have a gateway between an online team/games manager and a way of getting player data into the game board.
Hopefully - if we manage to keep on the "nice list" for the next few days - we'll have some spanky 20x4 character displays to actually demonstrate something come Boxing Day.....
But before we wind down for the holiday season, we've been busy working on a website for our Digital Blood Bowl game board. We've called it Blood Bowl Digital.
A preview of the site can be found at http://www.nerdclub.co.uk/bloodbowl
You can create teams and build online rosters and assign attributes and skills to all your players.
The idea behind this is to have a gateway between an online team/games manager and a way of getting player data into the game board.
Hopefully - if we manage to keep on the "nice list" for the next few days - we'll have some spanky 20x4 character displays to actually demonstrate something come Boxing Day.....
Wednesday 21 December 2011
Christmas clocks
It's beginning to look a lot like Christmas...... everywhere you go. Ok, it's not. I don't know what it is this year - the doom and gloom peddled on all the news channels, the recession, austerity measures or what - but it just doesn't feel Christmassy.
Maybe it's just because the weather is still quite mild and all the spring bulbs are popping up.
But there's something particularly un-Christmassy this year. There are a few lights about and a few shops have made a half-hearted nod towards Xmas, but in the main - and talking to other people, I'm not the only one - we're still waiting to be hit full in the face with Christmas Cheer.
Which is probably why I've left it so late to get making Xmas gifts this year. Normally, come December 1st, the first little door on the advent calendar gets opened and it's straight into maker-mode, planning and making for everyone. But for some reason, this year things have been left a little late.
Back in November, I was helping Jason with his toy cars and lights controller. But since then, not much on the Xmas front. So last night I fired up the laser cutter and got designing some novelty clocks.
Most of the time was spent on the designing and drawing rather than the actual manufacture (which meant sending to the cutter, waiting a while, then some basic assembly afterwards) but the end results are quite pleasing:
[photo here]
Here are the design files should anyone fancy having a go -
Send the dxf to your laser cutter and carve out from your favourite coloured sheet of A4 acrylic (loaded in landscape).
Links to files:
To finish the clock off (and mostly, to hide the clock movement from behind) I cut out some shapes from a second colour and fitted them inside some of the cut-outs from the main clock face. By turning the clock over they could simply be held in place with some tape. I used double-sided tape, then stuck a piece of card over the whole arrangement, to keep the shapes from falling out once the clock was on the wall.
[photo of reverse]
Here's a slightly different clock, requiring a little more assembly.
At first I wasn't too sure about the design but the more I look at it, the more it grows on me. At first I thought about making the smaller coloured numbers as inserts (so they mounted flush with the surrounding shapes) but now I think I prefer them as relief shapes, sitting on top of the basic number shape.
[photo of second clock]
I think it's the clear acrylic ring that makes this clock work so well. It means positioning the numbers is relatively easy (it would have been a nightmare trying to stick just the very edges of a few numbers to the centre disc to hold it all together) but when the clock is on the wall, the final effect is quite striking!
Here are the design files if you fancy making one of these yourself:
Lastly, here's a simpler version of the second clock that requires much less assembly, designed smaller to fit on a single A4 sheet of acrylic (or wood or whatever you're making your clocks out of!)
Links to files:
http://www.nerdclub.co.uk/files/clock1_single_piece.dxf
http://www.nerdclub.co.uk/files/clock1_with_insets.dxf
http://www.nerdclub.co.uk/files/clock1_inset_numbers.dxf
Maybe it's just because the weather is still quite mild and all the spring bulbs are popping up.
But there's something particularly un-Christmassy this year. There are a few lights about and a few shops have made a half-hearted nod towards Xmas, but in the main - and talking to other people, I'm not the only one - we're still waiting to be hit full in the face with Christmas Cheer.
Which is probably why I've left it so late to get making Xmas gifts this year. Normally, come December 1st, the first little door on the advent calendar gets opened and it's straight into maker-mode, planning and making for everyone. But for some reason, this year things have been left a little late.
Back in November, I was helping Jason with his toy cars and lights controller. But since then, not much on the Xmas front. So last night I fired up the laser cutter and got designing some novelty clocks.
Most of the time was spent on the designing and drawing rather than the actual manufacture (which meant sending to the cutter, waiting a while, then some basic assembly afterwards) but the end results are quite pleasing:
[photo here]
Here are the design files should anyone fancy having a go -
Send the dxf to your laser cutter and carve out from your favourite coloured sheet of A4 acrylic (loaded in landscape).
Links to files:
- http://www.nerdclub.co.uk/files/numbers_clock1.dxf
- http://www.nerdclub.co.uk/files/numbers_clock1b.dxf
To finish the clock off (and mostly, to hide the clock movement from behind) I cut out some shapes from a second colour and fitted them inside some of the cut-outs from the main clock face. By turning the clock over they could simply be held in place with some tape. I used double-sided tape, then stuck a piece of card over the whole arrangement, to keep the shapes from falling out once the clock was on the wall.
[photo of reverse]
Here's a slightly different clock, requiring a little more assembly.
At first I wasn't too sure about the design but the more I look at it, the more it grows on me. At first I thought about making the smaller coloured numbers as inserts (so they mounted flush with the surrounding shapes) but now I think I prefer them as relief shapes, sitting on top of the basic number shape.
[photo of second clock]
I think it's the clear acrylic ring that makes this clock work so well. It means positioning the numbers is relatively easy (it would have been a nightmare trying to stick just the very edges of a few numbers to the centre disc to hold it all together) but when the clock is on the wall, the final effect is quite striking!
Here are the design files if you fancy making one of these yourself:
this is the clear acrylic ring that some of the numbers mount onto
with some clever layout, you can get all the numbers onto a single A4 sheet
optional extra - inset characters for the numbers 2,4, 6, 8, 10 and 12
Links to files:
- http://www.nerdclub.co.uk/files/numbers_clock2_circle.dxf
- http://www.nerdclub.co.uk/files/numbers_clock2_clear_ring.dxf
- http://www.nerdclub.co.uk/files/numbers_clock2_insets.dxf
- http://www.nerdclub.co.uk/files/numbers_clock2_numbers.dxf
this clock has all the numbers connected to make a single solid piece
using the previous clock as a base, this clock can also have raised numbers placed on top of the base design, or you can cut the inset figures out and use different coloured acrylic (wood, whatever) to fill the gaps
Links to files:
http://www.nerdclub.co.uk/files/clock1_single_piece.dxf
http://www.nerdclub.co.uk/files/clock1_with_insets.dxf
http://www.nerdclub.co.uk/files/clock1_inset_numbers.dxf
Sunday 18 December 2011
Stripping paint from Blood Bowl miniatures
Yesterday morning the postie delivered a whole team of (second-hand eBay bargain) Orcs to Nerd Towers and - as is normal with most things when something new arrives - we immediately dropped everything and spent some time getting all excited about the newest thing to be working on!
They're the "older" - 2nd or 3rd edition - style Orc team called The Orcland Raiders, not the American Football style team we've mentioned in a previous post, but they were (relatively) cheap with the added bonus of already being painted.
None of us here have painted (or even shown any interest in) miniatures-based board games for nearly twenty years or more, so having a pre-painted team seemed like a good idea. Until they arrived....
The paint job on each miniature is ok-ish.
The basic colours are in the right places, and sometimes even the details are quite nicely done. But the colours seemed a bit "muddy" and not all the finer details were picked out in quite the way we'd have liked, so we've all decided to buy each other a set of Citadel paints (or similar acrylic-based colours) for Xmas and have a "getting-re-aquainted-with-painting-miniatures-again" session in the New Year.
Which means stripping all the miniatures we have and starting again.
We tried the usual tricks of Dettol, Fairy power spray and a whole heap of other detergents (there's no excuse in not keeping the place clean and tidy any more) but each was quite fiddly and required lots of soaking, scrubbing, re-soaking and so on. So we put on some rubber gloves and dropped the miniatures into some industrial strength paint and varnish remover. This is a white jelly-like substance, but the miniatures are ready for scrubbing after just 30 minutes soak.
The stripper causes the acrylic paint (and top coat varnish) to become a slimy coating over the entire model:
A quick scrub with a toothbrush and most of the paint comes off in just a minute or two under a running tap. Not all of the paint came off in one go, with some of the paint proving quite stubborn in the deepest of recesses. However, this does help show up some of the finer details of the model, which may have got lost under the previous paint job.
After each model is stripped, we leave to soak in a bottle of clean water, to remove any nasty chemical residue left by the paint stripper, then dab dry with a towel and leave to dry out for a few hours in front of the fire.
We're going to take reference photos of all our stripped models, so that we can see where the finer details are after we've splodged paint all over them - it's very easy to miss the little bits and bobs, but it's these tiny examples of attention to detail that make the miniatures so impressive in the first instance - it'd be a shame not to show off the exquisite modelling to its best, which means painting and highlighting these parts that could otherwise go un-noticed.
They're the "older" - 2nd or 3rd edition - style Orc team called The Orcland Raiders, not the American Football style team we've mentioned in a previous post, but they were (relatively) cheap with the added bonus of already being painted.
An orc team from Games Workshop. We're not expecting ours to be painted to anywhere near this standard!
The paint job on each miniature is ok-ish.
The basic colours are in the right places, and sometimes even the details are quite nicely done. But the colours seemed a bit "muddy" and not all the finer details were picked out in quite the way we'd have liked, so we've all decided to buy each other a set of Citadel paints (or similar acrylic-based colours) for Xmas and have a "getting-re-aquainted-with-painting-miniatures-again" session in the New Year.
Which means stripping all the miniatures we have and starting again.
We tried the usual tricks of Dettol, Fairy power spray and a whole heap of other detergents (there's no excuse in not keeping the place clean and tidy any more) but each was quite fiddly and required lots of soaking, scrubbing, re-soaking and so on. So we put on some rubber gloves and dropped the miniatures into some industrial strength paint and varnish remover. This is a white jelly-like substance, but the miniatures are ready for scrubbing after just 30 minutes soak.
The stripper causes the acrylic paint (and top coat varnish) to become a slimy coating over the entire model:
A quick scrub with a toothbrush and most of the paint comes off in just a minute or two under a running tap. Not all of the paint came off in one go, with some of the paint proving quite stubborn in the deepest of recesses. However, this does help show up some of the finer details of the model, which may have got lost under the previous paint job.
After each model is stripped, we leave to soak in a bottle of clean water, to remove any nasty chemical residue left by the paint stripper, then dab dry with a towel and leave to dry out for a few hours in front of the fire.
We're going to take reference photos of all our stripped models, so that we can see where the finer details are after we've splodged paint all over them - it's very easy to miss the little bits and bobs, but it's these tiny examples of attention to detail that make the miniatures so impressive in the first instance - it'd be a shame not to show off the exquisite modelling to its best, which means painting and highlighting these parts that could otherwise go un-noticed.
Wednesday 14 December 2011
Serial character LCD driver with Flash eeprom
No sooner had we got our serial character LCD display working than we were moving on to the next stage of the project - reading text from an Atmel AT45DB041D Flash eeprom chip to decide what to display on the screen.
We're already familiar with these chips, from our multiple servo controller board from back in May.
The idea is to store strings of text in these chips, then simply set a pointer (to tell the PIC where to start reading from) and get the microcontroller to read the text back and display it on the LCD.
We did look at I2C and other serial eeprom alternatives (at £1.20 each these Atmel chips are quite expensive for eeprom and at 4Mbit, are much bigger than we're ever going to need!) but most other (non-Flash) chips run at 100kz, or 400khz at best (yes, that's kilohertz, not Mhz). This will obviously make drawing text on the LCD run really slowly which is something we're keen to avoid.
These little Atmels can work up to 20Mhz. Which by happy coincidence is how fast the master chip will be running anyway, so hopefully we won't lose too much time reading and displaying text to the screen.
We wired our Flash eeprom chip up to PORTD on an 18F4550 (using RD.0-RD.3) and hacked some code together to read and write data to/from the chip. Amazingly, it worked first time!
AllDigital
Config PORTC = Output
Config PORTD = Output
Config PORTD.2 = Input
configuration:
Symbol enablepin = PORTC.0
Symbol clockpin = PORTC.1
Symbol datapin = PORTC.2
declarations:
Dim tmp As Byte
Dim i As Byte
Dim lcdi As Byte
Dim lcdbyte As Byte
Dim lcdbytetosend As Byte
Dim rs As Bit
Dim flag As Byte
Dim mask As Byte
Dim pageaddr As Word
Dim byteaddr As Byte
Dim byteswritten As Word
Dim bytesread As Word
Dim streamwrite As Bit
Dim streamread As Bit
init:
WaitMs 200
Define SPI_CS_REG = PORTD
Define SPI_CS_BIT = 0
Define SPI_SCK_REG = PORTD
Define SPI_SCK_BIT = 1
Define SPI_SDI_REG = PORTD
Define SPI_SDI_BIT = 2
Define SPI_SDO_REG = PORTD
Define SPI_SDO_BIT = 3
SPIPrepare
Gosub initialiselcd
Gosub initialiseeeprom
pageaddr = 1
byteaddr = 0
Gosub readanddisplaydata
loop:
pageaddr = 1
Gosub readanddisplaydata
WaitMs 4000
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
byteaddr = byteaddr + 16
If byteaddr > 60 Then byteaddr = 0
WaitMs 1000
Goto loop
End
writelcdnibble:
Low enablepin
Low clockpin
If rs = 1 Then High datapin Else Low datapin
Gosub toggleclockpin
'shift in 4 bits
mask = 8
For lcdi = 1 To 4
flag = lcdbyte And mask
If flag = 0 Then Low datapin Else High datapin
Gosub toggleclockpin
mask = ShiftRight(mask, 1)
Next lcdi
'now strobe the clock one more time because ST+SC are tied
Gosub toggleclockpin
'toggle the enable pin to "flush" the data into the lcd
Low datapin
High enablepin
Low enablepin
Return
toggleclockpin:
'toggle the clock pin
High clockpin
Low clockpin
Return
writelcddata:
rs = 1
Gosub senddatatolcd
Return
writelcdcommand:
rs = 0
Gosub senddatatolcd
Return
senddatatolcd:
lcdbyte = ShiftRight(lcdbytetosend, 4)
Gosub writelcdnibble
lcdbyte = lcdbytetosend And 15
Gosub writelcdnibble
Return
initialiselcd:
For i = 1 To 3
WaitMs 50
lcdbytetosend = 0x20
Gosub writelcdcommand
Next i
WaitMs 50
lcdbytetosend = 0x28 '4 bits, 2 lines, 5x7 font
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x0c 'display on, no cursors
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x06 'entry mode auto-increment
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
'send a space character to the display to test
WaitMs 50
lcdbytetosend = 32
Gosub writelcddata
Return
initialiseeeprom:
Gosub set256pagesize
Gosub chiperase
pageaddr = 1
byteaddr = 0
WaitMs 100
Gosub startstreamwrite
For i = 0 To 63
tmp = LookUp("Blood Bowl Griff Oberwald Varag Ghoulchew The Mighty Zug "), i
SPISend tmp
Next i
Gosub endstreamwrite
Return
startstreamread:
streamread = 1
SPICSOn
SPISend 0xe8 'stream read (legacy mode)
SPISend pageaddr.HB
SPISend pageaddr.LB
SPISend byteaddr
SPISend 0x00 'four don't care bytes
SPISend 0x00
SPISend 0x00
SPISend 0x00
bytesread = 0
Return
endstreamread:
SPICSOff
streamread = 0
Return
startstreamwrite:
SPICSOff
SPICSOn
SPISend 0x82 '0x82 'write THROUGH buffer1 command
SPISend pageaddr.HB '5 don't care bits + 11 address bits
SPISend pageaddr.LB 'is the same as sending page address as hb/lb
SPISend byteaddr 'last eight bits are buffer start byte
byteswritten = 0
streamwrite = 1
WaitMs 5
Return
endstreamwrite:
SPICSOff 'this causes the flash buffer to automatically get written to memory
WaitMs 5
streamwrite = 0
Return
set256pagesize:
SPICSOn
SPISend 0x3d
SPISend 0x2a
SPISend 0x80
SPISend 0xa6
SPICSOff
Return
chiperase:
SPICSOn
SPISend 0xc7
SPISend 0x94
SPISend 0x80
SPISend 0x9a
SPICSOff
WaitMs 100
Return
readanddisplaydata:
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
Gosub startstreamread
For i = 1 To 16
SPIReceive lcdbytetosend
'for testing
tmp = byteaddr + i
Write tmp, lcdbytetosend
Gosub writelcddata
Next i
Gosub endstreamread
Return
Note that in the initialiseeeprom routine we actually blank the Flash chip and write some data to it. In the final version of this code, we'll transfer data to Flash eeprom via a USB connection, but read it back just the same. Although this is just a basic test, it proves the idea of us storing character/player information in eeprom and calling it up and displaying it on a character-based LCD. All with just a few extra wires from the master microcontroller.
[photo or video goes here]
Note that in this example we're using a rather tiny 2x16 character LCD (because we had some hanging around). We've got our fingers crossed that Santa will bring some larger 4x20 displays, like the one below which uses the same Hitachi 44780 controller chip, so the code should work for both.
With four lines of twenty characters, we can split player names over two lines (to allow really long forenames/surnames) and write player stats (MA, ST, AG, AV) on a single line - each stat (0-9) would take up four characters (XX-digit-space) so the output could look something like
Or, if we can get the player's name on a single line, something like:
We're already familiar with these chips, from our multiple servo controller board from back in May.
The idea is to store strings of text in these chips, then simply set a pointer (to tell the PIC where to start reading from) and get the microcontroller to read the text back and display it on the LCD.
We did look at I2C and other serial eeprom alternatives (at £1.20 each these Atmel chips are quite expensive for eeprom and at 4Mbit, are much bigger than we're ever going to need!) but most other (non-Flash) chips run at 100kz, or 400khz at best (yes, that's kilohertz, not Mhz). This will obviously make drawing text on the LCD run really slowly which is something we're keen to avoid.
These little Atmels can work up to 20Mhz. Which by happy coincidence is how fast the master chip will be running anyway, so hopefully we won't lose too much time reading and displaying text to the screen.
We wired our Flash eeprom chip up to PORTD on an 18F4550 (using RD.0-RD.3) and hacked some code together to read and write data to/from the chip. Amazingly, it worked first time!
AllDigital
Config PORTC = Output
Config PORTD = Output
Config PORTD.2 = Input
configuration:
Symbol enablepin = PORTC.0
Symbol clockpin = PORTC.1
Symbol datapin = PORTC.2
declarations:
Dim tmp As Byte
Dim i As Byte
Dim lcdi As Byte
Dim lcdbyte As Byte
Dim lcdbytetosend As Byte
Dim rs As Bit
Dim flag As Byte
Dim mask As Byte
Dim pageaddr As Word
Dim byteaddr As Byte
Dim byteswritten As Word
Dim bytesread As Word
Dim streamwrite As Bit
Dim streamread As Bit
init:
WaitMs 200
Define SPI_CS_REG = PORTD
Define SPI_CS_BIT = 0
Define SPI_SCK_REG = PORTD
Define SPI_SCK_BIT = 1
Define SPI_SDI_REG = PORTD
Define SPI_SDI_BIT = 2
Define SPI_SDO_REG = PORTD
Define SPI_SDO_BIT = 3
SPIPrepare
Gosub initialiselcd
Gosub initialiseeeprom
pageaddr = 1
byteaddr = 0
Gosub readanddisplaydata
loop:
pageaddr = 1
Gosub readanddisplaydata
WaitMs 4000
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
byteaddr = byteaddr + 16
If byteaddr > 60 Then byteaddr = 0
WaitMs 1000
Goto loop
End
writelcdnibble:
Low enablepin
Low clockpin
If rs = 1 Then High datapin Else Low datapin
Gosub toggleclockpin
'shift in 4 bits
mask = 8
For lcdi = 1 To 4
flag = lcdbyte And mask
If flag = 0 Then Low datapin Else High datapin
Gosub toggleclockpin
mask = ShiftRight(mask, 1)
Next lcdi
'now strobe the clock one more time because ST+SC are tied
Gosub toggleclockpin
'toggle the enable pin to "flush" the data into the lcd
Low datapin
High enablepin
Low enablepin
Return
toggleclockpin:
'toggle the clock pin
High clockpin
Low clockpin
Return
writelcddata:
rs = 1
Gosub senddatatolcd
Return
writelcdcommand:
rs = 0
Gosub senddatatolcd
Return
senddatatolcd:
lcdbyte = ShiftRight(lcdbytetosend, 4)
Gosub writelcdnibble
lcdbyte = lcdbytetosend And 15
Gosub writelcdnibble
Return
initialiselcd:
For i = 1 To 3
WaitMs 50
lcdbytetosend = 0x20
Gosub writelcdcommand
Next i
WaitMs 50
lcdbytetosend = 0x28 '4 bits, 2 lines, 5x7 font
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x0c 'display on, no cursors
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x06 'entry mode auto-increment
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
'send a space character to the display to test
WaitMs 50
lcdbytetosend = 32
Gosub writelcddata
Return
initialiseeeprom:
Gosub set256pagesize
Gosub chiperase
pageaddr = 1
byteaddr = 0
WaitMs 100
Gosub startstreamwrite
For i = 0 To 63
tmp = LookUp("Blood Bowl Griff Oberwald Varag Ghoulchew The Mighty Zug "), i
SPISend tmp
Next i
Gosub endstreamwrite
Return
startstreamread:
streamread = 1
SPICSOn
SPISend 0xe8 'stream read (legacy mode)
SPISend pageaddr.HB
SPISend pageaddr.LB
SPISend byteaddr
SPISend 0x00 'four don't care bytes
SPISend 0x00
SPISend 0x00
SPISend 0x00
bytesread = 0
Return
endstreamread:
SPICSOff
streamread = 0
Return
startstreamwrite:
SPICSOff
SPICSOn
SPISend 0x82 '0x82 'write THROUGH buffer1 command
SPISend pageaddr.HB '5 don't care bits + 11 address bits
SPISend pageaddr.LB 'is the same as sending page address as hb/lb
SPISend byteaddr 'last eight bits are buffer start byte
byteswritten = 0
streamwrite = 1
WaitMs 5
Return
endstreamwrite:
SPICSOff 'this causes the flash buffer to automatically get written to memory
WaitMs 5
streamwrite = 0
Return
set256pagesize:
SPICSOn
SPISend 0x3d
SPISend 0x2a
SPISend 0x80
SPISend 0xa6
SPICSOff
Return
chiperase:
SPICSOn
SPISend 0xc7
SPISend 0x94
SPISend 0x80
SPISend 0x9a
SPICSOff
WaitMs 100
Return
readanddisplaydata:
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
Gosub startstreamread
For i = 1 To 16
SPIReceive lcdbytetosend
'for testing
tmp = byteaddr + i
Write tmp, lcdbytetosend
Gosub writelcddata
Next i
Gosub endstreamread
Return
Note that in the initialiseeeprom routine we actually blank the Flash chip and write some data to it. In the final version of this code, we'll transfer data to Flash eeprom via a USB connection, but read it back just the same. Although this is just a basic test, it proves the idea of us storing character/player information in eeprom and calling it up and displaying it on a character-based LCD. All with just a few extra wires from the master microcontroller.
[photo or video goes here]
Note that in this example we're using a rather tiny 2x16 character LCD (because we had some hanging around). We've got our fingers crossed that Santa will bring some larger 4x20 displays, like the one below which uses the same Hitachi 44780 controller chip, so the code should work for both.
With four lines of twenty characters, we can split player names over two lines (to allow really long forenames/surnames) and write player stats (MA, ST, AG, AV) on a single line - each stat (0-9) would take up four characters (XX-digit-space) so the output could look something like
GRIFF
OBERWALD
MA4 ST5 AG8 AV9
OBERWALD
MA4 ST5 AG8 AV9
Or, if we can get the player's name on a single line, something like:
GRIFF OBERWALD
MA ST AG AV
4 5 8 9
MA ST AG AV
4 5 8 9
Labels:
18F4550,
AT45DB041D,
blood bowl,
character lcd,
hitatchi 44780
Serial-to-parallel LCD display driver
Amazingly we managed to get a working serial character LCD in under an hour today!
Just followed the schematics at http://embedded-lab.com/blog/?p=30 and converted the code example they gave into Oshonsoft Basic. Fired it up and there we go - a blinking "Hello World!" message using just three pins on the microcontroller.
If, like us here at Nerd Towers, you're an Oshonsoft fan, here's the code listing to get everything working:
Just followed the schematics at http://embedded-lab.com/blog/?p=30 and converted the code example they gave into Oshonsoft Basic. Fired it up and there we go - a blinking "Hello World!" message using just three pins on the microcontroller.
The only real issue we had was that the contrast isn't brilliant; instead of a 10K linear pot, we've gone and used the first potentiometer that was to hand (a 1M logarithmic pot!)
If, like us here at Nerd Towers, you're an Oshonsoft fan, here's the code listing to get everything working:
AllDigital
Config PORTC = Output
configuration:
Symbol enablepin = PORTC.0
Symbol clockpin = PORTC.1
Symbol datapin = PORTC.2
declarations:
Dim i As Byte
Dim lcdi As Byte
Dim lcdbyte As Byte
Dim lcdbytetosend As Byte
Dim rs As Bit
Dim flag As Byte
Dim mask As Byte
init:
Gosub initialiselcd
loop:
lcdbytetosend = 32
Gosub writelcddata
lcdbytetosend = "H"
Gosub writelcddata
lcdbytetosend = "e"
Gosub writelcddata
lcdbytetosend = "l"
Gosub writelcddata
lcdbytetosend = "l"
Gosub writelcddata
lcdbytetosend = "o"
Gosub writelcddata
lcdbytetosend = 32
Gosub writelcddata
lcdbytetosend = "W"
Gosub writelcddata
lcdbytetosend = "o"
Gosub writelcddata
lcdbytetosend = "r"
Gosub writelcddata
lcdbytetosend = "l"
Gosub writelcddata
lcdbytetosend = "d"
Gosub writelcddata
lcdbytetosend = "!"
Gosub writelcddata
WaitMs 4000
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
WaitMs 2000
Goto loop
End
writelcdnibble:
Low enablepin
Low clockpin
If rs = 1 Then High datapin Else Low datapin
Gosub toggleclockpin
'shift in 4 bits
mask = 8
For lcdi = 1 To 4
flag = lcdbyte And mask
If flag = 0 Then Low datapin Else High datapin
Gosub toggleclockpin
mask = ShiftRight(mask, 1)
Next lcdi
'now strobe the clock one more time because ST+SC are tied
Gosub toggleclockpin
'toggle the enable pin to "flush" the data into the lcd
Low datapin
High enablepin
Low enablepin
Return
toggleclockpin:
'toggle the clock pin
High clockpin
Low clockpin
Return
writelcddata:
rs = 1
Gosub senddata
Return
writelcdcommand:
rs = 0
Gosub senddata
Return
senddata:
lcdbyte = ShiftRight(lcdbytetosend, 4)
Gosub writelcdnibble
lcdbyte = lcdbytetosend And 15
Gosub writelcdnibble
Return
initialiselcd:
For i = 1 To 3
WaitMs 50
lcdbytetosend = 0x20
Gosub writelcdcommand
Next i
WaitMs 50
lcdbytetosend = 0x28 '4 bits, 2 lines, 5x7 font
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x0c 'display on, no cursors
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x06 'entry mode auto-increment
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
Return
Config PORTC = Output
configuration:
Symbol enablepin = PORTC.0
Symbol clockpin = PORTC.1
Symbol datapin = PORTC.2
declarations:
Dim i As Byte
Dim lcdi As Byte
Dim lcdbyte As Byte
Dim lcdbytetosend As Byte
Dim rs As Bit
Dim flag As Byte
Dim mask As Byte
init:
Gosub initialiselcd
loop:
lcdbytetosend = 32
Gosub writelcddata
lcdbytetosend = "H"
Gosub writelcddata
lcdbytetosend = "e"
Gosub writelcddata
lcdbytetosend = "l"
Gosub writelcddata
lcdbytetosend = "l"
Gosub writelcddata
lcdbytetosend = "o"
Gosub writelcddata
lcdbytetosend = 32
Gosub writelcddata
lcdbytetosend = "W"
Gosub writelcddata
lcdbytetosend = "o"
Gosub writelcddata
lcdbytetosend = "r"
Gosub writelcddata
lcdbytetosend = "l"
Gosub writelcddata
lcdbytetosend = "d"
Gosub writelcddata
lcdbytetosend = "!"
Gosub writelcddata
WaitMs 4000
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
WaitMs 2000
Goto loop
End
writelcdnibble:
Low enablepin
Low clockpin
If rs = 1 Then High datapin Else Low datapin
Gosub toggleclockpin
'shift in 4 bits
mask = 8
For lcdi = 1 To 4
flag = lcdbyte And mask
If flag = 0 Then Low datapin Else High datapin
Gosub toggleclockpin
mask = ShiftRight(mask, 1)
Next lcdi
'now strobe the clock one more time because ST+SC are tied
Gosub toggleclockpin
'toggle the enable pin to "flush" the data into the lcd
Low datapin
High enablepin
Low enablepin
Return
toggleclockpin:
'toggle the clock pin
High clockpin
Low clockpin
Return
writelcddata:
rs = 1
Gosub senddata
Return
writelcdcommand:
rs = 0
Gosub senddata
Return
senddata:
lcdbyte = ShiftRight(lcdbytetosend, 4)
Gosub writelcdnibble
lcdbyte = lcdbytetosend And 15
Gosub writelcdnibble
Return
initialiselcd:
For i = 1 To 3
WaitMs 50
lcdbytetosend = 0x20
Gosub writelcdcommand
Next i
WaitMs 50
lcdbytetosend = 0x28 '4 bits, 2 lines, 5x7 font
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x0c 'display on, no cursors
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x06 'entry mode auto-increment
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
Return
Labels:
character lcd,
hitatchi 44780,
oshonsoft,
serial,
shift register
Back from Berlin
We've not really spoken much about our few days away in Berlin. Neither online, nor between ourselves. Which is a shame because we were really excited about going there and visiting a few of the different hackspaces. The problem was that the Kreuzberg region of Berlin where we were staying was pretty rough. And the so-called "hostel" we'd be invited to was little more than a doss-house squat.
After just a few days of living in squalor we changed our flights and came home. We never got to see any of the different 'spaces we'd planned on visiting scattered around the city (we'd arranged to visit the betahaus the morning after we'd arrived, which is also in Kreuzberg but got lost trying to find it!)
Graffitti is everywhere in Berlin - and especially so in Kruezberg. There are very few pictures or pieces of artwork (as shown in this photo) mostly it's mindless scrawlings, tags drawn in marker pen, and political slogans written in English.
There's a difference between "post-punk-industrial-style" and just filthy squalor. Coupled with a three-day "festival" during which thumping drum-n-bass played from midnight 'til around 10am (meaning no-one slept for the duration of the trip) we'd had enough after just a few days! Needless to say, it'll be some time before we endure another EasyJet flight to Germany's capital city!
After just a few days of living in squalor we changed our flights and came home. We never got to see any of the different 'spaces we'd planned on visiting scattered around the city (we'd arranged to visit the betahaus the morning after we'd arrived, which is also in Kreuzberg but got lost trying to find it!)
Graffitti is everywhere in Berlin - and especially so in Kruezberg. There are very few pictures or pieces of artwork (as shown in this photo) mostly it's mindless scrawlings, tags drawn in marker pen, and political slogans written in English.
There's a difference between "post-punk-industrial-style" and just filthy squalor. Coupled with a three-day "festival" during which thumping drum-n-bass played from midnight 'til around 10am (meaning no-one slept for the duration of the trip) we'd had enough after just a few days! Needless to say, it'll be some time before we endure another EasyJet flight to Germany's capital city!
Serial-to-parallel character LCD communication
We're getting close to hooking up all the component parts and testing our Blood Bowl game board. The master chip uses UART/serial to talk to the slave, so we've no easy means of talking to the master chip (in a lot of our 18F-based development we usually hook the chip up to a PC using USB to read data directly from the registers - even if USB won't be used in the final design - but this won't be possible in this case, since we can't run UART and USB together)
Since our game board will include two LCD character displays, we figured we could hook those up and use them to write out debug information during testing. In an attempt to keep as many pins free on our master chip, we're looking at converting an HD44780 parallel display into a serial LCD as in this article:
http://embedded-lab.com/blog/?p=30
So before we go plugging everything together and spending hours wondering why things aren't quite working properly, we're going to make a separate project which concentrates on just displaying the information we want on a 3-wire serial LCD (in our final project we'll be using two 20x4 character displays, one green, one blue. But they're on Santa's Xmas Wishlist and not likely to arrive before the big day, so we'll try things out with an old 2x16 that's lying around in the toolbox).
Since our game board will include two LCD character displays, we figured we could hook those up and use them to write out debug information during testing. In an attempt to keep as many pins free on our master chip, we're looking at converting an HD44780 parallel display into a serial LCD as in this article:
http://embedded-lab.com/blog/?p=30
So before we go plugging everything together and spending hours wondering why things aren't quite working properly, we're going to make a separate project which concentrates on just displaying the information we want on a 3-wire serial LCD (in our final project we'll be using two 20x4 character displays, one green, one blue. But they're on Santa's Xmas Wishlist and not likely to arrive before the big day, so we'll try things out with an old 2x16 that's lying around in the toolbox).
Blood Bowl miniatures
Back in the late 80s, Blood Bowl was all the rage, even with the cool kids who didn't even know that it had anything to do with Warhammer Fantasy miniatures, nor that Dungeons & Dragons was a game and not just an animated cartoon series on kids' TV.
Sadly none of our miniatures survived many house moves over the years (we've been nerds for a long time) - and maddeningly, the earlier, rarer pieces are commanding quite a price on eBay these days! Rather than pay over £30 for a team of original pieces, we've been looking for something a bit cheaper....
The original Blood Bowl teams were heavily armoured, with each character having lots of spikes, pads, over-sized shoulder pads and the like. The miniatures in the different teams looked very much like their Warhammer fantasy war-gaming counterparts (only without weapons).
The original Games Workshop Blood Bowl miniatures followed in this line.
But for us, Blood Bowl is first and foremost a strategy game of fantasy football that happens to include goblins and orcs and elves and other fantasy races. It's the game of football that makes the game fun and interesting to play, not the creatures that make up the different teams.
So it was really quite refreshing to find a team that were not only relatively cheap to buy (albeit second-hand) but they look more like a football team than a murdering crowd of goblins from Dungeons & Dragons:
Of course, for testing our electronic game board we can use copper discs (two pence pieces are the perfect size) but the whole thing would look much more like a board game with the correct pieces on it! Unfortunately it's that time of year again where buying stuff willy-nilly off the internet is out of the question, as friends and family members are on the look-out for gift ideas; so we'll just have to sit tight and see what Santa brings in a few weeks. In the meantime, there's the board to finish so we'll post some more updates here soon......
Sadly none of our miniatures survived many house moves over the years (we've been nerds for a long time) - and maddeningly, the earlier, rarer pieces are commanding quite a price on eBay these days! Rather than pay over £30 for a team of original pieces, we've been looking for something a bit cheaper....
The original Blood Bowl teams were heavily armoured, with each character having lots of spikes, pads, over-sized shoulder pads and the like. The miniatures in the different teams looked very much like their Warhammer fantasy war-gaming counterparts (only without weapons).
The original Games Workshop Blood Bowl miniatures followed in this line.
But for us, Blood Bowl is first and foremost a strategy game of fantasy football that happens to include goblins and orcs and elves and other fantasy races. It's the game of football that makes the game fun and interesting to play, not the creatures that make up the different teams.
So it was really quite refreshing to find a team that were not only relatively cheap to buy (albeit second-hand) but they look more like a football team than a murdering crowd of goblins from Dungeons & Dragons:
Of course, for testing our electronic game board we can use copper discs (two pence pieces are the perfect size) but the whole thing would look much more like a board game with the correct pieces on it! Unfortunately it's that time of year again where buying stuff willy-nilly off the internet is out of the question, as friends and family members are on the look-out for gift ideas; so we'll just have to sit tight and see what Santa brings in a few weeks. In the meantime, there's the board to finish so we'll post some more updates here soon......
Tuesday 13 December 2011
Blood Bowl electronic board - slave board complete
Here's a quick update on our slave board for the Blood Bowl electronic board
The top board is underside of the slave board, which is basically a 40-pin 16F877A (any 40-pin PIC with hardware UART/USART would do, even the 18F4550 - but you'd be spending a lot more than necessary on your slave chip and not using most of the peripherals that you'd paid for! We just used one of the many 16F chips we had knocking around, not necessarily the cheapest/best fit for the job. One of the cheaper 16Fs from Farnell is the 16F1939 available for about £2.80 per unit)
The bottom board shows an arrangement of four 1x4 board modules (ok, it's actually 2 of our earlier 2x4 boards but the wiring is exactly the same!) We've wired them so that the two boards vertically share the same "row" signal wire. So both the boards on the left will come "live" at the same time, when row1 is sent high by the master board. Then the boards on the right will both come on at the same time. The two orange wires are the "row" signal wires and will connect to the master controller. The grey wires (to the left) will connect to the inputs on the slave controller.
Although not immediately obvious from the nasty photo (iPad cameras are about as good as cheap HP ones in low light) the slave board is simply a PIC microcontroller, a crystal, 4 wires (1 power, 1 ground, 1 serial TX, 1 serial trigger/handshaking line on the RX pin) and all the remaining digital i/o pins pulled to ground through some 100K SMT resistors.
The top board is underside of the slave board, which is basically a 40-pin 16F877A (any 40-pin PIC with hardware UART/USART would do, even the 18F4550 - but you'd be spending a lot more than necessary on your slave chip and not using most of the peripherals that you'd paid for! We just used one of the many 16F chips we had knocking around, not necessarily the cheapest/best fit for the job. One of the cheaper 16Fs from Farnell is the 16F1939 available for about £2.80 per unit)
The bottom board shows an arrangement of four 1x4 board modules (ok, it's actually 2 of our earlier 2x4 boards but the wiring is exactly the same!) We've wired them so that the two boards vertically share the same "row" signal wire. So both the boards on the left will come "live" at the same time, when row1 is sent high by the master board. Then the boards on the right will both come on at the same time. The two orange wires are the "row" signal wires and will connect to the master controller. The grey wires (to the left) will connect to the inputs on the slave controller.
Although not immediately obvious from the nasty photo (iPad cameras are about as good as cheap HP ones in low light) the slave board is simply a PIC microcontroller, a crystal, 4 wires (1 power, 1 ground, 1 serial TX, 1 serial trigger/handshaking line on the RX pin) and all the remaining digital i/o pins pulled to ground through some 100K SMT resistors.
Blood Bowl board game slave board
Our intelligent Blood Bowl game board consists of two PIC micros which talk to each other via serial (during testing we're using 9600 baud but will crank this up for the final version). The slave board is simply a 40-pin 16F877A with pull-down resistors on all the digital i/o pins.
To allow for maximum flexibility, we're designing this slave board to accept as wide a range of PIC microcontrollers as possible, including some of the 18F series chips (if you have some hanging around from other projects, why not use them instead of buying in new?) Allowing for the power, ground, TX and RX pins (which are in the same place in the 40-pin 16F and 18F chips), as well as the useless Vusb pin on the 18F (useless in this case since we can't use UART and USB together) and the handshaking line we've got a maximum of 30 input pins (we could use the RX pin for handshaking, but for now we'll keep that clear in case we can come up with a use for it in future). In the diagram above, all available i/o pins have been taken out to a set of SMT (1206 sized) resistor pads, and all the resistors are tied to ground (making them pull-down resistors on each input).
30 inputs is an awkward number to work with since each board module is 4 squares in size the maximum number of inputs we can use is 28 (4*7=28). So we've got two free input pins on the slave board should the need arise, as we develop the concept further.
Slave Board
To allow for maximum flexibility, we're designing this slave board to accept as wide a range of PIC microcontrollers as possible, including some of the 18F series chips (if you have some hanging around from other projects, why not use them instead of buying in new?) Allowing for the power, ground, TX and RX pins (which are in the same place in the 40-pin 16F and 18F chips), as well as the useless Vusb pin on the 18F (useless in this case since we can't use UART and USB together) and the handshaking line we've got a maximum of 30 input pins (we could use the RX pin for handshaking, but for now we'll keep that clear in case we can come up with a use for it in future). In the diagram above, all available i/o pins have been taken out to a set of SMT (1206 sized) resistor pads, and all the resistors are tied to ground (making them pull-down resistors on each input).
30 inputs is an awkward number to work with since each board module is 4 squares in size the maximum number of inputs we can use is 28 (4*7=28). So we've got two free input pins on the slave board should the need arise, as we develop the concept further.
Slave Board
Saturday 3 December 2011
Intelligent board game (Blood Bowl) development
Here are some photos of the latest board game development;
although we're working on a Blood Bowl clone, the same technology could - in theory - be used for a large number of games, with different board sizes. To date, we've settled on a 4-square module and will make our board game(s) up from this/these.
These photos are from our 4x2 boards (earlier design) but the principles work the same for both.
On the sides of each playing square (N,S,E and W) we drilled a 1mm hole and soldered some pcb studs
The studs are slightly raised on the playing surface of the game board. This isn't as nasty as it sounds - for our Blood Bowl game, it means we can add some "flocking" or similar covering but still get the playing pieces to make a good contact with the pins.
The plan is to weight our playing piece bases with a small copper disk (something like a 2 pence piece would be ideal, only we don't want to get thrown in prison for "defacing a coin of the realm" or whatever the punishment is these days!). Placing these on the playing side of the board bridges the two connections between the "rows" output pin on the master controller and the "columns" input pin on the slave - so when the slave is asked "which inputs are high/low" this can be used to work out which squares have playing pieces on them.
The tracking of which playing piece is on which square will be done by the master IC. For these early prototypes, we're more concerned about proving the concept of tracking which piece is being lifted/replaced to/from the board.
although we're working on a Blood Bowl clone, the same technology could - in theory - be used for a large number of games, with different board sizes. To date, we've settled on a 4-square module and will make our board game(s) up from this/these.
These photos are from our 4x2 boards (earlier design) but the principles work the same for both.
On the sides of each playing square (N,S,E and W) we drilled a 1mm hole and soldered some pcb studs
The studs are slightly raised on the playing surface of the game board. This isn't as nasty as it sounds - for our Blood Bowl game, it means we can add some "flocking" or similar covering but still get the playing pieces to make a good contact with the pins.
stupid cheap HP camera - even in "macro mode" it doesn't quite know what to focus on!
The plan is to weight our playing piece bases with a small copper disk (something like a 2 pence piece would be ideal, only we don't want to get thrown in prison for "defacing a coin of the realm" or whatever the punishment is these days!). Placing these on the playing side of the board bridges the two connections between the "rows" output pin on the master controller and the "columns" input pin on the slave - so when the slave is asked "which inputs are high/low" this can be used to work out which squares have playing pieces on them.
once again, a nice focussing job by our little HP camera
The tracking of which playing piece is on which square will be done by the master IC. For these early prototypes, we're more concerned about proving the concept of tracking which piece is being lifted/replaced to/from the board.
Thursday 1 December 2011
Creating the playing squares for an intelligent board game board
While toner-transferring and etching our game board "modules" something became obvious - though it's not something we'd thought of when designing our PCBs. The photo below shows our game board etched onto a piece of eurocard sized (160mm x 100mm) copper-clad board
While trimming to size, we realised that the bit cut off the bottom was almost exactly the right size for a single row of 4 playing squares (the printed module above shows a 2x4 grid of playing squares). It then occurred to us that there's no real reason why we couldn't create modules that were 1x4 instead of 2x4.
After all, the top row still has to be connected to the bottom row using a wire jumper/via even when they are drawn/etched on the same piece of board. So here's the new PCB layout for four playing squares at a time:
Since the spacing of the playing squares is 30mm (standard Blood Bowl size) the PCB is also 30mm high (with the playing squares pretty much in the middle of each "strip" of 1x4 squares).
If you want smaller playing squares, simply resize the whole PCB. The overall size will shrink to match the size of each playing square so they should still be able to be cut to size and placed side-by-side, without affecting the spacing between playing squares.
A little bit of multi-core wire or maybe even some gloopy solder should connect the two boards, edge-to-edge.
Testing multi-plexed LEDs for word clock
Having ditched the impossible-to-debug charlie-plexing idea, we've made up a board which simply places LEDs in columns and rows.
We're going to drive the "rows" through a shift-register (to allow more than 20mA current to be sourced) and sink them through a number of ULN2803A darlington arrays (since sinking directly to the microcontroller pin would only allow up to 20mA per row which could make a full row of lit-up LEDs appear quite dim).
Before we get clever with the sinking and sourcing, we needed to make sure that our array of LEDs worked - and to test it we simply connected the +ve and -ve terminals of a 3V coin-cell battery to the different lines on the PCB.
By touching the exposed wire ends to the positive and negative terminals of a 3V battery, we were able to confirm that every LED in the array worked individually of the others.
We're going to drive the "rows" through a shift-register (to allow more than 20mA current to be sourced) and sink them through a number of ULN2803A darlington arrays (since sinking directly to the microcontroller pin would only allow up to 20mA per row which could make a full row of lit-up LEDs appear quite dim).
Before we get clever with the sinking and sourcing, we needed to make sure that our array of LEDs worked - and to test it we simply connected the +ve and -ve terminals of a 3V coin-cell battery to the different lines on the PCB.
By touching the exposed wire ends to the positive and negative terminals of a 3V battery, we were able to confirm that every LED in the array worked individually of the others.
Wednesday 30 November 2011
Serial/UART communication between two PICs (18F and 16F)
It's taken a long time and a lot of different approaches to get even simple serial communication between two PICs working. Perhaps hampered a little by using two different PICs (a 16F and an 18F series chip) but that really shouldn't make any difference. Serial/UART communication shouldn't be platform dependent!
We've tried serial/UART, SPI, I2C and even bit-banging and each time got different (non-working) results. It's too much to go into in this blog post, so we're just going to describe how we actually got a working prototype:
The first thing to note is that although we're using one of our favoured 18F4550 PICs, we couldn't use the USB and UART together. So for this experiment, we're reading the data back off our 18F (master) chip via serial, using the excellent PICKit2 programmer and software.
In our first (failed) attempt at creating pic-to-pic communication, we had our 16F (slave) device monitoring it's input pins and simply broadcasting the results as an 8-byte message over UART. The idea was for the 18F (master) chip to read this serial stream at intervals, find the start of the message and decode the rest of it, so that it knows the state of the slave chip.
In theory this sounds fine. In practice, sending more than about 4 bytes to the 18F (master) chip caused it to lock up on the Hserin command. We even tried connecting the PICKit2 to the RX pin on the 18F and removed our slave chip altogether. Our tests confirmed the same thing happening - if we sent one or two bytes at a time to the 18F from the PICKit2 terminal, it successfully received them and sent a response message back. If we sent more than about five bytes at a time, the 18F simply stopped responding - apparently locking up at the point where it reads in the serial data
(we proved this by switching an LED on just before the Hserin command, and turning it off again immediately after).
So it appears that we have a set-up whereby we can receive data from our slave, one byte at a time, but the master can't simply "dip in" to a serial stream being "broadcast" by the slave. After reading through the datasheet, it seems that the 18F has only a two (or was it four) byte buffer so blasting more bytes into the buffer than it can handle is causing some sort of buffer overrun error.
We need some way of getting the master chip to ask for data, one byte at a time.
This is what we came up with:
The master chip sends a pin high then requests a byte from the serial buffer.
The slave chip monitors the state of the "handshaking" line. When the line goes high, and the previous line state is low, this represents a request from the master, so send one byte.
Because we're using hardware UART on the master chip, after the line goes high, the code waits until a byte has arrived in the serial buffer. Because the slave only sends a byte on a low-to-high transition on the handshaking pin, we don't have to worry about buffer under-runs or errors in the master chip.
Slave code
Master code
AllDigital
declarations:
Dim a1 As Byte
Dim a2 As Byte
Symbol lineshake = PORTA.0
Config PORTA.0 = Output
init:
Low PORTA.0
WaitMs 200
Hseropen 9600
WaitMs 200
loop:
Gosub getnextbyte
'two 255 = start of message
Hserout 255
Hserout 255
Hserout a1
Goto loop
End
getnextbyte:
'to get the next byte, we send the lineshaking
'line high - this tells the slave to "release"
'another byte. Once we have this byte, we drive
'the lineshaking pin low to say we're done
High lineshake
Hserin a1
Low lineshake
Return
After connecting up the slave to the master (the TX pin of the slave into the RX pin of the master, and RA.0 on the master to RB.0 on the slave) we did actually start receiving intelligible data from the master. So it looks like we've (finally) cracked pic-to-pic communication over serial.
It's probably a bit slower than it needs to be (since the master has to "poll" each byte from the slave) but it's fast enough for what we want - and once we crank the baud rate up from 9600 to about 57600, or even 115200, it should be more than quick enough to scan an entire game board (of not more than 16 x 28 = 448 squares) at a reasonable rate.
We've tried serial/UART, SPI, I2C and even bit-banging and each time got different (non-working) results. It's too much to go into in this blog post, so we're just going to describe how we actually got a working prototype:
The first thing to note is that although we're using one of our favoured 18F4550 PICs, we couldn't use the USB and UART together. So for this experiment, we're reading the data back off our 18F (master) chip via serial, using the excellent PICKit2 programmer and software.
In our first (failed) attempt at creating pic-to-pic communication, we had our 16F (slave) device monitoring it's input pins and simply broadcasting the results as an 8-byte message over UART. The idea was for the 18F (master) chip to read this serial stream at intervals, find the start of the message and decode the rest of it, so that it knows the state of the slave chip.
In theory this sounds fine. In practice, sending more than about 4 bytes to the 18F (master) chip caused it to lock up on the Hserin command. We even tried connecting the PICKit2 to the RX pin on the 18F and removed our slave chip altogether. Our tests confirmed the same thing happening - if we sent one or two bytes at a time to the 18F from the PICKit2 terminal, it successfully received them and sent a response message back. If we sent more than about five bytes at a time, the 18F simply stopped responding - apparently locking up at the point where it reads in the serial data
(we proved this by switching an LED on just before the Hserin command, and turning it off again immediately after).
So it appears that we have a set-up whereby we can receive data from our slave, one byte at a time, but the master can't simply "dip in" to a serial stream being "broadcast" by the slave. After reading through the datasheet, it seems that the 18F has only a two (or was it four) byte buffer so blasting more bytes into the buffer than it can handle is causing some sort of buffer overrun error.
We need some way of getting the master chip to ask for data, one byte at a time.
This is what we came up with:
The master chip sends a pin high then requests a byte from the serial buffer.
The slave chip monitors the state of the "handshaking" line. When the line goes high, and the previous line state is low, this represents a request from the master, so send one byte.
Because we're using hardware UART on the master chip, after the line goes high, the code waits until a byte has arrived in the serial buffer. Because the slave only sends a byte on a low-to-high transition on the handshaking pin, we don't have to worry about buffer under-runs or errors in the master chip.
Slave code
'4Mhz external clock
Define CONF_WORD = 0x3f31
Define CLOCK_FREQUENCY = 4
AllDigital
Config PORTB = Input
Config PORTD = Input
Config PORTC = Input
Config PORTA = Input
declarations:
Dim linestate As Bit
Dim lastlinestate As Bit
Dim a1 As Byte
Dim a2 As Byte
Dim a3 As Byte
Dim a4 As Byte
Dim a5 As Byte
Dim xorval As Byte
Dim bytecounter As Byte
init:
WaitMs 50
Hseropen 9600
WaitMs 50
linestate = 0
lastlinestate = 0
bytecounter = 1
loop:
'all the slave does is read a whole load of input pins
'and write the response back to the master. The master chip
'will decide which "row" is live, this chip just takes all
'the "column" data and sends it back to the master.
'RA0-5
'RB1-7
'RC0-5 (6&7 are TX/RX)
'RD0-7
'RE0-2
'this should give us 6+7+6+8+3 = 30 inputs
a1 = PORTA And 63 '(mask off bits 7+6)
a2 = PORTB And 254 '(make off bit 0, handshake line)
a3 = PORTC And 63
a4 = PORTD
a5 = PORTE And 7
'now stream the values as a response back to the slave
'all messages begin 255,255 (since this sequence is not
'possible in the input stream because we bitmask bytes 1,3,5)
linestate = PORTB.0
If linestate = 1 And lastlinestate = 0 Then
'the host chip has asked for another byte of data
'create the checksum value
xorval = 0
xorval = xorval Xor a1
xorval = xorval Xor a2
xorval = xorval Xor a3
xorval = xorval Xor a4
xorval = xorval Xor a5
xorval = xorval And 127
'decide which byte of the message to send
'(the host has to ask for each message eight times for all 8 bytes)
Select Case bytecounter
Case 1
Hserout 255
Case 2
Hserout 255
Case 3
Hserout a1
Case 4
Hserout a2
Case 5
Hserout a3
Case 6
Hserout a4
Case 7
Hserout a5
Case 8
Hserout xorval
bytecounter = 0
EndSelect
bytecounter = bytecounter + 1
Endif
lastlinestate = linestate
Goto loop
End
Define CONF_WORD = 0x3f31
Define CLOCK_FREQUENCY = 4
AllDigital
Config PORTB = Input
Config PORTD = Input
Config PORTC = Input
Config PORTA = Input
declarations:
Dim linestate As Bit
Dim lastlinestate As Bit
Dim a1 As Byte
Dim a2 As Byte
Dim a3 As Byte
Dim a4 As Byte
Dim a5 As Byte
Dim xorval As Byte
Dim bytecounter As Byte
init:
WaitMs 50
Hseropen 9600
WaitMs 50
linestate = 0
lastlinestate = 0
bytecounter = 1
loop:
'all the slave does is read a whole load of input pins
'and write the response back to the master. The master chip
'will decide which "row" is live, this chip just takes all
'the "column" data and sends it back to the master.
'RA0-5
'RB1-7
'RC0-5 (6&7 are TX/RX)
'RD0-7
'RE0-2
'this should give us 6+7+6+8+3 = 30 inputs
a1 = PORTA And 63 '(mask off bits 7+6)
a2 = PORTB And 254 '(make off bit 0, handshake line)
a3 = PORTC And 63
a4 = PORTD
a5 = PORTE And 7
'now stream the values as a response back to the slave
'all messages begin 255,255 (since this sequence is not
'possible in the input stream because we bitmask bytes 1,3,5)
linestate = PORTB.0
If linestate = 1 And lastlinestate = 0 Then
'the host chip has asked for another byte of data
'create the checksum value
xorval = 0
xorval = xorval Xor a1
xorval = xorval Xor a2
xorval = xorval Xor a3
xorval = xorval Xor a4
xorval = xorval Xor a5
xorval = xorval And 127
'decide which byte of the message to send
'(the host has to ask for each message eight times for all 8 bytes)
Select Case bytecounter
Case 1
Hserout 255
Case 2
Hserout 255
Case 3
Hserout a1
Case 4
Hserout a2
Case 5
Hserout a3
Case 6
Hserout a4
Case 7
Hserout a5
Case 8
Hserout xorval
bytecounter = 0
EndSelect
bytecounter = bytecounter + 1
Endif
lastlinestate = linestate
Goto loop
End
Master code
AllDigital
declarations:
Dim a1 As Byte
Dim a2 As Byte
Symbol lineshake = PORTA.0
Config PORTA.0 = Output
init:
Low PORTA.0
WaitMs 200
Hseropen 9600
WaitMs 200
loop:
Gosub getnextbyte
'two 255 = start of message
Hserout 255
Hserout 255
Hserout a1
Goto loop
End
getnextbyte:
'to get the next byte, we send the lineshaking
'line high - this tells the slave to "release"
'another byte. Once we have this byte, we drive
'the lineshaking pin low to say we're done
High lineshake
Hserin a1
Low lineshake
Return
After connecting up the slave to the master (the TX pin of the slave into the RX pin of the master, and RA.0 on the master to RB.0 on the slave) we did actually start receiving intelligible data from the master. So it looks like we've (finally) cracked pic-to-pic communication over serial.
It's probably a bit slower than it needs to be (since the master has to "poll" each byte from the slave) but it's fast enough for what we want - and once we crank the baud rate up from 9600 to about 57600, or even 115200, it should be more than quick enough to scan an entire game board (of not more than 16 x 28 = 448 squares) at a reasonable rate.
Communication between two PIC microcontrollers
We're having a bit of a nightmare getting two PICs to talk to each other.
The master is an 18F4550 which will do most of the grunt work and talks to the PC host via USB (we use Oshonsoft's excellent USB/HID library for our USB work).
The slave is a 16F877A (no reason for this particular model other than we had quite a few of these lying around). This basic idea is that the 16F reads 28 input pins and writes a four-byte value out to the serial port.
The master periodically polls the slave, reading the serial data. It looks for two specific bytes which signify the start of the message, then reads in the next four bytes that make up the message (the fifth byte is the XOR sum of the previous four bytes so we have some sort of checksum).
The problem is that while we can check the 16F using the PICKit2 UART tool - and it successfully reads the message being "broadcast" by the slave - when we try to read data using the hardware UART port on the 18F master chip, the USB comms lock up and our PC app stops working.
It seems that we aren't the first people to run into this sort of problem and there are lots of queries across the 'net asking for help with USB and serial comms together. Here's just one example:
So it looks like USB and UART together isn't going to work.
Which is a bit of a bummer.
Also, like the author of the article above, we were also hoping to use the timer1 interrupt to keep a simple clock running, which makes software-based bit-banging and no-go either. Getting a PIC to work as an I2C slave looks quite complicated too, so we're running out of ideas.
The only thing left for us to try is getting two PICs talking to either other using SPI hardware on both the master and slave chips.
Hopefully this will work with both USB and timer1 interrupts running on the master chip. But until we try, we're not going to know......
PIC16F877A resetting
This is just a general post to remind anyone like me who often forgets the basics and spends far too long trying to find faults with hardware/firmware that just aren't there.
Although in my case, it's specific to my 18F877A, the same rules apply to 16F628A chips and pretty much any of the 16F range.
Here's why I'm so stupid......
You can connect anything that uses serial comms, and set the baud rate to any of the common bps values - 1200, 2400, 4800, 9600, 19200, 38400 etc as well as your own custom baud rate (ideal for debugging MIDI devices at 31250)
Anyway, after connecting everything up, setting it running and not touching a thing, the 16F would periodically shut down. I stripped out all the wires, rewired the board with a brand new set of jumper wires, put LEDs on all kinds of output pins and so on. I checked and double-checked the fuses, made sure the watchdog timer was disabled (and even tried enabling it and littering the firmware with watchdog reset commands) and checked the brown-out option wasn't selected. I even put a few different capacitors on the power rail of the 16F, just in case the input voltage was getting a bit wobbly.
The whole thing was suddenly a lot more complicated than any other PIC project I'd ever worked on and still it kept resetting.....
.... that's when I remembered that pin one (MCLR) has to be pulled high to stop the, erm, PIC from resetting all the time. Bugger.
It was as simple as that!
A single wire from pin one to 5V and everything worked beautifully.
If I had remembered about the MCLR pin earlier, instead of assuming it was always set to behave as an in input pin I think I'd have saved myself about two hours this evening.
Hopefully this post will help others in future to avoid wasting a similar amount of time on something so trivial!
Here's why I'm so stupid......
I've been working a lot lately with 18F series chips.
These are great because they have loads of different "fuses" which let you set up the chip in a particular way. One of the fuses on the 18F range allows you to reclaim pin one - the MCLR/PGV (programming voltage) pin and set it to an input. I do this with pretty much all my 18F chips.
So when I came back to the old 16F series chips (the 16F877A is an old favourite that first got me interested in PIC programming) I completely forgot that you need to apply 5v to the MCLR pin to stop the chip from resetting (pulling this pin low causes the PIC to reset completely).
So during testing, while trying to read the serial message(s) being "broadcast" from my 16F chip, I kept getting blackouts - periods when the serial stream would stop. Wiggle a few wires around on the breadboard and it would come back to life. For a little while.
Everything was pointing at a hardware problem - either a dodgy wire or a loose crystal or something. I re-wrote the firmware on both the slave and master chips, stripping each down to just the bare essentials, and used a really handy tool in the PICKit2 software to monitor the serial stream
You can connect anything that uses serial comms, and set the baud rate to any of the common bps values - 1200, 2400, 4800, 9600, 19200, 38400 etc as well as your own custom baud rate (ideal for debugging MIDI devices at 31250)
Anyway, after connecting everything up, setting it running and not touching a thing, the 16F would periodically shut down. I stripped out all the wires, rewired the board with a brand new set of jumper wires, put LEDs on all kinds of output pins and so on. I checked and double-checked the fuses, made sure the watchdog timer was disabled (and even tried enabling it and littering the firmware with watchdog reset commands) and checked the brown-out option wasn't selected. I even put a few different capacitors on the power rail of the 16F, just in case the input voltage was getting a bit wobbly.
The whole thing was suddenly a lot more complicated than any other PIC project I'd ever worked on and still it kept resetting.....
.... that's when I remembered that pin one (MCLR) has to be pulled high to stop the, erm, PIC from resetting all the time. Bugger.
It was as simple as that!
A single wire from pin one to 5V and everything worked beautifully.
If I had remembered about the MCLR pin earlier, instead of assuming it was always set to behave as an in input pin I think I'd have saved myself about two hours this evening.
Hopefully this post will help others in future to avoid wasting a similar amount of time on something so trivial!
Electronic board game - Blood Bowl clone
Some interesting developments over the last few evenings as we've put together all kinds of ideas for an intelligent board for a board game (like, our old favourite Blood Bowl).
Our original proposal - based on freeing up as many pins as possible from two 40-pin PIC microcontrollers - was to allow for up to 600 squares, or a grid of 20x30
To allow for as much flexibility as possible, while at the same time making it relatively easy to understand, we've decided on a modular approach. Our board game will actually be made up of a grid of 4x2 "blocks" which can then be wired together in any arrangement. It means we've lost the flexibility of really wacky board layouts (although using the same technology it should be possible to create one-off boards with pretty much any layout as required) but does mean that we can simplify making boards of different dimensions.
(it also means that anyone who buys their copper boards in eurocard 100mmx160mm size can still make a board game, using a "patchwork" of smaller boards)
4x2 Board Piece
Each playing square in this board is marked out by a "cross" shape on the board. Small through-hole studs are soldered to this underside, so that on the playing side of the board, a small contact point is visible on the playing surface. Each playing piece has a conductive base (a copper coin glued to the bottom would suffice!) and when placed over the four points of a cross, makes a connection between the top and right contacts and the bottom/left contacts.
Using the above layout, we can place these pieces side-by-side and join the edges, while connecting each group of top/right contacts together using short pieces of (insulated) wire
Using this approach, we've designed our Blood Bowl board.
It's not quite 30 x 20, but we found that vertically connecting 7 "rows" of 4 contacts means for each row we can read back up to 28 lines of "column" data. By placing four of these smaller boards side-by-side, our board size is 28 x 16 playing squares. Not a bad compromise and certainly a sizeable playing area for a lot of different board games.
So what does it look like? In short, a nightmare!
As you can see, each smaller board is connected to the board horizontally next to it (the traces were deliberately lined up to make this bit quite easy). Every 7 vertical rows of contacts are connected via wire traces (shown in this diagram by different coloured bars) and each group of these 7x4 = 28 contacts is then connected to the slave microcontroller via a short wire (the connection points for these wires are circled in a matching colour).
There are 16 wire connect points - these go to the master PIC. The 28 traces from the bottom/left sets of contact points are connected to the slave. By flashing one of the 16 wires at a time, and reading the input values on the 28 inputs, we should be able to work out which set(s) of contacts are being bridged by a playing piece on the board.
That's the theory anyway.......
Our original proposal - based on freeing up as many pins as possible from two 40-pin PIC microcontrollers - was to allow for up to 600 squares, or a grid of 20x30
To allow for as much flexibility as possible, while at the same time making it relatively easy to understand, we've decided on a modular approach. Our board game will actually be made up of a grid of 4x2 "blocks" which can then be wired together in any arrangement. It means we've lost the flexibility of really wacky board layouts (although using the same technology it should be possible to create one-off boards with pretty much any layout as required) but does mean that we can simplify making boards of different dimensions.
(it also means that anyone who buys their copper boards in eurocard 100mmx160mm size can still make a board game, using a "patchwork" of smaller boards)
4x2 Board Piece
Each playing square in this board is marked out by a "cross" shape on the board. Small through-hole studs are soldered to this underside, so that on the playing side of the board, a small contact point is visible on the playing surface. Each playing piece has a conductive base (a copper coin glued to the bottom would suffice!) and when placed over the four points of a cross, makes a connection between the top and right contacts and the bottom/left contacts.
Using the above layout, we can place these pieces side-by-side and join the edges, while connecting each group of top/right contacts together using short pieces of (insulated) wire
Using this approach, we've designed our Blood Bowl board.
It's not quite 30 x 20, but we found that vertically connecting 7 "rows" of 4 contacts means for each row we can read back up to 28 lines of "column" data. By placing four of these smaller boards side-by-side, our board size is 28 x 16 playing squares. Not a bad compromise and certainly a sizeable playing area for a lot of different board games.
So what does it look like? In short, a nightmare!
As you can see, each smaller board is connected to the board horizontally next to it (the traces were deliberately lined up to make this bit quite easy). Every 7 vertical rows of contacts are connected via wire traces (shown in this diagram by different coloured bars) and each group of these 7x4 = 28 contacts is then connected to the slave microcontroller via a short wire (the connection points for these wires are circled in a matching colour).
There are 16 wire connect points - these go to the master PIC. The 28 traces from the bottom/left sets of contact points are connected to the slave. By flashing one of the 16 wires at a time, and reading the input values on the 28 inputs, we should be able to work out which set(s) of contacts are being bridged by a playing piece on the board.
That's the theory anyway.......
PICKit2 clone programmer alternatives
Something has happened to our faithful old PIC programmer - it was (was being the key word) a PICKit2 clone, iCP01 from piccircuit.com and had worked tirelessly for about three years.
But for some reason, it has suddenly stopped working.
No puff of smoke or funny smell - it just stopped working.
At first it had problems recognising a 16F877A DIP, so - as we always do before wiggling wires - it was removed from the USB port (removing any power from the breadboard) and then when it was plugged in there was no "bing-bong" or any indication that the PC had recognised the USB device.
That's it. Despite stripping off the yellow shrink wrap and inspecting the components on the board (nothing seems to have blown and there's continuity across the connections where you'd expect there to be) the device simply refuses to work.
The PICKit2 software doesn't even recognise that the device is plugged in, and Device Manager fails to identify it too. So it's officially dead. The question is, do we get another one (they're great little programmers and really fast too) or try something else?
But for some reason, it has suddenly stopped working.
No puff of smoke or funny smell - it just stopped working.
At first it had problems recognising a 16F877A DIP, so - as we always do before wiggling wires - it was removed from the USB port (removing any power from the breadboard) and then when it was plugged in there was no "bing-bong" or any indication that the PC had recognised the USB device.
That's it. Despite stripping off the yellow shrink wrap and inspecting the components on the board (nothing seems to have blown and there's continuity across the connections where you'd expect there to be) the device simply refuses to work.
The PICKit2 software doesn't even recognise that the device is plugged in, and Device Manager fails to identify it too. So it's officially dead. The question is, do we get another one (they're great little programmers and really fast too) or try something else?
Tuesday 29 November 2011
Multi-plexing LEDs for word clock
Having failed miserably at debugging our charlie-plexed LED array we've decided to stick to the simpler approach of using multi-plexing.
There's a subtle difference, but since we're already getting down and dirty with multi-plexing for inputs on a board game it made sense to use this same approach for outputs/LEDs. The main difference is that we'll be using a pin for each row and a pin for each column (10 rows x 9 columns = 10+9 = 19 pins).
If we move away from the 16F628A (with 18 pins) and go far a larger chip, with more i/o pins, then multi-plexing gives us a simpler, easier-to-debug solution.
With this in mind, we set about creating a new PCB to use multi-plexing.
So far we've just put a load of LEDs into a grid formation - the actual controller board will be a separate PCB mounted onto the back:
Uln2803a Driven LED array
Here's a photo of the completed board, populated with LEDs, ready for testing.
Unlike last time, testing LEDs is quite straight-forward; and already we've found some potential problems; a lot of the LEDs are re-used from the old board and by connecting a 3v coin-cell battery straight across the anode and cathode of each LED, we've found about half-a-dozen that refuse to light up.
Whether these were damaged during removal, or never actually worked on the original board, we'll never know. But at least we've an explanation as to why the charlie-plexed board didn't work. Sort of.
Anyway, we're going to pop out those duds and test each individual LED on this board before even considering wiring it up to the rest of the project!
There's a subtle difference, but since we're already getting down and dirty with multi-plexing for inputs on a board game it made sense to use this same approach for outputs/LEDs. The main difference is that we'll be using a pin for each row and a pin for each column (10 rows x 9 columns = 10+9 = 19 pins).
If we move away from the 16F628A (with 18 pins) and go far a larger chip, with more i/o pins, then multi-plexing gives us a simpler, easier-to-debug solution.
With this in mind, we set about creating a new PCB to use multi-plexing.
So far we've just put a load of LEDs into a grid formation - the actual controller board will be a separate PCB mounted onto the back:
Uln2803a Driven LED array
Here's a photo of the completed board, populated with LEDs, ready for testing.
Unlike last time, testing LEDs is quite straight-forward; and already we've found some potential problems; a lot of the LEDs are re-used from the old board and by connecting a 3v coin-cell battery straight across the anode and cathode of each LED, we've found about half-a-dozen that refuse to light up.
Whether these were damaged during removal, or never actually worked on the original board, we'll never know. But at least we've an explanation as to why the charlie-plexed board didn't work. Sort of.
Anyway, we're going to pop out those duds and test each individual LED on this board before even considering wiring it up to the rest of the project!
Subscribe to:
Posts (Atom)