Sunday, 24 October 2010

Solenoid Drum Machine

Just a quick project to try out some new push solenoids...

Based on PIC16F688 and building on the MIDI input code used on my earlier POKEY project


include <system.h>
#include <memory.h>

#pragma DATA _CONFIG, _MCLRE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
#pragma CLOCK_FREQ 8000000
typedef unsigned char byte;

// define the pins
//#define P_LED portc.0

// MIDI defs
#define MIDIMSG(b) ((b)>>4)
#define MIDICHAN(b) ((b)&0xf)
#define MIDIMSG_NOTEON 0x09
#define MIDIMSG_NOTEOFF 0x08

// MIDI message registers
byte runningStatus = 0;
int numParams = 0;
byte midiParams[2] = {0};

#define SZ_RXBUFFER 20
byte rxBuffer[SZ_RXBUFFER];
byte rxHead = 0;
byte rxTail = 0;
int tmr[4] = {0};

////////////////////////////////////////////////////////////
// INTERRUPT HANDLER CALLED WHEN CHARACTER RECEIVED AT
// SERIAL PORT
void interrupt( void )
{
// check if this is serial rx interrupt
if(pir1.5)
{

// get the byte
byte b = rcreg;

// calculate next buffer head
byte nextHead = (rxHead + 1);
if(nextHead >= SZ_RXBUFFER)
{
nextHead -= SZ_RXBUFFER;
}

// if buffer is not full
if(nextHead != rxTail)
{
// store the byte
rxBuffer[rxHead] = b;
rxHead = nextHead;
}
}
}


////////////////////////////////////////////////////////////
// INITIALISE SERIAL PORT FOR MIDI
void init_usart()
{
pir1.1 = 1; //TXIF
pir1.5 = 0; //RCIF

pie1.1 = 0; //TXIE no interrupts
pie1.5 = 1; //RCIE interrupt on receive

baudctl.4 = 0; // SCKP synchronous bit polarity
baudctl.3 = 1; // BRG16 enable 16 bit brg
baudctl.1 = 0; // WUE wake up enable off
baudctl.0 = 0; // ABDEN auto baud detect

txsta.6 = 0; // TX9 8 bit transmission
txsta.5 = 1; // TXEN transmit enable
txsta.4 = 0; // SYNC async mode
txsta.3 = 0; // SEDNB break character
txsta.2 = 0; // BRGH high baudrate
txsta.0 = 0; // TX9D bit 9

rcsta.7 = 1; // SPEN serial port enable
rcsta.6 = 0; // RX9 8 bit operation
rcsta.5 = 1; // SREN enable receiver
rcsta.4 = 1; // CREN continuous receive enable

spbrgh = 0; // brg high byte
spbrg = 15; // brg low byte (31250)

}


byte rxInc(byte *pbIndex)
{
// any data in the buffer?
if((*pbIndex) == rxHead)
return 0;

// move to next char
if(++(*pbIndex) >= SZ_RXBUFFER)
(*pbIndex) -= SZ_RXBUFFER;
return 1;
}

////////////////////////////////////////////////////////////
// RECEIVE MIDI MESSAGE
// Return the status byte or 0 if nothing complete received
// caller must check midiParams array for byte 1 and 2
byte receiveMessage()
{
// buffer overrun error?
if(rcsta.1)
{
rcsta.4 = 0;
rcsta.4 = 1;
}

// any data in the buffer?
if(rxHead == rxTail)
return 0;

// peek at next char in buffer
byte rxPos = rxTail;
byte q = rxBuffer[rxPos];

// is it a channel msg
if((q&0x80)>0)
{
runningStatus = 0;
switch(q&0xf0)
{
case 0x80: // Note-off 2 key velocity
case 0x90: // Note-on 2 key veolcity
case 0xA0: // Aftertouch 2 key touch
case 0xB0: // Continuous controller 2 controller # controller value
case 0xC0: // Patch change 2 instrument #
case 0xE0: // Pitch bend 2 lsb (7 bits) msb (7 bits)
runningStatus = q;
numParams = 2;
break;
case 0xD0: // Channel Pressure 1 pressure
runningStatus = q;
numParams = 1;
break;
case 0xF0: // (non-musical commands) - ignore all data for now
return q;
}
// step over the message
if(!rxInc(&rxPos))
return 0;

}

// do we have an active channel message
if(runningStatus)
{

// read params
for(int thisParam = 0; thisParam < numParams; ++thisParam)
{
midiParams[thisParam] = rxBuffer[rxPos];
if(!rxInc(&rxPos))
return 0;
}
// commit removal of message
rxTail = rxPos;
return runningStatus;
}
else
{
// remove char from the buffer
rxInc(&rxTail);
return q;
}
return 0;
}


