Welcome, Guest
Username: Password: Remember me

TOPIC: Delay Effect Guitar Pedal

Delay Effect Guitar Pedal 1 year 3 months ago #1256

The delay effect is limited by the amount of SRAM memory. With 8KB or RAM (in Arduino MEGA/ADK) we can store up to 4096 samples of 16 bits each.

With the default parameters, the PWM signal is generated at 33KHz, that means that every sample is generated every 30us (1/33KHz) so with 2KB of ram we have a delay of:
4096 x 30us = 120ms

120ms is not a massive delay, more like a "doubler" effect, but there are some tricks to make this delay longer (store 8 bits instead of 16)

This is the complete delay code:
// CC-by-NC-www.Electrosmash.com/rights
// Based on OpenMusicLabs previous works.
// pedalshield_mega_delay.ino reads the ADC, saves it into the DelayBuffer[] array and plays it into the PWM output.
// pressing the pushbutton_1 or 2 makes the delay longer or shorter
 
#include "U8glib.h"
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NO_ACK);  // Display which does not send ACK
 
//defining harware resources.
#define LED 13
#define FOOTSWITCH 12
#define TOGGLE 2
#define PUSHBUTTON_1 A5
#define PUSHBUTTON_2 A4

//defining the output PWM parameters
#define PWM_FREQ 0x00FF // pwm frequency - 31.3KHz
#define PWM_MODE 0 // Fast (1) or Phase Correct (0)
#define PWM_QTY 2 // 2 PWMs in parallel

//other variables
int input, vol_variable=512;
int counter=0;
unsigned int ADC_low, ADC_high;
 
#define MAX_DELAY 3500
unsigned int DelayBuffer[MAX_DELAY];
unsigned int DelayCounter = 0;
unsigned int Delay_Depth = MAX_DELAY;
 
void setup() {
  //setup IO
  pinMode(FOOTSWITCH, INPUT_PULLUP);
  pinMode(TOGGLE, INPUT_PULLUP);
  pinMode(PUSHBUTTON_1, INPUT_PULLUP);
  pinMode(PUSHBUTTON_2, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  pinMode(6, OUTPUT); //PWM0 as output
  pinMode(7, OUTPUT); //PWM1 as output
 
  // setup ADC
  ADMUX = 0x60; // left adjust, adc0, internal vcc
  ADCSRA = 0xe5; // turn on adc, ck/32, auto trigger
  ADCSRB = 0x00; // free running mode
  DIDR0 = 0x01; // turn off digital inputs for adc0
 
  // setup PWM
  TCCR4A = (((PWM_QTY - 1) << 5) | 0x80 | (PWM_MODE << 1)); //
  TCCR4B = ((PWM_MODE << 3) | 0x11); // ck/1
  TIMSK4 = 0x20; // interrupt on capture interrupt
  ICR4H = (PWM_FREQ >> 8);
  ICR4L = (PWM_FREQ & 0xff);
  DDRB |= ((PWM_QTY << 1) | 0x02); // turn on outputs
  sei(); // turn on interrupts - not really necessary with arduino 
  }
 
void loop() 
{
  //Turn on the LED and write the OLED if the effect is ON.
  if (digitalRead(FOOTSWITCH)) 
  {
  digitalWrite(LED, HIGH); //light the LED
    u8g.firstPage(); 
 do {
   u8g.setFont(u8g_font_helvR14r);
   u8g.drawStr( 0, 16, "  DELAY  ");    
   u8g.setPrintPos(10, 50); 
   u8g.setFont(u8g_font_helvR24r); 
   u8g.print(Delay_Depth);
  } while( u8g.nextPage() );
  }
    else  
  {  
    digitalWrite(LED, LOW); // switch-off the LED
    u8g.firstPage(); 
    do {
        u8g.setFont(u8g_font_helvR24r);
        u8g.drawStr( 0, 32, "EFFECT ");    
        u8g.drawStr( 0, 64, "   OFF  ");    
        } while( u8g.nextPage() );
  }
}
 
 
ISR(TIMER4_CAPT_vect) 
{
  // get ADC data
  ADC_low = ADCL; // ADC_low always 0 to save space
  ADC_high = ADCH;
 
  //store the high bit only for 
  DelayBuffer[DelayCounter] = (((ADC_high << 8) | ADC_low) + 0x8000); 
 
counter++; //to save resources, the pushbuttons are checked every 100 times.
if(counter==100)
{ 
counter=0;
if (!digitalRead(PUSHBUTTON_1)) {
  if (Delay_Depth<MAX_DELAY)Delay_Depth=Delay_Depth+1; //increase the vol
    digitalWrite(LED, LOW); //blinks the led
    }
 
    if (!digitalRead(PUSHBUTTON_2)) {
  if (Delay_Depth>0)Delay_Depth=Delay_Depth-1; //decrease vol
  digitalWrite(LED, LOW); //blinks the led
    }
}
 
  //Increse/reset delay counter.   
  DelayCounter++;
  if(DelayCounter >= Delay_Depth) DelayCounter = 0; 
 
  //the output signal is = (delayed signal + current signal)/2
  input = (DelayBuffer[DelayCounter] +(((ADC_high << 8) | ADC_low) + 0x8000))>>1;
 
  //write the PWM signal
  OCR4AL = ((input + 0x8000) >> 8); // convert to unsigned, send out high byte
  OCR4BL = input; // send out low byte
 
}
 
The administrator has disabled public write access.

Delay Effect Guitar Pedal 1 year 3 months ago #1257

This code achieves double delay length (200ms approx) by saving only 8 bits in memory intead of 16, you can compare both codes there are only 4 lines changed between them.

This is the complete "long" delay effect:
// CC-by-NC-www.Electrosmash.com/rights
// pedalshield_mega_delay_long.ino reads the ADC, saves it into the DelayBuffer[] array and plays it into the PWM output.
// pressing the pushbutton_1 or 2 makes the delay longer or shorter
 
#include "U8glib.h"
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NO_ACK);  // Display which does not send ACK
 
