Please point me to some step by step basics to code the PICAXE using Blockly.

Gramps

Senior Member
Hello,
For a long time I have thought about learning to code.
Picaxe and Blockly look like the entry level for me.
It has been frustrating that among all the files and pages on the internet, this doesn't seem to be available.
I need someone to point me to some step by step basics to code the PICAXE using Blockly.
This is the project:
A hammered dulcimer has 35 notes (70 strings- two per note).
A LED is mounted under each set of strings. The first note to be played will light the first LED when the Picaxe is loaded. When that note is struck with a hammer, it will go out and the second LED will light.
By striking the notes one by one the LEDs will light and go out in order. So an inexperienced player can play a tune.
Input: A mike sensor that momentarily goes high with a sharp sound.(The hammer striking a note)
Output: 35 LEDs.
This should be a piece of cake for a Picaxe micro!
Thanks in advance for your help! Gramps.
 

lbenson

Senior Member
Welcome to the forum, and great first project.

This is not, in theory, a very hard problem. The greatest technical issue might be getting your mike sensor to reliably detect the striking of the note. Whether you want duration of the note to be included might be a programming problem.

I would recommend that you skip blockly and go directly to PICAXE basic. No picaxe has 35 available pins, so you either have to use some kind of multiplexing or perhaps a 28X2 with an MCP23017 to give you, in principle, 21-2 (for i2c) pins on the 20X2 and 16 on the MCP23017 for a total of 35. Or you could use a 14M2 and 2 MCP23017s.

Your tunes are stored as strings (arrays) of numbers, perhaps in EEPROM or in external EEPROM. They are made up of either 2 arrays of numbers--one for the note and another for the duration, or one array of note/duration pairs.

Your code then is pretty simple: a button to start; a do loop to light an LED, wait for a strike signal, turn off the LED, pause for the right duration, then repeat for the next LED.

Then you can add wrinkles: a menu with a few options to select a tune and some buttons.

Do you have a simple tune coded with string-pair number and note duration? Perhaps you would get ideas if you looked in Manual 2 at the tune command--there are some similarities to what you want to do on the note/duration side of things. Please post for us a hammer dulcimer string-to-note table.

In the picaxe simulator, with a 40X2 and a bit of trick code to translate your note-position numbers into PICAXE tune values, you could probably make a simulated 32-note hammer dulcimer (or fewer notes with some buttons for control).

(As an aside, I made about 6 dozen of the 3-4 string dulcimers about 4 decades and more ago.)

(As another aside, it just happened that yesterday after tutoring a high school student on programming with picaxe basic (extra-curricular--no grades depending) I had reason to look at the tune command and need to study it in detail today.)
 
Last edited:

AllyCat

Senior Member
Hi,

Yes, welcome to the forum and I agree that the PICaxe is an excellent way to begin learning to program. However, I also suggest that you start to program directly in Basic, if only because you will probably get much more help from us on the forum. ;)

To light one of 35 LEDs needs only 7 output pins on a PICaxe, using a method called "Charlieplexing", or there are other methods using a small amount of additional hardware that need even fewer pins on the PICaxe. So a 14M2 is all that's needed and maybe even an 08M2, but if you want to store "tunes" then the additional memory and facilities of a 14M2 (or larger) are probably worthwhile.

Similarly, detecting when a string is hit probably needs only a single pin (ADC input) and there happens to be a current thread on a similar topic (although that OP appears to be rather struggling at the moment). However, confirming which string was hit would be much more difficult and maybe beyond the capabilities of a PICaxe (at least using simple programming methods). Also, you haven't specified how or if a particular "tune" needs to to be selected/started, nor what is to happen if the player makes a "mistake".

Cheers, Alan.
 

Gramps

Senior Member
Thanks for writing!
Okay let's simplify this project just a bit.
We'll start out with eight notes, represented by 8 LEDs,(and add more LEDs later.)
D E F# G A B C & D
The first note will light on bootup.
It needs to stay lit until any note is struck, even the wrong note. Then it should go out and lamp 2 should light, and so on.
Duration and type of note do not need to enter the equation.
Once the program is written it will be simple to copy and change which LEDs should light for a different tune.
Gramps
 