void main()
{
// osc control / 8MHz / internal
osccon = 0b01110001;

// timer0... configure source and prescaler
cmcon0 = 7;

// enable serial receive interrupt
intcon = 0b11000000;
pie1.5 = 1;

// configure io
trisa = 0b00010000;
trisc = 0b00110000;
ansel = 0b00000000;

porta=0;
portc=0;
memset(tmr,0,sizeof(tmr));

// initialise MIDI comms
init_usart();


// loop forever
for(;;)
{
// get next MIDI note
byte msg = receiveMessage();
if(msg)
{
byte note = midiParams[0];
if(note >= 48 && note < 52)
{
int which = note-48;
// 0x90 note on
// 0x80 note ff
if((msg & 0xf0) == 0x90)
{
tmr[which] = 200;
}
}
}

for(int i=0;i<4;++i)
{
if(tmr[i] > 0)
tmr[i]--;
}

porta.2 = (tmr[0]>0)?1:0;
portc.0 = (tmr[1]>0)?1:0;
portc.1 = (tmr[2]>0)?1:0;
portc.2 = (tmr[3]>0)?1:0;
}
}

Saturday, 18 September 2010

Tesla Coil Diary - Part 1

I've wanted to own a Tesla coil pretty much since I knew what one was, but I always thought it would be a bit difficult to make and possibly a little bit dangerous... Anyway, I decided to bite the bullet and started gathering the bits a couple of months back and actually started the building of it a couple of weeks ago after I got the courage to fire up the 10kV Neon Sign Transformer I got off ebay.

I got all the information and many great tips of websites of other coilers and have borrowed many ideas. I will try to remember and credit as much as I can.

I started off by getting this neon transformer

its a 10kV 50mA F.A.R.T. (oh the fun!) Resinblock. Here is my first try out of it, making a Jacobs ladder from coat hanger wire....

So far so good...