//defining harware resources.
#define LED 13
#define FOOTSWITCH 12
#define TOGGLE 2
#define PUSHBUTTON_1 A5
#define PUSHBUTTON_2 A4

//defining the output PWM parameters
#define PWM_FREQ 0x00FF // pwm frequency - 31.3KHz
#define PWM_MODE 0 // Fast (1) or Phase Correct (0)
#define PWM_QTY 2 // 2 PWMs in parallel

//other variables
int input, vol_variable=512;
int counter=0;
unsigned int ADC_low, ADC_high;
 
#define MAX_DELAY 7500
byte DelayBuffer[MAX_DELAY];
unsigned int DelayCounter = 0;
unsigned int Delay_Depth = MAX_DELAY;
 
void setup() {
  //setup IO
  pinMode(FOOTSWITCH, INPUT_PULLUP);
  pinMode(TOGGLE, INPUT_PULLUP);
  pinMode(PUSHBUTTON_1, INPUT_PULLUP);
  pinMode(PUSHBUTTON_2, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  pinMode(6, OUTPUT); //PWM0 as output
  pinMode(7, OUTPUT); //PWM1 as output
 
  // setup ADC
  ADMUX = 0x60; // left adjust, adc0, internal vcc
  ADCSRA = 0xe5; // turn on adc, ck/32, auto trigger
  ADCSRB = 0x00; // free running mode
  DIDR0 = 0x01; // turn off digital inputs for adc0
 
  // setup PWM
  TCCR4A = (((PWM_QTY - 1) << 5) | 0x80 | (PWM_MODE << 1)); //
  TCCR4B = ((PWM_MODE << 3) | 0x11); // ck/1
  TIMSK4 = 0x20; // interrupt on capture interrupt
  ICR4H = (PWM_FREQ >> 8);
  ICR4L = (PWM_FREQ & 0xff);
  DDRB |= ((PWM_QTY << 1) | 0x02); // turn on outputs
  sei(); // turn on interrupts - not really necessary with arduino 
  }
 
void loop() 
{
  //Turn on the LED and write the OLED if the effect is ON.
  if (digitalRead(FOOTSWITCH)) 
  {
  digitalWrite(LED, HIGH); //light the LED
    u8g.firstPage(); 
 do {
   u8g.setFont(u8g_font_helvR14r);
   u8g.drawStr( 0, 16, "  DELAY  ");    
   u8g.setPrintPos(10, 50); 
   u8g.setFont(u8g_font_helvR24r); 
   u8g.print(Delay_Depth);
  } while( u8g.nextPage() );
  }
    else  
  {  
    digitalWrite(LED, LOW); // switch-off the LED
    u8g.firstPage(); 
    do {
        u8g.setFont(u8g_font_helvR24r);
        u8g.drawStr( 0, 32, "EFFECT ");    
        u8g.drawStr( 0, 64, "   OFF  ");    
        } while( u8g.nextPage() );
  }
}
 
 
ISR(TIMER4_CAPT_vect) 
{
  // get ADC data
  ADC_low = ADCL; // ADC_low always 0 to save space
  ADC_high = ADCH;
 
  //store the high bit only for 
  DelayBuffer[DelayCounter] = ADC_high; 
 
counter++; //to save resources, the pushbuttons are checked every 100 times.
if(counter==100)
{ 
counter=0;
if (!digitalRead(PUSHBUTTON_1)) {
  if (Delay_Depth<MAX_DELAY)Delay_Depth=Delay_Depth+1; //increase the vol
    digitalWrite(LED, LOW); //blinks the led
    }
 
    if (!digitalRead(PUSHBUTTON_2)) {
  if (Delay_Depth>0)Delay_Depth=Delay_Depth-1; //decrease vol
  digitalWrite(LED, LOW); //blinks the led
    }
}
 
  //Increse/reset delay counter.   
  DelayCounter++;
  if(DelayCounter >= Delay_Depth) DelayCounter = 0; 
 
  //the output signal is = (delayed signal + current signal)/2
  input = (DelayBuffer[DelayCounter] +(ADC_high))>>1;
 
  //write the PWM signal
  OCR4AL = input;
  //OCR4BL = input; // send out low byte
 
}
The administrator has disabled public write access.
Time to create page: 0.137 seconds
Powered by Kunena Forum
Joomla SEF URLs by Artio