Monday, June 30, 2008

Orange imposters

Mixed up LED package?

I'm sure about it now. Seven of the LEDs above are orange. The rest are yellow. I've asked the supplier if I can get a replacemet set of yellow ones.

Sunday, June 29, 2008

Flashing the EEPROM

In order that the MonomeSerial software 'sees' the monome clone, it's necessary to change the serial number of the arduino's EEPROM to resemble the serial number of a real monome.

I successfully followed Melka's instructions that have been posted on the bricktable blog (update: the bricktable blog instructions have been updated, you should follow those instructions rather than my version here).

You'll need access to a windows machine to complete this procedure, since the MProg software is windows only.

I'm going to paste his instructions here too (I hope that's not treading on anyone's toes), and include some of my own notes inbetween.

you have to install Mprog and the D2XX drivers from FTDI (your arduino will still work with the arduino IDE with this drivers)

MProg 3.0 > http://www.ftdichip.com/Resources/Utilities.htm
D2XX Drivers > http://www.ftdichip.com/Drivers/D2XX.htm

1/ Install both, then run Mprog

I installed the D2XX drivers on my winXP laptop first, following instructions in this PDF. This part requires you to have the arduino plugged into the PC via the usb cable. NB. while following these instructions the 'found hardware wizard' will run twice, this is normal, just point it to the directory that contains the drivers you downloaded both times.

I then installed Mprog on the same XP laptop, which was straightforward.
2/ Launch Mprog, then click on Device / Scan. You should see something like this appearing in the box down.
Code:

Number Of Blank Devices = 0
Number Of Programmed Devices = 1

3/ Click on Tools > Read and Parse. This will fill the boxes.
4/ Check the “use fixed serial number” box and change the value below.
To have your board recognized as a monome by monome serial, you have to enter something like
m40h-xxx (we used m40h-001)

I used the m40h-001 code too.
m64-xxxx
m128-xxx
m256-xxx
Choose whatever you want, I’m not sure what is different between the various IDs, for the moment I’m using m40h-001.
There is 2 protocols described on the monome site, and the 64/128/256 seems to be more complete (15 message IDs, 9 for the 40h protocol), so maybe you’d better use m256-xxx
5/ Click on File > save as
6/ Once saved, click on the flash icon (Program all existing devices, Ctrl+P).

It's the icon that looks like a lightening flash.
7/ Unplug / plug back your board from the usb port.

In my case, this meant unplugging the arduino's USB cable from my XP laptop and plugging it in to my macbook (where i have MonomeSerial installed).

8/ Run monomeserial, you should see something appear on the devices list.

You'll see the serial code you chose in the devices list (m40h-001).

Friday, June 27, 2008

Difficulty lighting a whole row

I've been adjusting the MAX test code, to gets the lights moving in different ways. While doing this I noticed that if a row is asked to light seven or eight of its LEDs at once, all the lights go out and I have to reset the arduino to get it going again. I'd like to find out why that is.
LED driver test
The button pad PCBs are all soldered up and all the components are in place in the breadboard version of the controller. To test that the MAX chip was working and wired up correctly, I uploaded this code to the arduino.

The MAX7219 has 'DIG' pins and 'SEG' pins, corresponding to the two axes of the LED matrix. The SEG pins supply voltage to the grid, and the DIG pins act as ground sinks. The SEG pins are named A to G and the eighth pin is called SEG DP. The DP pin should come first in the sequence, not last (the way I wired it first).

Once I'd corrected it, the example code gave the following pattern.

LED driver test

The difference between the two distinct colours of LED show up quite clearly (less so in the photo), that's a bit of a shame.

Tuesday, June 24, 2008

What's the best way to cleanly divide header strips?

This didn't work

The guy in my local electronics shop recommended that I just press in the notch with a knife. I tried it but wasn't able to snap them this way.

How do you break header strips apart cleanly?

So I used a chisel and hammer. Which snapped them in the correct place, but a few times the casing to one of the sides of the break was damaged, sometimes losing a pin.

So what's a reliable way to cleanly break header strips like this into the lengths that you need?

Two wires into one via

