1st timer, Laser Harp!

Mumphry

New Member
Hey guys!
I'm pretty much a beginner when it comes to PICAXE, as I only used it to make a really simple LED chaser last year in my Systems Electronics class, but I'm trying to make a Laser Harp for this years Systems product. As in, a harp body with the harps strings replaced by lasers and when one of the laser beams is interrupted by your hand, sets off a light-activated relay which will be an input for the PICAXE. Because I don't want to use about 50 logic gates, I thought the PICAXE would be great. I'm going to have 10 inputs, (1 for each Light-Activated Relay {8 in total}, with one note corresponding to each, and two for foot pedals that are going to shift the octave up or down).


I just have 2 questions;

1. Is it possible to store MIDI's on a PICAXE or am I limited to the monophonic ringtone beeps?

and

2. Is there any code that will check all inputs at the same time? Or do I have to stick with "checking" each input individually?


All help will be greatly, GREATLY appreciated.
 

westaust55

Moderator
Welcome to the PICAXE forum.

for Q1:
The PICAXE is limited with its BASIC commands to a single note (using the TUNE command) at a time.
Suggest that you do a search on the forum for "MIDI" for example. There are posts such as this one which suggest something is possible:
http://www.picaxeforum.co.uk/showthread.php?p=41106

There also external data on PIC chips and MIDI such as : http://www.audiomulch.com/midipic/


In terms of storing files (of any type) on a PICAXE, the amount of space is limited and depends on whether you want so save long term or constantly replacing. EEPROM has around 256 bytes in the larger PICAXE chips but has a limited life in terms of the number of time you can write to it (can always read EEPROM as often as you want). External EEPROM (eg 24C512) will hold up to around 64k bytes of data but again if frequent changes intended then EEPROM may not be ideal - could consider F-RAM but these are more expensive.

for Q2:
When used on the right of an assignment pins applies to the input port e.g.
let b1 = pins
will load b1 with the current state of the input port.

See manual 2 pages 14 to 17

That will load the 8 laser harp note inputs into a variable in one step.
As no current PICAXE has more than 8 "standard" inputs you will need to use 2 inputs from another port (eg 2 portA ADC inputs used as digital inputs on a 40X1) as inputs. These can only be tested with an IF...THEN statement.
 
Last edited:

alpacaman

Member
I made a laser harp using 12 laser pointers. The hardest part was aligning them up to the LDRs since they didn't shoot straight.

I used 2 PICAXEs. I used a 28x2 to read the 12 laser inputs and to produce a binary output. This may seem like a lot of computing power to just convert 12 inputs to binary but I'm also doing a lot of computing as well. For example, it cycles through the inputs and sends out a corresponding binary signal. If the same beam is still broken during the next cycle you don't want it to re-send the same note because the note is already being played. This also lets you play multiple notes at the same time which a simple decimal-to-binary converter wouldn't do.

