HomeArticlesProjectsBlogContact
Articles
Music Box
Colin Mitchell
Colin Mitchell
June 03, 2010
Make sure to subscribe to our newsletter and be the first to know the news.

Table Of Contents

01
MUSIC BOX
02
THE CIRCUIT
03
PRODUCING A TONE
04
THE PROGRAM
05
GOING FURTHER

MUSIC BOX

  • PIC Programmer MkV

  • Instruction Set for PIC12F629

  • PIC12F629

  • PIC16F628 PDF Data Sheet

  • BlankF629.asm

  • PIC12F629.inc

See more projects using micros:

This project is an extension of a number of musical projects (Happy Birthday and It’s a Small World) and puts 11 melodies into a single design.
It’s called EVOLUTION.
From the previous projects we learnt a lot about producing a tune.
The first thing we learnt: it takes a lot of memory.
Each note needs one, two, or even three bytes and this severely limits the length of the tune, as the PIC12F629 has a maximum of 256 bytes for a table and this can only be placed in the first page of memory (the chip does not have the facility to access a table in any other part of memory).
We had to re-design the program so all of the 1024 locations of program-space could be used.
This was done by omitting tables and using the program-space for the data-bytes.
We reduced the data-requirement further by requiring only a single byte to produce the length of the HIGH. The length of the LOW was obviously the same duration.
But now we had a problem.
To produce a note of say 300mS, we had to supply data for the number of cycles. Obviously a high frequency needs more cycles for 300mS, than a low-frequency note.
The answer was to complement the data-bye.
This produced a result very near to 300mS.
The only other thing we had to produce was a note of a suitable length.
This was done by shifting the file right (rrf) to get a value of 50% and adding it to the original value, plus performing other operations to generate the correct length.
This has changed the capacity of the project from 2 tunes to 11, with NO bytes to spare. You cannot use location 3FF for your program as it is used by the micro to store the oscillator value.
We have also included a button to increment through the tunes.
When the project is first turned on, it will play each tune twice. If the switch is pressed, the project will go to the first tune and it will be repeated. If it is pressed again, the second tune will be selected and repeated. See below for more details on this.
The melodies are recognisable but some of the notes are very hard to reproduce in monotone and we have left it up to an aspiring musical person to alter the tones to create an improvement.


Music Box project with battery snap and 9v battery. The 3 red LEDs regulate the supply to 5v

MusicBox 1
Music Box Project on a prototype PC board

Music Box Project on a prototype PC board

Here is the Music Box added to a Fox-Hunt transmitter by Bjorn Dinse PA4BWD of the Netherlands email: bwewdinse@quicknet.nl

THE CIRCUIT

The circuit uses just a few components on a small prototype PC board. It’s easy to construct and ideal for a beginner. It’s just a PIC chip, a piezo diaphragm and a switch. You can put it together in a few minutes on a prototype board and download the program from the website.
The pull-up resistor for the switch is inside the chip and this saves one component. We have not placed a 100n across the chip and this is another component saved. The circuit takes less than 1mA and everything else is inside the chip via a program.
The photo shows the prototype.
If you want to buy a kits, there are two versions:

  • Version 1 comes as a piece of matrix board consisting of solder lands. After placing and soldering the components to the lands, they are joined with fine tinned copper wire to represent the tracks of a printed circuit board.
  • Version 2 has a PC board and a battery snap for a 9v battery. Three LEDs on the board regulate the voltage to 5v and also act as an “ON” indicator. Music Box has a memory feature. Any of the tunes can be selected and when the project is turned on again, the selected melody will repeat.
    Simply increment through the melodies via the button and turn the project off. Turn the project on to hear the selected melody.
    To erase the selection, push the button when the project is off and turn it on. Release the button immediately and the program will start at the first melody and play each twice.
    This feature uses the EEPROM and the program below shows exactly how to use these instructions to perform read and write operations.
    When creating your own program, these instructions should always be copied and pasted to prevent a mistake.
    The full 1024 program locations have been used in this project plus the first location in EEPROM.

PRODUCING A TONE

Producing a tone is very easy. All you have to do is make an output go HIGH then LOW at a controlled rate.
The output goes HIGH and stays HIGH for a certain number of microseconds then goes LOW and stays LOW for the same time. If the HIGH and LOW times are not the same, the tone is not very “clean” and does not have a “ring” about it.
In our case, we have connected the piezo diaphragm to two outputs to increase the volume.
When one output goes HIGH the other goes LOW and vise versa. This causes the piezo to see an increased voltage because the piezo is actually a capacitor of about 22n and when it gets a voltage on one direction, it charges to a voltage equal to the applied voltage.
To make the discussion easy to understand, let’s say one lead is fixed at 0v, and the other lead is now supplied with a reverse voltage. The potential of the other lead will change from say a positive voltage to a negative voltage. This is a swing of twice the value of the supply and the additional voltage produces a louder output.

