Friday 29 November 2013

Running courses with an Arduino Mini Pro in Berlin

Once again, some of the nerds are off to Berlin.
This time, we're going to be running an introduction to electronics course, and getting people started with Arduino and microcontrollers in general. So the first thing we needed, of course, was some components and some Arduinos!


These Arduino clones use the AtMega328 mcu on a small form-factor board, for plugging into a breadboard. So they may not be ideal if you want to use one of the many existing "shields" for the original Arduino. But as a starter board, they're perfect - and super-cheap too. At the time of writing, an Arduino Pro Mini could be had for less than two of your finest English Pounds.

For £2 the board doesn't have a usb-to-serial adapter: you're expected to provide this yourself for programming or running a serial monitor. But another quick flick through eBay, and there are USB-to-serial converters for less than a quid!


(sometimes searching for "usb ttl" returns cheaper alternatives that might otherwise have been missed, if searching for just "usb serial" or even "usb uart")

All in all, we managed to get a load of Arduinos up and working for about £3 each. Not bad at all - especially when having to buy in bulk and pay for everything up front (people at the workshop will pay-on-the-day, so anything to keep the initial outlay down is a great help).


But it's not all plain sailing. The boards arrived yesterday, but it's not simply a case of plugging everything together and it all just works. For £3 an Ardunio, that would just be too easy! The first thing is, if you're using Windows 8, the built-in drivers for a non-FTDI based usb-to-serial converter may not work.
Ours show up as a Prolific USB-to-serial COM port (most converters use some kind of virtual com port)


When we first plugged the device into a Windows 8 machine, it said that the driver was up to date, but the device could not start. This was a little puzzling, so we did some digging about. No-one seems sure about why the newer drivers won't work with Windows 8, but the workaround is to download and use older drivers. We used the driver version 3.3.2


Great - now the board was installed and working. We fired up the Arduino IDE and the COM port was indeed recognised and we were able to select it as the target port for our programmer


Our boards are Arduino Pro Mini, running off 5v with a 16Mhz crystal. There are other variants of these boards available online, so make sure to select the right version of board!

But the fun hadn't ended yet.
With the usb-to-serial device working, and the Arduino connect correctly (tx-to-rx from the usb-to-serial device to the Arduino Pro Mini board) we tried to dump an amended "blink" example to the board, just to check everything was working. It seemed to spend a long time uploading the binary - and then stopped with a failed error message:


A bit like getting stuck on a crossword clue, it took a bit of messing about and trying different things before we gave up and asked Mr Google for the answer. Apparently, the trick with these little boards is to manually hold the device in reset before attempting to program. 

So to get the "sketch" onto the board, hold down the reset button on the Arduino Pro Mini board (they all come with a small pushbutton on them somewhere) and while the reset button is still pressed, hit the upload button in the Arduino IDE.

The IDE will compile the code - keep the reset button pressed. Once the code is compiled, and the IDE reports the message "Uploading...." release the reset button. The upload continues and (hopefully) the message will return to "Done uploading" without the crude avrdude error message in orange! Hopefully.... it did for us!

Monday 25 November 2013

Keypad membrane manufacture

Just had an email through from the factory in China with a couple of photos showing our electronic board game keypad membranes being dry-fit for testing


In the end we had to provide the artwork (which we were a bit nervous about - these guys are the keypad membrane specialists, not us!) but it was only so that the factory could be sure that they'd fully understood our requirements - particularly the bit about leaving a 5mm gutter around the playing surface (not around the inside of the keypad edge).


But here's our keypads being made up after the printing has been completed. Apparently the mould is already made, so the two layers are placed one on top of the other, with a spacer layer between them, and the whole thing is pressed, glued and cut in one go, in the mould.

Exciting stuff! After testing today (it's already quarter to eight in the evening in China, and they're still working on these) they should get made up tomorrow and in the post on Wednesday; all being well, we should have them here by the end of next week. Yay!

Friday 22 November 2013

Telephone dialler (DTMF tone generator using PIC 16F1825) for dementia sufferers

A lady called Pauline popped into BuildBrighton the other day and asked for help with a particular project. Now, quite often, we're all busy with our own projects and very often the odd chancer turns up, with promises of millions of pounds of venture capital seed money who proves nothing more than a distraction - while looking to get their "ground-breaking" invention prototyped for free. These people, we usually give a few pointers to, and let them find their own way towards professional prototyping companies (we're not running a free consultancy service for people to exploit our skills: we're a generous and knowledgeable lot, down at BuildBrighton, but we're not stupid!)

Anyway, Pauline had an idea for a product of a different kind.
And it resonated with a few members who have worked in the public sector - and in particular, within the NHS. Pauline isn't looking to launch a product and try to make a lot of money; she's looking for help making something that will genuinely change lives.

Pauline's mother has mild onset dementia.
She doesn't understand things like the time of day any more. If it's winter, and it's dark, and it's five o'clock, there's no indicator to say whether it's 5am or 5pm (and, having dementia,  her mother can't really understand what am/pm means - or remember what that little dot on the digital clock is actually there for - and a 24-hour clock is just plain confusing).

Because of this, Pauline's mother phones her at all hours of the day - often just to hear a voice, or for reassurance. And sometimes - when it's in the early hours of the morning, the phone might not be answered - which distresses her mother; or it might be (meaning both people are now up and out of bed in the small hours of the morning!)

