Can anyone clarify me whether the analogread() uses any hardware timer ?
because in loop i try to read sensor input using analogread() and output audio to the PWM
loop()
{
analogread()
outputaudio()
}
My output audio uses 2 outputcompare timers. when i comment the analogread(), i can able to hear the audio as it is. but when i place the analog read(), my audio gets corrupted.
so i want to know whether analogread() use any timer ?
No, but it pauses for around 104 uS while the analog hardware does the read. You can do it asynchronously so that the read is done while the program is executing. Example here:
(Scroll down to: "Read the Analog-to-Digital converter asynchronously")
OK. i changed the serial printing to the loop. still couldn able to read. is there any bug in my ISR ? do i need to enable External interrupt pin before ?
I putforth my requirements below. i need to read the FSR input and output some audio based on the FSR input. for that i did the coding as below
void loop()
{
analogread(fsr)
playaudio() // in this function i use 2 output compare timers. i just connect my speakers to the PWM output.
}
In the above implementation, audio is not getting played due to the analog read.
I got an suggestion to implement the analog read in ISR. but i dunno how to write ISR for analogread. i found examples only for digital read and not for analog read.
please gimme some input for the correct implementation and guide me
sorry for the incomplete code. -please find my complete code below
#include <MozziGuts.h>
#include <Oscil.h>
#include <WaveShaper.h>
#include <EventDelay.h>
#include <utils.h>
#include <Smooth.h>
#include <tables/sin2048_int8.h>
#include <tables/waveshape_chebyshev_3rd_256_int8.h>
#include <tables/waveshape_chebyshev_6th_256_int8.h>
#include <tables/waveshape_compress_512_to_488_int16.h>
int fsrAnalogPin = 0; // FSR is connected to analog 0
int fsrReading; // the analog reading from the FSR resistor divider
// use #define for CONTROL_RATE, not a constant
#define CONTROL_RATE 64 // powers of 2 please
// use: Oscil <table_size, update_rate> oscilName (wavetable)
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin(SIN2048_DATA); // sine wave sound source
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aGain1(SIN2048_DATA); // to fade sine wave in and out before waveshaping
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aGain2(SIN2048_DATA); // to fade sine wave in and out before waveshaping
// Chebyshev polynomial curves, The nth curve produces the n+2th harmonic component.
WaveShaper <char> aCheby3rd(CHEBYSHEV_3RD_256_DATA); // 5th harmonic
WaveShaper <char> aCheby6th(CHEBYSHEV_6TH_256_DATA); // 8th harmonic
WaveShaper <int> aCompress(WAVESHAPE_COMPRESS_512_TO_488_DATA); // to compress instead of dividing by 2 after adding signals
// for scheduling note changes
EventDelay kChangeNoteDelay(CONTROL_RATE);
// for random notes
Q8n0 octave_start_note = 42;
Q24n8 carrier_freq; // unsigned long with 24 integer bits and 8 fractional bits
// smooth transitions between notes
Smooth <unsigned int> kSmoothFreq(0.85f);
int target_freq, smoothed_freq;
void setup(){
startMozzi(CONTROL_RATE); // set a control rate of 64 (powers of 2 please)
aSin.setFreq(110u); // set the frequency with an unsigned int or a float
aGain1.setFreq(2.f); // use a float for low frequencies, in setup it doesn't need to be fast
aGain2.setFreq(.4f);
kChangeNoteDelay.set(4000); // note duration ms, within resolution of CONTROL_RATE
}
unsigned char rndPentatonic(){
unsigned char note = rand((byte)5);
switch(note){
case 0:
note = 0;
break;
case 1:
note = 3;
break;
case 2:
note = 5;
break;
case 3:
note = 7;
break;
case 4:
note = 10;
break;
}
return note;
}
void updateControl(){
if(kChangeNoteDelay.ready()){
if(rand((byte)5)==0){ // about 1 in 5 or so
// change octave to midi 24 or any of 3 octaves above
octave_start_note = (rand((byte)4)*12)+36;
}
Q16n16 midi_note = Q8n0_to_Q16n16(octave_start_note+rndPentatonic());
target_freq = Q16n16_to_Q16n0(Q16n16_mtof(midi_note)); // has to be 16 bits for Smooth
kChangeNoteDelay.start();
}
smoothed_freq = kSmoothFreq.next(target_freq*4); // temporarily scale up target_freq to get better int smoothing at low values
aSin.setFreq((unsigned int)smoothed_freq/4); // then scale it back down after it's smoothed
}
int updateAudio(){
char asig0 = aSin.next(); // sine wave source
// make 2 signals fading in and out to show effect of amplitude when waveshaping with Chebyshev polynomial curves
// offset the signals by 128 to fit in the 0-255 range for the waveshaping table lookups
unsigned char asig1 = (unsigned char)128+((asig0*((unsigned char)128+aGain1.next()))>>8);
unsigned char asig2 = (unsigned char)128+((asig0*((unsigned char)128+aGain2.next()))>>8);
// get the waveshaped signals
char awaveshaped1 = aCheby3rd.next(asig1);
char awaveshaped2 = aCheby6th.next(asig2);
// use a waveshaping table to squeeze 2 summed 8 bit signals into the range -244 to 243
int awaveshaped3 = aCompress.next(256u + awaveshaped1 + awaveshaped2);
return awaveshaped3;
}
void loop(){
fsrReading = analogread(fsrAnalogPin); // read fsr input
audioHook(); // play audio. It calls updateAudio() and puts the result into Mozzi's [audio library] output buffer.
}
In the above implementation, if i comment out the analog read, my sound library is working fine and can able to hear sound using a speaker connected to the PWM pin 9. but when i integrate my FSR read , my audio getting corrupted.
The link I provided above shows how to do it. You start an ADC conversion, setting up for an interrupt to occur when it finishes. That sets a flag and you get the reading. Then you can start another one.
i tried as you suggested. but that works only for the External interrupt (on some digital pins). i am using analog pin 0. is it possible to use attach_interrupt routine ?
int fsrPin = 0; // the FSR and 10K pulldown are connected to a0
int fsrReading; // the analog reading from the FSR resistor divider
void pinChange()
{
fsrReading = analogRead(fsrPin);
}
void setup(void) {
Serial.begin(9600); // We'll send debugging information via the Serial monitor
attachInterrupt (0, pinChange, CHANGE); // attach interrupt handler
}
void loop(void) {
Serial.print("Analog reading = ");
Serial.println(fsrReading);
}
In the above code, i don get any values from ISR.
Thanks
Anand
Below is the code i tried
...
In the above code, i don get any values from ISR.
Thanks
Thanks for what? You have totally ignored my suggested code.
I didn't say "attach an interrupt and everything will be solved". I posted code for starting an ADC conversion without waiting, using an interrupt to detect when that finished, and getting the converted value.