THE PROGRAM

The program is large because each note in a melody requires two bytes. The first instruction loads w with a value and the second sends the micro to the “oscillator” sub-routine.
If a table was used, it would require only one byte, but a table in a PIC12F629 can only occupy the first 256 bytes of the program-space and we need 4 times this length.
The instructions for producing a tone are very simple.
Turn ON an output and create a delay. Turn OFF the output and create the same delay.
When a switch is introduced to a program, we need to be able to detect it very quickly and the only place is to look is within the tone routine.
Next we had to analyse the frequency of the notes and work out the number of microseconds for the HIGH and LOW for each note. This has already been mentioned above and everything is straight-forward until the “Memory” section is created.
This involves using the EEPROM. This is a separate section within the microcontroller consisting of 128 locations that hold information and retain it after power is removed. The program memory consists of 1024 locations that cannot be altered after the chip is “burnt.” The chip also has 64 locations called files or registers that can be altered during the running of the program, but lose memory when power is removed. These are the three types of memory.
The first EEPROM location is loaded with 00 when the chip is burnt and this location is looked at to see if the program goes to a requested melody or if the 11 tunes are played in sequence.
If the button is pressed, the current melody number is stored in EEPROM so that if the project is turned off, it will return to the selected tune, when turned on.
Although these EEPROM routines are simple, they must be copied from data sheets to be sure the instructions are correct.
We have used only easy-to-understand instructions for all the other subroutines and once this is done, the program is complete.

NoteFrequency (Hz)
C3130.81
C#3/Db3138.59
D3146.83
D#3/Eb3155.56
E3164.81
F3174.61
F#3/Gb3185.00
G3196.00
G#3/Ab3207.65
A3220.00
A#3/Bb3233.08
B3246.94
C4261.63
C#4/Db4277.18
D4293.66
D#4/Eb4311.13
E4329.63
F4349.23
F#4/Gb4369.99
G4392.00
G#4/Ab4415.30
A4440.00
A#4/Bb4466.16
B4493.88
C5523.25
C#5/Db5554.37
D5587.33
D#5/Eb5622.25
E5659.26
F5698.46
F#5/Gb5739.99
G5783.99
G#5/Ab5830.61
A5880.00
A#5/Bb5932.33
B5987.77
C61046.50

The frequency for each note
C4 = middle C

Here are the files:

You must use the .hex file to “burn” the chip or the .asm file (if you want to modify the program) as these are laid out so the compiler and programmer can understand the data.
The following program is just for viewing and includes only the first melody.

;************************************************************
;MUSIC BOX TUNES                                            *
;  3-6-2010                                                 *
;Multi tune Music Box without tables - uses whole of memory!*
;Press Sw to increment to next tune                         *
;************************************************************
;
;       --+------------ +5v
;     |                  |  |
;    +--- | -----------------|\[\]|----+
;    |    |Vdd ---v---       |  |    |
;    |    +---|1   Gnd|      piezo   |
;    |        |       |              |
;    |  +-----|GP5 GP0|              |
;    |  |     |       |              |
;    +--------|GP4 GP1|              |
;       |     |       |              |
;       |     |GP3 GP2|--------------+
;       |      -------
;       o     PIC12F629
;  Sw    /
;       /
;      |
;     -+------------- 0v

    list    p=12F629
    radix   dec
    include "p12f629.inc"

    errorlevel  -302    ; Don't complain about BANK 1 Registers

    __CONFIG    _MCLRE_OFF & _CP_OFF
                     & _WDT_OFF & _INTRC_OSC_NOCLKOUT  ;Internal osc.


;========================
;
;    Equates
;
;========================

note      equ   21h ;value of HIGH and LOW for note
gap     equ 22h ;gap between notes - uses delay "gap_1"
loops     equ   23h ;loops of HIGH/LOW for 250mS or other duration
temp1     equ   24h ;temp file for note
melody  equ 25h ;counter for melody for switch
D1      equ 26h ;used in 250mS delay
D2      equ 27h ;used in 250mS delay

gapDel  equ 29h ;used in gap delay
tempA     equ   2Ah ;used in gap delay


;****************************************************************
;Beginning of program
;****************************************************************
          org       0x00
