Final project.
Here lies thy documentation for the final project, the Jukebox.
- Ideation
- Midi file format
- Cad Design
- Molding and casting
- CNC milling
- 3D printing
- Laser cutting
- Pcb design
- Shift register board design
- Microcontroller board design
- Shift register board milling
- Microcontroller board milling
- Programming
- Rotory encoder programming
- LCD programming
- SD card programming
- Menu navigation
- Midi file processing
- Assembly triangle wave generator
- UART buffering
- ADSR envelope
- Shift register programming
- Servo timer interrupts
- Bootloader burn
- Source files
- Slide
- Video
- Testing
- Finished
Ideation
This project is inspired by self playing pianos.
Player piano from wikipedia:
A melodica is a small piano with fewer keys.
Melodica played using midi.
Midi file format
Midi timings
A midi event will have the change in time from the previous event and the event data.
Example midi data in hexadecimal.
Delta time is calculated from the tempo and time signature of the midi track.
SourceMidi commands
Midi event flow.
Midi message structure.
Midi commands and their hex codes. Only note on and note off commands will be processed. Other commands are ignored.
A midi command also includes the note and velocity. The velocity is ignored and only the note and channel is used.
SourceMidi notes
128 midi notes and their corresponding keys. Source
MIDI note number | Key number (Organ) | Key number (Piano) | Note names (English) | Note names (German) | Frequency (Equal tuning at 440 Hz) |
---|---|---|---|---|---|
top of MIDI tuning range | G#9/Ab9 | gis’’’’’’/ges’’’’’’ | 13289.75 | ||
127 | G9 | g’’’’’’ | 12543.85 | ||
126 | F#9/Gb9 | fis’’’’’’/ges’’’’’’ | 11839.82 | ||
125 | F9 | f’’’’’’ | 11175.30 | ||
124 | E9 | e’’’’’’ | 10548.08 | ||
123 | D#9/Eb9 | dis’’’’’’/es’’’’’’ | 9956.06 | ||
122 | D9 | d’’’’’’ | 9397.27 | ||
121 | C#9/Db9 | cis’’’’’’/des’’’’’’ | 8869.84 | ||
120 | C9 | c’’’’’’ | 8372.02 | ||
119 | B8 | h’’’’’ | 7902.13 | ||
118 | A#8/Bb8 | ais’’’’’/b’’’’’ | 7458.62 | ||
117 | A8 | a’’’’’ | 7040.00 | ||
116 | G#8/Ab8 | gis’’’’’/ges’’’’’ | 6644.88 | ||
115 | G8 | g’’’’’ | 6271.93 | ||
114 | F#8/Gb8 | fis’’’’’/ges’’’’’ | 5919.91 | ||
113 | F8 | f’’’’’ | 5587.65 | ||
112 | E8 | e’’’’’ | 5274.04 | ||
111 | D#8/Eb8 | dis’’’’’/es’’’’’ | 4978.03 | ||
110 | D8 | d’’’’’ | 4698.64 | ||
109 | C#8/Db8 | cis’’’’’/des’’’’’ | 4434.92 | ||
108 | 88 | C8 | c’’’’’ | 4186.01 | |
107 | 87 | B7 | h’’’’ | 3951.07 | |
106 | 86 | A#7/Bb7 | ais’’’’/b’’’’ | 3729.31 | |
105 | 85 | A7 | a’’’’ | 3520.00 | |
104 | 84 | G#7/Ab7 | gis’’’’/ges’’’’ | 3322.44 | |
103 | 83 | G7 | g’’’’ | 3135.96 | |
102 | 82 | F#7/Gb7 | fis’’’’/ges’’’’ | 2959.96 | |
101 | 81 | F7 | f’’’’ | 2793.83 | |
100 | 80 | E7 | e’’’’ | 2637.02 | |
99 | 79 | D#7/Eb7 | dis’’’’/es’’’’ | 2489.02 | |
98 | 78 | D7 | d’’’’ | 2349.32 | |
97 | 77 | C#7/Db7 | cis’’’’/des’’’’ | 2217.46 | |
96 | 61 | 76 | C7 | c’’’’ | 2093.00 |
95 | 60 | 75 | B6 | h’’’ | 1975.53 |
94 | 59 | 74 | A#6/Bb6 | ais’’’/b’’’ | 1864.66 |
93 | 58 | 73 | A6 | a’’’ | 1760.00 |
92 | 57 | 72 | G#6/Ab6 | gis’’’/as’’’ | 1661.22 |
91 | 56 | 71 | G6 | g’’’ | 1567.98 |
90 | 55 | 70 | F#6/Gb6 | fis’’’/ges’’’ | 1479.98 |
89 | 54 | 69 | F6 | f’’’ | 1396.91 |
88 | 53 | 68 | E6 | e’’’ | 1318.51 |
87 | 52 | 67 | D#6/Eb6 | dis’’’/es’’’ | 1244.51 |
86 | 51 | 66 | D6 | d’’’ | 1174.66 |
85 | 50 | 65 | C#6/Db6 | cis’’’/des’’’ | 1108.73 |
84 | 49 | 64 | C6 | c’’’ | 1046.50 |
83 | 48 | 63 | B5 | h’’ | 987.77 |
82 | 47 | 62 | A#5/Bb5 | ais’’/b’’ | 932.33 |
81 | 46 | 61 | A5 | a’’ | 880.00 |
80 | 45 | 60 | G#5/Ab5 | gis’’/as’’ | 830.61 |
79 | 44 | 59 | G5 | g’’ | 783.99 |
78 | 43 | 58 | F#5/Gb5 | fis’’/ges’’ | 739.99 |
77 | 42 | 57 | F5 | f’’ | 698.46 |
76 | 41 | 56 | E5 | e’’ | 659.26 |
75 | 40 | 55 | D#5/Eb5 | dis’’/es’’ | 622.25 |
74 | 39 | 54 | D5 | d’’ | 587.33 |
73 | 38 | 53 | C#5/Db5 | cis’’/des’’ | 554.37 |
72 | 37 | 52 | C5 | c’’ | 523.25 |
71 | 36 | 51 | B4 | h’ | 493.88 |
70 | 35 | 50 | A#4/Bb4 | ais’/b’ | 466.16 |
69 | 34 | 49 | A4 concert pitch | a’ Kammerton | 440.00 |
68 | 33 | 48 | G#4/Ab4 | gis’/as’ | 415.30 |
67 | 32 | 47 | G4 | g’ | 392.00 |
66 | 31 | 46 | F#4/Gb4 | fis’/ges’ | 369.99 |
65 | 30 | 45 | F4 | f’ | 349.23 |
64 | 29 | 44 | E4 | e’ | 329.63 |
63 | 28 | 43 | D#4/Eb4 | dis’/es’ | 311.13 |
62 | 27 | 42 | D4 | d’ | 293.66 |
61 | 26 | 41 | C#4/Db4 | cis’/des’ | 277.18 |
60 | 25 | 40 | C4 (middle C) | c’ (Schloss-C) | 261.63 |
59 | 24 | 39 | B3 | h | 246.94 |
58 | 23 | 38 | A#3/Bb3 | ais/b | 233.08 |
57 | 22 | 37 | A3 | a | 220.00 |
56 | 21 | 36 | G#3/Ab3 | gis/as | 207.65 |
55 | 20 | 35 | G3 | g | 196.00 |
54 | 19 | 34 | F#3/Gb3 | fis/ges | 185.00 |
53 | 18 | 33 | F3 | f | 174.61 |
52 | 17 | 32 | E3 | e | 164.81 |
51 | 16 | 31 | D#3/Eb3 | dis/es | 155.56 |
50 | 15 | 30 | D3 | d | 146.83 |
49 | 14 | 29 | C#3/Db3 | cis/des | 138.59 |
48 | 13 | 28 | C3 | c | 130.81 |
47 | 12 | 27 | B2 | H | 123.47 |
46 | 11 | 26 | A#2/Bb2 | Ais/B | 116.54 |
45 | 10 | 25 | A2 | A | 110.00 |
44 | 9 | 24 | G#2/Ab2 | Gis/As | 103.83 |
43 | 8 | 23 | G2 | G | 98.00 |
42 | 7 | 22 | F#2/Gb2 | Fis/Ges | 92.50 |
41 | 6 | 21 | F2 | F | 87.31 |
40 | 5 | 20 | E2 | E | 82.41 |
39 | 4 | 19 | D#2/Eb2 | Dis/Es | 77.78 |
38 | 3 | 18 | D2 | D | 73.42 |
37 | 2 | 17 | C#2/Db2 | Cis/Des | 69.30 |
36 | 1 | 16 | C2 | C | 65.41 |
35 | 15 | B1 | H1 | 61.74 | |
34 | 14 | A#1/Bb1 | Ais1/b1 | 58.27 | |
33 | 13 | A1 | A1 | 55.00 | |
32 | 12 | G#1/Ab1 | Gis1/As1 | 51.91 | |
31 | 11 | G1 | G1 | 49.00 | |
30 | 10 | F#1/Gb1 | Fis1/Ges1 | 46.25 | |
29 | 9 | F1 | F1 | 43.65 | |
28 | 8 | E1 | E1 | 41.20 | |
27 | 7 | D#1/Eb1 | Dis1/Es1 | 38.89 | |
26 | 6 | D1 | D1 | 36.71 | |
25 | 5 | C#1/Db1 | Cis1/Des1 | 34.65 | |
24 | 4 | C1 | C1 | 32.70 | |
23 | 3 | B0 | H2 | 30.87 | |
22 | 2 | A#0/Bb0 | Ais2/B2 | 29.14 | |
21 | 1 | A0 | A2 | 27.50 | |
20 | 25.96 | ||||
19 | 24.50 | ||||
18 | 23.12 | ||||
17 | 21.83 | ||||
16 | 20.60 | ||||
15 | 19.45 | ||||
14 | 18.35 | ||||
13 | 17.32 | ||||
12 | 16.35 | ||||
11 | 15.43 | ||||
10 | 14.57 | ||||
9 | 13.75 | ||||
8 | 12.98 | ||||
7 | 12.25 | ||||
6 | 11.56 | ||||
5 | 10.91 | ||||
4 | 10.30 | ||||
3 | 9.72 | ||||
2 | 9.18 | ||||
1 | 8.66 | ||||
0 | 8.18 |
Cad Design
Finished cad design.
Servos are mounted in front.
Servos line up with keys.
Slots constraint the linkages.
LCD, SD card and the rotary encoder will be here.
Back view. The hole on the right was originally intended for a sever fan to supply the air pressure to play the melodica. It was not powerfull enough.
Servos are mounted in foam to absorb vibrations.
Molding and casting
CNC milling
Milling has started.
Toolpath.
Pocketing has begun.
Finishing passes.
Milling is done.
Close up of finished mold.
CNC milling underway.
Molding
Silicone is poured in at an angle.
Silicone pour is done.
Foam is broken off.
Finished mold.
Casting
Polyurathane is poured into the mold.
There are some overflows and spills.
Once hard enough they can be cut off with a knife.
Heat makes the polyurathane cure faster.
The mold is bent to demold the parts.
Parts are pushed out of the mold.
Cast parts.
Some parts did not reach the bottom of the mold.
One batch was not mixed well. The polyurathane did not set even after a day.
Holes are drilled into the ends.
Finished part with hole.
CNC milling
First attempt milling.
Facing the back.
Milling is done.
The first attempt has an inconsistent height because of the second side facing. The second attempt only has operations on one side.
Second attempt at milling left side.
Right side milling.
3D printing
3D printing of standoffs.
3D printing is done.
Printing in progress.
Another 3d printed part, holddown clamps for the melodica.
Laser cutting
Pcb design
This section documents printed circuit board design in kicad and milling.
Shift register board design
Shift registers convert serial data to parrallel data. Up to 40 outputs(5 shift registers) can be driven using only 5 pins.
This is the Kicad schematic design.
PCB design in Kicad.
Front side PCB view.
Back side PCB view.
Front copper toolpath in Flatcam.
Back copper toolpath in Flatcam.
Microcontroller board design
This is the microcontroller schematic.
This is the PCB design in kicad.
PCB 3d view in kicad.
Toolpaths in Flatcam.
Shift register board milling
Milling has started for the shift register board.
The back copper is isolation milled.
Excess copper is being removed.
Front copper milling is started.
Milling continues...
Isolation milling is done.
The holes are milled.
Finished holes.
Finished front copper board.
Two finished sides of the PCB.
Shift registers are soldered on.
Pcb is populated.
Pin headers are solder on.
Back copper view.
Microcontroller board milling
Milling for the microcontoller board has started.
Toolpath of microcontroller board.
FR4 is used for this PCB. Water is used to prevent fiberglass dust from getting into the air and makes the cut smoother.
Dust generated is trapped in the water.
Video of PCB milling.
The PCB is milled, board outline and holes are cut.
Finishd PCB.
One part did not cut through.
This was fixed with a penknife.
Some copper was removed near the atmega chip.
Finished, wired microcontroller board.
Soldered microcontroller.
Programming
The LCD and rotary encoder ate wired up.
Rotory encoder programming
The rotary encoder used is a pulse rotary encoder. The clock pulse is polled by the microcontroller when needed. Turning the rotary encoder scrolls the selection menu and clicking the rotary encoder selects the midi track.
Program to read rotary encoder.
Endoder count printed on serial monitor.
LCD programming
The LCD used is a 20x4 LCD. It communicates with the m328 through a 4 bit parallel interface.
Modified example program.
LCD hello world.
SD card programming
FatFs is used to communicate with the SD card. Fatfs is used because it can use file names longer than 8.5 characters. Limiting the file name lengths to 8 chars and a file extension made long file names hard to read. The fat FS library is used to buffer the data from the SD card in 512 byte blocks.
Code to read SD card data.
Menu navigation
Code for menu navigation.
Menu displayed on LCD.
Menu navigation.
Midi file processing
MD_midi library is used to buffer the midi data read from the SD card. The midi used is standard midi file type 0. The type 0 midi file only has 1 track and all channel events are on that one track, making it easier to read the midi file as all the data is in a continuous ckunk. Md_midi also generates clock timings using timer 0. The clock timings is determined using the rate of the music. MD_midi generates the midi events at the right time and sends the midi data through UART at a baud rate of 19200 to the other two microcontrollers.
Code for midi callback.
Assembly triangle wave generator
The ask synth library is used. It generates a polyphonic tone using triangle waves. Timer 2 is used with a prescaller of 4 to generate a interrupt at 15.6 khz. The microcontroller is programmed for up to 16 tones. Ask synth uses assembly and is programmed for the atmega328p. A speaker is used to generate the notes that could not be played by the melodica. Midi supports 128 notes and all notes can be played by the speaker. A l289 motor driver is used to drive the speaker. A second microcontroller is used because there was not enough memory and the microcontroller would reset itself.
Test code.
Assembly source code.
Configurations needed to be set before compile.
Example waveform generated by asmsynth. Source:Sezam
Example sketch.
UART buffering
The standard uart buffer of 64 bytes is not enough because the program is not fast enough to read the buffer before it is full.
The standard uart buffer size is 64.
Recieve buffer size is increades to 256 and transmit is reduced to 16.
ADSR envelope
An adsr envelope is used to make the notes sound more realistic. The adsr envelope use timer 0 for the clock.
Shift register programming
The shift register is used as the atmega328 dose not have enough pins to control 37 servos at once. The shift register converte serial data to parrallel data.
digitalWriteFast is a macro that compiles into a single assembly instrucion.
Shift register test with LEDs.
Servo timer interrupts
The third microcontroller controls the servo motors. Timer 1 compare and overflow interrupts are used to generate a pulse for the servo motor. The melodica only cover notes 35 hex to 59 hex. There is a 5 A poly fuse to limit the current into the servos so that in case too many servos move at once, it would not draw too much current. This polyfuse has been accidentaly tested and verified to be working. A third microcontroller was used because the second microcontroller uses too many of it cycles inside that timer 2 interrupt vector. There are only 1024 cycles between timer 2 interrupts and it was not enough. The timer 2 interrupt took too many cycles and caused the servo timings generated by timer 1 to be inconsistent. The srevos draw the most current. A 12v 3 a wall adaptor is used to supply the power. It goes through a 5v 5a buck convertor that supplies the microcontrollers and servos.
Timer 1 interrupts are used to drive the servos.
Timer 1 setup.
Servo test.
Servo test 2.
Bootloader burn
A bootloader is needed to program the atmega328 chip using uart. The standard programming via ISP does not. Fuses need to be set for the external crystal.
The chip is first tested with AVRdude.
Minicore is used because the standard arduino core dosent include the atmega328 chip.
The fuses and bootloader are burnt.
Source files
All source files including test code.
Download.Slide
Project video
Full test
Testing
Volume | Midi Track | Test result |
---|---|---|
Minecraft Volume Alpha | Calm | Good |
Key | Good | |
Living Mice | Missed notes | |
Sweden | Stuck notes | |
Minecraft Volume Beta | Mall | Stuck notes |
Mellohi | Good | |
Wait | Good | |
Undertale | Home | Good |
Once Upon A Time | Good | |
Undertale | Stuck notes | |
Misc | Hello World | Stuck notes |
Eight Melodies | Good |
Minecraft Volume Alpha
Calm
Key
Living Mice
Sweden
Minecraft Volume Beta
Mall
Mellohi
Wait
Undertale
Home
Once Upon A Time
Undertale
Hello World
Eight melodies
Finished
Wires bundled and tied. Boards mounted with 3d printed mounts.
A foot pump is used to supply air pressure. Initially a server fan was used, but it was not powerful enough and was too loud.
Balloon to smooth out air pressure.
Servo pressing keys.
Its Done!
That's all folks!