Thanks for sending this in Mitch! Via Random Project Lab
This is part two (see part one) of a post on a custom-built Arduino-based synthesizer and keyboard called “Pentasynth”. Pentasynth uses a keyboard based on a five note pentatonic scale, so it’s easy to play for people with limited background in music (such as young kids) and encourages experimentation and improvisation. Pentasynth creates a user-selectable accompaniment including different drum patterns, bass lines and chord progressions and allows the user to play a pentatonic melody line over the top. Under the hood, Pentasynth runs on an Adafruit Metro Mini (using the same ATmega328 microcontroller as the Arduino Uno) and generates three channel audio (two square-wave tones and one pseudo-random noise drum beat), which is passed through and onboard amplifier and speaker, while simultaneously passing all outputs as MIDI messages via the USB for either a lo-fi or hi-fi audio experience. Pentasynth has controls for volume, tempo and selection of different accompaniment patterns. The keys and case components are 3D printed, with the main case panelling carved from clear acrylic using Carvey. Custom PCBs containing switches for detection of key presses were also carved on Carvey.
In the previous post, I discussed the hardware development of the keyboard including 3D printed keys and CNCed case and key switch PCBs, and the use of a wavetable synth for audio. I wasn’t that happy with the audio quality from the wavetable synth, so I re-wrote my own system using hardware PWM square-waves for audio, with a bit of re-jigging to add MIDI output. I’ll also discuss the electronics in a bit more details and the code running on the Arduino.
The ATmega328 has three hardware timers that can each be used to drive interrupt routines or run a hardware Pulse Width Modulation (PWM) signal. Since I wanted to keep the main program on the microcontroller free to managing key and control inputs and running an accompaniment system, the hardware timers were the only way to generate audio signals. By default, two of these timers (Timer 1 and 2) are unused, and the other (Timer 0) is set to run at 1kHz and controls functions such as millis() and delay(): any change in this frequency would mess with these. I’ve setup Timer 2 to run a square-wave output based on the note pressed on the keyboard and Timer 1 to run a square-wave from an accompaniment baseline. In order to get a pseudo random noise signal for a drum beat, I’ve piggy-backed an interrupt routine on the existing 1kHz to generate a pseudo random square-wave (i.e. randomly ordered series of LOW/HIGH) using a Galois linear feedback shift register (see this nifty little post). The random signal switched at 1kHz sounds a bit like a snare or open high-hat, so makes for a decent (lo-fi) beat.