SetUp   bsf     status, rp0     ;Bank 1
      movlw b'00101011'     ;Set TRIS
      movwf TRISIO        ;GP2,4 outputs    GP5 input
      bcf       option_reg,7    ;pull-ups enabled
      bcf       status, rp0     ;bank 0
      movlw 07h           ;turn off Comparator
      movwf CMCON         ;must be placed in bank 0
      clrf  melody          ;jump value for melody table
      btfsc gpio,5
      goto  readEEPROM    ;read EEPROM at start-up
      movlw 00            ;If switch pressed at turn-on; clear EEPROM
      call  write
      goto  SetUp

;********************
;* Delays       *
;********************


    ;gap_1 produces the gap between notes each unit is 1mS

gap1    movlw     .30
      movwf   gapDel
      nop
      decfsz    tempA,1
      goto    $-2
      decfsz    gapDel,1 ;produces loops
      goto    $-4
      retlw   00

    ;extra pause between notes

pause   movlw     .60
      movwf   D2
      nop
      decfsz    D1,1
      goto    $-2
      decfsz    D2,1
      goto    $-4
      retlw   00


    ;250mS second delay

_250mS  nop
        goto      $+1
        decfsz  D1,1
        goto      _250mS
        decfsz  D2,1
        goto      _250mS
        retlw   00

_1Sec     call    _250mS
          call    _250mS
_500mS  call      _250mS
        call      _250mS
        retlw   00


;************************
;* Subroutines      *
;************************

    ;produces note length

length1 movwf     temp1     ;put note length HIGH into "temp1"
        movwf     loops     ;create number of loops to produce .25sec
        comf      loops,f     ;complement note value to get loops value
        clrc                ;clear carry before shifting
        rrf     loops,f   ;halve the value of loops
        clrc
        rrf     loops,w   ;halve the value of loops again and put into w
        addwf     loops,w   ;to get 0.75 of original
len1_a  movf      temp1,w
        movwf     note
        bsf     gpio,2
        bcf     gpio,4
        goto      $+1
        goto      $+1
        goto      $+1
        nop
        decfsz  note,1
        goto      $-5
        movf      temp1,w
        movwf     note
        bcf     gpio,2
        bsf     gpio,4
        goto      $+1
        btfss     gpio,5
        goto      switch
        goto      $+1
        nop
        decfsz  note,1
        goto      $-6
        decfsz  loops,f
        goto      len1_a
        call      gap1      ;gap between notes
        retlw     00

    ;produces note length



length2 movwf   temp1         ;put note length HIGH into "temp1"
        movwf   loops         ;create number of loops to produce .25sec
        comf    loops,f     ;complement note value to get loops value
        goto    len1_a



    ;produces note length

lengthX movwf   temp1         ;put note length HIGH into "temp1"
        movlw   60h
        movwf   loops         ;
        goto    len1_a

    ;produces long note length  for Happy Birthday


length2X
        movwf   temp1         ;put note length HIGH into "temp1"
        movlw   0FFh
        movwf   loops         ;
        goto    len1_a

    ;read melody number from EEPROM at turn-on

readEEPROM
        bsf   status,rp0
        clrf    EEADR           ;to read first location in EEPROM !!!
        bsf   EECON1,0    ;start EEPROM read operation - result in EEDATA
        movf    EEDATA,w      ;move read data into w
        bcf   status,rp0
        movwf   melody      ;jump value for melody table
        movlw   00
        xorwf   melody,w
        btfss   status,z
        goto    sw_M
        goto    Main


switch  call    _500mS
        incf    melody,f
        incf    melody,f      ;jump 2 bytes at a time on table
        movf    melody,w
        call    write           ;store melody value in EEPROM
sw_M      movf  melody,w
        addwf   02,1            ;Add W to the Program Counter for jump
        call    M1
        goto    $-1
        call    M2
        goto    $-1
        call    M3
        goto    $-1
        call    M4
        goto    $-1
        call    M5
        goto    $-1
        call    M6
        goto    $-1
        call    M7
        goto    $-1
        call    M8
        goto    $-1
        call    M9
        goto    $-1
        call    M10
        goto    $-1
        call    M11
        goto    $-1
        nop
        btfss   gpio,5
        goto    $-1
        call    _250mS
        clrf    melody
        goto    Main

write     bsf     status,rp0    ;select bank1
        clrf    eeadr           ;to load into first location
        movwf   eedata        ;w will have melody value
        bsf   eecon1,wren   ;enable write
        movlw   55h             ;unlock codes
        movwf   eecon2
        movlw   0aah
        movwf   eecon2
        bsf   eecon1,wr   ;write begins
        bcf   status,rp0    ;select bank0