Meanwhile, at Owen's suggestion I'm twisting wires together like this as a way of attaching two of them to a single via hole in the button pad PCBs (one wire is a jumper connecting the PCB to another one, the second wire leads to one of the shift registers or the max LED driver chip).

Misc parts

Misc parts
I got hold of a few more parts I needed.

The chip in the blue box is the MAX7219CNG LED driver.

There's a long strip of paired male headers. I'll snap this into four lengths of 16 pins.

The four black plastic things with female sockets are IDC connectors to attach to two ribbon cable lengths. I messed this up with the first one I tried and broke it, this time I'll use a vice to push down the part that cuts the cable. The IDC headers will plug into the paired header pin strips, forming a removable connection from the arduino shield PCB (at least I think I'll use a shield) to the button pad.

The things with pins are IC sockets. I'm using these so that I don't have to solder the chips directly to the PCBs, and can replace them easily if necessary. There are two 16 pin sockets for the shift registers, and one 24 pin socket for the max chip.

Sunday, June 22, 2008

IDC connectors

I'm waiting around to get some parts (IC sockets, because I don't want to plug the expensive max chip directly into the breadboard for risk of bending it's legs or damaging it some other way) that will allow me to do a full breadboard test.

In the meantime here's an illuminating PDF I found. It describes how the IDC connectors work. This project will use four of them to anchor two ribbon cables to the pcbs.

Friday, June 20, 2008

Monome/arduino code online

A new section has been added to the bricktable blog which is designed to document the construction of a single colour, sparkfun+arduino monome clone, just like the one I'm building. So far there's not much information there, but they have published the arduino code for their project, which is very useful.

Since this code takes care of a bunch of things I haven't started to implement yet, like serial reading and writing, LED control and button debouncing, It's likely that I'll end up using it, or at least something derived from it.

Another blog to add to my reader.

Thursday, June 19, 2008

Four boards need linking together

The four soldered-up button pads, with the button-press-related wires hooked into the vias:

Four button pads

Four button pads

I need to add inter-pad connections like this so that all the boards can be 'reached' by the arduino:

Four button pads

I'm not sure how to arrange that, mechanically, at the moment. Can anyone see how unsped has done it in this photo? I can't quite make out how he's attaching two cables to single vias along the outside edges of the boards.

EDIT: Unsped explains that, for the edge vias which needed more than one wire attached to them, he first soldered male header pins in place, then soldered the necessary wires to those pins. Finally he covered the pins and the joints with liquid plumbers tape to prevent short-circuits. He adds that if he were to do the project again he wouldn't use header pins, but instead solder one wire pushed through the hole, and then solder the second one onto the pad created by soldering the first.

Tuesday, June 17, 2008

Testing the Sparkfun buttonpad

Button pad test

I placed the silicon button pad ontop of the soldered-up PCB and hooked it up according to the circuit I'd made earlier in which I had simulated button presses using hookup wire.

Button pad test

I twisted two cables together from eight strands of coloured wire to help with testing. I'm using a colour's position in the sequence of hues that form a rainbow as an indicator of its index position so that I can see quickly whether I'm connecting to the correct pin.

Button pad test

I needed to alter the code a bit to get this working. Using the orientation of the silkscreen print on the PCB's, the arduino needs to supply voltage to the rows of the sparkfun pad, and read from its columns, not the other way around.

Here's the new code:

//**************************************************************//
// Name : 4x4 button test //
// Author : basementleds //
// Date : 17 Jun, 2008 //
// Version : 1.2 //
// Notes : registers pc74hct165p, pc74hct164p //
//****************************************************************

int pin_button_in_clock = 12;
int pin_button_in_apl = 13;
int pin_button_in_data = 11;
int pin_button_in_latch = pin_button_in_apl;

int pin_button_out_clock=2;
int pin_button_out_data=3;

byte my_bit;
byte activate_rows_byte;
byte activate_rows_byte_disposable_copy;
byte pressed_columns_byte;

void setup() {
Serial.begin(9600); //start serial
pinMode(pin_button_in_latch, OUTPUT);
pinMode(pin_button_in_clock, OUTPUT);
pinMode(pin_button_in_data, INPUT);
pinMode(pin_button_out_data, OUTPUT);
pinMode(pin_button_out_clock, OUTPUT);
}