After a bit of online reading I eventually decided to wind my secondary coil on 125mm PVC ducting pipe (After deciding the 68mm drainpipe I first bought was just too wimpy). I got a nice 2Kg reel of 0.71mm magnet wire from ebay and got winding. I initially rigged up a motor driven jig to wind the wire but ended up winding by hand so I could keep a good tension on the wire (The motor came in very useful later while varnishing). I wound 800 turns in a couple of hours then put on about 5 coats of polyurethane gloss varnish. I used kapton tape to secure the outer windings (I owe http://deepfriedneon.com/ for many tips I used ... given my DIY prowess, without this information I would have ended in disaster I am sure)

Here is my winding rig...

I was quite pleased with the end result, which looked nicely like something from a B-movie mad scientists lab.

I originally bought 6mm microbore copper tubing to make my primary coil, but realised that I had not bought enough, and it was rather too expensive to go and buy another, longer length, so I looked around for alternatives and found some 4.75mm solid aluminium wire at the much better price of £12 for 20 metres. The wire was a lot softer and easier to kink than I expected and at first I wasn't too happy with the result. But after some reworking I think its OK. Here is the result (set on MDF with acrylic stands secured with nylon zipties)


I managed about 17 turns. I think I need to tap the coil after about 10 turns based on what Tesla Coil CAD told me - but I thought it would be good to have the extra tunability offered by the extra coils

For the top load I got some 10mm semi-rigid aluminium ducting hose (as is a coiler traditional I believe) and set it between two 34cm steel trays from the local 99p shop (these have to be the best bargain of this build!). This whole procedure was more difficult than it probably sounds... I needed to bolt the trays together first, with a wood spacer, then use tensioned strips of gaffer tape to hold the 2 plates parallel to each other. Then I threaded a rubber bungee cord through the flexible duct and after putting the ducting around the rim of the trays I hooked up the bungee and spread the out ducting round the rim until it joined up. I used a bit of flexible plastic sheet to make a sleeve to put inside one end of the ducting and help join the ends together. A bit of aluminium tape joined the ends, then more aluminimum tape to secure the ducting on the rim of the trays (helpful tips from http://www.hvtesla.com/toroid.html)




It might not be the best looking toroid, but it does look pretty meaty and mean!

Next steps are to add a strike rail to the primary (finally getting some use out of that microbore copper pipe), build a chassis (in progress - out of chipboard and softwood) and add fittings to secure it all together properly without danger of it collapsing. In the mean time here are the parts stacked on top of each other for a photo opportunity....


And so onto the electrics... I threw caution to the wind and got some Cornell Dubilier 942C20P15K-F capacitors, which a bit of online research seemed to indicate were THE choice for a good coil, even though they are not cheap, especially when factoring postage from US to UK. My capacitor bank has 28 of these 0.15uF, 2000V capacitors arranged in two parallel strings of 14. I mounted them on clear acrylic and wired them up with 1M bleeder resistors using high current wire taken from a set of car jump leads.
I just made my spark gap this weekend... I initially intended making a cylindrical "Richard Quick" type design but I preferred the idea I saw on a web site (which I would credit if I could find it again) where the multiple copper tubes are laid out side by side on the top of a box, and air is drawn through them by fans mounted on the ends of the box. Airflow keeps the gaps cool, but also sucks away ionised air from the gaps and quenches the sparks more quickly, which (so I read) results in better operation of the coil.

I made the spark gap box from acrylic sheets with an 85mm 240VAC fans (from Maplin) mounted at each end. 10 copper tubes of 15mm diameter and 90mm length form the gap. Two layers of kapton tape at each end of each copper tube provide spacing of ~0.4mm between tubes when they are laid side by side. Connection is made (at the moment) by a plug of compressed aluminium foil around which is wound the connection wire (car jump lead) inside the two "terminal" tubes. I am not sure how well this arrangment is going to work... we shall see.. The tubes are not permanently attached to the box, so my idea is that the number of tubes included in the gap can be varied by moving one of the tubes to which the wire is attached (the other being fixed at one side) by simply removing and shuffling the tubes.


I still need to complete build of the Terry Filter circuit (which I hope will protect the neon transformer from voltage surges) as well as the structural bits and pieces, however I hope I can get this thing up and running before too much longer. Watch this space for the results....

Wednesday, 30 June 2010

DIY Boss PC-2 / Amdek PCK100 Analog Percussion Synth

Back at the end of the 80's I went in a music shop in London and on impulse I bought this wierd BOSS box that made weird bloopy noises... a PC-2 Percussion Synthesizer. It wasn't a difficult decision at the time since it only cost me £10 brand new boxed (I think they were trying to get rid of them) and it came with a free brand new BOSS HC-2 Hand Clapper pedal, although that seemed even less useful (though the guy did a good sales pitch involving a tale about a friend with no arms who had trouble applauding at gigs... :o)


Apart from a bit of novelty value I gotta be honest they didn't get a lot of use... I think the HC-2 got chucked during a house cleanout and the PC-2 was sold on ebay a few years back (and was amazed to get £100 for it). Well now I am kicking myself and wished I'd held on to these two collectables.

So when I saw the schematic of the Amdek PCK100 online (actually a kit form of the PC-2 sold by a Roland affiliate) I decided to try to make one and once again re-live boingy noise heaven.


On the page http://www.effectsdatabase.com/model/amdek/pck100 where I found the schematic I also found a photo of the PCB and decided to try to use it directly. With some manipulation in Paint Shop Pro and the use of Press'n'Peel PCB etching film I was able to make a copy of the board and after working out some workarounds (e.g. using BA6110 instead of ultra-rare BA662A VCA chip) I actually got it to work.. So in case you're interested ..here is how I did it

1) I started off with this photo of the track side of the original PCB

2) Turned to mono, upped the contrast, then very carefully use the "eraser" tool to ensure there are good clean gaps between all the tracks

3) Marked drill holes with circles

4) Drop colour depth to 2 colours

5) Negative image and a few embellishments and its ready to press'n'peel

6) Laser printed etch-resist transferred to copper clad board using a hot iron

7) Etched, drilled and trimmed ready for components

I mounted the board inside a project box from Maplin. By the way I have a thing for Dymo embossed label tape :)





The Amdek user guide gives info on some mods to the board (VCO wave form change, mod waveform change) which I added toggle switches for. Usually the Sweep control is a center tap pot.. I didn't have one so I instead rigged up a DPDT toggle and a resistor to a normal pot so that the same effect could be acheived (although I am not sure it works so well)

The original board calls for a Roland BA662A VCA chip... you won't find one! you can use a similar BA6110 chip but the pinout is different. I found the following worked

  • socket 1 connect to BA6110 pin# 4
  • socket 2 connect to BA6110 pin# 2
  • socket 3 connect to BA6110 pin# 1
  • socket 4 no connection. BA6110 pin#3 connected to GND (pin 5)
  • socket 5 connect to BA6110 pin#5
  • socket 6 connect to BA6110 pin#6
  • socket 7 connect to BA6110 pin#7
  • socket 8 connect to BA6110 pin#8
  • socket 9 connect to BA6110 pin#9
