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

Gramps

Senior Member
Yes sir, you are correct!
Perhaps we would need 9 transistors or some other kind of drivers?
 

Gramps

Senior Member
I'm having a little trouble visualizing this 16 diode Matrix.
Can we tie all 35 diodes to a common cathode?
Or should we keep the Matrix diodes separate and bring out individual leads for the 9 double and triple lamps?
Thanks, Gramps
 

lbenson

Senior Member
The 16 LED 4x4 matrix would be as shown in the link in post 34.

I hope tomorrow to be able to post a 28X2 program which uses port B for the 4x4 matrix--"common row anode" form with B.0-B.3 as the anode rows and B.4-B.7 as the cathode columns. I've been around the barn programming a conversion from the "abc" notation popular with fiddlers (in which there are many tunes appropriate for the hammered dulcimer) to picaxe "TUNE" encoding.

I'm not at all sure that the wiring for a matrix would be easier than with an added 16-pin MCP23017.
 

lbenson

Senior Member
Here's a version for the 28X2 which uses a 4x4 matrix for the 16 singly-occurring notes on the 35-note hammered dulcimer, and C.0 through A.0 for the nine notes which occur twice or 3 times.
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,"Ashokan",$FE,$41,$02,$41,$4B,$49,$C6,$44,$46,$07,$46,$44,$42,$2B,$02,$6B,$29,$02,$06,$09,$02,$06,$06,$47,$06,$C4,$49,$41,$02,$41,$4B,$49,$C6,$44,$46,$07,$46,$44,$42,$2B,$02,$6B,$29,$02,$FF,$FF)


' BELOW: 1st row, # duplicate if > 1; 2nd row, notes ("-" if not available); 3rd row, note coding
'                            2        2          2        3      2   2        2       2           2 
' G3,-G#3,A3,-Bb3,B3,C4, C#4,D4,-Eb4, E4,F4, F#4,G4, G#4, A4,Bb4,B4, C5, C#5, D5,-Eb5,E5, F5,F#5, G5,-G#5,A5,-Bb5,B5, C6,-C#6,D6
'$00,$FF,$01,$FF,$02,$03,$10,$C0,$FF,$C1,$11,$12,$C2,$13,$C3,$20,$C4,$C5,$21,$C6,$FF,$C7,$22,$23,$C8,$FF,$30,$FF,$31,$32,$FF,$33
' Note coding: $FF=not available; $C?--pin C.0-C.7,A.0; other: 1st nybble is B-port string B0-B3; 2nd is B4-7
table 0,($00,$FF,$01,$FF,$02,$03,$10,$C0,$FF,$C1,$11,$12,$C2,$13,$C3,$20,$C4,$C5,$21,$C6,$FF,$C7,$22,$23,$C8,$FF,$30,$FF,$31,$32,$FF,$33)
table 40,("G3,-G#3,A3,-Bb3,B3,C4,C#4,D4,-Eb4,E4,F4,F#4,G4,G#4,A4,Bb4,B4,C5,C#5,D5,-Eb5,E5,F5,F#5,G5,-G#5,A5,-Bb5,B5,C6,-C#6,D6,",0,0,0)

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

symbol newTune=bit0

symbol notech=b2
symbol lastch=b3
symbol eePtr=b4
symbol note=b5
symbol codedNote=b6
symbol pinNo=b7
symbol oldPinNo=b8
symbol octive=b9
symbol checkTime=b10
symbol tunePtr=b11
symbol LEDcoding=b12
symbol ch=b13
symbol noteNdxAdr = 56 ' start of upper ram; note text index

'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)
newTune = 1
dirsB=%11111111 ' all outputs
pinsB=%00000000 ' all low
dirsB=%00000000 ' all inputs
dirsC=%11111111 ' all outputs
bptr = noteNdxAdr ' array of 35 byte pointers to note text
eePtr = 30 ' beginning of note-name data in table
readtable eePtr,ch
do while ch <> 0
  @bptrinc = eePtr
  readtable eePtr,ch
  do while ch <> "," ' comma separated text
    inc eePtr
    readtable eePtr,ch
  loop
  inc eePtr
  readtable eePtr,ch
