Sunday, 10 January 2010

DIY radio controller for Lego

This was an experiment with a couple of Holtek remote control encoder and decoder chips (HT12E and HT12D) together with a cheap RF transmitter and receiver pair I picked up off ebay. OK, so the chips are not really designed for controlling models (more for opening your garage doors and so on) and lego's own IR controller would probably work better but its all good fun!

The receiver connects up to the Lego Power Functions 9V battery box and drives 2 power functions motors independently with forward/stop/reverse control. I bought a couple of power functions extension cables to get the connectors.

The receiver uses a cheap RF receiver module from ebay (I got receiver + transmitter for about £9) which is connected to the Holtek H12D. The address bits are all tied to ground and the data bits feed the 4 inputs of an L293D motor driver. A 7805 +5V regulator supplies the IC's and the RF receiver circuit (since the Lego 9V supply is too high for them)

The timing resistors on the H12D receiver are 100K + 12K in series. These pair with the transmitter's 1M + 470K (I'm not sure how good these selections are but it seems to work...)

The transmitter simply drives the 4 data bits of the H12E with tactile switches (closed to ground, pull ups on open). The H12E is powered and transmit enabled all the time the transmitter is on (to make sure the "all buttons off" state is transmitted to stop the motors)

Since there is no proportional control its all a bit stop-start and sometimes I found the receiver got "stuck" while the car was spinning on the spot and I had to place the transmitter really close (I think the electrical noise from the motors might be to blame.. but I also suspect my timing resistors not be quite right)

Wednesday, 6 January 2010

PLAYPAD program for Launchpad fun

I've been promising it for a while but I finally got round to making a download for other people to try out my Launchpad MIDI experiments.

Downloads and description are here...

Check out the mindblowing visuals...

Sunday, 3 January 2010

Make your own annoying musical greetings card!

I love the tiny 8 pin PICs from Microchip.. an entire computer in a package the size of a fingernail that costs pennies and can be programmed from your PC using just C and run on a watch battery. They're great.. but its taken me a while to find a use for one.

This was a quick and silly project to play a tune on a piezo sounder. Hopefully the comments in the source code included below are enough to work out whats going on.. this was actually a great project to work out how to use timers and interrupts on PICs, which I'd not done before. There were a few little hoops to jump through to fit the melody data into the tiny EEPROM space (128 bytes) of the 12F629.

I used SourceBoost C and PICkit 2 USB programmer.

#include <system.h>

// config word; internal oscillator, watchdog and master clear are off

//Set clock frequency
#pragma CLOCK_FREQ 4000000

// This is the tune data... high nybble of each byte is the relative duration (1-16) and the
// low nybble is the note (1-16) or a break (0). Note numbers are mapped to frequencies in
// code. A melody can use only 15 different notes in total and the total number of bytes that
// can be stored in EEPROM on a PIC12F629 is 128. There is a null terminator at the end of the
// melody data
#pragma DATA _EEPROM,
0x44, 0x20, 0x44, 0x10, 0x18, 0x16, 0x10, 0x14, 0x16, 0x10, 0x18, 0x1b, 0x10, 0x18, 0x16, 0x10,
0x14, 0x41, 0x20, 0x41, 0x10, 0x15, 0x13, 0x10, 0x11, 0x13, 0x10, 0x15, 0x17, 0x10, 0x15, 0x13,
0x10, 0x11, 0x44, 0x20, 0x44, 0x10, 0x18, 0x16, 0x10, 0x14, 0x16, 0x10, 0x18, 0x1b, 0x10, 0x18,
0x16, 0x10, 0x24, 0x10, 0x1b, 0x1a, 0x10, 0x19, 0x18, 0x10, 0x17, 0x16, 0x10, 0x15, 0x14, 0x20,
0x16, 0x20, 0x14, 0x10, 0x14, 0x16, 0x10, 0x17, 0x48, 0x20, 0x48, 0x10, 0x18, 0x19, 0x10, 0x1a,
0x1b, 0x10, 0x1a, 0x19, 0x10, 0x18, 0x17, 0x10, 0x16, 0x15, 0x10, 0x16, 0x17, 0x10, 0x16, 0x15,
0x10, 0x11, 0x12, 0x10, 0x13, 0x44, 0x20, 0x44, 0x20, 0x44, 0x20, 0x44, 0x20, 0x24, 0x1b, 0x1a,
0x10, 0x19, 0x18, 0x10, 0x17, 0x16, 0x10, 0x15, 0x34, 0x36, 0x44, 0x40, 0x00

