Wednesday, 12 March 2014

Getting one up on the kids!

Free Stuff!

Over at the EEVBlog forum a PCB Fab house by the name of JAKO made an offer - FREE 5x5 cm PCB Service.

Woot!


I quickly signed up on this generous offer and then ran smack bang into a problem in the 'good to have' category.  I had no idea what I wanted that could fit on a 5x5 cm service!  After mulling it over for a few days, I decided to take advantage of the offer and try some stuff I've not yet attempted.  This new project had to:
  1. Use Charlieplexing, because I've always wanted to experiment with it
  2. Use PIC16F648A's, because I have a box of them   
  3. Be battery operated, because all my other projects have been tethered to a power supply and I've not tried to implement power saving features.
  4. Play with PortB Weak Pull Ups
  5. Use a touch sensor, because they're like bow ties (you know, cool).
  6. Be amusing to the kids.
After mulling it over for a few days, I decided to revisit the classic beginners project - LED Dice!  

Classic LED Dice

Rather than use a 555 oscillator and a counter I decided to use the 16F648A as the heart of the project.  What's nifty about the 16F648A is the the micro includes an internal comparator module - which can be configured as a touch sensor.  WIN!

Touch Sensor

Microchip released an application note (AN1202 - but I'll be damned if I can find it on their site, so I'll post it here) that showed how to configure the comparator in the PIC10F as a relaxation oscillator.  

Relax!

In a nutshell, if you increase the capacitive loading of the sensor, the oscillator will run slower, and if your count the output of a timer over a fixed period, you can detect a touch event when the counts are below a certain threshold.  Nice.

So the 16F648A has an internal comparator (actually two!) that I can use, but it doesn't have a band gap reference - but I can get around this by using an external diode.

Prototype

The picture above shows my prototype schematic for the micro / touch switch.  You might notice that I've used two physical buttons as well as my touch sensor.  There's a few reasons for this:
  1. As I plan to run this from a coin cell, I'll need to sleep this device and to wake it I need a physical button connected to RB0 to make this happen.
  2. I planned on displaying 'two dice' - two groups of 7 LEDs and one button was to 'roll one' and the other was to 'roll two'
  3. I planned to hide the touch sensor so I can enable 'cheat' mode.
The touch sensor is made by simply connecting the sense line to one of the M3 mounting screws as shown below:


Cheat Mode.  Whaaaa?

What is 'cheat mode' and why do I want it?  Mostly 'because I can', and partly to keep ahead of the kids.  Family game night is getting competitive and I must keep my undefeated status at Cluedo intact!

The idea with Cheat Mode is this:

  • Hold down the touch sensor for (say) 2 seconds to enable cheat mode
  • Distract the kids, and while still holding down the touch sensor, tap the roll one or roll two buttons (for dice one and two respectively) a number of times to correspond to the number you want the dice to show
  • Release the touch sensor 
  • Then roll as usual and act surprised that you've rolled double 6 *again*
Okay, so it's not the easiest trick to perform, but family games can be noisy and it's easy to distract the kids.. at least for now.  

Charliplexing

This is a topic that's been well covered by the wiki article, so I wont go into details here. For the dice, I need to control 14 LEDs in total, which can be done with a minimum of 5 I/O lines.  But to make my life easier, I split the LEDs into two groups of 4, using 4 I/O lines each, for a total of 8 I/O lines. 

Two Dice Patterns

For the actual LED's I went with Green and Blue PLCC2 LED's that I'd previously picked up off of eBay.

Build and Integrate

Once I had the plan in mind, I threw together a layout in Altium one evening and got the board's fabbed.  Sooner rather than later, I had not 5 but SIX shiny new PCBs from Jako.  


Shiny and New

I whipped up a solder stencil at work and got to assembly.  



Stencils and Jig


Paste Applied


Parts Placed Wonky


Hot Air Fixes All


Almost Finished Product

Part placement went quickly and my eBay special hot air gun made quick work of soldering.  I'm now a big convert to paste and hot air - it's just that much easier than soldering stuff by hand, especially 0603 part!

I didn't have any BAS16 diodes to hand so I left those out for now - but there's no need to stop there.

Code and Test

First up, was the Charlieplexing.  My test code simply advanced a counter on each button press and I light up the required LED pattern.  I didn't try to write efficient code, just proof if concept - get it working code.

Here it is in all it's ugliness:



while (TRUE) {
switch (da) {
case 1:
output_high(PIN_B5); output_low(PIN_B2);
delay_ms(1);
output_float(PIN_B5); output_float(PIN_B2);

delay_ms(5);
break;

case 2:
output_high(PIN_B2); output_low(PIN_B3);
delay_ms(1);
output_float(PIN_B2); output_float(PIN_B3);

output_high(PIN_B4); output_low(PIN_B5);
delay_ms(1);
output_float(PIN_B5); output_float(PIN_B4);

delay_ms(4);
break;

case 3:
output_high(PIN_B2); output_low(PIN_B3);
delay_ms(1);
output_float(PIN_B2); output_float(PIN_B3);

output_high(PIN_B4); output_low(PIN_B5);
delay_ms(1);
output_float(PIN_B5); output_float(PIN_B4);

output_high(PIN_B5); output_low(PIN_B2);
delay_ms(1);
output_float(PIN_B5); output_float(PIN_B2);

delay_ms(3);


break;

case 4:
output_high(PIN_B2); output_low(PIN_B3);
delay_ms(1);
output_float(PIN_B2); output_float(PIN_B3);


output_high(PIN_B5); output_low(PIN_B4);
delay_ms(1);
output_float(PIN_B5); output_float(PIN_B4);


output_low(PIN_B2); output_high(PIN_B3);
delay_ms(1);
output_float(PIN_B2); output_float(PIN_B3);


output_low(PIN_B5); output_high(PIN_B4);
delay_ms(1);
output_float(PIN_B5); output_float(PIN_B4);


delay_ms(2);
break;

case 5:
output_high(PIN_B2); output_low(PIN_B3);
delay_ms(1);
output_float(PIN_B2); output_float(PIN_B3);


output_high(PIN_B5); output_low(PIN_B4);
delay_ms(1);
output_float(PIN_B5); output_float(PIN_B4);

output_high(PIN_B5); output_low(PIN_B2);
delay_ms(1);
output_float(PIN_B5); output_float(PIN_B2);

output_low(PIN_B2); output_high(PIN_B3);
delay_ms(1);
output_float(PIN_B2); output_float(PIN_B3);

output_low(PIN_B5); output_high(PIN_B4);
delay_ms(1);
output_float(PIN_B5); output_float(PIN_B4);

delay_ms(1);
break;

case 6:
output_high(PIN_B2); output_low(PIN_B3);
delay_ms(1);
output_float(PIN_B2); output_float(PIN_B3);


output_high(PIN_B5); output_low(PIN_B4);
delay_ms(1);
output_float(PIN_B5); output_float(PIN_B4);

output_low(PIN_B2); output_high(PIN_B3);
delay_ms(1);
output_float(PIN_B2); output_float(PIN_B3);


output_low(PIN_B5); output_high(PIN_B4);
delay_ms(1);
output_float(PIN_B5); output_float(PIN_B4);


output_low(PIN_B4); output_high(PIN_B3);
delay_ms(1);
output_float(PIN_B4); output_float(PIN_B3);

output_low(PIN_B3); output_high(PIN_B4);
delay_ms(1);
output_float(PIN_B3); output_float(PIN_B4);
break;
}

As you can see I turned on each lead as required and delayed for 1ms to leave it lit, and then moved onto the next led.  Some patterns I could turn on more than 1 led at a time (i.e. for a 2) but as some patterns take less time to set (i.e. a 1 versus a 6) I added extra delays to the shorter patterns so that the overall LED brightness (for each pattern) remained the same.

To keep my part count to a minimum I enabled the PortB 'Weak pull ups' to pull my buttons high.  However as these are enabled for all pins on PortB at the same time, the LEDs attached to PortB pins remained very dimly lit.  To work around this I needed to turn off the weak pull ups while displaying the LEDs, then turn them back on and read the status of my push buttons, and then turn the pull ups off and repeat.  Easy.

Problem With Rushing

As usual, I made a few errors with my board.  
  1. I placed my decoupling cap *under* my coin cell.  That doesn't work to well but I was able to patch one in next to power pin of the coin cell.
  2. I wanted to use an external diode drop for my comparator reference.  If you  look at my schematic you'll see that I reverse biased it.  But there's an interesting work around for that!
  3. I ballsed up my comparator configuration



Options...

From my schematic above, I set my reference voltage on RA0, the touch sensor on RA2 and RA3 is the output.  I had assumed I could use the mode set via setting the CM bits of the configuration register to CM<2:0> to 100 (two independent comparators).  However the C2VOUT output doesn't come out on RA4 in this mode, and thus my relaxation oscillator couldn't oscillate.... 

Switching CM<2:0> to 110 (Two common reference comparators with outputs) gives me the options I need - but I needed to mod my board. 

To get it to work I had to lift Pin 1 of the micro, and add a link from RA0 to the sensor (and remove the diode pull up resistor R9).  To cure my screwed up reverse biased DAS16 diode, I had a better look at the micro's datasheet.

No, the 16F648A doesn't have a band gap reference.  It DOES have a voltage reference module, which can be routed to RA2.  This reduces my part count by TWO, and as the VREF module is programmable I have a sensitivity adjustment for the touch sensor.

Once reconfigured and coded, I hung a scope off RA4 and could see a square wave from my comparator, and touching the sensor reduced the frequency noticeably.  Win!

Sleep

Finally, I was able to implement a sleep mode in my micro - when running I was drawing milli-amps from my battery, and when sleeping it went too low for my crappy multimeter to measure.

At this stage, I've called a halt to the prototype.  I've got another project on the go and have tacked my dice to the PCB 'panel' (Seeed studio 10 x 15cm service) and will finish up the code when those boards are ready (including my final version of my Alarm Interface).


Coming Soon!


No comments:

Post a Comment