One solution we came up with was a telephone "auto-dialler".
Something that could monitor which phone numbers were being called, and check the current time (against a real-time clock). If the call were being made during "unsociable hours" the clever gizmo would terminate the call immediately (so it didn't ring at the other end) and then phone an alternative number instead (such as a 24 hour careline). If we can achieve this seamlessly, it means that Pauline can get some sleep during the night, while her mother can be put through to someone on the phone, whatever time she decides to ring!

There are basically two parts to this project:
The first is to be able to monitor the phone line and "read" the DTMF tones generated by the telephone handset as a call is being made. As each tone is received, it is decoded and turned back into a number. If the entire phone number matches one of those in the "redirect these calls please" list, we can look up the time and if it's outside certain hours, hang up the phone.

The second part of the project is actually making the call out to the alternative number.
This is actually the easier part of the project, so that's where we'll start - with a device which can take the phone "off-hook" and dial any number.

We're going to be using an HT9200A DTMF tone generator to make the calls; hooking into the phone lines is serious stuff and not something anyone should do lightly, so for now we're going to concentrate on generating the correct tones to dial any given number.
Here's how we did it:

In this circuit, we're going to play the DTMF tones through a speaker, just to check that everything is working as it should. In the final version, we'll connect to the phone lines through a 1:1 transformer, to ensure everything is safely isolated.

Using the same basic amplification circuit that we used for our clock project a while back, we simply use the DTMF tone to toggle a BS170 transistor, connecting a speaker to ground. The capacitor is simply a DC blocking capacitor, to ensure that we can't accidentally leave DC current running through the coil.

The HT9200A accepts data as 5-bit values (yeah, weird that they didn't go for a full, padded, byte - but the datasheet says five bits, so that's what we'll use) over an I2C interface. I2C is so easy to work with - it's just pin wiggling!

To send a single bit of data, hold the clock line high, then put the single bit onto the data line (high = 1, low = 0). Then send the clock line low. On the falling edge of the clock, the HT9200A puts whatever value was on the data line into it's shift register buffer. Data is sent LSB (least significant bit) first.

After receiving 5 bits, the DTMF generator will either play the appropriate tone(s) or stop playing the previous tone. So if we send, for example, the value 6 over serial (00110 in binary) the DTMF generator receives this and plays a combination of tones at 770Hz and 1477Hz



To tell the DTMF generator to stop playing, we send it the decimal value 24.
With all this information, we can write some code to dial a telephone number. We got our PIC to dial the BuildBrighton VOIP phone number: (ok, it's generating the DTMF tones that would dial the BB number, but you get the idea)

#include <system.h>
// ##################################
// using a 32 Mhz internal oscillator
// on a PIC16F1825
#pragma DATA _CONFIG1, 0x0804
#pragma DATA _CONFIG2, 0x1DFF
#pragma CLOCK_FREQ 32000000
// ##################################

#define cs portc.0
#define dta portc.1
#define clk portc.2
#define ledTest portc.3

const char DTMF_OFF=24;

char state;
char k;
char c;
char phoneNumber[16];

// program initialise
void initialise(){
   
     osccon=0b11110000;       // oscillator=32mhz
     delay_ms(50);            // wait for internal voltages to settle

     intcon=0b11000000;       // global interrupts and peripheral interrupts
     apfcon0=0b01000000;      // alternative tx/rx so pickit can use pins for uart
     wpua=0xFF;               // inputs on portA have weak pull-ups
     wpuc=0xFF;               // inputs on portC have weak pull-ups
     trisa=0b00000010;        // RA.1 is an input (uart rx)
     trisc=0b00000000;        // PORTC are outputs
     ansela=0x00;             // turn off analogue pins on portA
     anselc=0x00;             // turn off analogue pins on portC
     porta=0x00;              // set all output pins on portA off
     portc=0x00;              // turn off all output pins on portC
     option_reg=0x00;
}

void initUART(){
     //
     // UART
     //
     baudcon.4 = 0; // SCKP synchronous bit polarity
     baudcon.3 = 0; // BRG16 enable 16 bit brg
     baudcon.1 = 0; // WUE wake up enable off
     baudcon.0 = 0; // ABDEN auto baud detect

     txsta.6 = 0; // TX9 8 bit transmission
     txsta.5 = 1; // TXEN transmit enable
     txsta.4 = 0; // SYNC async mode
     txsta.3 = 0; // SEDNB break character
     txsta.2 = 0; // BRGH high baudrate
     txsta.0 = 0; // TX9D bit 9

     rcsta.7 = 1; // SPEN serial port enable
     rcsta.6 = 0; // RX9 8 bit operation
     rcsta.5 = 1; // SREN enable receiver
     rcsta.4 = 1; // CREN continuous receive enable

     spbrgh = 0; // brg high byte
     spbrg = 51; // brg low byte (see datasheet for 9600@32Mhz)

     apfcon0.2=1; // tx onto RA.0 (for PicKit2 sharing)
}

void UARTSend(unsigned char c){
     txreg = c;
     while(!txsta.1);
}

void uart_print(char t){UARTSend(t);}

void uart_print(char *s){
     while(*s) {
           UARTSend(*s);
           s++;
     }
}

void uart_println(char *s){
     uart_print(s);
     uart_print("\r\n");
}

void uart_print_dec(char number){
     if(number > 99) {uart_print(((number / 100) % 10) + '0');}
     if(number > 9) {uart_print(((number / 10) % 10) + '0');}
     uart_print((number % 10) + '0');
}

void setUpPhoneNumber(){
     phoneNumber[0]=0;
     phoneNumber[1]=1;
     phoneNumber[2]=2;
     phoneNumber[3]=7;
     phoneNumber[4]=3;
     phoneNumber[5]=3;
     phoneNumber[6]=5;
     phoneNumber[7]=8;
     phoneNumber[8]=2;
     phoneNumber[9]=6;
     phoneNumber[10]=3;
     phoneNumber[11]=99;      // we'll use termination characters later
}

void dtmf_out(unsigned char v){
     char digit=v;
     char i=0;
     char r=0;
     for(c=0; c<=1; c++){
           if(c==0){digit=v;}
           if(c==1){digit=DTMF_OFF;}
           if(digit==0){digit=10;}
           for(i=0; i<5; i++){
                 clk=1;                  // clock high while setting data
                 r=digit & 1;
                 if(r==0){
                       dta=0;
                 }else{
                       dta=1;
                 }
                 delay_us(5);      // delay 1/2 of 100khz
                 clk=0;                  // send the clock line low
                 delay_us(5);      // delay 1/2 of 100khz
                 digit=digit>>1;      // bit-shift so we start with LSB
           }
         
           // now wait 100ms (1/10th sec) and the tone plays
           delay_ms(100);
         
           // now the tone has finished playing,
           // send the command to turn off the signal
     }
}

void initHT9200(){
     cs=1;                  // disable the cs line
     clk=1;                  // force the clock line high
     cs=0;                  // enable the chip
     delay_ms(10);      // let the oscillator settle
     dtmf_out(DTMF_OFF);      // send the off command
   
}

void callNumber(){
     char ix;
     char iy;
     for(ix=0; ix<11; ix++){
           iy=phoneNumber[ix];
           dtmf_out(iy);
     }
}

// main program executes from here
void main(){

     initialise();
     initUART();
     delay_ms(250);
     ledTest=1;
   
     setUpPhoneNumber();
     initHT9200();
   
     // this is the main code loop
     while(1){
           callNumber();
           for(c=0; c<8; c++){
                 delay_ms(250);
           }
           if(ledTest==1){ledTest=0;}else{ledTest=1;}
     }
}

Here's a quick video showing the result:

Tuesday 19 November 2013

More miniature painting with Army Painter Quickshade - this time zombies

While looking for zombie-themed game ideas, I stumbled across this on Twitter which made me smile - it was a group of people discussing how best to prepare for the inevitable soon-to-be-upon-us zombie apocalypse:

As a mortician, I always tie the shoelaces together of the dead. Cause if there is ever a zombie apocalypse, it will be hilarious.

Now that's forward planning!
Having spent too long in front of the computer over the last few days, I thought it best to spend a few hours catching up with a bit of painting. I think I'm slowly developing my own style. Whether it's an actual style, or just not being too bothered about making a miniature look any better than "alright" I'm not sure. I think my style is summed up as "that'll do".

I'm also getting quicker at painting miniatures. But maybe that's because I've gone from "this needs to be really good" to "I think I'll get away with that". I'm not interested in blending and multi-layer gradients. I just want playing pieces that will look good in a few photos and on the board.

I wanted to find out exactly how fast I can "get away with" painting a bunch of miniatures using the Army Painter method. I'd hoped to paint a batch of seven zombies in just a couple of evenings. Even as I started, I thought this might be a bit adventurous - but still I thought that perhaps five might be realistically achievable.

My current painting technique is:

Spray a number of miniatures with the appropriate primer (so far I've only got white and grey, but I hope to expand on this in future - I guess it depends which kind of minis I'm likely to be painting in future)


Slap on the basic colour(s). This is a "messy" step - it doesn't matter really where the paint goes (if I had another primer, I might have base-coated all the minis in this slightly green-y flesh colour)


After this I sometimes do a bit of touching up. My Army Painter yellows and reds are not very good at covering up other colours. If I know I'm likely to use one of these "weaker" colours, I'll touch up any messy edges with white before applying the second colour.

Next, block in the remaining colours - making sure the edges are good, solid lines.
I use either a Citadel "standard orange" or an Army Painter "regiment" brush for these (whichever is first to hand). These slightly larger brushes (they're certainly bigger than the detail brushes) mean they hold more paint, which actually makes painting fiddly edges easier than a smaller brush.


I try to keep the number of colours per miniature to two or three at most. I also use much brighter colours than I expect the miniature to end up with. This is because the QuickShade will tone down the base colours quite a bit.


Here's the miniatures after applying the QuickShade (I use a brush rather than dipping) and both before and after a good 24 hour drying and some Testor's Dullcote:


So it took all of one evening to get the miniatures base-coloured and QuickShaded. It takes about 24 hours for the QuickShade to dry, and an hour or so for the Dullcote to harden, ready to take more paints. So by the second evening (some time well after Pointless) it's time to paint in some details and add a few highlights.


On this fat guy I couldn't find a bright colour to add highlights to the tracksuit, so just went with the original orangey-yellow. The effect is more noticeable than in the photo, but it's still not as striking as some other miniatures I've painted.


The zip and the white piping on the tracksuit took a steady hand, but I'm slowly learning to control the shakes when it comes to the smaller details. The spots I painted red, then topped off with a bone colour to make them look like angry red, pus-filled spots, just ready to burst!

I much prefer the highlighting on this second model. The technique was exactly the same - paint, shade, dullcote, highlight.


For the highlights I went two or three shades "brighter" than the base colour. The jeans, for example, were painted in Ultramarine blue, which goes quite dark after shading. It's tempting to highlight with the same blue, for a subtle effect. I prefer the Electric blue highlights which almost glow against the darker blue. True, it doesn't make the trousers look like demin - but you can see the highlights even from a distance. My reasoning is, if you're going to take the time and trouble to highlight your miniatures, why not make them really visible?

Sadly, I'm still rubbish at painting hair.
The rest of the models (both the fat guy and the girl) look fine. I managed to get the eyes and teeth painted in the right places and the shading and highlighting - though simple - make the miniatures stand out nicely. It's just a shame that the shonky hair painting spoils the rest of the model.

If anyone has any tips on painting hair, please leave comments below!

Sunday 17 November 2013

Drawing cards to determine player turn during a boardgame

We've been looking at a few Wild West skirmish game rulesets online, with a view to implementing some ideas in our electronic board game. One thing we were unsure about was how a turn-based shoot-out could actually work:

"My go. I shoot your characters - him, him and him. And that got just got wounded. Four of your five guys are out of action. Your go."

What a boring game that would make!
Some games try to address this problem using "initiative" - players can bid or roll dice to determine who gets to go first. Some Wild West type games split each turn into movement and firing. One player moves all their pieces, then the other player all theirs. Only then does the shooting start.

But all these feel like a "fudge" to address the problem that the person who goes first has a distinct advantage. An interesting solution to this problem used by many games (including "Blaze of Glory" and "The Rules With No Name") is to use a deck of cards (either playing cards, where each card represents a character in the game, or a deck of specially made cards, each depicting a character from the game).


The basic idea is that a card (or cards) for each playing piece is put into a deck and at the start of each turn, the deck is shuffled. Players activate their characters as their card is turned from the top of the deck.
Some rules use just one card per playing piece, some rules give each character a "level" which represents how many times their card should appear in the deck (suggesting that "better" characters can be activated more times per turn).

It's a neat idea, and solves the problem of one player annihilating the other completely, before the second player has a chance to take their turn. It also means that one player may have the opportunity of moving two or more pieces in succession but this would only be addressed by the other player having the same opportunity later in the turn.

An important element of this "random" turn taking that doesn't get much discussion is that it stops players anticipating what may happen during their opponent's turn, and moving their pieces to accommodate this. For example, in a typical you-go-I-go style game, the first player may anticipate where their opponent is likely to move to, move half of their playing pieces to perform tasks to stop this (shooting at opposing characters) and if this fails, move their remaining pieces in a sort of Plan B defence move (move and put them on overwatch, to fire at enemy characters during the other player's turn).

By not being able to anticipate which character moves next during a turn, each player must "think on their feet" and try to maximise what each playing piece can do while activated.

We think it's a great game mechanic.
It obviously wouldn't work for games played over distance, or for turn-based games played online (each turn could potentially take days to resolve, as each player moves just one character then hands play over to their opponent) but for face-to-face games, it seems like a really good idea. So good, in fact, we might borrow the mechanic for a sports simulator game for our electronic board game(s).

The problem with games like Blood Bowl (which originally started this whole project about two years ago!) is that the turn-based approach gets abused by players looking to win.
All too often, they will move their entire team during their turn (while the opponent looks on helplessly) to create an almost impenetrable formation. Because each player can move every character in their entire team during their turn, the game does not "flow" naturally.

For example, in Blood Bowl, a dropped ball means the immediate end of your turn. So a player may move a piece ready to catch the ball - but instead of then throwing the ball, the fear of it being dropped and causing the turn to end immediately means they then move supporting players into strategic positions (either supporting the catching player, or trying to "take out" opposing players who might be able to reach the catcher on their next turn) before attempting to complete the pass.

This is, of course, entirely within the rules. But it just makes the gameplay feel a little disjointed. Having to perform an action with the character whose card is next of the deck is a great way of introducing that spur-of-the-moment action back into what is supposed to be a fast-paced sports game.

We're really looking forward to trying these rules out and seeing how they work for a sports-style game. Of course, it'd be great to be able to run it on some hardware and try out an electronic version. But for now, we'll have to settle with a board drawn with felt-tipped pens and a handful of dice!

Keypads for digital board game

We're both excited and a little disappointed with our current board game design.
Excited, because it's look more and more likely that we'll have a demonstrable, working design, that's easy to assemble (manufacture) and will create a far better "product" than we'd decided to settle on. But disappointed too - disappointed that we couldn't fulfil our original remit of manufacturing our board game(s) here in the UK.

A while back we had some PCBs made (in China for £8 each, best quote for an A4 PCB manufactured in the UK was a massive £120!). The idea behind using PCBs for our game board was because they are things we could either make ourselves, or have made locally (using screen printing and ferric chloride etching) while the upper playing surface would be printed and assembled here too. Each board section would have a fixed printed playing surface on the top.

Then we started thinking about making the top printed layer removeable - creating a "tray" to house the PCB with recessed edges with magnetic strips embedded in them. The top layer could then have magnetic strip around the edges and simply be placed over the PCB (and held in place by the magnetic strips).

But even making up just one or two board sections revealed this to be unsustainable for anything more than a niche product, selling a few tens of copies. Building a tray and assembling the push-to-make contacts from three separate layers was very fiddly. Also, we needed to affix small discs of steel under each "square" on the PCB, so that a playing piece with a magnet embedded in the base would be attracted to the playing surface. To date, the cheapest steel discs we found were one penny pieces!

So we've gone full circle and gone back to the very first design we had (and then discounted because it would be too expensive to have manufactured) which is  to use a keypad membrane. Here's our design for a simple keypad matrix:



We had some quotes for having the keypads manufactured in the UK.
The best quote from a UK-based company included the caveat that the membranes would actually be manufactured in "their" factory in China, but all design and discussion would go through the UK company. This seemed like a compromise rather than having everything made in the UK - but one we might live with, if it encouraged local business. Where the compromise fell down was on price.

Simply put, every one of the UK companies we approached wanted far too much - in both setup/tooling fees and per-unit price. Which is very disappointing - given that we really wanted to support and use UK-based businesses as much as possible.

However, once we got over the disappointment, we found a factory in China willing to make a small volume of samples for a couple of hundred pounds; this includes set-up and tooling and should we require any more in volume, the per-unit price is about one-tenth of the nearest UK supplier!

Which means that, once again we're taking a bit of a punt on an unknown supplier, but with the possibility of having access to lots of ready-built, easy-to-use keypad membranes for our digital board game.
And with a super-thin membrane (less than 0.6mm) the entire keypad could be stuck to a sheet of magnetic rubber (the stuff we were using for the copper-tape prototypes). If the dimensions of the keypad were slightly smaller (all round) than the magnetic board, then the top surface could be held in place easily too. The top printed surface just has magnetic strips on the underside, which fix straight onto the magnetic rubber mat. And, of course, there's no need to hot-glue pennies to the underside - the playing pieces would naturally be attracted to the magnetic playing surface.

Which means that once again, we're excited about receiving some components which will help us (finally) complete our electronic board game project.

Look out for more details - and, no doubt, a KickStarter project - in the near future ;-)

Thursday 14 November 2013

Reading analogue data directly from the registers of a PIC 16F1825 with SourceBoostC

It's over a year ago since we first made a WAV player using a PIC16F1825 and a transistor, but with Xmas coming up, it's time to start thinking about making geeky-gifts and nerdy presents, so they can be finished in plenty of time for the big day.

This year we're making  some "talking toys".
The idea is to have a base with the sound player part in it, and a couple of connections exposed on a top surface, connected to a couple of magnets. Different characters will be placed on the base, triggering different sounds.

By simply embedding a resistor inside each of the characters, we can change the "bottom half" of a voltage divider and detect which character has been placed on top of the contacts.


Since we're using pretty much the same code as last time for playing WAVs, we've a limited number of pins we can use for the analogue input. Luckily, most of the pins on the 16F1825 can be used as analogue inputs - so we picked RC2 (pin8) as it wasn't being used for anything important.

Now before we go hacking our wav player code, we just wanted to check that we could read analogue input values accurately. In Oshonsoft, this was a doddle - two lines of code. In our now-preferred compiler,  SourceboostC it's not so obvious.

There are a few functions that can assist - things like adc_get(x) but in practice they didn't work very well. After doing a bit of searching, it seems that you need to prepare the correct registers for your target chip before the built-in Sourceboost ADC functions will work properly.

Well, while we're digging about in the datasheets we thought we may as well do the whole thing "old-school" using registers instead of pre-built functions and libraries (SourceboostC has renewed our interest in understanding what these magic little black boxes can do by hitting the datasheet quite often, while Oshonsoft tends to encourage you to rely on pre-built functions; some people like the simplicity of the abstracted layers - we like to know what's going on under the hood!)

For the 16F1825 there are two registers you need to focus on: ADCON0 and ADCON1
The chip puts the analogue inputs into "channels" and you really need to use the datasheet to get the channel numbers - you couldn't just guess that, in our case, RC2 is analogue channel 6!
We need to tell the chip which "channel" to listen to for the analogue-to-digital conversion by setting bits 6-2 of the ADCON0 register. Then set bit zero to tell it to activate the A2D peripheral.

ADCON1 is where we set the acquisition speed, positive and negative voltage references and so on. We went for the slowest option (fosc/64) to hopefully give more reliable values.

In the code below, we sample the analogue input (RC2) every 1/4 second and convert the received value into an id number (our ID numbers run from 0-9). If the received ID number is different to the previous value, we then display a message over UART. In the fullness of time, this will be used to start/stop different sound samples - for now we're just focussing on getting the A2D conversion working, so replying over UART/serial is just fine!


#include <system.h>

// ##################################
// using a 32 Mhz internal oscillator
// on a PIC16F1825
#pragma DATA _CONFIG1, 0x0804
#pragma DATA _CONFIG2, 0x1DFF
#pragma CLOCK_FREQ 32000000
// ##################################

char lastID;
char id;

// program initialise
void initialise(){

       osccon=0b11110000;     // oscillator=32mhz
       delay_ms(50);          // wait for internal voltages to settle
   
       intcon =0b11000000;    // global interrupts enabled and peripheral interrupts
       apfcon0=0b01000000;    // alternative tx/rx so pickit can use prog pins for uart
       trisa=0x00;            // portA is all outputs
       ansela=0x00;           // turn off analogue pins on portA  
       trisc= 0b00000100;     // RC.2 is an input (analogue in)
       wpuc = 0b00000100;     // any inputs on portC have weak pull-ups (except RC2)
       anselc=0b00000100;     // turn off analogue pins on portC except RC2
       porta=0x00;            // set all output pins on portA off
       portc=0x00;            // turn off all output pins on portC
     
       option_reg=0x00;
       option_reg.7=0;        // weak pull-ups enabled on any input pins  
}


void initUART(){
       //
       // UART
       //
       baudcon.4 = 0;    // SCKP            synchronous bit polarity
       baudcon.3 = 0;    // BRG16            enable 16 bit brg
       baudcon.1 = 0;    // WUE            wake up enable off
       baudcon.0 = 0;    // ABDEN            auto baud detect
         
       txsta.6 = 0;        // TX9            8 bit transmission
       txsta.5 = 1;        // TXEN            transmit enable
       txsta.4 = 0;        // SYNC            async mode
       txsta.3 = 0;        // SEDNB            break character
       txsta.2 = 0;        // BRGH            high baudrate
       txsta.0 = 0;        // TX9D            bit 9

       rcsta.7 = 1;        // SPEN serial port enable
       rcsta.6 = 0;        // RX9 8 bit operation
       rcsta.5 = 1;        // SREN enable receiver
       rcsta.4 = 1;        // CREN continuous receive enable
         
       spbrgh = 0;         // brg high byte
       spbrg = 51;         // brg low byte (see datasheet for 9600@32Mhz)
         
       apfcon0.2=1;        // tx onto RA.0 (for PicKit2 sharing)
       pie1.5=1;           // rcie bit 5 on the pie1 enables interrupt on usart receive                  
}

void UARTSend(unsigned char c){
       txreg = c;
       while(!txsta.1);
}

void uart_print(char t){UARTSend(t);}

void uart_print(char *s){
       while(*s) {
           UARTSend(*s);
           s++;
       }    
}

void uart_println(char *s){
       uart_print(s);
       uart_print("\r\n");
}

void uart_print_dec(char number){
       if(number > 99) {uart_print(((number / 100) % 10) + '0');}
       if(number > 9)    {uart_print(((number / 10) % 10) + '0');}
       uart_print((number % 10) + '0');
}

unsigned char getAnalogueInput(){
       unsigned char temp;

       // start the analogue circuit
       adcon0.1=1;
       // wait for the result to come in
       // (hardware clears the bit we just set when done)
       while(adcon0.1==1){}
     
       // return the result
       temp=adresl;
       return(temp);
}

void readInput(){
       char iA;
       iA=getAnalogueInput();
       if(iA<20){
            id=9;
       }else if(iA<40){
            id=8;
       }else if(iA<60){
            id=7;
       }else if(iA<80){
            id=6;
       }else if(iA<100){
            id=5;
       }else if(iA<120){
            id=4;
       }else if(iA<140){
            id=3;
       }else if(iA<160){
            id=2;
       }else if(iA<180){
            id=1;
       }else{
            id=0;
       }

       if(id!=lastID){
            uart_print("new id ");
            uart_print_dec(id);
            uart_println(" ");
       }

       lastID=id;
}

// main program executes from here
void main(){

       initialise();
       delay_ms(50);
       initUART();
       delay_ms(250);
       uart_println("Let's go!");

       // start the analogue circuit (right justified)
       adcon0=0b00011001;    // bit 7 blank, 6-2 are the channel and bit one activates
       adcon1=0b11110000;

       // this is the main code loop
       while(1){
            readInput();
            delay_ms(250);    
       }
}


The key to capturing analogue data is in the getAnalogueInput function.
Set the first bit to start capturing data on the selected analogue "channel". When the data acquisition is complete, and the PIC has converted the analogue input into a digital value, this same bit gets cleared. In our example above, we've used a simple "blocking" loop - i.e. loop until the bit is cleared (or, while the bit is set, it amounts to the same thing). Once the data has been converted, the first bit of the ADCON0 register is cleared (by the hardware) and the rest of the code can execute.

The 10 bit value is stored in the ADRESH and ADRESL registers.
Simply read these values to get the converted value. You can set the ADCON1 register to determine whether this value should be "left shifted" or "right shifted" in the registers. For testing, we're just taking the value from the lower byte register, but in a working product, we should really be combining these two values into a two-byte integer for better accuracy.

But that's it - the code to get data from the analogue-to-digital converter isn't actually more more complex by reading/writing to registers than it is to use the abstracted adc_ functions in SourceBoost. And by doing it this way, we've reacquainted ourselves with the 16F1825 chip and the underlying hardware.

Sunday 10 November 2013

New pound-shop guns for quickdraw shootout game

Just over a week ago, we built a simple "quickdraw shootout" game using some toy guns from a local 99p store. The game worked well enough - the idea is that a tilt switch tells the embedded microcontroller when the gun has been tipped such that it is horizontal (ie. it has been moved from the vertical position in it's holster, to a horizontal position - simulating the motion of taking it out of the holster and pointing it at an opponent).

Once the gun has registered as being horizontal, pulling the trigger causes the mcu to send a signal to a host device. The host device listens for these messages and reports back which gun was "fired" first (since only shots are recognised after the gun has been held horizontally, it makes the players actually draw their guns before pulling the trigger). Despite working in practice, we've not really done much with the guns following the trial at BuildBrighton last week. Maybe it's because they were so small and obviously "child-sized".

Paul Bash sorted this out for us, with some awesome monster-sized guns he picked up recently.
To paraphrase Crocodile Dundee, "that's not a gun.... now that's a gun"


These bright orange monstrosities just need a spray coat of black and a bit of silver acrylic drybrushing to make them look less nasty. But with a massive bullet chamber, and a nice big wood-effect handle, these could easily take a 9v PP3 battery in the handle and there's plenty of space inside for electronics gubbins.

These are going to make awesome quickdraw guns - we've got our single-wire data transfer working between two PICs and have managed to get a pin state to display wirelessly across our 433Mhz RF modules (write up to follow). We've already proved the gun firing code works. All that's left is to put the whole lot together and actually get the quickdraw game working!

Saturday 9 November 2013

Receiving Manchester encoded data over a single wire using PIC 16F1825 - VirtualWire for PIC

Following an earlier post, describing how to send Manchester Encoded data over a single wire, we just realised that we've been using, but not posted an entry on the blog, for receiving the encoded data! So first up, get familiar with how we encode and send the data (the timing graph from the logic probe is especially useful)


To decode the data, we're going to use a state machine which goes through the following states:

  1. Wait for a falling edge on the data input pin. Remember that this could be happening anywhere within the incoming data stream - but we've got to start somewhere!
  2. Monitor the incoming data, and look for the preamble 10101010 followed by 101011 (the two successive bit values of one tell us that it's the end of the preamble)
  3. Read the rest of the incoming data stream until four bytes have been received (this could easily be amended to look for either an end of message marker, or perhaps the data line being held low for more than two "cycle-lengths"
  4. Display the received data (in our case, we'll spit it out over serial)
  5. (not included in this example, but should be added in any production environment) Recreate the XOR sum and compare to the last byte sent (the XOR checksum). If they match, the data is valid - if there is a mismatch, discard the data and treat as a lost data packet.
We set up a breadboard with two PICs, connecting the dataOut pin of the transmitting mcu to the dataIn on the receiving mcu with a simple jumper wire.

the transmitting PIC is on the left of the breadboard and the large red button starts the data transfer routine; data captured by the PIC on the right is sent via UART to a host (we're using the UART tool in the PICKit2 programmer to display the results onscreen)

Because we know the "baud rate" of the incoming data (since we wrote the code that sends it, we can just reuse the same Timer1 interrupt setup code) we can simple set the Timer1 interrupt to grab the state of the data input pin at a very precise, regular interval.

Since Manchester data is encoded with a transition per bit, we can automatically syncronise with the incoming data stream. Every "cycle" should consist of a high or low data line, followed by the opposite state. So every half cycle should consist of a high followed by a low, or a low followed by a high.

If we ever receive two high or two low data states, we know that we're not reading the correct part of the data signal, and can simply skip by half a cycle step to get back into sync. But skipping a cycle step would mean that instead of 7 lots of 0b10 followed by one 0b11 we'd only get 6 0b10 (since we've effectively discarded one set of binary 0b10 getting back in sync). And because we may lose the very first part of the data signal waiting for our very first high-to-low transition on the data pin, we're going to wait for at least five lots of binary 0b10 on the data line followed by one single 0b11 value. If these two conditions are met, we can say we've reached the end of our preamble, and are ready to start receiving data.

Here's the code

#include <system.h>
// ##################################
// using a 32 Mhz internal oscillator
// on a PIC16F1825
#pragma DATA _CONFIG1, 0x0804
#pragma DATA _CONFIG2, 0x1DFF
#pragma CLOCK_FREQ 32000000
// ##################################

#define dataPin portc.2
#define ledRed portc.5
#define ledGreen portc.4
#define ledBlue portc.3

char state;
char k;
char preAmbleCount;
bit pinState;
bit lastPinState;
int pulseCount;
bit bitValue;
bit bitReceived;
char bitsReceived;
bit lastBitValue;
char byteValue;
char byteCount;
char byteValues[5];

// program initialise
void initialise(){
   
     osccon=0b11110000;            // oscillator=32mhz
delay_ms(50);                  // wait for internal voltages to settle

intcon=0b11000000;            // global interrupts enabled and peripheral interrupts
apfcon0=0b01000000;      // alternative tx/rx so pickit can use programming pins for uart
wpua=0xFF;                        // inputs on portA have weak pull-ups except the data pin (RA.5)
wpuc=0xFF;                        // inputs on portC have weak pull-ups except the data pin (RC.2)
trisa=0b00000010;            // RA.1 is an input (uart rx)
trisc=0b00000100;            // RC.2 is an input (data)
ansela=0x00;                  // turn off analogue pins on portA
anselc=0x00;                  // turn off analogue pins on portC
porta=0x00;                        // set all output pins on portA off
portc=0x00;                        // turn off all output pins on portC

option_reg=0x00;
option_reg.7=0;                  // weak pull-ups enabled on any input pins

     // set up timer1
     t1con=0b00001000;            // set bit zero of t1con to 1 to actually start the timer
pie1.TMR1IE=1;                  // enable the timer1 interrupt

     // enable the global and peripheral interrupts
     intcon.GIE=1;
     intcon.PEIE=1;
   
}

void initUART(){
     //
// UART
//
baudcon.4 = 0; // SCKP synchronous bit polarity
baudcon.3 = 0; // BRG16 enable 16 bit brg
baudcon.1 = 0; // WUE wake up enable off
baudcon.0 = 0; // ABDEN auto baud detect

txsta.6 = 0; // TX9 8 bit transmission
txsta.5 = 1; // TXEN transmit enable
txsta.4 = 0; // SYNC async mode
txsta.3 = 0; // SEDNB break character
txsta.2 = 0; // BRGH high baudrate
txsta.0 = 0; // TX9D bit 9

rcsta.7 = 1; // SPEN serial port enable
rcsta.6 = 0; // RX9 8 bit operation
rcsta.5 = 1; // SREN enable receiver
rcsta.4 = 1; // CREN continuous receive enable

spbrgh = 0; // brg high byte
spbrg = 51; // brg low byte (see datasheet for 9600@32Mhz)

apfcon0.2=1; // tx onto RA.0 (for PicKit2 sharing)
}

void UARTSend(unsigned char c){
txreg = c;
while(!txsta.1);
}

void uart_print(char t){UARTSend(t);}

void uart_print(char *s){
     while(*s) {
           UARTSend(*s);
           s++;
     }
}

void uart_println(char *s){
     uart_print(s);
     uart_print("\r\n");
}

void uart_print_dec(char number){
     if(number > 99) {uart_print(((number / 100) % 10) + '0');}
if(number > 9) {uart_print(((number / 10) % 10) + '0');}
uart_print((number % 10) + '0');
}

// set timer1 value so it fires every X-uS
void preloadTimer1(){
     // at 32Mhz, fosc/4=8million
     // our radio modules are rated *up to* 4khz
     // so let's stick to about half that for now
     // 8m/2000 = 4000
     // so we want our timer1 to only count up to 4000
// timer1 is a 16-bit timer (0-65535) so we need to
// preload it with 65535-4000 = 61535 (0xF05F)
tmr1h=0xF0;
tmr1l=0x5F;
}

void startTimer(){
     // clear any left over interrupt flag
     pir1.TMR1IF=0;
     // set bit zero to start the timer
     t1con.0=1;
}

void stopTimer(){
     // clear bit zero to stop the timer
     t1con.0=0;
}

void endTransmission(){
     // first, kill the timer
     stopTimer();
   
     // turn off any transmission leds
     ledBlue=0;          
         
}

void getPinState(){
     pulseCount++;
     pinState=dataPin;
     k=pulseCount & 1;
     if(k==1){
           // this is the first of a two-part bit
     }else{
         
           // decide which value bit we've just received
           bitReceived=0;
           if(lastPinState==0 && pinState==1){
                 // a rising edge is a bit value 0
                 bitValue=0;
                 bitReceived=1;
           }else if(lastPinState==1 && pinState==0){
                 // a falling edge is a bit value 1
                 bitValue=1;
                 bitReceived=1;
           }else{
                 // no change detected- need to re-sync?
                 bitReceived=0;
                 // move the pulse count on by one, so this
                 // will run again on the next half-cycle
                 pulseCount++;
           }
         
           if(bitReceived==1){
         
           }
     }
     lastPinState=pinState;
}

// main program executes from here
void main(){

     initialise();
     initUART();
     delay_ms(250);
     state=4;
     uart_println("Waiting for data...");
   
   
     // this is the main code loop
     while(1){
           switch(state){
         
                 case 0:
                 // wait for a falling edge on the dataPin
                 if(lastPinState==1 && pinState==0){
                       state=1;
                 }
                 break;
               
                 case 1:
                 // we're monitoring the preamble
                 if(bitReceived==1){
                       // count the number of ones and zeros received
                       if(bitValue==1){
                             if(lastBitValue==0){
                                   preAmbleCount++;
                             }else{
                                   if(preAmbleCount>=5){
                                         // cool, this is the end of the preamble.
                                         // get ready for some data!
                                         ledBlue=1;
                                         byteValue=0;
                                         byteCount=0;
                                         bitsReceived=0;
                                         lastBitValue=0;
                                         state=2;
                                   }else{
                                         // we have two ones, but not following the
                                         // 101010 preamble, so we might be in the middle
                                         // of a datastream. Reset the preamble count
                                         preAmbleCount=0;
                                   }
                             }
                       }else{
                             if(lastBitValue==0){
                                   // we've had two zeros in succession. Ditch this and
                                   // wait for the start of the next preamble
                                   preAmbleCount=0;
                             }
                       }
                     
                       lastBitValue=bitValue;
                       bitReceived=0;
                 }
                 break;
               
                 case 2:
                 if(bitReceived==1){
                       // prepare the byte value for the incoming bit
                       bitsReceived++;
                       byteValue=byteValue<<1;
                       if(bitValue==1){byteValue|=1;}
                     
                       if(bitsReceived>=8){
                             // we've had a full byte of data,
                             // store it in a buffer
                             byteValues[byteCount]=byteValue;
                             byteCount++;
                           
                             byteValue=0;
                             bitsReceived=0;
                           
                             if(byteCount>3){
                                   stopTimer();
                                   state=3;
                             }
                       }
                       bitReceived=0;
                 }
                 break;
               
               
                 case 3:
                 // send what you've received over serial
                 uart_println("received data");
                 for(k=0; k<4; k++){
                       uart_print_dec(byteValues[k]);
                       uart_print(" ");
                 }
                 uart_println(" ");
                 state=4;
                 break;
               
               
                 case 4:
                 ledBlue=0;
                 pinState=0;
                 lastPinState=0;
                 preAmbleCount=0;
                 startTimer();
                 state=0;
                 break;
               
               
           }    
     }
}

void interrupt(){
     // every time timer1 fires, we send another part of a bit
     // (in Manchester encoding). Bit zero of pir1 is tmr1 overflow interrupt
if(pir1.TMR1IF==1){
           // clear the timer1 interrupt flag
           pir1.TMR1IF=0;
           // preload timer1 to get the next interrupt to occur in a timely manner
preloadTimer1();
// send the appropriate bit-part
getPinState();
     }
}


It still needs a little bit of amending for use in a production environment, but demonstrates the principle of reading Manchester Encoded data from a single wire interface.


This matches exactly with the data being sent by our little transmitter mcu:

if(button==0){

     // light the led to show we've acknowledged user action
     ledBlue=1;
   
     // wait for release
     while(button==0){}
   
     // send some data
     // (values chosen to be a mix of 1 and 0 in binary)
     sendData(179,227,24);
     ledBlue=0;
   
}

(The final value 72 is the checksum that the transmitter generates. If we start with a value zero, XOR the value 179, then XOR 227 to the result, and finally XOR this with 24, the result is, indeed, 72 - demonstrating that the data has been transmitted and received correctly).

As we've had this working for a little while, and we've had our toy guns wired up on a breadboard to demonstrate those working, the last little bit of our quickdraw shootout game is to replace the wire between the gun and the host with a 433Mhz RF transmitter/receiver pair.


These are really simple to understand (though to use them you need to implement your own "VirtualWire" single wire interface). When a paired transmitter and receiver are active, the state of the dataOut pin on the transmitter is reflected instantaneously on the dataIn pin on the receiver.

So in theory, we should be able to replace our piece of wire between the data pins with an RF transmitter module at one end, and a receiver module at the other. Schematics, photos and a write up explaining how to achieve this will be in a following post....



Monday 4 November 2013

More miniature painting - Wild West cowboys

Work in progress.
We're not even sure that these guys all belong in the same "gang". We've yet to even begin to think about how the rules for an (electronic) Wild West board game would play. So while we're trying to work it out, here's a shot of some western style miniatures, all painted exclusively using the Army Painter/Quickshade system.

Here's a few things we learned along the way:

  • Subtle highlights are no highlights. There's no point highlighting a dulled down grey with an almost-the-same-but-slightly-lighter grey. True, it creates a really natural, subtle effect. But in the world of miniatures, big, bright and bold is better - unless you're an expert painter, putting in days (and even weeks) into each model, emphasis and exaggeration make for a decent paintjob, quickly!
  • Leaving the basing to the end causes it's own problems - particularly painting glue and drybrushing around the feet. In future we're going to base our models first.
  • Every paint stroke needs to be bold and look intentional. A thin, wobbly, wispy line may pick out a raised ridge, but it'll always look either half-finished, or it was an accident. Make each line obvious and deliberate and the miniature will look all the better for it (even if it's not quite in the right place!)
  • Keep the number of different colours to a minimum, to keep a consistent colour scheme running through the miniature. Different shades are fine (in fact, necessary, to highlight details) but a limited palette gives a much more dramatic effect - especially if just one or two smaller details are picked out in a completely different colour
  • Freehand painting patterns and shapes on large areas really improves the look of a model - provided you make a good job of it. Badly painted lines (like the stripes on our sheriff!) add nothing and actually detract from the rest of the paintwork!

 water down the PVA glue too much and the basing material just falls off when it's dry!

 even when glued down properly, go easy with the drybrushing, else you'll just scrub all the basing material off the base!

leaving the PVA too thick results in a similar problem - the basing material clumps together and leaves bald patches on the base

finally we got the glue consistency right - a nice, thick, well-covered base, drybrushed and finished to a half-decent standard.

With these miniatures based, we're going to call them finished and move on to some others now.
So far we've got a number of different genres identified for our electronic board game so there are plenty more miniatures still to paint!