Go Down

Topic: 8 step gate sequencer for modular synths (Read 1 time) previous topic - next topic

mkeep

Sep 30, 2007, 07:28 pm Last Edit: Oct 01, 2007, 06:53 am by mkeep Reason: 1
This is a simple 8 step gate sequencer with controls for clock speed, gate time and swing.  It was pieced together out of various tutorials like the pushbutton, reading an analog pot, and the 595 shift register so look to those pages for more detailed build info.  The switches are read from the built in digital pins and the leds are driven by the shift register.  

I was originally planning to expand this to 16 steps and add some kind of reverse and pendulum functions but then I didn't touch the Arduino for 6 months and I forgot all about this project.  So now I decided to post it as-is.  There's currently a bug where the steps will clear themselves if you crank the clock speed up too fast but I haven't been able to fix that yet.

But it works just fine as-is for feeding gate sequences into my Doepfer modular so maybe it will be useful for somebody else too.  I didn't have any 1/8" sockets so I just alligator clipped the tip and sleeve of a cable to the gate out and ground.



Code: [Select]
int y;
int j = 0;

// pins for the demux
int latchPin = 10;
int clockPin = 12;
int dataPin = 11;
int clockPotPin = 2;
int gatePotPin = 1;
int swingPotPin = 3;
int gateOutPin = 13;

// if the step is turned on we blink it off briefly to indicate the current step
int lastblink = 0;
int blinkstat = 0;
int blinkInt = 50;

// arrays for the toggle switches
byte inPin[8];
byte state[8];
byte previous[8];
int reading;

// for debouncing the switch
long time = 0;
long debounce = 200;

// clock
long previousMillis = 0;
long clockspeed = 1000;

// for swing
long stepLength;
long evenStep;
long oddStep;

// gate time as a percentage
int gatePercent = 50;
int gateTime;

// swing
int swingPercent = 0;
int swingTime;

// initial state
byte data = 0;

void setup() {
 state[0] = HIGH;
 state[1] = HIGH;
 state[2] = HIGH;
 state[3] = HIGH;
 state[4] = HIGH;
 state[5] = HIGH;
 state[6] = HIGH;
 state[7] = HIGH;
 previous[0] = LOW;
 previous[1] = LOW;
 previous[2] = LOW;
 previous[3] = LOW;
 previous[4] = LOW;
 previous[5] = LOW;
 previous[6] = LOW;
 previous[7] = LOW;
 inPin[0] = 2;
 inPin[1] = 3;
 inPin[2] = 4;
 inPin[3] = 5;
 inPin[4] = 6;
 inPin[5] = 7;
 inPin[6] = 8;
 inPin[7] = 9;
 pinMode(latchPin, OUTPUT);
 pinMode(gateOutPin, OUTPUT);
 pinMode(inPin[0], INPUT);
 pinMode(inPin[1], INPUT);
 pinMode(inPin[2], INPUT);
 pinMode(inPin[3], INPUT);
 pinMode(inPin[4], INPUT);
 pinMode(inPin[5], INPUT);
 pinMode(inPin[6], INPUT);
 pinMode(inPin[7], INPUT);
 Serial.begin(9600);
}


void loop() {

 // check the pushbuttons
 for (int i = 0; i < 8; i++) {
   reading = digitalRead(inPin[i]);
   if (reading == HIGH && previous[i] == LOW && millis() - time > debounce) {
     if (state[i] == HIGH){
       state[i] = LOW;
     }
     else{
       state[i] = HIGH;
       time = millis();    
     }
     data ^= (1 << i);
   }
   previous[i] = reading;
 }

 // check the clock speed
 clockspeed = analogRead(clockPotPin)+51;

 // check the swing pot & calculate swing time
 swingPercent = analogRead(swingPotPin)/20;
 swingTime = clockspeed*(swingPercent+50)/400;

 // if it's an even numbered step
 if (j%2 == 0){
   stepLength = swingTime*2;
 }  
 else {
   stepLength = clockspeed-(swingTime*2);

 }


 // check the gate pot & calculate gate time
 gatePercent = analogRead(gatePotPin)/10;
 gateTime = clockspeed*gatePercent/100;



 // if the blink interval has finished
 if (millis() - previousMillis > blinkInt) {
   // and if this step is turned on
   if (blinkstat == 1){
     // toggle the light off
     data ^= (1 << lastblink);
     digitalWrite(latchPin, 0);
     shiftOut(dataPin, clockPin, data);  
     digitalWrite(latchPin, 1);
     blinkstat = 0;
   }
 }

 // if the gate time is over
 if (millis() - previousMillis > gateTime) {
   // set the gate output to low
   digitalWrite(gateOutPin, 0);
 }

 // if the step is over
 if (millis() - previousMillis > stepLength) {
   //  reset the timer
   previousMillis = millis();
   // if we're at step 8, go back to 1
   if (j == 8) {
     j = 0;
   }
   // toggle the light for this step
   y = (data >> j) & 1;
   // if the step is turned on toggle the light off and set the blink status to 1
   if ( y == 1 ) {
     data ^= (1 << j);
     digitalWrite(latchPin, 0);
     shiftOut(dataPin, clockPin, data);  
     digitalWrite(latchPin, 1);
     lastblink = j;
     blinkstat = 1;
     // and set the gate output to high
     digitalWrite(gateOutPin, 1);
   }
   // if the step is turned off, toggle the light on until the next step
   else {      
     data ^= (1 << j);
     digitalWrite(latchPin, 0);
     shiftOut(dataPin, clockPin, data);  
     digitalWrite(latchPin, 1);
     data ^= (1 << j);
     blinkstat = 0;
     // and set the gate output to low
     digitalWrite(gateOutPin, 0);
   }
   j++;
 }
}

void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
 int i=0;
 int pinState;
 pinMode(myClockPin, OUTPUT);
 pinMode(myDataPin, OUTPUT);
 digitalWrite(myDataPin, 0);
 digitalWrite(myClockPin, 0);
 for (i=8; i>=0; i--)  {
   digitalWrite(myClockPin, 0);
   if ( myDataOut & (1<<i) ) {
     pinState= 1;
   }
   else {      
     pinState= 0;
   }
   digitalWrite(myDataPin, pinState);
   digitalWrite(myClockPin, 1);
   digitalWrite(myDataPin, 0);
 }
 digitalWrite(myClockPin, 0);
}

Go Up