Line 6 DL4 Dotted Eighth Tap Tempo Mod
Hey guys,
So almost a year ago now, my brother Brian and I decided to make a dotted eighth tap tempo feature available on a Line 6 DL4 that I use on my guitar rig. We used an Arduino platform to prototype the project. I have been successfully using the mod for about 8 months now. Check out these videos for more info:
Here’s the full source code for a standard Arduino or a standalone ATMega328 chip:
[EDIT]
I noticed there was a bug in the original code I posted. I went through and parsed a lot of stuff down in my original source code but I apparently made some errors. This code is the original source code and it is fully functional! 🙂
/* DL4 Dotted Eighth Tap Tempo Written By: Joe Schoolcraft Brian Schoolcraft Written for Brian Wampler of Wampler Pedals Hardware Details: Pin 10 : Tempo Out Signal - connected to base of NPN Pin 13 : Momentary switch to ground */ //Pin Definition #define TEMPO_OUT 10 #define TEMPO_BUTTON 13 //Constant inputs #define DEBOUNCE_DELAY 40 // length of debounce "wait period" #define HOLD_DELAY 750 #define RESET_TIME 2002 // Time it takes for the current timer and tap count to reset if only one tap is put in #define PULSES 4 #define OUTPUT_TIME 40 // Variables that will change byte outputCount = 0; byte tapCount = 0; byte intervalCount = 0; byte reading = HIGH; // temporary button state storage (used in debounce routine) byte tapState = HIGH; // current tap button state byte lastTapState = HIGH; // the last tap button state byte lastButtonState = LOW; // the previous reading from the input pin byte pulseCount = 4; // Number of pulses sent to pedal byte divisor; int alpha; int currentTimer[3]; // array of most recent tap counts int bpm; float tempoScale = 0.75; // Tempo scale factor (dotted eighth, etc) float interval; unsigned long timeoutTime = 0; // this is when the timer will trigger next unsigned long indicatorTimeout; // sets the turn off time for the LED unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long lastTap; // when the last tap happened void setup() { pinMode( TEMPO_BUTTON, INPUT ); // tap button - press it to set the tempo pinMode( TEMPO_OUT, OUTPUT ); // Tempo output to pedal // Serial.begin(115200); } void loop() { reading = digitalRead(TEMPO_BUTTON); tapState = debounce(reading, lastButtonState, &lastDebounceTime, DEBOUNCE_DELAY, HOLD_DELAY); lastButtonState = reading; // save the state for comparison on the next loop // read the state of the switch into a local variable: if( tapState == LOW && tapState != lastTapState ) { // button just changed from HIGH to LOW if (tapCount != 0) { // We've already recorded a tap in this set tapCount++; for(int n = 2; n > 0; n--){ currentTimer[n] = currentTimer[n-1]; } currentTimer[0] = millis() - lastTap; // calculate the tap interval lastTap = millis(); // Store the tap time for the next loop pulseCount = 0; // reset pulse count to zero outputCount = 0; // reset pulse count to zero intervalCount = tapCount - 1; alpha = currentTimer[0] + currentTimer[1] + currentTimer[2]; divisor = constrain(intervalCount,0,3); interval = alpha/divisor; bpm = 1/(interval/60000); interval = (60000/bpm) * tempoScale; } else { // We haven't seen a tap since the last output to the pedal lastTap = millis(); // Store the tap time for the next loop tapCount++; } } lastTapState = tapState; // keep track of the state for the next loop // check for timer timeout if (millis() >= timeoutTime && pulseCount < PULSES) // it's time to send the output pulse { pulseCount++; // keep track of how many pulses we've sent outputCount++; indicatorTimeout = millis() + OUTPUT_TIME; // set the time for the output to turn back off timeoutTime = millis() + (interval); // set the time for the next output pulse // clear all the taps we've recorded } // display the button state on LED 2 // send the output pulse to the LED and the transistor if( millis() < indicatorTimeout ) { digitalWrite(TEMPO_OUT, HIGH ); } else { digitalWrite(TEMPO_OUT, LOW ); } if (outputCount > PULSES-1 && currentTimer[0] != 0 | millis() - lastTap > RESET_TIME){ clearTaps(); } // Serial.print(tapCount); // Serial.print('\t'); // Serial.print(bpm); // Serial.print('\t'); // Serial.print(interval); // Serial.print('\t'); // Serial.print(millis()); // Serial.print('\t'); // Serial.print(pulseCount); // Serial.print('\t'); // Serial.print(outputCount); // Serial.print('\t'); // Serial.print(currentTimer[1]); // Serial.print('\t'); // Serial.println(tempoScale); } //Clears the currentTimer array void clearTaps(){ for(int t = 0; t < 3; t++){ currentTimer[t] = 0; if(currentTimer[t + 1] == 0){ break; } } tapCount = 0; } //Debounces any footswitch byte debounce(byte _reading, byte _lastButtonState, unsigned long *_lastDebounceTime, int _holdDelay, byte dbounceTime) { byte state = HIGH; if (_reading != _lastButtonState) { // button state just changed *_lastDebounceTime = millis(); // reset the debouncing timer } if ((millis() - *_lastDebounceTime) >= _holdDelay && state == HIGH) { // whatever the reading is at, it's been there for longer // than the hold delay, so take it as the actual current state for use in the rest of the script state = _reading; } else{ state = HIGH; } if ((millis() - *_lastDebounceTime) >= dbounceTime && state == LOW){ state = _reading; clearTaps(); } return state; }
Troy 9:57 pm on September 21, 2013 Permalink |
awesome mod. Do you have diy kits yet? If not would you be willing to hook me up with a schematic or possibly just some more details on this?
jschoolie 10:19 pm on September 26, 2013 Permalink |
Thanks! I’m working on finalizing everything right now. I’m very close to having a kit put together. I finished revising the pcb layout/schematic for the mod last night. The revised version uses an ATtiny85 and everything fits on a 1×1 pcb that fastens to the original screw holes on the DL4. Sorry for things moving so slowly, I’m currently enrolled in engineering at Purdue which eats up most of my free time 😉
Troy 10:46 pm on September 26, 2013 Permalink |
No prob. Thanks a lot for posting the code. I was missing the transistor part of the circuit and it gave me fits, but I was finally able to figure it out with an arduino uno and a transistor. I’m just a civil engineer (EIT)… It takes us a little longer to catch on. I think you would have a huge market if you started offering this mod. Thanks again for posting your code!
jschoolie 11:36 pm on September 26, 2013 Permalink |
You’re Welcome! I’m glad you got it working. Lol, you haven’t seen me try to build a bridge! And thanks, I hope so!
Troy 9:34 pm on September 30, 2013 Permalink |
After playing with it for a few days I think i have noticed a weakness in the code at least as it functions for me. On slow songs sometimes I will depress the tap on the beat and let it back up on the and of the beat to help me tap in time. I find that subdividing the rhythm helps me lock it in better (I have been accused of not having rhythm). I’m not sure why this is happening but I’m thinking the HOLD_DELAY 750 is timing out and resetting the tapstate variable. Is there any reason in the way you coded it that the HOLD_DELAY can’t equal 2002 to match the RESET_TIME? Was the selection of 750 arbitrary or did you have a reason?
jschoolie 12:26 am on October 1, 2013 Permalink |
Ah, you’re running into the double preset part of the mod. On the full mod, I have an extra MOSFET switch hooked up that receives either 5V or ground from the arduino. When hooked up properly to the DL4 it will act like an expression pedal. Holding the switch down for 750ms (which is what appears to be happening on the slow songs) flip flops the 5V/ground output from digital pin 8 I think, and it does reset the tap counts thus messing up the tempo. That feature should be pretty easy to remove in the debounce function as it is only necessary if you want the double preset thing to work. I’ll take a look at it tomorrow or Wednesday and try and post a version without that feature in it and that should fix it! Sorry about that!
Troy 12:07 pm on October 1, 2013 Permalink |
Thanks. I appreciate it. I use the double preset wheel instead of the switch. Thanks again for posting the code. It has made my dl4 infinitely more useable.
jschoolie 11:12 am on October 3, 2013 Permalink |
No problem, I’m glad it’s helping you out!
Marius 9:35 am on October 3, 2013 Permalink |
Hello jschoolie, I’m interested in your mod on DL4. Can you send me the list of parts i need and some info so I can make one for mine?
jschoolie 11:14 am on October 3, 2013 Permalink |
Hey Marius, I’m actually fairly close to having a PDF with the instructions and parts list etc. put together and I will post it on here when I have it done in a few days.
Bobby Meeks 12:59 am on October 5, 2013 Permalink |
This is great… Have you heard of anyone trying this on the HD300/400 that sadly has no .8th feature? I may be your first Guinea pig…
jschoolie 6:01 pm on October 5, 2013 Permalink |
Thanks Bobby, and I haven’t heard of any one doing that but I’d be willing to give it a shot! There may be some modifications to the code/process in general but I’m sure it could be done.
Ulises 12:45 pm on February 1, 2014 Permalink |
Hey man!! I play in a worship group and i love the dl4 except for the part that there is no 1/8!! You’re video inspired me!!! I am 17 and i just bout the Arduino mega!! I spent so much money so i can copy that code into a micro-controller but i would like to know if u have finished your pdf file showing what kind of switch i need and what parts (resistors, capacitors,regulators) i need and where to put them in the pref-board! Please man!! God Bless You!
jschoolie 4:02 pm on February 6, 2014 Permalink |
Hey dude! Glad to hear you like the mod and I’m also glad to hear you are using your talents to serve the Lord. I’ll have the PDF done and posted within a couple of weeks. I’m waiting on parts to get in and get my directions tested out before I post anything official. Thanks for your interest!
Ulises 9:02 pm on February 21, 2014 Permalink |
Thank you soo much man!!! Please let me know asap when you get everything done!! I dont need a kit i just need a pdf with all the intructions and i can get the stuff my self! You will help me use my dl4 in a better way!! God bless man!!
jschoolie 8:41 pm on March 5, 2014 Permalink |
Hey dude, I just got everything up and running on our shiny new site: http://www.schoolcraftspecialties.com/SmartSwitch. It’ll have everything you need to get you going. The sites pretty new (i.e. we just learned how to write html a few weeks ago) so we are still working out a few kinks. If you see anything horrendous, please let me know lol 😉
jschoolie 1:21 am on March 7, 2014 Permalink |
Hey Everyone!
I’m to the point where I feel like I’m ready to sell this mod to a few brave beta testers! The kit will include all of the components required to do the mod (custom PCB, programmed microcontroller, footswitch, resistors, etc.). You’ll need to be able to solder and connect wires to the DL4 PCB, as well as assemble the Smart Switch PCB.
Check out our shiny new website for more details:
http://www.schoolcraftspecialties.com/SmartSwitch
Ulises 8:35 pm on March 22, 2014 Permalink |
Hey man! did u receive my email?
Austin 5:15 am on June 10, 2015 Permalink |
Very cool! I am very new to avr programming, but this project really caught my attention. How easy would it be to add to the code allowing you to choose between a few different tap multipliers that are controlled via spdt switch of some kind? like choosing between 1/4, dotted 1/8 and 1/8.