void loop() {
activate_rows_byte=1;
for (int r=7; r>-1; r--) { // for each row
activate_rows_byte_disposable_copy=activate_rows_byte;
for (int x=0;x<8; x++){ // for each digit of the activate rows byte
if((activate_rows_byte_disposable_copy & 1) != 0){
digitalWrite(pin_button_out_data,HIGH); // if the LSB is 1, activate 'current' row
}
else {
digitalWrite(pin_button_out_data,LOW);
}
pulse_pin(pin_button_out_clock);
activate_rows_byte_disposable_copy=activate_rows_byte_disposable_copy >> 1;
}
send_row_events(get_pressed_columns(),r);
activate_rows_byte=activate_rows_byte << 1; // cue the next lsb
}// eo each row
delay(900);
Serial.println(" ");
}

void send_row_events(byte active_columns_byte,int row){
for (int e=0; e<8; e++){
if((active_columns_byte & 1) != 0){
print_keypress(e,row); // send index of the detected column press, and the row index
}
active_columns_byte=active_columns_byte >> 1;
}
}

void print_keypress(int column,int row){
Serial.print("Pressed: column");
Serial.print(column);
Serial.print(", row ");
Serial.println(row);
}

byte get_pressed_columns(){
pulse_pin(pin_button_in_latch); // sample the button states
pressed_columns_byte=0; // clear the byte ready for new data
for (int n=0; n<8; n++){
pressed_columns_byte = pressed_columns_byte << 1 ; // shift bits to the left, making space to capture the state of the next button
pressed_columns_byte=clear_lsb(pressed_columns_byte); // make sure the new lsb is zero, to avoid surprises
my_bit = digitalRead(pin_button_in_data); // store the current Q7 value from the button register in my_bit
pressed_columns_byte = pressed_columns_byte | my_bit; // OR pressed_rows_byte with the new bit to add it to the lsb
pulse_pin(pin_button_in_clock); // cue the next bit slot for reading
}
return(pressed_columns_byte);
}

// Set a pin to low, then high
void pulse_pin(int pin_number){
digitalWrite(pin_number,LOW);
digitalWrite(pin_number,HIGH);
}

// Clear the least significant bit
byte clear_lsb(byte byte_to_clear){
return(byte_to_clear & 0xfe); // AND the byte with 11111110 to be sure that the LSB is zero
}

Soldering diodes and LEDs to the Sparkfun buttonpad PCB.

I needed to solder the components to the button pad PCBs to test further. I read a few soldering guides before beginning. This one is pretty good.

Many of the guides stress the importance of beginning with the components that would be hard to reach if others were already soldered in place. In general this means working from the middle of the pcb outwards. As I progressed, I clipped the legs off each component after it's solder had hardened, to keep things transparent.

Here's the first diode slotted in place.
Button pad test

View of the underside.
Button pad test

The first solder, it could be prettier.
Button pad test

