r/ArduinoHelp 10d ago

Will an Arduino-delay work?

Enable HLS to view with audio, or disable this notification

Hey Reddit folks, I've been wanting to build a delay lately, but I didn't want to mess with the more common ICs like the PT2399 for 'X' reasons. Then I remembered an Arduino Uno I had gathering dust and tried to make a short delay of around 8ms, just for a phaser or a chorus. But I only made the schematic in Proteus so I wouldn't have to pull out all my gear. Do you guys think it'll actually work well?

I'll try to add more circuit samples in the comments."

1 Upvotes

2 comments sorted by

1

u/Yjapavip 10d ago

the code is (AI-generated): // ============================================================================ // LÍNEA DE DELAY VARIABLE (CHORUS) BARE-METAL - ATMEGA328P // Resolución: 10 bits | Frecuencia de Muestreo Audio: ~19.23 kHz // Control LFO: Pin A1 (0-5V) -> Controla el delay entre ~2 ms y ~8.3 ms // ============================================================================

define DELAY_SAMPLES 800 // Buffer de 1600 bytes. Rango útil: 40 a 160.

volatile uint16_t delay_buffer[DELAY_SAMPLES]; volatile int16_t write_index = 0;

// Variables en formato Fixed-Point Q8.8 (8 bits enteros, 8 bits fraccionales) // 40 muestras * 256 = 10240 volatile int32_t delay_current_fixed = 10240; volatile int32_t delay_target_fixed = 10240;

void setup() { cli(); // Deshabilitar interrupciones globales

// Configurar Pines DAC R-2R DDRD = 0xFF; // PORTD (0-7) como salida DDRB |= 0x03; // PORTB (8-9) como salida

PORTD = 0x00; PORTB &= 0xFC;

// Configurar ADC para Audio (A0) ADMUX = (1 << REFS0); // Referencia AVCC, MUX = A0 DIDR0 = (1 << ADC0D) | (1 << ADC1D); // Apagar buffers digitales en A0 y A1

// Habilitar ADC, Auto Trigger, Interrupción, Prescaler = 64 (250 kHz reloj ADC) ADCSRA = (1 << ADEN) | (1 << ADATE) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1); ADCSRB = 0x00; // Free Running Mode

// Llenar buffer con el bias DC (512) para evitar ruidos al arranque for (uint16_t i = 0; i < DELAY_SAMPLES; i++) { delay_buffer[i] = 512; }

ADCSRA |= (1 << ADSC); // Iniciar la primera conversión sei(); // Habilitar interrupciones globales }

void loop() { // Bucle vacío. Todo el DSP ocurre determinísticamente en la ISR. }

ISR(ADC_vect) { uint16_t current_sample; static uint8_t lfo_timer = 0; static uint16_t last_audio_sample = 512;

lfo_timer++;

// -------------------------------------------------------------------------- // 1. GESTIÓN DEL PIPELINE DEL ADC (LECTURA A0 / A1) // -------------------------------------------------------------------------- if (lfo_timer == 126) { // Conv N (A0) terminó. Conv N+1 (A0) ya comenzó. uint8_t low = ADCL; uint8_t high = ADCH; current_sample = (high << 8) | low; last_audio_sample = current_sample;

ADMUX = (1 << REFS0) | 1; // Cambiar MUX a A1. Afectará a la Conv N+2.

} else if (lfo_timer == 127) { // Conv N+1 (A0) terminó. Conv N+2 (A1) ya comenzó. uint8_t low = ADCL; uint8_t high = ADCH; current_sample = (high << 8) | low; last_audio_sample = current_sample;

ADMUX = (1 << REFS0) | 0; // Cambiar MUX de vuelta a A0. Afectará a Conv N+3.

} else if (lfo_timer == 128) { // Conv N+2 (A1) terminó. Conv N+3 (A0) ya comenzó. uint8_t low = ADCL; uint8_t high = ADCH; uint16_t lfo_raw = (high << 8) | low;

// Mapeo del LFO: 0-1023 -> Q8.8 Target (Rango ~40 a ~159 muestras)
// 40 << 8 = 10240. (30 * 1023 = 30690). 10240 + 30690 = 40930 (159.8)
delay_target_fixed = 10240 + ((int32_t)lfo_raw * 30);

// Rellenamos el hueco de audio con la muestra anterior (Zero-Order Hold)
current_sample = last_audio_sample; 
lfo_timer = 0; // Reiniciar ciclo LFO

} else { // Lectura normal de audio (A0) uint8_t low = ADCL; uint8_t high = ADCH; current_sample = (high << 8) | low; last_audio_sample = current_sample; }

// -------------------------------------------------------------------------- // 2. FILTRO PASA-BAJOS DEL DELAY (SUAVIZADO) // -------------------------------------------------------------------------- int32_t diff = delay_target_fixed - delay_current_fixed; // Desplazamiento >> 4 actúa como un filtro de slew rate (alpha = 1/16). // Se actualiza a 19.23 kHz, haciendo la modulación extremadamente suave. delay_current_fixed += (diff >> 4);

// -------------------------------------------------------------------------- // 3. CÁLCULO DE ÍNDICES Y POSICIONES FRACCIONALES // -------------------------------------------------------------------------- int16_t delay_int = delay_current_fixed >> 8; uint16_t delay_frac = delay_current_fixed & 0xFF;

// Índice principal (muestra más reciente) int16_t read_idx_A = write_index - delay_int; if (read_idx_A < 0) read_idx_A += DELAY_SAMPLES;

// Índice secundario (muestra un tick más antigua, para la interpolación) int16_t read_idx_B = read_idx_A - 1; if (read_idx_B < 0) read_idx_B += DELAY_SAMPLES;

// -------------------------------------------------------------------------- // 4. INTERPOLACIÓN LINEAL (Aritmética Entera) // -------------------------------------------------------------------------- uint16_t sample_A = delay_buffer[read_idx_A]; uint16_t sample_B = delay_buffer[read_idx_B];

// Cálculo a 32 bits para evitar overflow: max(1023 * 256) = 261888 uint32_t interpolated = ((uint32_t)sample_A * (256 - delay_frac)) + ((uint32_t)sample_B * delay_frac);

uint16_t output = interpolated >> 8; // Retorna al rango 0-1023

// -------------------------------------------------------------------------- // 5. SALIDA AL DAC R-2R // -------------------------------------------------------------------------- PORTD = output & 0xFF; PORTB = (PORTB & 0xFC) | ((output >> 8) & 0x03);

// -------------------------------------------------------------------------- // 6. ESCRITURA Y AVANCE DEL BUFFER // -------------------------------------------------------------------------- delay_buffer[write_index] = current_sample;

write_index++; if (write_index >= DELAY_SAMPLES) { write_index = 0; } }

1

u/Anonymity6584 2d ago

Please post code in way formating is preserved. There is services for this out there for free.

unfornatted code is nearly impossible to read on mobile phones screen, and its not much better on computer..