Drum Sequencer
For my final project I have created is an 8-step, 5-channel audio step sequencer. Basically, a physical drum machine. Each button represents one of eight steps in a sequencer. When pressed, that step is activated and a sound is played. Built in is a an 808 electronic drum kit, which includes a snare, a hi-hat, and a kick. There’s a blue knob to control the tempo (potentiometer). The sequence is represented visually on a strip of 8 LEDs, with each channel having the same color, white. There’s a button that flips through the channels to build up the drum beat as far as up to 5 channels.
Here’s a demo of how my sequencer works:
How Does it Work? :
My project is based around a Teensy 3.5 and code written in C++ language using the Arduino/ Teensyduino software. Everything going on happens inside the Teensy, the analog components are only telling the Teensy what to do. Here’s what’s a breakdown of each component of my project:
The LEDs: The visual representation of this sequencer is the LED strip. The 8 LEDs light up in time with the sequencer and if a step on the sequence is active and triggering a sound and the buttons toggle between those channels.
The Buttons: The 8 buttons correlate to each of the 8 steps in the sequencer. When a button is pressed, it activates its step in the sequence. When that step is landed on by the sequencer, it triggers a sound correlating to whichever sequencer channel it’s linked to, hi-hat, kick, etc. When the button is pressed again it shuts off the sound that was initially triggered. The channel switch button allows for whatever sounds were triggered on the first channel to remain playing, but then more sounds could be added on the following channel to build up the drum beat.
DAW: The DAW that you chose will allow for the notes called upon in your code to trigger the sounds that correlate to the code. I used Logic Pro X.
Code:
int buttonPin[8] = {32, 31, 30, 29, 28, 27, 26, 25};
int ledPin[8] = {2, 3, 4, 5, 6, 7, 8, 9};
bool lastButton1State[8] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW};
bool button1State[8] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW};
bool switchedOn[5][8] = {
{LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW},
{LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW},
{LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW},
{LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW},
{LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW},
};
int currentStep = 0;
unsigned long lastStepTime = 0;
int totalSteps = 8;
int tempo = 1000;
int tempoPot = A19;
int channelDisplayed = 0;
int channelLedPins[5] = {34, 35, 36, 37, 39};
int channelButtonPin = 33;
bool buttonState = LOW;
bool lastButtonState = LOW;
int midiNotes [5] = {36, 38, 40, 41, 43};
void setup() {
for (int i = 0; i < totalSteps; i++) {
pinMode(ledPin[i], OUTPUT);
}
for (int i = 0; i < 8; i++) {
pinMode(buttonPin[i], INPUT);
}
for (int i = 0; i < 5; i++) {
pinMode(channelLedPins[i], OUTPUT);
}
pinMode(channelButtonPin, INPUT);
}
void loop() {
checkButton();
checkButtons();
updateLeds();
updateChannelLeds();
stepForwards();
}
void checkButtons() {
for (int i = 0; i < 8; i++) {
lastButton1State[i] = button1State[i];
button1State[i] = digitalRead(buttonPin[i]);
if (lastButton1State[i] == LOW && button1State[i] == HIGH) {
switchedOn[channelDisplayed][i] = !switchedOn[channelDisplayed][i]; // this means: if switchedOn is true then set it to false, if switchedOn is false then set it to true
delay(5);
} else if (lastButton1State[i] == HIGH && button1State[i] == LOW) {
delay(5);
}
}
}
void updateLeds() {
for (int i = 0; i < 8; i++) {
if (switchedOn[channelDisplayed][i] == true or i == currentStep) {
digitalWrite(ledPin[i], HIGH);
} else {
digitalWrite(ledPin[i], LOW);
}
}
}
void stepForwards() {
tempo = analogRead(A19);
if (millis() > lastStepTime + tempo) {
lastStepTime = millis();
//usbMIDI.sendNoteOff(65, 0, 1);
for (int i = 0; i < 5; i++) {
usbMIDI.sendNoteOff(midiNotes[i], 0, 1);
}
//digitalWrite(ledPin[currentStep], LOW);
countUp();
//digitalWrite(ledPin[currentStep], HIGH);
for (int i = 0; i < 5; i++) {
if (switchedOn[i][currentStep] == HIGH) {
usbMIDI.sendNoteOn(midiNotes[i], 127, 1);
}
}
}
}
void countUp() {
currentStep++;
if (currentStep == totalSteps) {
currentStep = 0;
}
}
void checkButton() {
lastButtonState = buttonState;
buttonState = digitalRead(channelButtonPin);
if (lastButtonState == LOW and buttonState == HIGH) {
countUpCh();
delay(5);
} else if (lastButtonState == HIGH and buttonState == LOW) {
delay(5);
}
}
void countUpCh() {
channelDisplayed++;
if (channelDisplayed >= 5) {
channelDisplayed = 0;
}
}
void updateChannelLeds() {
for (int i = 0; i < 5; i++) {
if (i == channelDisplayed) {
digitalWrite(channelLedPins[i], HIGH);
} else {
digitalWrite(channelLedPins[i], LOW);
}
}
}