Tuesday, September 29, 2009

I (heart) you

Beer.  As Homer Simpson said, “Beer, the cause of, and solution to, all of lifes problems

It turns out that making things talk to each other is heaps easier if you don’t crack open the ale first.  A few days away and a clear head tonight mean that within 10 minutes, everything is working perfectly.

So perfectly in fact that there’s there imminent risk of feature creep and really only the miniaturisation left to do (which I won’t trivialise because I’m sure I’ll mess up my veroboard layouts a time or two).

Be that as it may, it all works. 

I (heart) you from Simon Devlin on Vimeo.

My heart rate. This end has a Duemilanova with a MAX7219 LED driver powering an 8 LED level meter and a Nordic nRF2401 wireless link. The Nordic chipset receives 9600bps data from another Arduino (the host end, I suppose) equipped with a corresponding Nordic transceiver that reads serial data from a Suunto PC POD and acts as a relay.

Monday, September 14, 2009

Light me up with your heart

So a friend of mine is having a light themed party in a few weeks and I have an idea.

I want LED’s on me to move in sync with my heart beat.  More to the point, I want more lights if my heart goes faster.  Enter the Suunto product range which I’d been dicking around with for a while.  Nominally, there’s a Sparkfun breakout board that talks the ANT protocol that is used by the Suunto gear.  But, for reasons that are several and boring, it’s not that simple.

So, owning a USB stick from Suunto and previously having come up with a .Net implementation of the god-awful C++ headers, I’m using that, coupled with a pair of Nrf24L01+ transceivers to bridge the gap.

The downside is that this will only work within about 10 meters of the USB stick in the PC, whereas the Nrf24AP1 chipset could have been done entirely off PC.  As it happens I think I have the missing information (courtesy of someone else who found it elsewhere), but I started a new job today, am away for the following two weekends and frankly don’t have time to mess around with a ANT implementation.

Unfortunately, I can’t actually find my HRM strap, but that’s OK as I can simulate the imput data (read serial off the PC via the arduino – works a treat), and right now, all I’ve got is the two ends of the radio link chattering back and forth (not much more than loading the Mirf library examples, but that’s been a bigger effort than you’d think using RBBB’s and a dodgy Arduino).

Ideally I want a series of LED’s – baselined at around say, 60BPM but the transceivers take up quite a few pins (5) so I (and I only just thought of this), may be limited in what I can do.  The original thought had been to bung in a MAX7221 and run >8 but that needs a heap of pins too.  Cock.  Looks like I’ll have to dig out the datasheet.

Someone once said “The dizzying highs and the terrifying lows”.  Grrr.

Saturday, June 13, 2009


It’s been 15 years since I soldered in anger – and that was a 2 week placement for work experience in a company that fabricated circuit boards for some product that I no longer recall.

So I sat down tonight to do a couple of bits.  Disaster is a bit strong because the house is still standing and I didn’t burn myself but just rubbish results.  In the intervening period I’ve clearly lost all the skills that I ever had, and in my fuzzy recollection of those days, I was a virtuoso with an iron.

My iron was very very cheap in the first place.  A week or so ago, I left it on for hours by mistake and I think that may have degraded the tip.  The point just doesn’t seem to be able to conduct enough heat and it may also be a bit grubby.