I used an 18x to read the binary from the 28x2 which then outputs the MIDI signals (search forum on how to do this - I modified the code provided by hippy. The 18x also controls an LCD and reads other inputs. The other inputs let you change octive, voice, etc... That is why I'm only using 12 lasers instead of 16 - to leave some room for the control inputs. The LCD dispalys what octive, voice, etc is currently set at.

I built the 18x portion on a seperate circuit board so I could re-use it for other MIDI instrument I might think up. For example, I built a MIDI `trumpet` by using 4 pushbuttons to produce the binary input to the 18x circuit board. Since a trumpet requires you to blow into the mouth piece I have a black baloon which is going through a hole in a block of wood. On one side of the wood is a hole with an LDR and on another side of the wood is a hole with an LED. When you blow into the baloon in blocks the light from the LED from reaching the LDR. This then allows the input from the 4 pushbuttons to be sent to the 18x.

The MIDI produced is sent to the USB posrt on my PC via a special cable and I'm using freeware I downloaded called MidiOX to read and the play the MIDI signal.
 

Mumphry

New Member
Thanks tonnes!

I made a laser harp using 12 laser pointers
That's awesome! I've only got 8, so that means it's possible at least :D

I used a 28x2 to read the 12 laser inputs and to produce a binary output. This may seem like a lot of computing power to just convert 12 inputs to binary but I'm also doing a lot of computing as well. For example, it cycles through the inputs and sends out a corresponding binary signal. If the same beam is still broken during the next cycle you don't want it to re-send the same note because the note is already being played. This also lets you play multiple notes at the same time which a simple decimal-to-binary converter wouldn't do.
That sounds pretty complicated :p. Do you still have the code that you used to do it? If you do, could you post it up here or pm it to me so I can have a look at it? It would be much appreciated.

That is why I'm only using 12 lasers instead of 16 - to leave some room for the control inputs
So does the 28x2 have 16 inputs? If so, I might add a voice changing function as well.
 

westaust55

Moderator
Laser Harp!

The 28X1 has 8 “normal” inputs and a further 4 inputs normally used for Analogue signals which can be used for very basic digital inputs using IF porta pinx THEN . . . . so a max of 12 inputs per 28X1.
 

alpacaman

Member
Do you still have the code that you used to do it? If you do, could you post it up here or pm it to me so I can have a look at it? It would be much appreciated.
I'm sure that the following code could be improved upon - it works so don't be too critical.

The code is too long for a single post - so it's in 2 parts.

28x1 (I thought I had used a 28x2 but it was actually a 28x1):
Code:
'**************
'* LASER HARP *
'**************
'28X1

symbol lowNotes = b0
symbol hiNotes = b1
symbol lowNotesHold = b2
symbol hiNotesHold = b3
symbol midiOut = b4
symbol x = b5
symbol y = b6

setfreq M8
lowNotes = 255
hiNotes = 255
lowNotesHold = 255
hiNotesHold = 255
midiOut = 0

pins = midiOut

Main:
	dirsc = %00000000
	
	lowNotes = pins
	hiNotes = 255
	if porta pin0 = 0 then
		hiNotes = hiNotes - 1
	end if
	if porta pin1 = 0 then
		hiNotes = hiNotes - 2
	end if
	if porta pin2 = 0 then
		hiNotes = hiNotes - 4
	end if
	if porta pin3 = 0 then
		hiNotes = hiNotes - 8
	end if
	
	if lowNotes < 255 or hiNotes < 255 then 
		x = lowNotes & %00000001
		y = lowNotesHold & %00000001
		if x = %00000000 and y = %00000001 then
			pins = %00000001
			pause 10
		end if 
		
		x = lowNotes & %00000010
		y = lowNotesHold & %00000010
		if x = %00000000 and y = %00000010 then
			pins = %00000010
			pause 10
		end if
	 
		x = lowNotes & %00000100
		y = lowNotesHold & %00000100
		if x = %00000000 and y = %00000100 then
			pins = %00000011
			pause 10
		end if
		 
		x = lowNotes & %00001000
		y = lowNotesHold & %00001000
		if x = %00000000 and y = %00001000 then
			pins = %00000100
			pause 10
		end if
		 
		x = lowNotes & %00010000
		y = lowNotesHold & %00010000
		if x = %00000000 and y = %00010000 then
			pins = %00000101
			pause 10
		end if
		 
		x = lowNotes & %00100000
		y = lowNotesHold & %00100000
		if x = %00000000 and y = %00100000 then
			pins = %00000110
			pause 10
		end if
		 
		x = lowNotes & %01000000
		y = lowNotesHold & %01000000
		if x = %00000000 and y = %01000000 then
			pins = %00000111
			pause 10
		end if
		 
		x = lowNotes & %10000000
		y = lowNotesHold & %10000000
		if x = %00000000 and y = %10000000 then
			pins = %00001000
			pause 10
		end if
		
		x = hiNotes & %00000001
		y = hiNotesHold & %00000001
		if x = %00000000 and y = %00000001 then
			pins = %00001001
			pause 10
		end if 
		
		x = hiNotes & %00000010
		y = hiNotesHold & %00000010
		if x = %00000000 and y = %00000010 then
			pins = %00001010
			pause 10
		end if
	 
		x = hiNotes & %00000100
		y = hiNotesHold & %00000100
		if x = %00000000 and y = %00000100 then
			pins = %00001011
			pause 10
		end if
		 
		x = hiNotes & %00001000
		y = hiNotesHold & %00001000
		if x = %00000000 and y = %00001000 then
			pins = %00001100
			pause 10
		end if
			
		if lowNotes <> lowNotesHold then
			lowNotesHold = lowNotes
		end if
			
		if hiNotes <> hiNotesHold then
			hiNotesHold = hiNotes
		end if
	else
		lowNotesHold = %11111111
		hiNotes = %11111111
		hiNotesHold = %11111111
		pins = %00000000
	end if
		
goto Main
 

alpacaman

Member
The code is too long for a single post - so it's in 2 parts.
OK - It's still too long - so it's in 3 parts.
18x:
Code:
'***************
'* MIDI Output *
'***************
'PICAXE-18X

'*******************************************************************************
'* Code from: http://homepage.ntlworld.com/the.happy.hippy/picaxe/midiuart.txt *
'*******************************************************************************
'variables
symbol char = b0
symbol status = b1	'Must be b1
symbol voice = b2
symbol keyIndex = b3
symbol keyNumber = b4
symbol lastCommand = b5
symbol pauseTime = w6

'registers
symbol rcsta = $18
symbol txreg = $19
symbol rcreg = $1A
symbol txsta = $98
symbol spbrg = $99

'txsta bit masks
symbol csrc	= %10000000
symbol tx9 = %01000000
symbol txen = %00100000
symbol sync	= %00010000
symbol brgh	= %00000100
symbol trmt	= %00000010
symbol tx9d	= %00000001

symbol csrc_bit = bit15
symbol tx9_bit = bit14
symbol txen_bit = bit13
symbol sync_bit = bit12
symbol brgh_bit = bit10
symbol trmt_bit = bit9
symbol tx9d_bit = bit8

'rcsta bit masks
symbol spen	= %10000000
symbol rx9 = %01000000
symbol sren = %00100000
symbol cren	= %00010000
symbol adden = %00001000
symbol ferr	= %00000100
symbol oerr	= %00000010
symbol rx9d	= %00000001

symbol spen_bit = bit15
symbol rx9_bit = bit14
symbol sren_bit = bit13
symbol cren_bit = bit12
symbol adden_bit = bit11
symbol ferr_bit = bit10
symbol oerr_bit = bit9
symbol rx9d_bit = bit8

'********************
'* MIDI Definitions *
'********************

'voice = 1
symbol note_off = $B0	'$80
symbol note_on = $90
symbol prog_change = $C0
'***********************
'* End code from hippy *
'***********************

symbol channel = b9
symbol readinput = b10
symbol holdinput = b11
symbol octive = b12

'*************
'* main loop *
'*************
PowerOnReset:
	setfreq M8
	gosub UartInit
	channel = 1
	voice = 0
	octive = 6

MainLoop:
	readinput = pins & %11000111
	if readinput <> holdinput then
		holdinput = readinput
		
		'*** Voice Increase ***
		if readinput = %11000101 and voice < 127 then
			voice = voice + 1
			char = prog_change + channel - 1 :gosub MidTx	'prog change
			char = voice :gosub MidTx	'voice number
		end if
		
		'*** Voice Decrease ***
		if readinput = %11000110 and voice > 0 then
			voice = voice - 1
			char = prog_change + channel - 1 :gosub MidTx	'prog change
			char = voice :gosub MidTx	'voice number
		end if
		
		'*** Channel Change ***
		if readinput = %11000011 then
			if channel = 16 then
				channel = 1
			else
				channel = channel + 1
			end if
			char = prog_change + channel - 1 :gosub MidTx	'prog change
			char = voice :gosub MidTx	'voice number
		end if
		
		'*** Octive Change ***
		if readinput = %10000111 then
			if octive = 7 then
				octive = 0
			else
				octive = octive + 1
			end if
			char = prog_change + channel - 1 :gosub MidTx	'prog change
			char = voice :gosub MidTx	'voice number
		end if

		'*** Play Note ***
		'  _______________________________
		' |  |#| |#|  |  |#| |#| |#|  |   |
		' |  |#| |#|  |  |#| |#| |#|  |   |
		' |   |   |   |   |   |   |   |   |
		' |   |   |   |   |   |   |   |   |
		'  -------------------------------
		'   C   D   E   F   G   A   B   C
		'   60  62  64  65  67  69  71  72	Octive 5

		if readinput = %01000111 then 
			goto stopNote
		elseif octive = 0 then
			if readinput = %01000110 then
				keyNumber = 0	'C
				goto playNote
			elseif readinput = %01000101 then
				keyNumber = 1	'C#
				goto playNote
			elseif readinput = %01000100 then
				keyNumber = 2	'D
				goto playNote
			elseif readinput = %01000011 then
				keyNumber = 3	'D#
				goto playNote
			elseif readinput = %01000010 then
				keyNumber = 4	'E
				goto playNote
			elseif readinput = %01000001 then
				keyNumber = 5	'F
				goto playNote
			elseif readinput = %01000000 then
				keyNumber = 6	'F#
				goto playNote
			elseif readinput = %00000111 then
				keyNumber = 7	'G
				goto playNote
			elseif readinput = %00000110 then
				keyNumber = 8	'G#
				goto playNote
			elseif readinput = %00000101 then
				keyNumber = 9	'A
				goto playNote
			elseif readinput = %00000100 then
				keyNumber = 10	'A#
				goto playNote
			elseif readinput = %00000011 then
				keyNumber = 11	'B
				goto playNote
			end if
		elseif octive = 1 then
			if readinput = %01000110 then
				keyNumber = 12	'C
				goto playNote
			elseif readinput = %01000101 then
				keyNumber = 13	'C#
				goto playNote
			elseif readinput = %01000100 then
				keyNumber = 14	'D
				goto playNote
			elseif readinput = %01000011 then
				keyNumber = 15	'D#
				goto playNote
			elseif readinput = %01000010 then
				keyNumber = 16	'E
				goto playNote
			elseif readinput = %01000001 then
				keyNumber = 17	'F
				goto playNote
			elseif readinput = %01000000 then
				keyNumber = 18	'F#
				goto playNote
			elseif readinput = %00000111 then
				keyNumber = 19	'G
				goto playNote
			elseif readinput = %00000110 then
				keyNumber = 20	'G#
				goto playNote
			elseif readinput = %00000101 then
				keyNumber = 21	'A
				goto playNote
			elseif readinput = %00000100 then
				keyNumber = 22	'A#
				goto playNote
			elseif readinput = %00000011 then
				keyNumber = 23	'B
				goto playNote
			end if
		elseif octive = 2 then
			if readinput = %01000110 then
				keyNumber = 24	'C
				goto playNote
			elseif readinput = %01000101 then
				keyNumber = 25	'C#
				goto playNote
			elseif readinput = %01000100 then
				keyNumber = 26	'D
				goto playNote
			elseif readinput = %01000011 then
				keyNumber = 27	'D#
				goto playNote
			elseif readinput = %01000010 then
				keyNumber = 28	'E
				goto playNote
			elseif readinput = %01000001 then
				keyNumber = 29	'F
				goto playNote
			elseif readinput = %01000000 then
				keyNumber = 30	'F#
				goto playNote
			elseif readinput = %00000111 then
				keyNumber = 31	'G
				goto playNote
			elseif readinput = %00000110 then
				keyNumber = 32	'G#
				goto playNote
			elseif readinput = %00000101 then
				keyNumber = 33	'A
				goto playNote
			elseif readinput = %00000100 then
				keyNumber = 34	'A#
				goto playNote
			elseif readinput = %00000011 then
				keyNumber = 35	'B
				goto playNote
			end if
 

alpacaman

Member
part 3: 18x cont.
Code:
		elseif octive = 3 then
			if readinput = %01000110 then
				keyNumber = 36	'C
				goto playNote
			elseif readinput = %01000101 then
				keyNumber = 37	'C#
				goto playNote
			elseif readinput = %01000100 then
				keyNumber = 38	'D
				goto playNote
			elseif readinput = %01000011 then
				keyNumber = 39	'D#
				goto playNote
			elseif readinput = %01000010 then
				keyNumber = 40	'E
				goto playNote
			elseif readinput = %01000001 then
				keyNumber = 41	'F
				goto playNote
			elseif readinput = %01000000 then
				keyNumber = 42	'F#
				goto playNote
			elseif readinput = %00000111 then
				keyNumber = 43	'G
				goto playNote
			elseif readinput = %00000110 then
				keyNumber = 44	'G#
				goto playNote
			elseif readinput = %00000101 then
				keyNumber = 45	'A
				goto playNote
			elseif readinput = %00000100 then
				keyNumber = 46	'A#
				goto playNote
			elseif readinput = %00000011 then
				keyNumber = 47	'B
				goto playNote
			end if
		elseif octive = 4 then
			if readinput = %01000110 then
				keyNumber = 48	'C
				goto playNote
			elseif readinput = %01000101 then
				keyNumber = 49	'C#
				goto playNote
			elseif readinput = %01000100 then
				keyNumber = 50	'D
				goto playNote
			elseif readinput = %01000011 then
				keyNumber = 51	'D#
				goto playNote
			elseif readinput = %01000010 then
				keyNumber = 52	'E
				goto playNote
			elseif readinput = %01000001 then
				keyNumber = 53	'F
				goto playNote
			elseif readinput = %01000000 then
				keyNumber = 54	'F#
				goto playNote
			elseif readinput = %00000111 then
				keyNumber = 55	'G
				goto playNote
			elseif readinput = %00000110 then
				keyNumber = 56	'G#
				goto playNote
			elseif readinput = %00000101 then
				keyNumber = 57	'A
				goto playNote
			elseif readinput = %00000100 then
				keyNumber = 58	'A#
				goto playNote
			elseif readinput = %00000011 then
				keyNumber = 59	'B
				goto playNote
			end if
		elseif octive = 5 then
			if readinput = %01000110 then
				keyNumber = 60	'C
				goto playNote
			elseif readinput = %01000101 then
				keyNumber = 61	'C#
				goto playNote
			elseif readinput = %01000100 then
				keyNumber = 62	'D
				goto playNote
			elseif readinput = %01000011 then
				keyNumber = 63	'D#
				goto playNote
			elseif readinput = %01000010 then
				keyNumber = 64	'E
				goto playNote
			elseif readinput = %01000001 then
				keyNumber = 65	'F
				goto playNote
			elseif readinput = %01000000 then
				keyNumber = 66	'F#
				goto playNote
			elseif readinput = %00000111 then
				keyNumber = 67	'G
				goto playNote
			elseif readinput = %00000110 then
				keyNumber = 68	'G#
				goto playNote
			elseif readinput = %00000101 then
				keyNumber = 69	'A
				goto playNote
			elseif readinput = %00000100 then
				keyNumber = 70	'A#
				goto playNote
			elseif readinput = %00000011 then
				keyNumber = 71	'B
				goto playNote
			end if
		elseif octive = 6 then
			if readinput = %01000110 then
				keyNumber = 72	'C
				goto playNote
			elseif readinput = %01000101 then
				keyNumber = 73	'C#
				goto playNote
			elseif readinput = %01000100 then
				keyNumber = 74	'D
				goto playNote
			elseif readinput = %01000011 then
				keyNumber = 75	'D#
				goto playNote
			elseif readinput = %01000010 then
				keyNumber = 76	'E
				goto playNote
			elseif readinput = %01000001 then
				keyNumber = 77	'F
				goto playNote
			elseif readinput = %01000000 then
				keyNumber = 78	'F#
				goto playNote
			elseif readinput = %00000111 then
				keyNumber = 79	'G
				goto playNote
			elseif readinput = %00000110 then
				keyNumber = 80	'G#
				goto playNote
			elseif readinput = %00000101 then
				keyNumber = 81	'A
				goto playNote
			elseif readinput = %00000100 then
				keyNumber = 82	'A#
				goto playNote
			elseif readinput = %00000011 then
				keyNumber = 83	'B
				goto playNote
			end if
		elseif octive = 7 then
			if readinput = %01000110 then
				keyNumber = 84	'C
				goto playNote
			elseif readinput = %01000101 then
				keyNumber = 85	'C#
				goto playNote
			elseif readinput = %01000100 then
				keyNumber = 86	'D
				goto playNote
			elseif readinput = %01000011 then
				keyNumber = 87	'D#
				goto playNote
			elseif readinput = %01000010 then
				keyNumber = 88	'E
				goto playNote
			elseif readinput = %01000001 then
				keyNumber = 89	'F
				goto playNote
			elseif readinput = %01000000 then
				keyNumber = 90	'F#
				goto playNote
			elseif readinput = %00000111 then
				keyNumber = 91	'G
				goto playNote
			elseif readinput = %00000110 then
				keyNumber = 92	'G#
				goto playNote
			elseif readinput = %00000101 then
				keyNumber = 93	'A
				goto playNote
			elseif readinput = %00000100 then
				keyNumber = 94	'A#
				goto playNote
			elseif readinput = %00000011 then
				keyNumber = 95	'B
				goto playNote
			end if
		end if
	end if
	
	goto MainLoop
	

'*******************************************************************************
'* Code from: http://homepage.ntlworld.com/the.happy.hippy/picaxe/midiuart.txt *
'*******************************************************************************

'*************
'* Play Note *
'*************
playNote:
	char = note_on | channel - 1	:gosub MidTx	'note on
	char = keyNumber			:gosub MidTx	'key number
	char = 127				:gosub MidTx	'max velocity
	pause pauseTime
	
	goto MainLoop

'*************
'* Stop Note *
'*************	
stopNote:		
	char = note_off + channel - 1	:gosub MidTx
	char = $7B				:gosub MidTx
	char = 0				:gosub MidTx	'off
	pause pauseTime
	
	goto MainLoop

'***************************************************************
'* Send a MIDI byte. This handles 'Running Status' compression *
'***************************************************************
MidTx:
	If char < $80 Then UartTx			'not a command, just send
	If char = lastCommand Then MidTxIgnore	'don't send duplicate command
	
	lastCommand = char				'update running status...
	goto UartTx						'...and send command

MidTxIgnore:
	return

'*************************
'* AUSART Initialization *
'*************************
symbol spbrg_init = 3		'31250 baud @ 8Mhz
symbol txsta_init = txen
symbol rxsta_init = spen | cren

UartInit:
	poke spbrg, spbrg_init
	poke txsta, txsta_init
	poke rcsta, rxsta_init
	
	return

'*******************
'* AUSART Transmit *
'*******************
UartTx:
	peek txsta, status		'wait for TX buffer empty
	If trmt_bit = 0 Then UartTx
	
	poke txreg, char
	
	return
'***********************
'* End code from hippy *
'***********************
 

Jeremy Leach

Senior Member
Hey, I think your balloon idea is pure genius ! But does it just turn the sound on/off or does it vary the amplitude depending on how hard you blow? All sounds very creative.

I suppose with the harp, you could also control amplitude depending on how quickly the beam is interrupted - ie the pulse width when the beam is broken ??? Not sure if it would work very well though, and wouldn't be easy in code perhaps.
 

rWAVE

Member
MAKE Magazine Laser Harp

Mumphry,

The latest issue of MAKE Magazine (Issue 15 - August 2008) page 64 has details of one possible implementation of a laser harp.

Richard
 

alpacaman

Member
Hey, I think your balloon idea is pure genius ! But does it just turn the sound on/off or does it vary the amplitude depending on how hard you blow? All sounds very creative.
I have it so it just turns the sound on. I guess you could feed the LDR to an analog input to change the amplitude.
 

Mumphry

New Member
The 28X1 has 8 “normal” inputs and a further 4 inputs normally used for Analogue signals which can be used for very basic digital inputs using IF porta pinx THEN . . . . so a max of 12 inputs per 28X1.
So there's room for 12 lasers to be inputs,
Ah, I see. So you used all the inputs on the 28x1 for the lasers and let the 18x do the octave/voice changes and MIDI output? The 18x is the only one that can do MIDI output isn't it cause it has AUSART?

The latest issue of MAKE Magazine (Issue 15 - August 2008) page 64 has details of one possible implementation of a laser harp.
I checked out the magazine on the internet and found the issue. Is the one in the magazine an "endless" laser harp? As in the lasers don't fall onto LED's? Cause the lasers used in those harps cost a couple hundred of bucks :(

Thanks everyone for your help, this is helping me out a lot!
 
Top