23 Aug 2012

[ part of the orb series ]

The base of my original Orb was cut out of a thick piece of wood using a circle cutting drill bit. A pair of slightly smaller circular bits were then used to create a recess in the top of the base and finally a hole drilled through the centre. This was all it needed to glue the BlinkM in place with the lead running out of the base to the off-board arduino.

This approach wasn’t going to work for the new Orb, which needs a hollow base to house all of the boards. It also needed to be something that others could easily replicate.

I discounted 3D printing early on, as I wanted the base to be wooden. This left some sort of laser cut thing. There are a number of on-line services for getting things laser cut, such as Ponoko. They offer a wide range of materials, including 3mm thick plywood – ideal for this.

To figure out what that base was going to look like, I started by glueing a stack of cardboard together and literally carved out the shape I wanted. This let me work out what each of the individual 3mm layers needed to look like. It also helped to identify how to make the base in such a way as to allow the PCB to be accessed; I didn’t want it to be a permanently sealed unit.

Orb Base Layers
Prototype base

The base consists of 12 layers, with 3 in the bottom ‘half’ and 9 in the top (the diagram over on the left omits most of the layers). A pair of nuts, shown in red on the diagram, are sandwiched between layers in the top half, which allow the two sections to be held together using screws. The bottom of the base also includes holes for mounting the PCB stack to it.

With the layers drawn up in inkscape, it was time to get them made. A chance conversation with Adrian McEwen at a #iotlondon meetup enabled me to take advantage of DoES Liverpool’s laser cutter.

Adrian kindly took some photos of the LASER in action.

Lasers! Lasers! Lasers! Lasers!

Proving yet again, atoms are hard, this first pass wasn’t a complete success. I had made the space in the centre of the base layers the exact same size as the PCBs – so exact that the PCBs didn’t quite fit. A quick rework of the design and another pass with the lasers and I had all the bits I needed.

Orb Base

Some glueing and sanding later, and the base looks quite good – although I don’t appear to have a more recent photo of it to hand. It needs some more work as the design didn’t properly take into account how the orb actually attaches to the base – I have vague thoughts about the liberal use of a hot-glue gun to achieve this currently. I’ve also had some thoughts about changing the style of power-supply connector, which will change the size of opening needed in the side.

But all in all, a significant step forward as it now looks more like something people would be prepared to have sat in their home.

1 Aug 2012

[ part of the orb series ]

With the Orb needing to be wireless, one of the early decisions was what sort of wireless to use.

The first option to consider was Wi-Fi. This would allow the Orb to connect straight to the Internet via the home router – no intermediary is needed. The downside is that the Orb doesn’t have any sort of UI that would allow configuration of the Wi-Fi settings. Some Arduino WiFi shields will read the configuration from an SD card – but that is not at all a nice user experience. Nor is there a lot of space available on the bottom board to fit all of the hardware in. It is also an expensive option. Likewise Bluetooth and ZigBee weren’t really a good fit.

That left a 433Mhz, or similar, radio link. I had played around with some cheap radio transceivers before and they seemed a good way to go. But then I discovered the RFM12B module via JeeLabs. Jean-Claude has written a lot about the module on his blog and has created an Arduino library for driving it – perfect for the Orb. Another benefit is that the Nanode board comes with this module – making it nicely interoperable.

The downside of the module is that it runs at 3.3V – but the rest of the Orb runs at 5V. I considered squeezing in the appropriate voltage regulators to provide both voltages from an unregulated supply. But I decided it would be easier to offload some of that by requiring a regulated 5V power supply. That way, the bottom board only needs a regulator to provide 3.3V to the radio, as well as a set of voltage dividers on each of the signal lines between the radio and the ATmega328. It also opens the option of using a micro-USB port as has become standard with mobile phone chargers – although that’s for the future.

Although I said the Orb has no configuration interface, I decided it needed something. A common pattern with radio-linked devices, such as the CurrentCost meters, is that you press and hold a switch to put the device into a pairing-mode. This mode allows you to not only establish a link between the device and a base station, but also to link multiple devices with a single base, whilst maintaining their individual addressability. To this end, I included a surface-mount switch on the underside of this board so it can be accessed through the bottom of the Orb housing.

As ever, the schematics are on github.