writeA  btfss   pir1,eeif     ;wait for write to complete
        goto    writeA
        bcf   pir1,eeif
        bsf   status,rp0    ;select bank1
        bcf   eecon1,wren   ;disable other writes
        bcf   status,rp0    ;select bank0
        retlw   00


;************************
;*Melodies      *
;************************

    ;It's A Small World

M1  movlw   .151        ;It's
    call    length1
    movlw   .142        ;a
    call    length1
    movlw   .128        ;world
    call    length2
    movlw   .75       ;of
    call    length2
    movlw   .95       ;laugh-
    call    length2
    movlw   .84       ;-ter
    call    length1
    movlw   .95       ;a
    call    length1
    movlw   .95     ;world
    call    length2
    movlw   .102        ;of
    call    length2
    movlw   .102        ;tears
    call    length2
    movlw   .172        ;It's
    call    length1
    movlw   .151        ;a
    call    length1
    movlw   .142        ;world
    call    length2
    movlw   .84       ;of
    call    length2
    movlw   .102        ;hopes
    call    length2
    movlw   .95       ;and
    call    length1
    movlw   .102        ;a
    call    length1
    movlw   .113        ;world
    call    length2
    movlw   .128        ;of
    call    length2
    movlw   .128        ;fears
    call    length2
    movlw   .151        ;There's
    call    length1
    movlw   .142        ;so
    call    length1
    movlw   .128        ;much
    call    length2
    movlw   .95       ;that
    call    length1
    movlw   .84       ;we
    call    length1
    movlw   .75       ;share
    call    length2
    movlw   .84       ;that
    call    length1
    movlw   .95       ;it's
    call    length1
    movlw   .113        ;time
    call    length2
    movlw   .84       ;we're
    call    length1
    movlw   .75       ;a
    call    length1
    movlw   .71       ;ware
    call    length2
    call    pause
    movlw   .75       ;It's
    call    length1
    movlw   .102        ;a
    call    length1
    movlw   .113        ;small
    call    length2
    movlw   .71       ;world
    call    length2
    movlw   .75       ;aft-
    call    length2
    movlw   .84       ;-ter
    call    length1
    movlw   .95       ;all
    call    length2
    call    _250mS
    movlw   .95       ;It's
    call    length2
    movlw   .95       ;a
    call    length1
    movlw   .75       ;small
    call    length2
    movlw   .95       ;world
    call    length2
    movlw   .84       ;aft-
    call    length2
    movlw   .84       ;-ter
    call    length1
    movlw   .84       ;all
    call    length2
    call    _250mS
    movlw   .84       ;It's
    call    length2
    movlw   .84       ;a
    call    length1
    movlw   .71       ;small
    call    length2
    movlw   .84       ;world
    call    length2
    movlw   .75       ;aft-
    call    length2
    movlw   .75       ;-ter
    call    length1
    movlw   .75       ;all
    call    length2
    call    _250mS
    movlw   .75       ;It's
    call    length2
    movlw   .75       ;a
    call    length1
    movlw   .64       ;small
    call    length2
    movlw   .71       ;world
    call    length2
    movlw   .71       ;aft-
    call    length2
    movlw   .71       ;-ter
    call    length1
    movlw   .71       ;all
    call    length2
    movlw   .75       ;It's
    call    length1
    movlw   .84       ;a
    call    length1
    movlw   .128        ;small
    call    length2
    movlw   .102        ;small
    call    length2
    movlw   .95       ;world
    call    length2
    call    _1Sec
    retlw   00



;************************
;*Main          *
;************************


Main    call    M1
      call  M1
      call  M2
      call  M2
      call  M3
      call  M3
      call  M4
      call  M4
      call  M5
      call  M5
      call  M6
      call  M6
      call  M7
      call  M7
      call  M8
      call  M8
      call  M9
      call  M9
      call  M10
      call  M10
      call  M11
      call  M11
      goto  SetUp


;************************************
;*EEPROM                    *
;************************************

    org     2100h

    de      00h,

    END

GOING FURTHER

This project provides you with the tools to create your own tune or download one of the “old favourites” and annoy everyone in the household with its incessant playing. The program-space is completely full so you will have to delete one of the melodies to create space for your new tune.


Tags

#elektor
Colin Mitchell

Colin Mitchell

Expertise

electronics
writing
PIC-Chips

Social Media

instagramtwitterwebsite

Related Posts

TODO
PIC Elmer 160
March 06, 2012
© 2021, All Rights Reserved.

Quick Links

Advertise with usAbout UsContact Us

Social Media