micros() timing issues

Hi all!

i've been messing with some simple code to generate audio, changing the frequency of a square wave by turning a pot connected to a analog input

i started from the blink without delay example, and found that for some reason there are values which are omited by the code, resulting in "steppy" and not linear frequency ramps

i tried to do the same the old way, by using delayMicroseconds() function, and it is working fine this way.

Does anyone know why this happens and what can be done to solve this?

i have tried the replacement for the blinkwithoutdelay example that is suggested in this thread: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1265097594 but its behaving the same way..

i attach my code below:

const int AudioPin =  12;
int AudioState = LOW;         
long previousMicros = 0;   


void setup() {

  pinMode(AudioPin, OUTPUT);      
}

void loop()
{

  ///This code makes the frequency changes at intervals
  if (micros() - previousMicros >= analogRead(0)) {
    previousMicros = micros();   

    if (AudioState == LOW)
      AudioState = HIGH;
    else
      AudioState = LOW;

    digitalWrite(AudioPin, AudioState);
  }
   
   //this code does it fine
  
//  digitalWrite(AudioPin, HIGH);
//  delayMicroseconds(analogRead(0));
//  digitalWrite(AudioPin, LOW);
//  delayMicroseconds(analogRead(0));
  

}

thank you all!

May or may not help but is certainly a good idea...

const [glow]byte[/glow] AudioPin =  12;
[glow]byte[/glow] AudioState = LOW;
[glow]unsigned [/glow]long previousMicros = 0;

Just a thought - an analogRead takes around 100us (I think), but you’re now doing one every time through “loop”, whereas before you were doing the read and immediately delaying by the value returned.

Got to think about this one. Scope time!

AudioState = !AudioState;

is a little simpler (IMHO)

Hey, thanks for your help!

I just tested both of your suggestions, and it's still behaving the steppy way

i also tried to replace micros() with millis(), and its presenting the same behavior

it's strange no one reported this until now, it's certainly easier to notice it while working with audio, as it's something very recognizable from the sound side...

I wonder if the fact that you have two different calls to micros is causing a problem. One occurs before the call to analogRead(), while the other occurs after.

You might try saving the value returned by micros(), and using that value in the if test and assignment.

Hi Paul,

i just changed my code as you suggested:

const byte AudioPin =  12;
byte AudioState = LOW;
unsigned long previousMicros = 0;


void setup() {

  pinMode(AudioPin, OUTPUT);
}

void loop()
{

  ///This code makes the frequency changes at intervals
  unsigned long currentMicros = micros();
  if (currentMicros - previousMicros >= analogRead(0)) {
      previousMicros = currentMicros;
  
      AudioState=!AudioState;
      digitalWrite(AudioPin, AudioState);
  }


   //this code does it fine

//  digitalWrite(AudioPin, HIGH);
//  delayMicroseconds(analogRead(0));
//  digitalWrite(AudioPin, LOW);
//  delayMicroseconds(analogRead(0));


}

and unfortunately there's still the same steppy signal! :-/

The only other suggestion I have is that analogRead returns an int, and you are comparing that with the difference between two unsigned longs. Perhaps the different types is causing a problem. You could store the retsult of the call to analogRead in an unsigned long variable, or cast the analogRead value using (unsigned long) in front of it.

messing around i find some interesting code to fasten up analogread() http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1208715493/11

i just made a copy and paste to my code and it's so much better now, although it's not as fast as with the delay() option...

the whole code ends up as follows:

const byte AudioPin =  12;
byte AudioState = LOW;
unsigned long previousMicros = 0;

#define FASTADC 1

// 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 setup() {
  
#if FASTADC
  // set prescale to 16
  sbi(ADCSRA,ADPS2) ;
  cbi(ADCSRA,ADPS1) ;
  cbi(ADCSRA,ADPS0) ;
#endif
  
  pinMode(AudioPin, OUTPUT);
}

void loop()
{

  ///This code makes the frequency changes at intervals
  unsigned long currentMicros = micros();
  if (currentMicros - previousMicros >= analogRead(0)) {
      previousMicros = currentMicros;
  
      AudioState=!AudioState;
      digitalWrite(AudioPin, AudioState);
  }


   //this code does it fine

//  digitalWrite(AudioPin, HIGH);
//  delayMicroseconds(analogRead(0));
//  digitalWrite(AudioPin, LOW);
//  delayMicroseconds(analogRead(0));


}

i don't really now what i'm doing, and maybe this is not the better solution, but it looks like the thing is working better now, so let's try!

any suggestions?

and thanks again for your help!

Try this...

const byte AudioPin =  12;
byte AudioState = LOW;
unsigned long previousMicros = 0;
[glow]unsigned long interval;[/glow]

#define FASTADC 1

// 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 setup() {

#if FASTADC
  // set prescale to 16
  sbi(ADCSRA,ADPS2) ;
  cbi(ADCSRA,ADPS1) ;
  cbi(ADCSRA,ADPS0) ;
#endif

  pinMode(AudioPin, OUTPUT);
  [glow]interval = analogRead(0);[/glow]
}

void loop()
{

  ///This code makes the frequency changes at intervals
  unsigned long currentMicros = micros();
  if (currentMicros - previousMicros >= [glow]interval[/glow]) {
      previousMicros = currentMicros;

      AudioState=!AudioState;
      digitalWrite(AudioPin, AudioState);
      [glow]interval = analogRead(0);[/glow]
  }


   //this code does it fine

//  digitalWrite(AudioPin, HIGH);
//  delayMicroseconds(analogRead(0));
//  digitalWrite(AudioPin, LOW);
//  delayMicroseconds(analogRead(0));


}

it's so smooooooth now almost undistinguishable from the delay() code option

GREAT!!!!!!!

thanks a lot to everyone!