premelec

Senior Member
Using a MAX9814 Electret Microphone board [see ref in forum] and squaring the audio output you could also use that signal to read sound frequency using PULSIN and then perhaps light your LED appropriate to a string nearest to tone being 'heard'- thus converting a sung tone to string LED - and perhaps store a sung sequence into PICAXE memory for later play... so many possibilities! and... yes... use BASIC ... it takes some learning but isn't so hard ;-0
 

lbenson

Senior Member
Here's a solution (not fully tested) for 31 notes on a PICAXE 40X2 (absent detection of a hammer dulcimer strike). It can play in the simulator and show pins B.0-7, C.0-7, A.0-7, and D.0-6 lighting for the appropriate note. The note codes are the same as for the TUNE command, with duration, octave, and note (C-B), and that command is used to play the notes one by one. The duration is not correct in the simulator because of the time the code takes to execute, but it should be close to right on real hardware.
Code:
#picaxe 40X2
' uses duration, octive, note coding from "tune" command

eeprom 0,($29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$29,$67,$E7,$29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5,$27,$27,$29,$25,$27,$69,$60,$29,$25,$27,$69,$60,$27,$27,$29,$25,$27,$69,$6A,$29,$25,$27,$69,$6A,$29,$27,$25,$27,$2A,$E9,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5,$FF)

symbol eePtr=b4
symbol note=b5
symbol codedNote=b6
symbol pinNo=b7
symbol oldPinNo=b8
symbol octive=b9
symbol startAdr = 12

'tune 5, 8,($29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$29,$67,$E7,$29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5
'tune 5, 8,($27,$27,$29,$25,$27,$69,$6A,$29,$25,$27,$69,$6A,$29,$27,$25,$27,$2A,$E9,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5)