I’m scoping out a better iron figuring that it will last for years (I’m a believer in the saying ‘he who buys cheap, buys twice’ but I didn’t want to spent 80-120UKP not knowing that I’d even get as far as trying to use it.  Ah well.

Anyway, I found this on youtube.  Excellent description and clear do’s / don’ts of the whole process.

Tuesday, June 2, 2009

Dusty Ledfield

I got a good deal (I think) on some bright 10mm LED’s (130k mcd’s) but they’re clear rather than diffuse and they look weird behind the ping pong balls I was planning to house them in.

Sanding one or two down with some 240 grit sandpaper works just fine but it’s frightfully slow.

So, never adverse to buying a gadget (economic stimulus is my excuse) I unleash the Dremel 300, delivered today, on them. 

It works great.  In fact, almost too well.  I wish the device had a lower ‘lowest’ speed.  I really ought to be wearing a dust mask too!

But all said and done, I reckon it will save 2 minutes per LED.  So 64 x 2 minutes, the best part of 2 hours.  At my professional rate, that’s already paid for the Dremel a bunch of times over.  Result, me=happy (apart from polywhatsit-dust in my respiratory tract)

Clear vs. Dremel from Simon Devlin on Vimeo.

Thursday, May 28, 2009

Max 7221 LED matrix driver & Arduino

I’ve parked my current project for a while because I get fascinated by new shiny things.

As summer is coming I thought some light type stuff for the yard would be fun.  I’ve barely progressed beyond the blink example and moved straight to the 8x8 as a stepping stone to 8x8x8 and ambient influences (wind, temperature, humidity, proximity and how pissed the guests are)

But the first step is getting the $30 arduino to address more outputs.  One of the ways is via multiplexing with a Max7221 LED driver.  This chip is designed to operate an 8x8 matrix, or a 7 segment character display.

The datasheet for the 7221 is certainly comprehensive and there’s a well documented control library (LedControl.h) available but even so it took me a few days to figure out, what in hindsight is obvious.  Hopefully this will help someone else in the future.

Things to consider -

  • The pins you use for DIN, CLK and LOAD/CS must be set to output (they default to input)
  • The 7219/7221 initialises in power saving mode.  Makes sense but is also kind of dumb.  So you need to explicitly turn the MAX output pins on if you want to see the fruits of your labour.  To be fair the datasheet says this, but it’s obscured in the LedControl docs.  Again, to be fair the datasheet is referenced and this behaviour is documented but as a beginner lots of the data may as well be in Martian and so I probably skipped past it with glazed eyes.

On initial power-up, all control registers are reset, the
display is blanked, and the MAX7219/MAX7221 enter
shutdown mode. Program the display driver prior to
display use. Otherwise, it will initially be set to scan one
digit, it will not decode data in the data registers, and
the intensity register will be set to its minimum value.

  • Brightness.  Following on from the last sentence the range from low to high is 0..15 and you don’t get anywhere near 15 by default.  Blurb from the datasheet is below but the details are abstracted by LedControl and the setBrightness() function.  That’s just as well.

The MAX7219/MAX7221 allow display brightness to be
controlled with an external resistor (RSET) connected
between V+ and ISET. The peak current sourced from
the segment drivers is nominally 100 times the current
entering ISET. This resistor can either be fixed or vari-
able to allow brightness adjustment from the front
panel. Its minimum value should be 9.53kΩ, which typi-
cally sets the segment current at 40mA. Display bright-
ness can also be controlled digitally by using the
intensity register.

Digital control of display brightness is provided by an
internal pulse-width modulator, which is controlled by
the lower nibble of the intensity register. The modulator
scales the average segment current in 16 steps from a
maximum of 31/32 down to 1/32 of the peak current set
by RSET (15/16 to 1/16 on MAX7221). Table 7 lists the
intensity register format. The minimum interdigit blank-
ing time is set to 1/32 of a cycle.

  • Capacitors… no idea if they’re necessary.  In principal I understand the need to smooth out a noisy +5v but for my first simple test it all works fine with out them.  I have a spare 7221 in case I killed the first one so I’ll try cascading it and see if that makes a difference.  The next milestone however is to move from a breadboard to a 8 foot square grid and bust apart some coat hangers.

What really got me was that as a beginner I didn’t really know if I’d messed up the wiring or what.  An end to end example would have been great and so, code follows.  I’ll add breadboard photos in the next day or two so that the whole world can marvel at it…

This example powers a single row (row 0) of 8 LEDs (0..7).  Now this works (video to follow) it should be easy to wire common cathode to the remaining DIGn pins (DIG0, or pin 2 is all that’s used in this example)

#include "LedControl.h"

int DIN = 12;
int CLK = 11;
int LOADCS = 10;
int flashDelay = 10;  // delay in MS (1000=1 second)
int ledBrightness = 15;  // range is 0-15.  0=lowest, 15 = full power

// define the LedControl instance - add more if >8 required
LedControl lc1=LedControl(DIN,CLK,LOADCS,1);    // DIN, CLK, Load/CS, 1 = only one chip MAX chip attached.

void setup()                    // run once, when the sketch starts
  // mark the three pins for the MAX signals as outputs
  pinMode(DIN, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(LOADCS, OUTPUT);
  // take pins out of power save mode.  No updates otherwise.
  for(int index=0;index<lc1.getDeviceCount();index++) {
  lc1.setIntensity(0,ledBrightness  );

void loop()                     // run over and over again

    int row = 0;
    int chipId = 0;
    // for this test I only wired up one row attached to PIN 2 (row 0)
    // this is why row is defined as loop scoped and initialised to 0
    // you could easily wrap row in another for (int row...) construct
    // LED's share +5v/cathode with Anodes on each LED connected
    //to pins SegA - SegG
    for (int col=0; col<=7; col++) {
      lc1.setLed(chipId, row, col,true);
      lc1.setLed(chipId, row, col, false);