loop
eePtr = 0

do
  if newTune = 1 then
    serout pLCD,N2400,(254,1) : pause 30 ' clear screen; see http://www.picaxe.com/docs/axe033.pdf
    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: A.4=piezo; A.3=LCD; A.2=button
'      low oldPinNo
'      high pinNo
'      oldPinNo = pinNo
      readtable pinNo, LEDcoding
      serout pLCD,N2400,(254,200) : pause 30 ' set cursor at row 2, position 8
      bptr = pinNo + noteNdxAdr ' address of address in table of note text
      bptr = @bptr ' get address in table of text
      readtable bptr,ch
      do while ch <> ","
        serout pLCD,N2400,(ch)
        inc bptr
        readtable bptr,ch
      loop
      serout pLCD,N2400,("  ")
      sertxd(#codedNote,"/",#pinNo,"/")
      pinsB = %00000000 ' set all portB pins to low
      dirsB = %00000000 ' set all portB pins inputs
      pinsC = %00000000 ' set all portC pins to low
      low D.0 '
      if LEDcoding = $FF then ' invalid
      elseif LEDcoding => $C0 then
        pinNo = LEDcoding & %00000111 + 8 ' 8-16: C.0-C.7, A.0
        high pinNo
        pinNo = pinNo - 8
        sertxd("C.",#pinNo," ")
      else ' portB LED matrix control--
        pinNo = LEDcoding / 16 & %00001111 ' 0-3: B.0-B.3: high pin for matrix
        high pinNo
        sertxd("B.",#pinNo,"-")
        pinNo = LEDcoding & %00001111 + 4 ' 4-7: B.4-B.7: low pin for matrix
        low pinNo
        sertxd("B.",#pinNo," ")
      endif
      tune pPiezo,8,(codedNote)
      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
This still runs in the PE6 simulator (visibly with the delay set to 32), but slower than before because it is now breaking down the TUNE coded notes to determine which LEDs to light. It also prints the note and octave (e.g., "D3", "G#4") on the display. I think it would still run at an acceptable speed on a real chip. In simulation there is about a 30-second delay on startup while the program builds an index to the note name text which has been stored with the "TABLE" command.

The possible hammered dulcimer notes are shown in the comment line below, and the encoding for the LEDs in the line following:
Code:
' G3,-G#3,A3,-Bb3,B3,C4, C#4,D4,-Eb4, E4,F4, F#4,G4, G#4, A4,Bb4,B4, C5, C#5, D5,-Eb5,E5, F5,F#5, G5,-G#5,A5,-Bb5,B5, C6,-C#6,D6
'$00,$FF,$01,$FF,$02,$03,$10,$C0,$FF,$C1,$11,$12,$C2,$13,$C3,$20,$C4,$C5,$21,$C6,$FF,$C7,$22,$23,$C8,$FF,$30,$FF,$31,$32,$FF,$33
In the encoding, "$FF" means not available (as does "-" in the first line), "$C0-$C8" means pins C.0 through C.7 and A.0 (for the 9 notes which occur more than once), and other values indicate which pins in portB are activated for the appropriate LED in the 4x4 matrix. Each matrix-indicating byte value is made up of 2 nybbles, each of which may have a value between 0 and 3. The high nybble I've assigned to the anode (positive) side of the led, and will bring high B.0, B.1, B.2, or B.3. The low nybble will have 4 added to it so that it refers to B.4, B.5, B.6, and B.7 (one of which will be brought low). The non-selected high nybble and low nybble pins are tri-stated (made inputs)

Some notes in the "TUNE" range are unplayable on the hammered dulcimer (at least in certain octaves).

Not tested on real hardware, but I believe the analysis is correct, even if adjustments are needed.

This matrix layout will make for non-trivial wiring. My current thought is that this project would best be done using a 20X2 (or even 20M2) with an I2C MCP23017 16-pin I/O extender (no matrix wiring). Having I2C would also allow a large EEPROM to be added so that many more tunes could be included.

As I mentioned in the previous post, I spent a good bit of time the previous 2 days figuring out how to decode "abc" notation files and re-encode them as picaxe "TUNE" notes. This opens up many thousands of tunes. So far I've run "Ashokan Farewell", "The Irish Washerwoman", and "The Boys of Blue Hill" through my PC Basic converter program. I'll post more on that later.

(I've realized that the LED encoding for the matix might be clearer if the nybbles always indicated the portB pins to activate (either low or high), for instance, $52 would mean LOW B.5, HIGH B.2, which would turn on the LED on row 3, column 2. At present this is encoded $21.)
 
Last edited:

Gramps

Senior Member
Thank you Ibenson, is an awesome piece of work! And I thought this would be a simple beginner's project!
 

lbenson

Senior Member
The scheme of correspondences is shown in the two TABLE commands:

table 0,($00,$FF,$01,$FF,$02,$03,$10,$C0,$FF,$C1,$11,$12,$C2,$13,$C3,$20,$C4,$C5,$21,$C6,$FF,$C7,$22,$23,$C8,$FF,$30,$FF,$31,$32,$FF,$33)
table 40,("G3,-G#3,A3,-Bb3,B3,C4,C#4,D4,-Eb4,E4,F4,F#4,G4,G#4,A4,Bb4,B4,C5,C#5,D5,-Eb5,E5,F5,F#5,G5,-G#5,A5,-Bb5,B5,C6,-C#6,D6,",0,0,0)

The first line gives the picaxe pin number encoding, the second, the corresponding note on the hammered dulcimer. " The "$" in the first line is the PICAXE language indicator for a hexidecimal number, in which 4 bits (a "nybble") are encoded as 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, for values 0-15). Two 4-bit hex numbers make up a byte (8-bit number).

Ignore the "$FF"s (note not available on 35-note hammered dulcimer; also denoted by "-" in the note-name text); "$C#" (C followed by a numeral "0"-"8") indicates which C-port pin the note corresponds to, C.0-C.7, plus A.0; remaining hex numbers encode the matrix, with the high nybble indicating the row (B.0-B.3--which must be brought high to light an LED), and the low nybble indicating the column (B.3-B.4--which is brought low for the appropriate LED).

Thus for the first note, "G3", the matrix address is given by "$00", so B.0 goes high and B.3 goes low, with the other pins tri-stated (made inputs, so neither sourcing nor sinking current). "G#3" is not available, "A3" is "01", so B.0 is high and B.4 is low.

As long as all 16 of the singly-occurring notes are included in the matrix, it isn't critical if some are swapped around (not wired according to the encoding in the TABLE statement). For instance, if G3 is actually on B.0 and B.4, and A3 is on B.0 and B.3, the TABLE entries could be swapped and all would be fine.
 
Last edited:

lbenson

Senior Member
I count 25 unique notes, as follows:
Dang, I put one in the wrong place: C#4
I think I got it right in the program. Here is the list corrected:
Code:
G3
A3
B3
C4
C#4
D4,D4
E4,E4
F4
F#4
G4,G4
G#4
A4,A4,A4
Bb4
B4,B4
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.
 

lbenson

Senior Member
I think this is the right layout for the 16 unique single notes (it confuses me too--good luck with your wires).
hammer led matrix.jpg
 

Gramps

Senior Member
Thank you so much!
Questions:
Do you think 1 pin can light two LEDs?
What about 3? I would think they would be very dim if it worked at all.
Should we put one of the A notes on a separate pin? It looks like we have some pins left over. Or do we need that pin for an input?
How about using the load resistors on the LEDs to get them all to light equally bright?
 
Last edited:

lbenson

Senior Member
Do you think 1 pin can light two LEDs? What about 3?
I considered this. I think with the newer (last 10 years) high-brightness LEDs you would get plenty of brightness if you put each on a 1K resistor. If you want to get close to the maximum brightness with three LEDs on one picaxe pin, you would use 820 Ohm resistors (5 volts / 820 ohms * 3 LEDs = 18 milliamps--under the PICAXE pin limit of 20mA).

The two (or three) LEDs would each have its own resistor.

This would surely be bright enough indoors. If you needed it to be highly visible outdoors, you would need to test.

(I have tested on a breadboard and found that 3.3K ohm resistors provided sufficient indoors brightness for many purposes with red LEDs.)
 

Gramps

Senior Member
I don't think we would ever use the instrument outdoor's. What about the placement of the resistors on the individual LED pairs? Should we parallel the LEDs first or do the resistors go first?
 

lbenson

Senior Member
It doesn't matter whether the resistors are on the + side of the LED or on the 0V side. Whichever is most convenient for your layout. One resistor per LED, maximum of 3 LED+R pairs with 1K or 820 ohm Rs per pin.
 

AllyCat

Senior Member
Hi,

You only need 4 resistors (in series with either the column or row driver pins), probably with a value slightly lower than the paired/triple LEDs (because there are voltage drops across both the column and row driver FETs within the PICaxe). You can put resistors in series with both but then the value should be slightly less than half of that for the paired LEDs (because 2 resistors are in series with each LED).

The choice of (lowest acceptable) resistor values is quite complex, depending on many factors such as the supply rail, colour (and type) of LEDs (because they may have significantly different voltage drops). You may need to look at the specifications of several LEDs (maybe even buy a few samples) to see what's satisfactory. Look at the specified brightness output, but also the beam width because some "bright" LEDs have a very narrow beam angle ("lensed"), so often don't actually appear very "bright" (viewed off-axis).

In my (recent) experience white LEDs have seemed the most efficient, but they have a 3 volts drop, so you may need only a few hundred ohms from a 5 volt supply. The PIC(axe) output FETs are specified up to 25 mA per pin so you could work with up to 8 mA each for the tripled LEDs. But the human eye has a logarithmic brightness response so in practice a few extra mA may be hardly noticeable.

Cheers, Alan.
 

Gramps

Senior Member
Thanks Alan, so it looks like we'll have to wait until the picaxe board arrives before we can determine which resistor values to use.
 

Gramps

Senior Member
Looking online at input devices for the dulcimer, that would detect the hammer strikes.
Has anyone experimented with a vibration sensor?
I have a microphone from Radio Shack designed for an
Arduino. Would that work? Any other ideas?
 

Gramps

Senior Member
We printed Ibenson's matrix diagram and taped it to a piece of PC board and threaded the leads from the LEDs through the diagram!
Works perfect!!!:D
 

Attachments

lbenson

Senior Member
Alan's correction of up to 25 mA per pin means you could use the more common 680 ohm resistor instead of the 820 ohm to maximize brightness (howevermuch the difference might not be detectable by eyeball).

I admit that I am clueless as to how the LED voltage drop (differing by LED color) effects the resistance needed, and would be happy to be educated.
 

lbenson

Senior Member
Link is correct. I frequently search for "arduino +some+ module"--can give better results than without the "arduino".

The module you refer to looks like it could easily be used by a picaxe--just needs ADC reads to determine whether or not vibration was detected. It might well work to detect a hammer strike.
 

Gramps

Senior Member
Sorry about that. Is there another drawing app available that's better to use for in this forum?
 

Jeremy Harris

Senior Member
You can just attach images and some files to a post here. As well as avoiding the need for people to have to sign up to any other service to see them, it also means they are here for keeps.

The recent change by one of the image hosting sites that has disabled image sharing has caused major problems with a lot of forum linked images, making it now hard to look back and understand what people have done. Keeping images on the forum gets around that, and means that older posts can still be really useful.
 

AllyCat

Senior Member
Hi,

Strictly, each LED should have its own 680 ohm (or whatever) series resistor so that they each receive the same (correct) amount of current. That could be done with one resistor per LED, but a better way is to create three "resistive earths" (i.e. a resistor in series with earth) and connect the (cathodes of the) individual LEDs for each "set" to a different resistive earth. Thus one of the three earths (could be the same or different ones) will be unused except for the triplet of LEDs.

An alternative "better" way is to use "Active Low" drive, i.e. the anodes of the LEDs (of each set) connect via the "shared" resistors to the supply rail, and the LED cathodes connect directly to the appropriate driver pin. The reason for this is that the PIC{axe} pin drivers are rather better at pulling down (to earth) compared with pulling up (to the supply rail), because the N-channel FETs have less internal resistance.

I admit that I am clueless as to how the LED voltage drop (differing by LED color) effects the resistance needed, and would be happy to be educated.
Basically, almost any "load driving" circuit (e.g. for a LED) will have some "fixed" voltage drops and some "variable" drops (i.e. dependent on the resistance, according to Ohms Law). Nearly all components will exhibit some of both, but one of these elements is often negligible. Examples of fixed drops are typically a transistor base-emitter voltage and LED forward drops*. To calculate the total resistance (and thence the amount that needs to be added in the form of the series resistor) we subtract the total of the "fixed" voltage drops from the supply rail voltage (noting that the supply itself may have some series resistance). Then apply Ohms Law to find the total resistance (for the required current) and finally subtract what is already accounted for (in the pin driver FETs and LEDs, etc.) to find what the "680 ohms" really should be. ;)

*You really need to look at some LED data sheets, but a "rule of thumb" is that normal Red LEDs have a forward voltage drop of something over 1 volt, Yellow and Green higher at up to about 2.5 volts and White/Blue usually 3 volts or more. Thus (other factors being equal), Red LEDs would need higher resistance values than Yellow/Green and White/Blue rather less for a specific current. But White/Blue etc. will probably have a higher light output per unit current (because they receive more power due to their higher forward drop) and Red rather less.

Cheers, Alan.
 

lbenson

Senior Member
The easiest thing, and probably plenty suitable, is to put one resistor per LED, the same topology as the matrix so as to end up with one resistor of the same value per LED lit. This should also keep the apparent brightness the same. The 680 ohm value is chosen because it gives the greatest brightness while keeping below 25mA per pin and allowing up to 3 LEDs per pin.

(Calculations subject to revision with more subtle analysis.)
 

Gramps

Senior Member
ok, so ground all the cathodes, each through an individual resister, and tie all 3 anodes to the pin. Correct?
 

Gramps

Senior Member
How do we get by with only seven? There are 8 LED pairs and one LED triple? That adds up to 19 resisters. Plus we need 4 more for the matrix, correct?
Come on guys, don't keep me in suspense!!!
 
Last edited:

lbenson

Senior Member
... Come on guys, don't keep me in suspense!!!
I think Alan is messing with you. "7 resistors" would appear to refer back to the "charlieplexing" method mentioned in post 3. But you already have your more conventional multiplexing matrix wired.
 

AllyCat

Senior Member
Hi,

I think Alan is messing with you.
No, I wouldn't do that. ;)

The maximum number of LEDs illuminated at the same time is 3, so 3 series resistors can limit/balance the currents by the "resistive source" method (in series with earth or supply rail) that I outlined in #69. Then another 4 resistors for either the columns or rows of the 4 x 4 matrix.

I have been idly wondering what is the minimum realistic hardware configuration, which I think is 7 pins and 7 resistors, but I might consider 8 pins and a few extra resistors. The requirement for multiple LEDs to be illuminated makes Charlieplexing less attractive, so I'd apply a dedicated pin for the 3 common LEDs and a 7 pin Charlie matrix, with each pair of "common" LEDs arranged to share a pin (rather than use time-sharing).

The LED mapping/Charlie lookup table might be a little more complicated, but I believe it should (just) still be possible to fit within a single byte per note.

Cheers, Alan.
 
Top