PCB #3 PCB #3 - built

And that’s the final board. All soldered, stacked and ready to do its thing. What’s next? Making a base to house these boards in. But that’s for another day.

Stacked
30 Jul 2012

[ part of the orb series ]

A couple of years ago, I bought a Component Bundle from oomlout – a kit of parts to build your own Arduino-compatible board. This proved to be a great lesson in what an Arduino actually is and how it can ultimately boil down to a small handful of components.

As with the other boards, the Eagle files are on github. I’ve also included pngs of both the schematic and board for those without Eagle.

Here’s a quick run through of that handful of components. C1, C2 and the 16MHz Crystal keep the ATmega328 at the heart of the board ticking. C3 is a smoothing capacitor between Vcc and GND. C4 smooths the reset line from the FTDI header – in comparing various Arduino-clone schematics, I couldn’t find a consensus on whether it’s actually needed. As it’s easier to solder a jumper across unused gaps than it is to retro-fit an additional component, I decided to play safe and added it in. Finally, R1 and the switch allow the board to be manually reset.

Eagling

Laying this board out in Eagle was when I discovered how addictive it can be manually routing all of the connections. There’s an art in making the mess of connections aesthetically pleasing; completely pointless for the functionality of the board, but satisfying to get just so. I also discovered how to add a ground plane to the board – making the bottom layer much easier to layout.

PCB #2 PCB #2 - half built PCBs #1 & #2

After another three-week wait, the boards arrived and the first soldered together. Thankfully, the lessons learnt with the LED boards, and the hours spent making minute tweaks to the layout meant it worked first time. Which, in hindsight, was very pleasing as I hadn’t actually verified the circuit on a breadboard and had going straight into production with a theoretical circuit.

8 Apr 2012

[ part of the orb series ]

The Hello-World of Arduino sketches is making the on-board LED blink on and off. The equivalent for the orb is getting the three LEDs cycle through their three colours.

// The nine LED pins
int LEDS[] = {7,6,5,A0,A1,A2,A3,A4,A5};

void setup() {
  // Set them all to be outputs
  for (int i=0; i<9; i++) {
    pinMode(LEDS[i],OUTPUT);
  }
}

void loop() {
  // Toggle each LED in turn
  for (int i=0; i<9; i++) {
    digitalWrite(LEDS[i],HIGH);
    delay(300);
    digitalWrite(LEDS[i],LOW);
  }
}

Toggling the individual LEDs on and off like this is trivial but the Orb needs to be able to fade smoothly between colours. The normal approach to do this would be to use the Arduino’s PWM pins and let the hardware deal with it. But with nine pins to control that isn’t an option so the Orb has to resort to software PWM.

So, what is PWM and how can it be done in software? Pulse-width modulation is where an LED is rapidly turned on and off, many times a second. The greater the ratio of off to on, the dimmer the LED appears. If done fast enough, the eye doesn’t see any flicker.

But therein lies a problem; the digitalWrite command is slow. Arduino is a great environment for hiding some of the underlying complexity of the hardware, but it occasionally does this at the cost of efficiency.

To speed things up, the Orb has to go back to basics and manipulate the pins directly.

All of the IO pins on an Arduino are grouped into one of three port registers. By toggling the appropriate bits in the registers, the pins can be controlled.

Using the same pin assignments as the previous example, the following macros can be used to control the LEDs.

// Bit-masks for each pin of each LED
#define l1rm 0x80
#define l1gm 0x40
#define l1bm 0x20

#define l2rm 0x01
#define l2gm 0x02
#define l2bm 0x04

#define l3rm 0x08
#define l3gm 0x10
#define l3bm 0x20

#define LEDA(r1,g1,b1) PORTD = (PORTD&0x03)|(r1*l1rm)|(g1*l1gm)|(b1*l1bm)
#define LEDB(r2,g2,b2) PORTC = (PORTC&0xF8)|(r2*l2rm)|(g2*l2gm)|(b2*l2bm)
#define LEDC(r3,g3,b3) PORTC = (PORTC&0xC7)|(r3*l3rm)|(g3*l3gm)|(b3*l3bm)

With this is place, we can do a first pass at PWM. For each LED, we’ll define a brightness between 0 and 255. In each loop of the arduino code, a global counter is incremented. If the counter is less then an LED’s brightness, the LED should be on, otherwise it should be off. Which looks something like this:

byte brightness[] = {0,128,255, 0,128,255, 0,0,0 };
byte counter = 0;
void loop() {
  LEDA((brightness[0]>counter)?1:0,
       (brightness[1]>counter)?1:0,
       (brightness[2]>counter)?1:0);
        
  LEDB((brightness[3]>counter)?1:0,
       (brightness[4]>counter)?1:0,
       (brightness[5]>counter)?1:0);
        
  LEDC((brightness[6]>counter)?1:0,
       (brightness[7]>counter)?1:0,
       (brightness[8]>counter)?1:0);
  counter++;
}

The problem with this approach is that it assumes loop will get called with an absolute regularity to keep things smooth. The code above would probably work fine, but once you add in handling of the radio to control things, then that regularity could be lost.

I came across a solution for this in a blog post from the marvellous JeeLabs:

What occurred to me, is that you could re-use a hardware counter which is always running in the ATmega when working with the Arduino libraries: the TIMER-0 millisecond clock!

It increments every 4 µs, from 0 to 255, and wraps around every 1024 µs. So if we take the current value of the timer as the current time slot, then all we need to do is use that same map as in the original rgbAdjust sketch to set all I/O pins!

This introduces another idea that can make the code more efficient; rather than evaluate the brightness levels every time around the loop, create an array representing the 256 time-slots with the appropriate port register values pre-calculated.

With the arrays in place, the code in the loop function simply becomes:

void loop() {
  PORTD = (PORTD&0x03)|portDSlots[TCNT0];
  PORTC = (PORTC&0xC0)|portCSlots[TCNT0];
}

Setting up the slots can be done with the following code:

void setupSlots(int r1,int g1,int b1,int r2,int g2,int b2,int r3,int g3,int b3) {
  memset(portDSlots,0,256);
  memset(portCSlots,0,256);
  
  for (int i=0;i<256;i++) {
    portDSlots[i] = ((r1>i)?l1rm:0)|((g1>i)?l1gm:0)|((b1>i)?l1bm:0);
    portCSlots[i] = ((r2>i)?l2rm:0)|((g2>i)?l2gm:0)|((b2>i)?l2bm:0)|
                    ((r3>i)?l3rm:0)|((g3>i)?l3gm:0)|((b3>i)?l3bm:0);
  }
}

Fading can then be achieved by incrementally stepping to the desired brightness levels.

As before, the full code is available on github.

2 Apr 2012

[ part of the orb series ]

The top board in the Orb is the most simple – all it needs is three RGB LEDs and their resistors.

A quick search on ebay found a good supply of LEDs similar to those used on the BlinkMs. The datasheet on the auction listing gave me all the information I needed to start laying out the PCB.

I considered writing a more detailed post about using Eagle, but there are plenty of tutorials out there already (here’s the Sparkfun one that got me started).

The Eagle files for the board are on github.

With that done, I looked around at options for getting the PCB made. Olimex had been recommended to me by a colleague, but to be honest I found their long list of design rules quite overwhelming for a first timer. I eventually settled on SeeedStudio’s Fusion PCB service – who provide their own Eagle design rules file for you to run against your design. It worked out at about £1 for each board – which seemed pretty reasonable and you get 10 of them to play with.

The only downside was the wait – it took just over three weeks for the boards to arrive. Rapid prototyping for those not in a hurry.

PCB #1 PCB #1 PCB #1

When they did eventually arrive, it didn’t take me long to find the faults in the design. Despite my hours staring at the layout in Eagle, there were a couple things wrong. First, I realised I had missed a connection on the board layout – this was before I learnt enough about the Ratsnest tool which would have spotted the mistake. The second fault was with the custom Eagle part I had made for the LEDs – the outline was rotated 90°, putting GND somewhere it shouldn’t be. I didn’t spot this until I was figuring out what had caused the LEDs to burn-out on my first fully soldered board. Thankfully both of these could be resolved without having to get another batch of boards made – a jumper wire replaces the missing connection and I need to remember to ignore the printed outline when placing the LEDs.

With these faults worked around, I had a working LED board. It only took a handful of wires and an Arduino to see it in action. Cue the video.