Hi,
I have successfully managed to loop audio through my Arduino Uno via the method outlined in numerous examples. The system diagram is basically:
Opamp to convert audio level to 0-5V -> Analogue input 0 of Arduino -> PWM output of Arduino -> Low pass filter -> Opamp to convert 0-5v to audio level
I am using the ADC_vect in free-running mode, to get the fastest read time possible.
This is all working great, but I also want to read potentiometers on the other inputs. I have added a 10k pot on Analogue input 1 of Arduino. My interrupt code looks like this:
volatile unsigned char master_output;
volatile float process;
volatile byte curInput;
void setup() {
Init_Register();
}
void loop() {
}
//Interrupt loop. Sets PWM output (i.e. generates the audio)
ISR(TIMER1_COMPA_vect) {
master_output = (char)process + 128;
OCR2B = master_output; //sets sample value
}
ISR(ADC_vect) {//when new ADC value ready
byte a;
a = ADCH;
switch (curInput){
case 0:
process = (float)a - 128;
break;
case 1:
//do stuff with pot here
break;
}
curInput++;
if (curInput>1){
curInput = 0;
}
ADMUX = B00100000 | curInput;
}
I'm now getting very strange behaviour.
- If I connect the potentiometer, the audio stops being read completely.
- If I move the audio to analogue input 1 (pot unconnected) I still hear the audio, even though code doesn't use input 1 at present.
- If I move the audio to analogue input 2 (pot still unconnected) I still hear a little bit of audio. Code doesn't even read input 2!!
It's though I am getting some kind of cross talk between inputs. And why connecting the pot stops the audio being read is beyond me! I have checked the pot with the demo analogue read sketch and it's fine.
I believe that there's a capacitor that has to discharge when changing inputs. Is this part of the problem? If so, is there no way to scan all the inputs very fast? I was eventually hoping to scan them in the order 0,1,0,2,0,3,0,4,0,5 etc, because the audio needs updating at a fast rate, but the pots don't.
Any help would be appreciated! ![]()
Paul
Code for Init_register below:
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
void Init_Register() {
// Set up Timer 2 to do pulse width modulation on the speaker
// pin.
pinMode(3, OUTPUT);
//use internal clock
cbi(ASSR,EXCLK); //disable external clock
cbi(ASSR,AS2); //clock timers from internal clock
//Fast PWM mode
sbi(TCCR2A,WGM20); //TOV flag set on max
sbi(TCCR2A,WGM21); //Update OCRx at bottom
cbi(TCCR2B,WGM22); //Top = 0xFF
//Set non-inverting PWM on OC2B pin
cbi(TCCR2A,COM2B0);
sbi(TCCR2A,COM2B1);
//set normal operation on OC2A pin
cbi(TCCR2A,COM2A0);
cbi(TCCR2A,COM2A1);
//no prescaler
sbi(TCCR2B,CS20);
cbi(TCCR2B,CS21);
cbi(TCCR2B,CS22);
// Set Timer 1 to update sample on interrupt
cli(); //pause interrupts
// Set CTC mode (Clear timer on compare match)
cbi(TCCR1A,WGM10);
cbi(TCCR1A,WGM11);
sbi(TCCR1B,WGM12);
cbi(TCCR1B,WGM13);
//No prescaler
sbi(TCCR1B,CS10);
cbi(TCCR1B,CS11);
cbi(TCCR1B,CS12);
// Set the compare register (OCR1A) initial value
OCR1A = master_ocr1;
// Timer 1, output compare A match interrupt enable
sbi(TIMSK1,OCIE1A);
//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;
cbi(ADMUX,REFS0); //use ref voltage
cbi(ADMUX,REFS1);
sbi(ADMUX, ADLAR); //left align to read highest 8 bits only
sbi(ADCSRA,ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
cbi(ADCSRA,ADPS1);
sbi(ADCSRA,ADPS2);
sbi(ADCSRA,ADATE); //enable auto trigger
sbi(ADCSRA,ADIE); //enable interrupt
sbi(ADCSRA,ADEN); //enable ADC
sbi(ADCSRA,ADSC); //start ADC
sei(); //start interrupts
}