HI everyone,
Any of you guys into making synths and noise making devices?
I'm working on a sequencer at the moment, it plays different modes and different keys.
its mostly bits of code from different examples I've cobbled together, its based on the tone melody example from the arduino ide. I hoped you guys might be able to help refine the code a bit,
its all working ok but could be better, there are 3 small issues
1 lots of the code is repeated so maybe it needs a function or two adding in.
2 the tempo control wanders a bit and it would be nice if it could be set to a specific bpm
3 the noTone is not actually silent you can hear some weird background static.
Anyway thought id ask to see if there are any obvious changes I could make before I solder it all together
Here is a video of it on action 8 step sequencer
really want to incorporate the mozzi library into it at some point but thats a long way off
Thanks!
Spoilerthe code//#include <Arduino.h>
#include "pitches.h"
#include <LedControl.h>
#define tempoPot A0
#include "ssd1306.h"
#include "nano_gfx.h"
#include "sova.h"
//#define modeSelector A1
/*
* speaker connected to pin 8
* matrix to arduino:-
* vcc to 5v
* gnd to ground
* din to d11
* cs to d10
* clk to d13
*/
// ERROR HERE IN PLATFORMIO BUT NOT IN ARDUINO IDE?
LedControl lc=LedControl(11,13,10,1); // see above notes for wiring,
//1 is how many matrix are connected
//the notes of C lydian, this will eventually be a 3d array containing all of the modes in all keys
const int notes[] = {
NOTE_B0,
NOTE_C1,
NOTE_CS1,
NOTE_D1,
NOTE_DS1,
NOTE_E1,
NOTE_F1,
NOTE_FS1,
NOTE_G1,
NOTE_GS1,
NOTE_A1,
NOTE_AS1,
NOTE_B1,
NOTE_C2,
NOTE_CS2,
NOTE_D2,
NOTE_DS2,
NOTE_E2,
NOTE_F2,
NOTE_FS2,
NOTE_G2,
NOTE_GS2,
NOTE_A2,
NOTE_AS2,
NOTE_B2,
NOTE_C3,
NOTE_CS3,
NOTE_D3,
NOTE_DS3,
NOTE_E3,
NOTE_F3,
NOTE_FS3,
NOTE_G3,
NOTE_GS3,
NOTE_A3,
NOTE_AS3,
NOTE_B3,
NOTE_C4,
NOTE_CS4,
NOTE_D4,
NOTE_DS4,
NOTE_E4,
NOTE_F4,
NOTE_FS4,
NOTE_G4,
NOTE_GS4,
NOTE_A4,
NOTE_AS4,
NOTE_B4,
NOTE_C5,
NOTE_CS5,
NOTE_D5,
NOTE_DS5,
NOTE_E5,
NOTE_F5,
NOTE_FS5,
NOTE_G5,
NOTE_GS5,
NOTE_A5,
NOTE_AS5,
NOTE_B5,
NOTE_C6,
NOTE_CS6,
NOTE_D6,
NOTE_DS6,
NOTE_E6,
NOTE_F6,
NOTE_FS6,
NOTE_G6,
NOTE_GS6,
NOTE_A6,
NOTE_AS6,
NOTE_B6,
NOTE_C7,
NOTE_CS7,
NOTE_D7,
NOTE_DS7,
NOTE_E7,
NOTE_F7,
NOTE_FS7,
NOTE_G7,
NOTE_GS7,
NOTE_A7,
NOTE_AS7,
NOTE_B7,
NOTE_C8,
NOTE_CS8,
NOTE_D8,
NOTE_DS8
};
const int modeTemplate [7][9]{
{0, 2, 4, 5, 7, 9, 11, 12, noTone}, //Ionian w, w, h, w, w, w, h
{0, 2, 3, 5, 7, 9, 10, 12, noTone}, //Dorian
{0, 1, 3, 5, 7, 8, 10, 12, noTone}, //Phrygian
{0, 2, 4, 6, 7, 9, 11, 12, noTone}, // Lydian
{0, 2, 4, 5, 7, 9, 10, 12, noTone}, // Mixolydian
{0, 2, 3, 5, 7, 8, 10, 12, noTone}, // Aeolian
{0, 1, 3, 5, 6, 8, 10, 12, noTone}, //Locrian
};
int rest; // rest inbetween notes, acting as tempo control in this case
//holds the data to set the tempo
int tempoVal;
// to hold the mode state
int mode = 0;
//holds the key state (starting note aka root note)
int key = 37;
//hold the number of steps or beats
int beat = 8;
//debounce time
int debounce = 1;
// variable to hold the button states
int b1s = 0;
int b2s = 0;
int b3s = 0;
int b4s = 0;
int b5s = 0;
int b6s = 0;
int b7s = 0;
int b8s = 0;
// assigning buttons to pins
// buttons connected from pin to ground with 10k pulldown resistor
const int b1 = 2;
const int b2 = 3;
const int b3 = 4;
const int b4 = 5;
const int b5 = 6;
const int b6 = 7;
const int b7 = 8;
const int b8 = 9;
// button to select modes, keys and beats
const int keyPin = A1;
const int modePin = A2;
const int beatPin = A3;
//setting up the speaker
const int speaker = 12;
void setup() {
/*
The MAX72XX is in power-saving mode on startup,
we have to do a wakeup call
*/
lc.shutdown(0,false);
/* Set the brightness to a medium values */
lc.setIntensity(0,8);
/* and clear the display */
lc.clearDisplay(0);
// buttons to change the notes
pinMode(b1, INPUT);
pinMode(b2, INPUT);
pinMode(b3, INPUT);
pinMode(b4, INPUT);
pinMode(b5, INPUT);
pinMode(b6, INPUT);
pinMode(b7, INPUT);
pinMode(b8, INPUT);
// button to change the modes
pinMode(modePin, INPUT);
pinMode(keyPin, INPUT);
pinMode(beatPin, INPUT);
//oled stuff
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_128x64_i2c_init();
// ssd1306_128x64_spi_init(-1, 0, 1); // Use this line for nano pi (RST not used, 0=CE, gpio1=D/C)
// ssd1306_128x64_spi_init(3,4,5); // Use this line for Atmega328p (3=RST, 4=CE, 5=D/C)
// ssd1306_128x64_spi_init(24, 0, 23); // Use this line for Raspberry (gpio24=RST, 0=CE, gpio23=D/C)
// ssd1306_128x64_spi_init(22, 5, 21); // Use this line for ESP32 (VSPI) (gpio22=RST, gpio5=CE for VSPI, gpio21=D/C)
// composite_video_128x64_mono_init(); // Use this line for ESP32 with Composite video support
ssd1306_clearScreen();
}
void loop() {
Serial.begin(9600);
// the tempo section
tempoVal = analogRead(tempoPot);
tempoVal = map(tempoVal, 1, 1024, 1, 255);
rest = tempoVal*2;
//Serial.println(tempoVal);
// the amount of beats
for (int x = 0; x < beat; x++){
//checking for mode button press
int modeSelector = digitalRead(modePin);
int keySelector = digitalRead(keyPin);
int beatSelector = digitalRead(beatPin);
//selecting the mode
if (modeSelector == 1){
delay(debounce);
mode++;
if (mode > 6){
mode = 0;
}
}
//selecting the key
if (keySelector == 1){
delay(debounce);
key++;
if (key > 89){
key = 0;
}
}
//selecting the number of steps (beats)
if (beatSelector == 1){
delay(debounce);
beat--;
if (beat < 1){
beat = 8;
}
}
// display the key
switch (key % 12){
case 0:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "B ", STYLE_NORMAL);
break;
case 1:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "C ", STYLE_NORMAL);
break;
case 2:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "C# ", STYLE_NORMAL);
break;
case 3:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "D ", STYLE_NORMAL);
break;
case 4:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "D# ", STYLE_NORMAL);
break;
case 5:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "E ", STYLE_NORMAL);
break;
case 6:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "F ", STYLE_NORMAL);
break;
case 7:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "F# ", STYLE_NORMAL);
break;
case 8:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "G ", STYLE_NORMAL);
break;
case 9:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "G# ", STYLE_NORMAL);
break;
case 10:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "A ", STYLE_NORMAL);
break;
case 11:
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 32, "A# ", STYLE_NORMAL);
break;
}
//reading the mode select button and displaying it on the screen
switch(mode) {
case 0:
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 16, "Ionian ", STYLE_NORMAL);
break;
case 1:
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 16, "Dorian ", STYLE_NORMAL);
break;
case 2:
// ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 16, "Phrygian ", STYLE_NORMAL);
break;
case 3:
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 16, "Lydian ", STYLE_NORMAL);
break;
case 4:
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 16, "Mixolydian ", STYLE_NORMAL);
break;
case 5:
// ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 16, "Aeolian ", STYLE_NORMAL);
break;
default:
// ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 16, "Locrian ", STYLE_NORMAL);
}
Serial.print(mode);
//updating the button counters when the buttons are pressed
//these variables hold the note info
//each time a button is pressed bxst goes up by 1
//this corresponds to the note array position
int b1st = digitalRead(b1);
int b2st = digitalRead(b2);
int b3st = digitalRead(b3);
int b4st = digitalRead(b4);
int b5st = digitalRead(b5);
int b6st = digitalRead(b6);
int b7st = digitalRead(b7);
int b8st = digitalRead(b8);
//this section calculates the notes of each beat
//if a button press is sensed then it increments the note by one
if (b1st == 1){
delay(debounce);
b1s++;
if (b1s == 9){ // if it goes past the end of the array, go back to the start
b1s = 0;
}
}
if (b2st == 1){
delay(debounce);
b2s++;
if (b2s == 9){
b2s = 0;
}
}
if (b3st == 1){
delay(debounce);
b3s++;
if (b3s == 9){
b3s = 0;
}
}
if (b4st == 1){
delay(debounce);
b4s++;
if (b4s == 9){
b4s = 0;
}
}
if (b5st == 1){
delay(debounce);
b5s++;
if (b5s == 9){
b5s = 0;
}
}
if (b6st == 1){
delay(debounce);
b6s++;
if (b6s == 9){
b6s = 0;
}
}
if (b7st == 1){
delay(debounce);
b7s++;
if (b7s == 9){
b7s = 0;
}
}
if (b8st == 1){
delay(debounce);
b8s++;
if (b8s == 9){
b8s = 0;
}
}
//this section turns on the correct led on the matrix and plays the tone
//left to right shows the beats
//bottom to top shows which note is selected from the notes array
//ssd1306_clearScreen();
if (x == 0){
lc.setLed(0,0,b1s, true); //sets the correct led on the 8*8 matrix
int thisKey1 = key + modeTemplate[mode][b1s];
int thisNote1 = notes[thisKey1];
if (b1s == 8){
thisNote1 = 99999999;
}
tone(speaker, thisNote1);
// Serial.print(thisMode1);
// Serial.print(thisKey1);
Serial.print(thisNote1);
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 0, "Step 1", STYLE_NORMAL);
delay(rest);
lc.setLed(0,0,b1s ,false);
}
else if (x == 1){
lc.setLed(0,1,b2s,true);
int thisKey2 = key + modeTemplate[mode][b2s];
int thisNote2 = notes[thisKey2];
if (b2s == 8){
thisNote2 = 99999999;
}
tone(speaker, thisNote2);
Serial.println(key);
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 0, "Step 2", STYLE_NORMAL);
delay(rest);
lc.setLed(0,1,b2s,false);
}
else if (x == 2){
lc.setLed(0,2,b3s,true);
int thisKey3 = key + modeTemplate[mode][b3s];
int thisNote3 = notes[thisKey3];
if (b3s == 8){
thisNote3 = 99999999;
}
tone(speaker, thisNote3);
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 0, "Step 3", STYLE_NORMAL);
delay(rest);
lc.setLed(0,2,b3s,false);
}
else if (x == 3){
lc.setLed(0,3,b4s,true);
int thisKey4 = key + modeTemplate[mode][b4s];
int thisNote4 = notes[thisKey4];
if (b4s == 8){
thisNote4 = 99999999;
} tone(speaker, thisNote4);
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 0, "Step 4", STYLE_NORMAL);
delay(rest);
lc.setLed(0,3,b4s,false);
}
else if (x == 4){
lc.setLed(0,4,b5s,true);
int thisKey5 = key + modeTemplate[mode][b5s];
int thisNote5 = notes[thisKey5];
if (b5s == 8){
thisNote5 = 99999999;
}
tone(speaker, thisNote5);
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 0, "Step 5", STYLE_NORMAL);
delay(rest);
lc.setLed(0,4,b5s,false);
}
else if (x == 5){
lc.setLed(0,5,b6s,true);
int thisKey6 = key + modeTemplate[mode][b6s];
int thisNote6 = notes[thisKey6];
if (b6s == 8){
thisNote6 = 99999999;
}
tone(speaker, thisNote6);
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 0, "Step 6", STYLE_NORMAL);
delay(rest);
lc.setLed(0,5,b6s,false);
}
else if (x == 6){
lc.setLed(0,6,b7s,true);
int thisKey7 = key + modeTemplate[mode][b7s];
int thisNote7 = notes[thisKey7];
if (b7s == 8){
thisNote7 = 99999999;
}
tone(speaker, thisNote7);
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 0, "Step 7", STYLE_NORMAL);
delay(rest);
lc.setLed(0,6,b7s,false);
}
else {
lc.setLed(0,7,b8s,true);
int thisKey8 = key + modeTemplate[mode][b8s];
int thisNote8 = notes[thisKey8];
if (b8s == 8){
thisNote8 = 99999999;
}
tone(speaker, thisNote8);
//ssd1306_clearScreen();
ssd1306_setFixedFont(ssd1306xled_font8x16);
ssd1306_printFixed(0, 0, "Step 8", STYLE_NORMAL);
delay(rest);
lc.setLed(0,7,b8s,false);
}
}
}
A better video of it, the original one was the wrong orientation sorry!
couldn't figure out how to edit my previous post