Click below to get the full size PCB template to use directly. See the link at start of article for schematic, photo of top of the board and original PCK100 kit instructions



Tuesday, 11 May 2010

Battlezone with lasers

This is a project I've had simmering on the back burner for a while. Still at the early stages but thought it might be fun to keep track of each step here

A few months back I got a 20kps laser scanner galvo set off ebay with the intention of making my own laser projector and a vision of using it to play some old vector arcade games... particularly my old fave Atari Battlezone. The arcade game bit seemed pretty easy, since you can play BZ on the open source MAME emulator so I thought I could hook into the vector terminal emulation.

I found the asynchronous UART on an Arduino board was not quite fast enough to cope with the data... dropping bits all over the place, so I started looking at a USB conneciton to a PIC2455. As a SourceBoost C user I was not able to find any easy to understand USB CDC (Communication Device Class, a.k.a serial port) implementations for the PIC - so I decided to make my own, leaning heavily on sample code I found online.

Well I finally got to the point where my PIC would connect via USB show up as a COM port and be easy to access from a Windows program. Then I hooked up an 12-bit SPI dual DAC and connected it to the galvo setup and tried the first random hacking into MAMEs vector module.

I didn't expect it to work first time, and didn't! but my impatient hacking did produce some interesting squiggles at about 2 fps. I needed to use a long exposure photograph to actually make sense of it, but eventually I recognised a couple of parts of the display and got quite excited that the concept was proved!

The coordinate handling is obviously messed up and the image is wrapping on itself multiple times, also there is no attempt at blanking yet - so there are stray lines all over. The big job will be to find some way to optimise the render list to stop throwing the galvos all over the place and improve on the 2 fps refresh!

As you can see I have a long way to go!

Here is the plot showing the bits I recognised


Here is an actual MAME screen showing what it should look like


If things improve I will post an update!

Monday, 3 May 2010

Motion detection to midi with puredata

another experiment with puredata, webcam image is passed through pix_movement object and a pix_blob turns the result into two midi note streams which are sent into reason via midi yoke. the image is the output of the pix_movement (difference between frames)



I put the pd patch at http://sites.google.com/site/skriyl/Home/pd-projects (motion noise.pd)



The patch outputs on midi channels 1 and 2. I used midi yoke and PD's midi output, then piped this into propellerheads reason, where you can use the "advanced midi" to set up midi bus A then lock down channels 1 and 2 to specific instruments in the rack. I used an NNXT with glockenspiel patch and nn19 with strings patch

Sunday, 2 May 2010

First play with PureData

I was thinking about making a midi "harp" and thought of trying with a webcam, using puredata to analyse the images and generate midi/sounds. This is the first time I have played with PD and I don't really know what I am doing with it yet... you'll see I am not quite there with the midi harp yet, but I am impressed with how quickly you can get something fun working in PD



Here is the PD sketch, which I got to by hacking about with one of the GEM tutorial sketches

Thursday, 22 April 2010

Matrix feedback in Reason

How to do something like this...



A great thing about Reason is that it allows you to wire a continuous input (like a CV, MIDI CC#, Mod wheel etc) to pattern changes on something like the Matrix sequencer or Redrum. You can't do this directly (there is no pattern change CV input) but you can do it via the "programmer" in the combinator. This is a great thing to experiment with...especially if the patterns are different beat lengths/step values and you layer a few of them . In one of my other clips I used MIDI CC# signals generated by a Lavalamp to randomly switch patterns on a set of Redrum modules.

In the above above clip I have 3 matrix sequences driving each other, which can result in some random sounding patterns which repeat over long periods and can descend into chaos with one small tweak.. eventually arriving at a new repeating cycle (of course you need to drive one or more sound modules like NNXT etc with the matrix outputs to be able to hear anything...)

Start by making a Combinator...

Inside the combinator, create 3 matrix sequencers.

Wire Curve CV output from each Matrix Rotary inputs 1,2,3 on the combinator. Ensure these are only connections between matrixes (-ices?) and combinator

Click the "show programmer" button. Click on Matrix 1 and next to "Rotary 2" source select "Pattern Select" target. For Matrix 2 map Rotary 3 to pattern select, For Matrix 3 map Rotary 1 to pattern select

Flip to Curve view on each matrix and draw a few random curves (Randomize pattern option can be good). Start the Matrixes and click randomly on their pattern screens. Soon they should be flicking between patterns almost at random

Wire the Gate and Note CV outputs of one or more matrix to a sound module such as NNXT.


Flip the matrixes to note mode and click at random on the screens. Change pattern lengths and note resolutions, try the "randomize pattern" option. After a while things should be getting pretty freaked out