typedef unsigned char byte;

// info used by the interrupt handler
byte next_tmr1h = 0;
byte next_tmr1l = 0;
byte wave = 0;

// interrupt handler called when the timer1 overflows
void interrupt( void )
// check if this is timer1 overflow event
if( pir1 & (1 << TMR1IF) )
// set up the timer 1 counters so they will overflow
// again after the appropriate time delay
tmr1h = next_tmr1h;
tmr1l = next_tmr1l;

// toggle pin state GPIO5, which drives the piezo sounder
gpio = wave? 0b100000 : 0b000000;

//clear timer 1 interrupt bit
clear_bit( pir1, TMR1IF );

void main( void )
// configure timer1 for interrupts / no prescaler
clear_bit( pir1, TMR1IF ); //clear timer 1 interrupt bit

// set up IO pins
trisio = 0;

// loop forever
byte addr = 0;
byte data = 0;

// loop through the tune
// read byte from EEPROM
eeadr = addr;
eecon1.0 = 1;
data = eedata;

// a zero byte indicates end of the tune
if(!data || addr > 0x7f)

// extract the note number from the low nybble
byte note = data & 0x0f;

// play a note?
// lookup corresponding frequency
long freq = 0;
case 1: freq=196; break; // G
case 2: freq=220; break; // A
case 3: freq=247; break; // B
case 4: freq=262; break; // C
case 5: freq=294; break; // D
case 6: freq=330; break; // E
case 7: freq=349; break; // F
case 8: freq=392; break; // G
case 9: freq=440; break; // A
case 10: freq=494; break; // B
case 11: freq=524; break; // C

// convert this into the correct timer count values
// Internal clock is 4MHz and Timer1 counts at 1/4
// of this frequency (1MHz). We need to call the
// interrupt handler at double the pitch frequency so
// that we can generate the 2 phases of the square wave
// pulse. What we calculate here is the initial 16 bit
// Timer1 value that will overflow (at 0xffff) after the
// appropriate period of time.
long l = (0xffff - (500000L/freq));
next_tmr1h = l >> 8;
next_tmr1l = l&0xff;
tmr1h = next_tmr1h;
tmr1l = next_tmr1l;
wave = 0;

// enable the timer (start sound)
// disable the timer (stop sound)

// duration is in top 4 bits. We'll just
// us an empty "for" loop to provide a delay
int dur = 70*(data >> 4);
for(int p=0;p<dur;++p)
// empty for loop for delay
for(byte q=1;q;++q);


The poor mans Harmonic Keyboard

I have always been curious about the Axis Controllers and their unusual key layout, particularly as this 'harmonic table' layout is intended to make chord structures simpler and easier to understand. I wondered what it would be like to play one and thought, hey, maybe I could do it on my Novation Launchpad..!

The first problem is that the Axis has a staggered honeycomb of a hexagonal keys where the Launchpad is a square 8x8 grid. I thought the notes might translate better if the Launchpad was held at 45 degress, but eventually decided to keep it simple.

Here is the key layout I ended up with...

The code is based on some earlier Launchpad MIDI projects. It is Visual C++ / Windows API code which simply receives input from the pad, sends MIDI to light up the buttons and outputs a MIDI stream to Reason (which actually makes the sounds). I used the wonderful Midi Yoke utility from Midi-OX which lets you transmit MIDI from one Windows application and use that stream as input to another (without that I would need to implement a Windows Midi Input device)

I am gathering all my recent Launchpad experiments into a single app which I will post for download together with source code some time soon. Watch this space.

edit: get it here

what the blog?

Well, here I am in the blogosphere... lets see how long this lasts... At the very least I hope to post up info about my various spare-time projects; music, electronics and so on. Maybe the occasional rant if you are lucky. Catch you later