The idea below has been floating around, I know of some others who have done it but can't find their postings right now. I decided to post it so interested people can use it as they like.
It's a small double-sided PCB, that contains all the I/O that you normally use in a pedal. Input, output, power, switch, led.
It uses a bistable relay, like mictesters switching scheme, but then controlled by an Attiny85 (these are only $1.15 at Tayda). Furthermore it uses a momentary for switching, I like those cheap soft-switching momentaries. The PCB is small enough to fit on the head-end of a Hammond 125B, and you can space the output so that it will also look ok on the short end of a 1590BB. There are connections for a battery clip, which will be switched off if you use a powersupply. The input of the effect will be shorted when the effect is switched off.
Here are a few pics to get an idea of what it looks like:
Suitable for 1590BB: Mass-production: This is what it looks like in a 125B: Gut shot, enough room for pots to sit under the pcb: And now the projectfiles, first the eagle files: (rename to .brd, cannot attach .brd files!)
I had the pcb's made at iTeadstudio, using this zip-file: The code can be found at the bottom of this post, I programmed this with the Attiny85 core for Arduino which can be found here: http://highlowtech.org/?p=1695
The code supports the 'Primetime' feature, when you hold the switch for more than a predefined time (set at 1s for the moment) it will switch back to off when you release the switch. Idea stolen from TC Electronic
The led shows the entering of PrimeTime with a double-flash. Also, when you hold the switch at powerup, you can toggle the power-up state of the relay. The led will flash to confirm this. Just check the code, it's all in there. You need the Arduino EEPROM and Bounce libraries. Todo: low-power code, sleep/standby, pin-change interrupt to wake etc.
Have fun!
Pruttel.
Code: Select all
// Relay.ino
// true-bypass pedal switcher for guitar effects
// (c) 2014 Iwan Heskamp, but this is really basic so anybody could probably do it better!
#include <EEPROM.h>
#include <Bounce.h>
// for attiny25/45/85
#define SW 3 // pin 2
//#define SW_INT PCINT3 // interrupt name
#define RELAY1 4 // pins for AL5WN-K bistable (latching) relay
#define RELAY2 0
#define LED 2 // pin 7 on ATtiny 45/85
#define ON 1
#define OFF 0
#define DEBOUNCETIME 25
#define RELAYDELAY 15 // bi-stable relay, time for the coil to be energized
#define PRIMETIME 1000 // PrimeTime delay in milliseconds
#define DOUBLECLICK 500 // click twice in less than these ms to be registered as doubleclick
Bounce sw = Bounce(SW, DEBOUNCETIME); // initialize debouncer
int state = 0; // effect on or off?
int primetime = 0; // TC Electronics 'PrimeTime' mode
int address = 0; // EEPROM address of state value
unsigned long lastMillis=0;
unsigned long doubleMillis=0;
void effectOn() {
digitalWrite(LED, LOW); // turn LED on
digitalWrite(RELAY1, HIGH); // switch relay to on position
delay(RELAYDELAY); // wait a little bit
digitalWrite(RELAY1, LOW); // turn current through coil off
state = ON; // remember on state
}
void effectOff() {
digitalWrite(LED, HIGH); // turn LED off
digitalWrite(RELAY2, HIGH); // switch relay to off position
delay(RELAYDELAY); // wait a little bit
digitalWrite(RELAY2, LOW); // turn current through coil off
state = OFF; // remember off state
}
void setup() {
ADCSRA = 0; // turn ADC off
pinMode(SW, INPUT); // make switch input
digitalWrite(SW, HIGH); // internal pullup
digitalWrite(LED, HIGH); // led off
pinMode(LED, OUTPUT); // make led output
digitalWrite(RELAY1, LOW);
pinMode(RELAY1, OUTPUT); digitalWrite(RELAY1, LOW);
digitalWrite(RELAY2, LOW);
pinMode(RELAY2,OUTPUT); digitalWrite(RELAY2, LOW);
state = EEPROM.read(address); // get state from EEPROM
sw.update();
if(digitalRead(SW) == 0) { // button pushed at startup -> save 'on' state for next!
state &= 1; // to be sure it's written only 1 or 0. (chip can be initialized to random value!)
state ^= 1; // flip stored state
EEPROM.write(address, state); // write flipped state to EEPROM
digitalWrite(LED, HIGH); delay(300); // blink three times as confirmation
digitalWrite(LED, LOW); delay(300);
digitalWrite(LED, HIGH); delay(300);
digitalWrite(LED, LOW); delay(300);
digitalWrite(LED, HIGH);
}
if(state == OFF) { // state == 0 -> turn effect off, led off
effectOff();
} else { // state == 1 -> turn effect on, led on
effectOn();
}
// TODO: this would also be the time to switch some stuff off (UART, ADC, etc) (p.34?)
// more power can be saved by running the attiny on 128kHz! (p.28)
// TODO: interrupt on switch input?
unsigned long lastMillis = millis(); // store timestamp for PrimeTime function
}
void loop() {
if(sw.update()) {
if(sw.fallingEdge() == 1) { // switch is pressed (it's pulled-up, remember?)
if(state == 1) { // were we on, turn off
// remember: we cannot be on *and* in PrimeTime when the button is pressed!
effectOff(); // turn effect off, led off
} else { // we were off, turn on
effectOn();
lastMillis = millis(); // update timer for PrimeTime checks
}
// now check when the last time was that we were here
/* if(millis() - doubleMillis < DOUBLECLICK) { // SPECIAL SUPER DUPER MODE!
digitalWrite(LED, LOW); delay(100);
digitalWrite(LED, HIGH); delay(100);
digitalWrite(LED, LOW); delay(100);
digitalWrite(LED, HIGH); delay(100);
digitalWrite(LED, LOW); delay(100);
digitalWrite(LED, HIGH); delay(100);
digitalWrite(LED, LOW); delay(100);
digitalWrite(LED, HIGH);
doubleMillis = 0;
} else {
doubleMillis = millis();
} */
}
if(sw.fallingEdge() == 0) { // switch is released (it's pulled up so invert test)
if(primetime == ON) { // we're in PrimeTime mode, so switch effect off
effectOff(); // turn effect off
primetime = OFF; // turn off PrimeTime mode
} // there is no else: if not in PrimeTime mode, do nothing on release of the switch...
}
}
// now check if enough time has passed to turn on PrimeTime mode
if(state == ON && (millis() - lastMillis > PRIMETIME) && primetime == OFF) { // more than PRIMETIME ms since button was pressed!
if(!sw.read()) { // button still pressed, so enter PrimeTime
primetime = ON;
digitalWrite(LED, HIGH); delay(50);
digitalWrite(LED, LOW); delay(50);
digitalWrite(LED, HIGH); delay(50);
digitalWrite(LED, LOW);
}
}
// TODO: check if we should sleep for a while?
}