Dr.Godfried-Willem RAES
Kursus Experimentele Muziek: Boekdeel
2: Live electronics
Hogeschool Gent : Departement Muziek & Drama
2118
Some time ago we were asked to design a metronome wherewith
the tempo could be adjusted in equal tempered semitone steps (2^(1/12)) instead
of the usual divisions "Lento- presto" and their MM (Maelzel Metronome)
equivalents. Of course such a task would be easy to accomplish using <GMT>
on a Wintel PC. Such a solution could however never compete with the compactness
of commercial metronome devices. Hence our recourse to the infamous PIC controllers
programmable in Basic from Parallax Inc.
We used
a basic Stamp (a BS2 type from Parallax) to implement this with just a few components
and, of course, some software:
This is the circuit:
Twelve I/O pins (0-11) are used to select the semitone for the tempo (a 12
position rotary switch came in very handy here), and 2 bits are used to set
the octave (12,13). Here also we could have used a rotary switch, but we finaly
did put two toggle switches. We provided 2 octaves for a range rquivalent to
MM=30 up to MM=240. So the tempo corresponding to 'C' with the octave switch
set to down, will be exactly MM30. The octave up is then 60 and one higher 120.
Using the last free pin, it could be expanded to an extra octave easily.. The
output is a single LED connected to I/O pin 15. For an audible output, you can
replace the LED with a small piezobuzzer. If you want a loud click, use a PNP
transistor driver and a small loudspeaker. Current output of the stamp is limited!
And the software, as you should download it once into the PIC controller looks
like:
- '*************************************************************************
- '* Chromatic Metronome *
- '* by *
- '* Dr.Godfried-Willem RAES *
- '* Stamp2 Hardware version 1.0 *
- '* Filename : Metronoom_BS2.BS2 *
- '* Code version 1.0 *
- '* commisioned by Marc Maes *
- '*************************************************************************
- ' DECLARATIONS:
- note VAR byte ' should be note number 0-11
- octdown VAR bit
- octup VAR bit
- oct VAR nib
- tempo VAR word ' in milliseconds per period
- ontim VAR word ' in 2 microsecond units
- ontimms VAR word ' LED flash time in milliseconds
- ' Initialisation of variables:
- ' we need 12 bits for the notes: d0-d11
- ' 1 bit for octave down (tempi 30- 56)
- ' 1 bit for octave up (tempi 120 - 226)
- ' we will use bit 15 for metronome output: this bit can drive a LED and
a piezo.
- ' INITIALISATION:
- ' parallel input bits 0 to 11 ' these bits are mapped on notes 0-11
- ' make the low byte an input:
- DIRA = 0 ' bit d0-d7
- DIRB = 0
- DIRC = 0 ' bit d8-d11
- DIR12 = 0 ' octave down bit
- DIR13 = 0 ' octave up bit
- DIR14 = 1 ' output DIR15 = 1 ' output
- ' look up table in ms for a complete period (this goes into the EEPROM):
- TABLE DATA WORD $7D0, WORD $760, WORD $6F6, WORD $692, WORD $633, WORD
$5DA, WORD $586, WORD $537, WORD $4EC, WORD $4A5, WORD $462, WORD $423, WORD
$3E8, WORD $3B0, WORD $37B, WORD $349, WORD $31A, WORD $2ED, WORD $2C3, WORD
$29B, WORD $276, WORD $253, WORD $231, WORD $212, WORD $1F4, WORD $1D8, WORD
$1BD, WORD $1A4, WORD $18D, WORD $177, WORD $162, WORD $14E, WORD $13B, WORD
$129, WORD $119, WORD $109, WORD $FA
- ontim = $61A8 '=50 * 500 ' flash time for the LED in 2 microsecond units
(1ms = 500 2-microsecond units) ' this sets the flashtime to 50ms
- ontimms = ontim / 500
- '********************************************************************************************************
- ' selectnote:
- IF IN0 = 0 THEN C ' the default is 1, since we have hardwired pull-ups
- IF IN1 = 0 THEN Cis
- IF IN2 = 0 THEN D
- IF IN3 = 0 THEN Es
- IF IN4 = 0 THEN E
- IF IN5 = 0 THEN F
- IF IN6 = 0 THEN Fis
- IF IN7 = 0 THEN G
- IF IN8 = 0 THEN Gis
- IF IN9 = 0 THEN A
- IF IN10 = 0 THEN Bes
- IF IN11 = 0 THEN B
- 'GOTO C ' make this the default, in case we read only one's
- DEBUG "Check rotary switch wiring... "
- selectoctave:
- octdown = IN12 ' default is 1
- octup = IN13 ' default is 1
- octdown = ~ octdown ' invert
- octup = ~ octup oct = octup | octdown
- IF oct = 0 THEN leesnormaal
- IF octdown = 1 THEN init
- IF octup = 1 THEN leeshoog
- GOTO init
- leeshoog:
- tempo = tempo / 4
- GOTO init
- leesnormaal:
- tempo = tempo / 2
- GOTO init
- init:
- IF ontimms > (tempo / 2) THEN adjustontim
- init2:
- tempo = tempo - ontimms
- LOW 14
- HIGH 15
- DEBUG " O.K."
- 'DEBUG "tempo ", DEC tempo, " ontim ", DEC ontimms, " note =", DEC note
- ' START OF RUN-CODE:*****************************************************
- Lus:
- PULSOUT 15,ontim ' in 2 microsecond units - causes downgoing pulse
- PAUSE tempo ' werkt in ms
- GOTO Lus
- '************************************************************************
- C:
- READ 1,tempo ' reading only 1 byte! (would be msb) - order lsb-msb in eeprom
- tempo = tempo << 8 'shift left tempo,8
- READ 0, note
- tempo = tempo | note ' | = OR , now we have the complete word
- note = 0
- GOTO selectoctave
- Cis:
- READ 3,tempo
- tempo = tempo << 8
- READ 2, note
- tempo = tempo | note
- note = 1
- GOTO selectoctave
- D:
- READ 5,tempo
- tempo = tempo << 8
- READ 4, note
- tempo = tempo | note
- note = 2
- GOTO selectoctave
- Es:
- READ 7,tempo
- tempo = tempo << 8
- READ 6, note
- tempo = tempo | note
- note = 3
- GOTO selectoctave
- E: READ 9,tempo
- tempo = tempo << 8
- READ 8, note
- tempo = tempo | note
- note = 4
- GOTO selectoctave
- F:
- READ 11,tempo
- tempo = tempo << 8
- READ 10, note
- tempo = tempo | note
- note = 5
- GOTO selectoctave
- Fis:
- READ 13,tempo
- tempo = tempo << 8
- READ 12, note
- tempo = tempo | note
- note = 6
- GOTO selectoctave
- G:
- READ 15,tempo
- tempo = tempo << 8
- READ 14, note
- tempo = tempo | note
- note = 7
- GOTO selectoctave
- Gis:
- READ 17,tempo
- tempo = tempo << 8
- READ 16, note
- tempo = tempo | note
- note = 8
- GOTO selectoctave
- A:
- READ 19,tempo
- tempo = tempo << 8
- READ 18, note
- tempo = tempo | note
- note = 9
- GOTO selectoctave
- Bes:
- READ 21,tempo
- tempo = tempo << 8
- READ 20, note
- tempo = tempo | note
- note = 10
- GOTO selectoctave
- B: READ 23,tempo
- tempo = tempo << 8
- READ 22, note
- tempo = tempo | note
- note = 11
- GOTO selectoctave
- AdjustOnTim:
- Ontimms = tempo / 2 ' in milliseconds
- Ontim = Ontimms * 500 ' in 2 microsecond units.
- GOTO Init2
- END
Finished metronomes can be obtained from the Logos Foundation Labs on request.
Price is around 100 Euro.
Filedate: 2001-07-21
last update: 2004-04-19