eePtr = 0
read eePtr,codedNote
do while codedNote <> $ff
  octive = codedNote & %00110000 >> 4 ' %00=middle; %01=high; %10=low
  note = codedNote & %00001111
  if octive = 0 then : note = note + 12 : endif ' middle octive
  if octive = 1 then : note = note + 24 : endif ' high octive
  pinNo = note ' 0-35: b.0-b.7, c.0-c.7, a.0-a.7, d.0-d.6 (D.7 plays tune)
  if pinNo > 30 then : pinNo = 30 : endif
  low oldPinNo
  high pinNo
  oldPinNo = pinNo
  tune 31,8,(codedNote)
  sertxd(#codedNote,"/",#pinNo," ")
  inc eePtr
  read eePtr,codedNote
loop
Note that I used PE6 for the simulator. In PE5, I could not get single-note TUNE commands to play the correct note (playing the whole tune with one command worked fine.

The program takes advantage of the fact that the PICAXE ports are numbered sequentially--B.0-B.7 is 0-7; C.0-C.7 is 8-15; A.0-A.7 is 16-23, and D.0-D.7 is 24-31. The program uses pin D.7 to play the tune. Thus you can map note C in the low octave to pin #0 (B.0), up through F# in the high octave as pin #30 (D.6).

The advantage of using the TUNE coding is that you can, using the ringtone wizard, use many thousands of tunes that can be found on the internet. http://www.picaxe.com/RTTTL-Ringtones-for-Tune-Command/ has 5 zip files of tunes, the largest of which has 10,000 tunes. However, the tune coding may not be correct--YMMV. There are some wrong notes in this tune which I have yet not been able to figure out.

The second value of the tune command can adjust the tempo.
 
Last edited:

lbenson

Senior Member
Here's a 29-note version with 3 tunes, a serial LCD (AXE033-type) and pushbutton tune selector. It can run in the simulator with the AXE033 selected on D.6. The tunes are "Ode to Joy", "Amazing Grace", and "Wildwood Flower".
Code:
' 40hammer -- plays tunes one note at a time & lights LED corresponding to note
#picaxe 40X2
' uses duration, octive, note coding from "tune" command


eeprom 0,("Ode To Joy",$FE,$29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$29,$67,$E7,$29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5,$27,$27,$29,$25,$27,$69,$6A,$29,$25,$27,$69,$6A,$29,$27,$25,$27,$25,$E9,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5,$FF,"Amazing Grace",$FE,$64,$69,$29,$41,$6B,$69,$01,$6B,$29,$66,$24,$64,$66,$29,$41,$6B,$69,$01,$6B,$41,$04,$41,$44,$04,$41,$6B,$69,$01,$6B,$29,$66,$24,$64,$66,$29,$41,$6B,$69,$01,$6B,$29,$FF,"Wildwood Flower",$FE,$66,$67,$29,$6B,$42,$26,$67,$66,$24,$67,$62,$22,$66,$67,$29,$6B,$42,$26,$67,$66,$24,$67,$41,$22,$29,$06,$46,$44,$02,$69,$69,$2B,$41,$6B,$29,$26,$26,$66,$64,$26,$69,$66,$24,$67,$21,$22,$FF,$FF)

symbol newTune=bit0

symbol eePtr=b4
symbol note=b5
symbol codedNote=b6
symbol ch=b6         ' NOTE overloaded variable b6
symbol pinNo=b7
symbol oldPinNo=b8
symbol octive=b9
symbol checkTime=b10
symbol tunePtr=b11
symbol startAdr = 12

'amazing
'tune D.7, 15,($64,$69,$29,$41,$6B,$69,$01,$6B,$29,$66,$24,$64,$66,$29,$41,$6B,$69,$01,$6B,$41,$04,$41,$44,$04,$41,$6B,$69,$01,$6B,$29,$66,$24,$64,$66,$29,$41,$6B,$69,$01,$6B,$29)

'ode
'tune 5, 8,($29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$29,$67,$E7,$29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5
'tune 5, 8,($27,$27,$29,$25,$27,$69,$6A,$29,$25,$27,$69,$6A,$29,$27,$25,$27,$2A,$E9,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5)
settimer t1s_8 ' set timer to 1 second ticks at 8MHz (default speed)
eePtr = 0
newTune = 1

do
  if newTune = 1 then
    serout D.6,N2400,(254,1) : pause 30 ' clear screen
    read eePtr, ch
    do : serout D.6,N2400,(ch) : inc eePtr : read eePtr, ch : loop until ch = $FE ' display name of selected tune
    tunePtr = eePtr + 1
  endif
  do : loop while pinD.5 = 0 ' wait until button is pressed
  timer = 0 ' one-second timer
  checkTime=1
  do : loop while pinD.5 = 1 ' wait until button is released
  if timer <= checkTime then ' next tune
    do : read eePtr, codedNote : inc eePtr : loop until codedNote = $FF ' read past this tune
    read eePtr,ch
    if ch = $FF then : eePtr = 0 : endif ' end of tunes; start over
    newTune = 1
  else ' we've selected this tune
    serout D.6,N2400,(254,192,"Playing") 
    eePtr = tunePtr
    newTune = 0
    read eePtr,codedNote
    do while codedNote <> $ff
      octive = codedNote & %00110000 >> 4 ' %00=middle; %01=high; %10=low
      note = codedNote & %00001111
      if octive = 0 then : note = note + 12 : endif ' middle octive
      if octive = 1 then : note = note + 24 : endif ' high octive
      pinNo = note ' 0-35: b.0-b.7, c.0-c.7, a.0-a.7, d.0-d.6 (D.7 plays tune)
      if pinNo > 28 then : pinNo = 28 : endif ' reserved pins: D.7=piezo; D.6=LCD; D.5=button
      low oldPinNo
      high pinNo
      oldPinNo = pinNo
      tune 31,8,(codedNote)
      sertxd(#codedNote,"/",#pinNo," ")
      inc eePtr
      read eePtr,codedNote
      if pinD.5 = 1 then  ' terminate playing
        serout D.6,N2400,(254,192,"       ") 
        do while codedNote <> $FF : inc eePtr : read eePtr,codedNote : loop
        do while pinD.5 = 1 : loop ' wait until released
      endif
    loop
    serout D.6,N2400,(254,192,"Done   ") 
  endif
loop
Here is a screen shot of the simulation, with the "Options" panel open showing the AXE033 simulation selected. "Options" button is pointed to in red; also pinD.5 (used for making selections); and Options panel with the LCD selected. The simulated LCD is also shown.
hammer1.jpg
Output D.6 is used for the serial connection to the LCD. Input pinD.5 is used to make selections. A single button allows scrolling through the three tunes which are stored in EEPROM and also selecting which one to play, based on how long the button is on.

After the program is started in the PE6 simulator, the first tune name is displayed. A quick click and release of pinD.5 will advance to the next tune. If the last tune is reached, the display will scroll back around to the first. To play the tune the name of which is displayed, click pinD.5 to the active state, count off three seconds, and click it again to deactivate it. The tune will start playing (slowly in the simulator--the simulation delay should be set as low as possible). The appropriate LEDs will go on for each note (29 total notes up from lower octave C (I'm not sure where the corresponding note on a piano is)). If you click pinD.5 while a tune is playing, it will terminate. If not playing, the tune can be restarted with 3 seconds on and then off on pinD.5.

The number of tunes in any single version of the program is limited by the size of eeprom. By modifying the program, external eeprom could be used.

One issue is that the picaxe notes are not registered to the hammer dulcimer string arrangement, and in fact I have no idea what that arrangement is for a 35-note instrument. Adjustments would have to be made to fit the register of the instrument.
 

Gramps

Senior Member
Thank you so much for your in-depth replies to my post!
Waiting now for a package from the UK containing my new pickaxe and computer cable.
 

lbenson

Senior Member
Glad you found the posts encouraging. Remember that you don't have to wait to play--the PE6 simulator allows you to do a lot of development even if you don't have hardware.

You suggested starting with "D E F# G A B C & D" (is that C#?), so key of D? If the tunes I included in the programs are in D, it's just luck. If a D is the lowest note on your hammered dulcimer, do you know which frequency D it is? Or to put it another way, can you say which "A" is 440Hz? Does the next set of notes just repeat the sequence "D E F# G A B C & D" and so on for all 35 notes you mentioned?

I would be interested in writing an RTTTL "convert to D" program if that would be a step in the right direction to enable you to use existing RTTTL tunes.

Hope this is not too many questions for you. I do find this an interesting project, and would be happy to adjust the code I've provided to suit the specifics of your instrument. It seems that hammered dulcimers can come in a number of different flavors.
 

Gramps

Senior Member
Thank you for posting!
I purchased the PICAXE-28 Starter Pack (USB) AXE001U 1 and hope it will arrive soon.
Can't seem to locate the step by step instructions on how to use the PE-6 simulator. I'm not sure about the frequency of the notes perhaps we can find that online someplace
Could you please point me to that instructional.
thank you, Gramps
 

lbenson

Senior Member
I'm not sure how good it is on using the simulator, but the "PE6 BETA TESTING BRIEFING" datasheet is here: http://www.picaxe.com/docs/pe6.pdf

If you open PE6, start a new document, and cut and paste the program from post 7 above, then look at the image in that post to see how to set it up for a PICAXE 40X2 with simulation of an LCD, you should be able to click the Simulate tab (on the line just below the very top with the red picaxe icon), then click Run. At the very bottom right there is a "Simulation Delay" slider. If you want to see how the code is executing, move the slider to the right to the speed that works for you. If you want to play the tunes as fast as possible (in simulation), move the slider all the way to the left. You can single-step or run to breakpoints if you like.

Read post #7 for the timing of how to click pinD.5 in order to scroll through the titles of the three available tunes, or to select to play a tune.

I looked online about the hammered dulcimer, and the ones I saw did not have 35 notes. They did appear to show a preference for the key of D, but some apparently have strings for additional notes so that other keys are possible. Do you have an instruction booklet for the hammered dulcimer that you have--perhaps it would show the notes.

(Note that the tunes will play slowly in simulation, but on a real picaxe with a piezo sounder on D.7, they should be close to the speed specified in the TUNE command.)

I'll try to find time in the next few days to modify the program for the 28X2. Only 21-3 or 18 notes will be available without an I/O expander (or some form of multiplexing).
 

Gramps

Senior Member
I hope to attempt to load your code this weekend and see if I can get it to run. Thanks again for your help!
Gramps
 

erco

Senior Member
Awesome! I'm the same erco. How's that relay H-bridge on your car window motor arm working? :)
 

Gramps

Senior Member
erco! Good to hear from you! The H Bridges worked as good as expected but we realized we had to go digital proportional in order to get real smooth operation.
 

ZanderPIC

New Member
The following code uses the APA102 LED light strip to minimize amount of pins used. Simply update the EEPROM table, number of LED and number of notes. For more information on the APA102 LEDs refer to this.


The below program works nicely in the simulator when replacing the readadc command with a micIn value > 512
Code:
readadc10 c.7, micIn
with
Code:
micIn = 600
pause 500
this'll run and iterate through the program without the need of the mic.



Code:
;********************************
; WRITEN BY ZanderPIC
; UPDATED: MAY 11, 2018
; PICAXE 20X2 @ 8MHZ
; PROGRAM SIZE: 119 BYTES
; USE APA102 LED STRIP WITH HSPI
; PIN c.1 HSPI cod
; PIN B.7 HSPI SCL
; PIN c.7 mic
;*******************************



; Change values below in respect to the number of LEDs/notes and the order
;*********************************************************************
; Number at each EEPROM byte refers to the LED index (ex. 1 = LED 1).
; Order refers to the order of notes. 
EEPROM 0,(1,  2,  3,  4,  5,  6,  2, 5, 1, 2)

; total amount of notes pressed - 1, aka length of EEPROM - 1.
symbol number_of_notes = 9

; total amount of LEDs
symbol number_of_LEDs = 6
;*********************************************************************




symbol micIn = w0
symbol counter = b3
symbol EEPROM_In = b4
symbol hold = b5


; Setup SPI
#macro Init()
	hspisetup spimode00, spifast 
#endmacro


; Send start frame
#macro head()
	sendPacket($00, $00, $00, $00)
#endmacro


; Send end frame
#macro tail()
	sendPacket( $FF, $FF, $FF, $FF )
#endmacro



; Send a four byte packet out via HSPI
#macro sendPacket( n1, n2, n3, n4 )
	hspiout( n1, n2, n3, n4 )
#endmacro

; Receives three bytes (RGB) and adds a ones byte to the front.
#macro send(red, blue, green)
	sendPacket( $FF, red, blue, green)
#endmacro

; Read EEPROM at position counter with variable EEPROM_IN 
#macro ReadEEPROM()
	read counter, EEPROM_IN
#endmacro


main:
	counter = 0
	Init
	
	; initialize first LED
	ReadEEPROM
	call LedToScratch
	call ToLED
	
	
	do until counter = number_of_notes
		
		; Reads mic value.
		readadc10 c.7, micIn
		
		; checks if mic value is high, arbitrary value of 512
		if micIn > 512 then
			inc counter
			ReadEEPROM
			call LedToScratch
			call ToLED
                        do: loop while micIn > 400
		endif	
	
	loop
	end


; Function writes to Scratchpad and determines if the LED is on.
LedToScratch:
	ptr = 0
	for hold = 1 to number_of_LEDs
		if EEPROM_IN = hold then
			; three bytes for RGB values. to change colour change bytes 
			; respectively (values: 1 - 255). 
			@ptrinc = 20
			@ptrinc = 20
			@ptrinc = 20
		else
			@ptrinc = 0
			@ptrinc = 0
			@ptrinc = 0
		endif
	next
	return
	
; Function reads from Scratchpad and sends values out via HSPI
ToLED:
	head
	ptr = 0
	for hold = 1 To number_of_LEDs
		b50 = @ptrinc
		b51 = @ptrinc
		b52 = @ptrinc
		send(b50,b51,b52)
                
	next
	return
The program may look daunting with the macros and such, but is actually not very complicated.

Zander
 
Last edited:

Gramps

Senior Member
Here's an update.
After two failed attempts to get the simulator working we moved on to building the first LED array. Still waiting for the picaxe 28 starter kit to come from UK.
Question, how to wire the LEDs?
There are 12 in the first array.
Perhaps two groups of six with the anodes tied together?
Then we need eight pins to run 12 LEDs. Correct?
Is there a more efficient way to wire them to use less pins?
Thanks, Gramps
 

lbenson

Senior Member
Can't help with multiplexing LEDs, but possibly could with "failed attempts to get the simulator working".

What I posted definitely works in the PE6 simulator. If that was what failed, what was it about it that failed?

Both the setup and the timing of the clicks on pinD.5 are picky, so if you have questions, I'll try to answer them.

(The Wikipedia article on "charlieplexing" shows a circuit with 6 LEDs for 3 pins: https://en.wikipedia.org/wiki/Charlieplexing The article indicates that 42 LEDs can be driven with 7 pins.)
 

AllyCat

Senior Member
Hi,

Question, how to wire the LEDs?
The simplest method is a "matrix array" with rows and columns, most efficient when the number of rows and coulmns is equal, e.g. 6 + 6. That can drive 36 LEDs, with for example the first 6 anodes connected to the "row1" pin, the next 6 to "row2", etc.. Then Cathodes 1, 7, 13, ... etc. connect to "Column1", etc..

For Charlieplexing, the Rows and Columns are connected to the same pin, which can work because most pins are set to "Tri-State" or "Open Circuit" (neither High nor Low), which can be achieved by setting them as Inputs. Then one pin is driven as a High output and another Low, to select the required LED. Obviously the same pin cannot be driven both High and Low at the same time, so the Charlieplex matrix "loses" the LEDs which correspond to the diagonal (Row1, Column1, etc.), for example 30 LEDs instead of 36, but it needs only half as many pins. Thus for 35 LEDs you'd need 7 pins, i.e. 7 x 7 - 7 (or 7 x 6) which can drive up to 42 LEDs.

The "mapping" of the rows/columns to individual LEDs is not trivial, but apparently neither is the string arrangement on a dulcimer ;) . So you probably just need a single "Lookup table" to relate each LED/note to a specific row/column combination. For example the Low nibble (bits 3-0) of the lookup byte might indicate the pin number which is driven Low and the High nibble (bits7-4) the pin which is driven High (having first set all the pins as inputs).

Cheers, Alan.
 
Last edited:

Gramps

Senior Member
when i open PE6 it says "start" but there doesn't seem to be any place to paste the program!
 

Gramps

Senior Member
The simulation runs until it gets too wait till the button is pressed.

How do I press the button?
 

lbenson

Senior Member
How do I press the button?
Click with the mouse pointer on D.5. It should turn yellow (you can click the icon, "Zoom in" in the simulation pane so that you can see better). If you click again in about one second, the yellow will disappear and after about 5 seconds, the next tune name will appear (everything is slow in simulation--make sure you have the "Simulation Delay" slider as far to the left as possible). If you click D.5 and leave it on (yellow) for about 3 seconds, then click off, the tune whose name appears in the simulated LCD will play (slowly). Clicking on and off will stop it (after a few seconds). After the last (of three) tunes it will cycle back to the first.

On a real chip, everything should run at an acceptable speed.
 

lbenson

Senior Member
Here's a version for the PICAXE 28X2. Only 18 LEDs can be lit (without multiplexing). This works in simulation with the LCD on A.3, the piezo on A.4, and the pushbutton on A.2. This will work on your module when it arrives (but you would need a serial LCD, a piezo buzzer or speaker (see Manual 3), and a button wired up).

As it turns out, Amazing Grace (in this version) doesn't go above LED 18. If the simulation speed is set to 66ms, it is only a little slower than the fastest setting, and you can see it walk through the code, and you can see the pins flashing green for each note. Remember that you have to set up the LCD pin in "Options" in the Simulation pane.

Code:
' 28hammer -- plays tunes one note at a time & lights LED corresponding to note
#picaxe 28X2
' uses duration, octave, note coding from "tune" command

'eeprom 0,($29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$29,$67,$E7,$29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5,$27,$27,$29,$25,$27,$69,$6A,$29,$25,$27,$69,$6A,$29,$27,$25,$27,$2A,$E9,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5,$FF)
eeprom 0,("Ode To Joy",$FE,$29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$29,$67,$E7,$29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5,$27,$27,$29,$25,$27,$69,$6A,$29,$25,$27,$69,$6A,$29,$27,$25,$27,$25,$E9,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5,$FF,"Amazing Grace",$FE,$64,$69,$29,$41,$6B,$69,$01,$6B,$29,$66,$24,$64,$66,$29,$41,$6B,$69,$01,$6B,$41,$04,$41,$44,$04,$41,$6B,$69,$01,$6B,$29,$66,$24,$64,$66,$29,$41,$6B,$69,$01,$6B,$29,$FF,"Wildwood Flower",$FE,$66,$67,$29,$6B,$42,$26,$67,$66,$24,$67,$62,$22,$66,$67,$29,$6B,$42,$26,$67,$66,$24,$67,$41,$22,$29,$06,$46,$44,$02,$69,$69,$2B,$41,$6B,$29,$26,$26,$66,$64,$26,$69,$66,$24,$67,$21,$22,$FF,$FF)

symbol pButtonPin=pinA.2
symbol pLCD=A.3
symbol pPiezo=A.4

symbol newTune=bit0

symbol lastch=b3
symbol eePtr=b4
symbol note=b5
symbol codedNote=b6
symbol ch=b6         ' NOTE overloaded variable b6
symbol pinNo=b7
symbol oldPinNo=b8
symbol octive=b9
symbol checkTime=b10
symbol tunePtr=b11
symbol startAdr = 12

'amazing
'tune D.7, 15,($64,$69,$29,$41,$6B,$69,$01,$6B,$29,$66,$24,$64,$66,$29,$41,$6B,$69,$01,$6B,$41,$04,$41,$44,$04,$41,$6B,$69,$01,$6B,$29,$66,$24,$64,$66,$29,$41,$6B,$69,$01,$6B,$29)

'ode
'tune 5, 8,($29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$29,$67,$E7,$29,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5
'tune 5, 8,($27,$27,$29,$25,$27,$69,$6A,$29,$25,$27,$69,$6A,$29,$27,$25,$27,$2A,$E9,$29,$2A,$00,$00,$2A,$29,$27,$25,$25,$27,$29,$27,$65,$E5)
settimer t1s_8 ' set timer to 1 second ticks at 8MHz (default speed)
eePtr = 0
newTune = 1

do
  if newTune = 1 then
    serout pLCD,N2400,(254,1) : pause 30 ' clear screen
    read eePtr, ch
    do : serout pLCD,N2400,(ch) : inc eePtr : read eePtr, ch : loop until ch = $FE ' display name of selected tune
    tunePtr = eePtr + 1
  endif
  do : loop while pButtonPin = 0 ' wait until button is pressed
  timer = 0 ' one-second timer
  checkTime=1
  do : loop while pButtonPin = 1 ' wait until button is released
  if timer <= checkTime then ' next tune
    do : read eePtr, codedNote : inc eePtr : loop until codedNote = $FF ' read past this tune
    read eePtr,ch
    if ch = $FF then : eePtr = 0 : endif ' end of tunes; start over
    newTune = 1
  else ' we've selected this tune
    serout pLCD,N2400,(254,192,"Playing") 
    eePtr = tunePtr
    newTune = 0
    read eePtr,codedNote
    do while codedNote <> $ff
      octive = codedNote & %00110000 >> 4 ' %00=middle; %01=high; %10=low
      note = codedNote & %00001111
      if octive = 0 then : note = note + 12 : endif ' middle octive
      if octive = 1 then : note = note + 24 : endif ' high octive
      pinNo = note ' 0-35: b.0-b.7, c.0-c.7, a.0-a.7, d.0-d.6 (D.7 plays tune)
      if pinNo > 17 then : pinNo = 17 : endif ' reserved pins: D.7=piezo; D.6=LCD; D.5=button
      low oldPinNo
      high pinNo
      oldPinNo = pinNo
      tune pPiezo,8,(codedNote)
      sertxd(#codedNote,"/",#pinNo," ")
      inc eePtr
      read eePtr,codedNote
      if pButtonPin = 1 then  ' terminate playing
        serout pLCD,N2400,(254,192,"       ") 
        do while codedNote <> $FF : inc eePtr : read eePtr,codedNote : loop
        do while pButtonPin = 1 : loop ' wait until released
      endif
    loop
    serout pLCD,N2400,(254,192,"Done   ") 
  endif
loop
 
Last edited:

Gramps

Senior Member
The simplest method is a "matrix array" with rows and columns, most efficient when the number of rows and coulmns is equal, e.g. 6 + 6. That can drive 36 LEDs, with for example the first 6 anodes connected to the "row1" pin, the next 6 to "row2", etc.. Then Cathodes 1, 7, 13, ... etc. connect to "Column1", etc..

Thanks Alan!
We have 3 arrays, 2 with 12 LEDS and one with 11. Can you point me to a wiring schematic?
 

AllyCat

Senior Member
Hi,

That sounds quite easy for a conventional (Row/Column) matrix. Just consider each string in two halves, each grouping 6 LEDs as a "Row" (treat the group of 11 as another 12 and just don't fit whichever LED isn't needed). This is a good example of why Computer Programmers normally start counting from zero! The LED number is then the Column number plus six times the Row number. For example LED3 would be Column 3 + 6 * 0 (Row zero).

The circuit diagram is basically 6 horizontal lines (the rows) crossing 6 vertical lines (columns). At each "crossover" connect a LED (diode) diagonally from the nearest column to the nearest row (or vice versa). It's normal to show the diodes pointing downwards (SE or SW), i.e. anode towards the top, but the anodes or cathodes (if they are both driven directly by the PICaxe) can go to the row or column (but must of course all be in the same direction), with the software written accordingly. Put a current-limiting resistor (usually a few hundred ohms) in series with each column- or row- driving pin (whichever is on the cathode side is probably preferable).

Charlieplexing doesn't look too difficult either: There would be 7 pins so for each group (row) of 6 LEDs, connect the first pin to all anodes of the first group of LEDs and the second pin to the second group of anodes, etc. Then connect the remaining 6 pins/wires for each group to the 6 cathodes of the respective group. The resistors would be half the value of a row/column matrix (because two resistors are always in series between the pins).

Cheers, Alan.
 

Gramps

Senior Member
Thanks Alan! Here is a new twist. The Dulcimer has a number of duplicate notes in different places, to make it easier to play.
Fer example it has two G4's, C5's, D4's, D5's, etc.. . The correct note needs to light in both place. This will also reduce the number of total pins needed.
edit: Excluding the duplicates, we have 24 notes!
edit2: There are three A4's!
 
Last edited:

AllyCat

Senior Member
Hi,

Actually it's rather a complication because you can't connect the LEDs directly in series or parallel (because each LED needs its own series resistor). With Charlieplexing I think you'd still need the same number of pins, but need to multiplex (time divide) the illumination of the LEDs.

For the normal row/column method, one solution is to put a resistor in series with each LED (i.e. 35) but a further issue is whether the PICaxe pins can drive more than one LED at a time, brightly enough. If they can, then maybe the resistors can still be shared by ensuring that the LEDs which illuminate at the same time are driven by the same row or column. In either case a common cathode configuration probably is necessary.

Cheers, Alan.
 

Gramps

Senior Member
Yes I also thought of that, so it might be better to just code all three A4 diodes to light at the same time
 

AllyCat

Senior Member
Hi,

That's not necessarily possible. See the section of lbenson's link in #34, after the part headed "Addressing Single LED", beginning "Intuition....".

Cheers, Alan.
 

lbenson

Senior Member
I count 25 unique notes, as follows:
Code:
G3
A3
B3
C4
D4,D4
E4,E4
F4
F#4
G4,G4
G#4
A4,A4,A4
Bb4
B4,B4
C#4
C5,C5
C#5
D5,D5
E5,E5
F5
F#5
G5,G5
A5
B5
C6
D6
16 of these are unique single notes, so a 4x4 matrix would work for them (8 pins).
8 are double notes and 1 triple, so 9 pins would work for them.
17 pins needed total.
With 21 pins available on a 28x2, that leaves 4 for control.
 
Top