Before I attached each LED to the board, I tested that it worked by slotting it into one of the other boards that I had hooked some wires to from my breadboard (don't forget to include a suitable resistor before the LED to prevent it from burning out).
Button pad test

Here's a view of the underside of the PCB I used to test the LEDs. It seemed to make sense to connect the anode (+ side, longer leg) of the LEDs to the BLUE via, because this places them neatly in the middle of the button area without the need to bend their little legs. While testing the LEDs I noticed that there seemed to be distinct colours of yellow in the batch that I ordered. Some LEDs shone a warm, orangy yellow and anothers a more lemony colour. I'm hoping the difference won't be pronounced enough to be disturbing, or that perhaps when the LEDs are being driven by the MAX driver, their colour will be consistent.
Button pad test

I soldered LEDs and diodes alternately, turning the PCB around as necessary while it was gripped by the pincers of the 'helping hand'. Here's the middle section almost done.
Button pad test

The finished thing.
Button pad test
Button pad test

Once it was done I used some wires from the LED testing circuit on the breadboard to touch the joints of the LEDs again to verify that they still worked. One of them didn't, I probably damaged it by applying the soldering iron for too long. Once the iron is fully heated it seems that about 2 seconds of contact with the joint before applying the solder was enough to get a good result.

I removed the dead LED using solder wick to remove the solder while pulling the plastic dome gently with pliers. I ordered 70 LEDs, so I can afford 6 of them to be wasted.

Saturday, June 14, 2008

4x4 button matrix mock-up

Using one of the spakfun pcb's as a reference, I made a test to help understand the way a small button matrix would work with the shift registers and the arduino code.

4x4 Button Pad

I'm not sure I've set this up in the most sensible way, but it's working. Here's a high level account of what's going on:

  1. The arduino loads the parallel-out register with a byte which has just one bit turned on. The one bit corresponds to one of the channels.

  2. The corresponding pin of the parallel out register goes high, this provides voltage to one of the rows of the button matrix.

  3. The arduino pulses the latch pin of the serial out register so that it samples from the outputs of the button matrix columns

  4. If a button is pressed in the active row, the column of that button will be HIGH when the register samples it

  5. Next the arduino reads the contents of the serial output register, sending it clock pulses to access the byte one bit at a time.

  6. Now that the arduino 'knows' which buttons are pressed in the current column, it creates a new byte to send to the parallel out register, to active the next row in the sequence


Here's how the schematic looks.

4x4 Button Pad

Here's a closeup of the PCB. The wires are just loosely hooked in place as an aid to understanding how the signal will flow in the future.

4x4 Button Pad

This is the code running on the arduino.

//**************************************************************//
// Name : 4x4 button test //
// Author : basementleds //
// Date : 13 Jun, 2008 //
// Version : 1.0 //
// Notes : registers pc74hct165p, pc74hct164p //
//****************************************************************

int pin_button_in_clock = 12;
int pin_button_in_apl = 13;
int pin_button_in_data = 11;
int pin_button_in_latch = pin_button_in_apl;

int pin_button_out_clock=2;
int pin_button_out_data=3;

byte my_bit;
byte pressed_rows_byte;
byte column_byte;
byte column_byte_disposable_copy;

void setup() {
Serial.begin(9600); //start serial
pinMode(pin_button_in_latch, OUTPUT);
pinMode(pin_button_in_clock, OUTPUT);
pinMode(pin_button_in_data, INPUT);
pinMode(pin_button_out_data, OUTPUT);
pinMode(pin_button_out_clock, OUTPUT);
}

void loop() {
column_byte=1;
for (int c=7; c>-1; c--) { // for each column
column_byte_disposable_copy=column_byte;
for (int x=0;x<8; x++){
if((column_byte_disposable_copy & 1) != 0){
digitalWrite(pin_button_out_data,HIGH); // if the LSB is 1, turn the 'current' led on
}
else {
digitalWrite(pin_button_out_data,LOW);
}
pulse_pin(pin_button_out_clock);
column_byte_disposable_copy=column_byte_disposable_copy >> 1;
}
send_column_events(get_pressed_rows(),c);
column_byte=column_byte << 1;
}// eo each column
delay(900);
Serial.println(" ");
}

void send_column_events(byte active_rows_byte,int column){
for (int e=0; e<8; e++){
if((active_rows_byte & 1) != 0){
print_keypress(column,e);
}
active_rows_byte=active_rows_byte >> 1;
}
}

void print_keypress(int x,int y){
Serial.print("Pressed: ");
Serial.print(x);
Serial.print(", ");
Serial.println(y);
}

byte get_pressed_rows(){
pulse_pin(pin_button_in_latch); // sample the button states
pressed_rows_byte=0; // clear the byte ready for new data
for (int n=0; n<8; n++){
pressed_rows_byte = pressed_rows_byte << 1 ; // shift bits to the left, making space to capture the state of the next button
pressed_rows_byte=clear_lsb(pressed_rows_byte); // make sure the new lsb is zero, to avoid surprises
my_bit = digitalRead(pin_button_in_data); // store the current Q7 value from the button register in my_bit
pressed_rows_byte = pressed_rows_byte | my_bit; // OR pressed_rows_byte with the new bit to add it to the lsb
pulse_pin(pin_button_in_clock); // cue the next bit slot for reading
}
return(pressed_rows_byte);
}

// Set a pin to low, then high
void pulse_pin(int pin_number){
digitalWrite(pin_number,LOW);
digitalWrite(pin_number,HIGH);
}

// Clear the least significant bit
byte clear_lsb(byte byte_to_clear){
return(byte_to_clear & 0xfe); // AND the byte with 11111110 to be sure that the LSB is zero
}


Here I've simulated pressing three buttons by making connections between the input (SWITCH) and the output (SWITCH-GND) sockets. Below you see the output of the serial window in the arduino software.

buttonpad_test_with_readout

Next I need to figure out how to connect these wires to the PCB in a non-permanent way so that I can test this circuit with the real buttons, and see if it's still working as expected. If anyone has any thoughts about how I could do that please post in the comments.

Button matrixes, part one

The next thing I'd like to get a proper handle on is how the button matrix will work. Specifically, how the arduino will know the coordinates of any buttons that are being pressed. So far, this excellent little article has been very helpful.

This diagram captures how I'm expecting it to work in a general way:

Sparkfun button pad pcb

Friday, June 13, 2008

The 164 isn't built for controlling LEDs

Latchless shift register
I swapped the 7JE75K shift register I was using in a previous post for a PC74HCT165P (the monome uses a 164 too, for detecting button presses). To test it out I linked it to the same set of LEDs. When one of the 'switches' was closed, the corresponding LED should light up.

Once I got this working I noticed that whenever I had any LEDs thhttp://www.blogger.com/img/gl.link.gifat were on, the LEDs that supposed to be off were also glowing faintly (see image). It turns out that this is a side effect of the PC74HCT164P having no latch pin. When it shifts data from one slot to the next, that data is also immediately sent to the output pins. A latch, like the one the 7JE75K has, makes it possible to shuffle the bits around in the register in 'secret' and when they're ready, they're 'revealed' to the output pins all at once. So with the 165, when one bit in the register is high, it very briefly activates each of it's output pins as that bit gets shifted. When this happens many times a second it looks like the LEDs are faintly glowing.

Of course the 164 doesn't actually control LEDs in the monome. So this isn't a problem.

Yellow LEDs 3mm 1000 mcd clear

Yellow LED 3mm 1000 mcd clear
The LEDs arrived. They're clear so I wondered whether they would project a 'spot' on the inside of the sparkfun buttons, but the light seems to spread pretty well through the rubber.

136-3700_IMGhttp://www.htvision.com/product.asp?intProdID=159

Monday, June 9, 2008

Shift Register ins and outs

There are two shift registers in the monome schematic. A parallel to serial (74HC165), and a serial to parallel one (74HC164).

I knew that these had something to do with dealing with button presses but I wanted to understand exactly what they were doing. With the help of an electronics-savvy friend I set up an arduino circuit. In this post I'll add the schematic and the code, and in the following post I'll try to explain what the code is doing (though it's heavily annotated, so that might be redundant). Click the images to see bigger versions.

shiftregistertute1

Here's how it looks on the breadboard (NB: I'm using a wire to simulate the operation of the switches).

shiftregisters1

Here's the Arduino code.


//**************************************************************//
// Name : shiftIn/shiftOut Example //
// Author : basementleds //
// Date : 9 Jun, 2008 //
// Version : 1.0 //
// Notes : button register pc74hct165p, led register 7JE75K //
//****************************************************************

int pin_button_clock = 12;
int pin_button_apl = 13;
int pin_button_data = 11;
int pin_button_latch = pin_button_apl;

int pin_led_clock=2;
int pin_led_latch=3;
int pin_led_data=4;

byte my_bit;
byte button_byte;

void setup() {
Serial.begin(9600); //start serial

pinMode(pin_button_latch, OUTPUT);
pinMode(pin_button_clock, OUTPUT);
pinMode(pin_button_data, INPUT);

pinMode(pin_led_data, OUTPUT);
pinMode(pin_led_latch, OUTPUT);
pinMode(pin_led_clock, OUTPUT);
}

void loop() {
set_led_states(get_button_states());
}

byte get_button_states(){
pulse_pin(pin_button_latch); // sample the button states
button_byte=0; // clear the byte ready for new data
for (int n=0; n<8; n++){
button_byte = button_byte << 1 ; // shift bits to the left, making space to capture the state of the next button
button_byte=clear_lsb(button_byte); // make sure the new lsb is zero, to avoid surprises
my_bit = digitalRead(pin_button_data); // store the current Q7 value from the button register in my_bit
button_byte = button_byte | my_bit; // OR th my_input with the new bit to add it to the lsb
pulse_pin(pin_button_clock); // cue the next bit slot for reading
}
Serial.println (button_byte,BIN);
return(button_byte);
}

void set_led_states(byte button_states){
for (int n=0; n<8; n++) {
if((button_states & 1) != 0) digitalWrite(pin_led_data,HIGH); // if the LSB is 1, turn the 'current' led on
else digitalWrite(pin_led_data,LOW);
button_states = button_states >> 1; // Shift to get a new LSB from buttonstates
pulse_pin(pin_led_clock); // address the next bit slot
}
pulse_pin(pin_led_latch); // when the latch goes from low to high, the data that's been stored to the register's memory gets sent to its output pins
}

// Set a pin to low, then high
void pulse_pin(int pin_number){
digitalWrite(pin_number,LOW);
digitalWrite(pin_number,HIGH);
}

// Clear the least significant bit
byte clear_lsb(byte byte_to_clear){
return(byte_to_clear & 0xfe); // AND the byte with 11111110 to be sure that the LSB is zero
}



Here's how it should look when it's running:

Shift registers 1 from basementhum on Vimeo.

Hello World/Arduino

Once I had the Arduino board in my greasy paws I worked through this excellent little series of tutorials. They're a very simple introduction to how to get data in and out of the thing, and to how the Arduino software works. Strongly recommended!

Photo: Adactio

Tools

Because this is the first electronics project I've attempted, I needed to buy some general stuff that wasn't specific to the monome project. For anyone following along here's what (I think) you'll need:

  • Soldering Iron

  • Soldering Iron Holder, with sponge

  • Solderless Breadboard.

  • Solid core hookup wire (bring your Arduino along to the shop to make sure you get wire of a suitable thickness to securely anchor in the Arduino's pin sockets, the first bunch of wire that I bought was too thin)

  • Assorted resistors

  • Assorted capacitors

  • Assorted diodes

  • LEDs for testing (I got ten)

  • Wire clippers

  • Multimeter

I'll add to this list if and when I discover that I needed more general purpose bits and pieces.

Photo: aaronharmon

Costs & Parts

Here's a list of the costs I'm making and the parts I'm using. I've included a link to the supplier page where possible. I'll update this list as I order new parts, or if I discover that I didn't end up using bits that I ordered.

Whenever shipping costs are mentioned this refers to shipping the product to the Netherlands.



Arduino Diecimila126.18 EUR
Sparkfun Button Pads422.82 EUR
Sparkfun Button Pad PCBs425.33 EUR
Diode Small Signal - 1N4148706.68 EUR
Shipping of Sparkfun order135 EUR
Yellow LEDs (3mm, 1000 mcd, shipping included)7011.35 EUR
Shift register 74HCT165 (Parallel in/serial out)10.95 EUR
Shift register 74HCT164 (Serial in/parallel out)10.95 EUR
MAX7219CNG+ (LED driver)118.19 EUR
10Kohm, 10 pin, Resistor network10.23
0.1uf Capacitor3
10uf Capacitor1
16 pin IC Socket1
14 pin IC Socket1
24 pin IC Socket11.79 EUR
Arduino Shield PCB (files, 4pcb)122.78 EUR
MachineCollective Enclosure180 EUR

Total ±270 EUR

What it's all about

Posts on this blog will document the construction of an 8*8, Arduino-powered, Sparkfun button pad using, DIY monome.

Although the Sparkfun buttons are big enough to accommodate RGB LEDs, I'll be using single colour ones to keep things simpler.

My knowledge of electronics is hovering just above absolute beginner level, so I hope this will develop into a useful source of information for other electronics beginners wanting to build a monome controller.