Help with simple PWM code

Hey guys I am new to the arduino but not microcontrollers. I wrote up a simple program that is supposed to fade the pin 13 LED. Could someone run the program and see what the problem is? When I use serial terminal to view my High and Low time values they start correctly but once it is supposed to switch direction I start getting negative values. Could someone load it up and see if you can figure it out? Thanks!

byte updown = 1;
int Ht = 0;
int Lt = 1000;


void setup()  { 
  pinMode(13, OUTPUT);
  Serial.begin(9600);
} 

void loop()  {
 Serial.println(Ht);
 Serial.println(Lt);
 rep();
 Ht += updown;    //as high time goes up lower low time by same amount
 Lt -= updown;
 if(Lt == 0 || Lt == 1000){
   updown = -updown;
  }
}

void rep()  {
  digitalWrite(13, LOW);
  delayMicroseconds(Lt);
  digitalWrite(13, HIGH);
  delayMicroseconds(Ht);
}

When I use serial terminal to view my High and Low time values they start correctly but once it is supposed to switch direction I start getting negative values.

Negative values for what?

A suggestion:

 [glow]Serial.print("Ht = ");[/glow]Serial.println(Ht);
 [glow]Serial.print("Lt = ");[/glow]Serial.println(Lt);

byte updown = 1;

byte is an unsigned type. It cannot store a negative one. At least not the way you're expecting it to store a negative one.

Try this...

int updown = 1;

Ok that pretty much fixed it except the LED flashes when at full brightness and flashes when off too. I modified the code and was able to make it not flash when full on but it still flashes when off. anything obvious?

int updown = 1;
int Ht = 0;
int Lt = 999;


void setup()  { 
  // declare pin 9 to be an output:
  pinMode(13, OUTPUT);
  //Serial.begin(9600);
} 

void loop()  {
 //Lt = 255 - Ht; 
 //Serial.println(Ht);
 //Serial.println(Lt);
 rep();
 Ht += updown;
 Lt -= updown;
 if(Lt == 1 || Lt == 1000){
   updown = -updown;
  }
}

void rep()  {
  digitalWrite(13, HIGH);
  delayMicroseconds(Ht);
  digitalWrite(13, LOW);
  delayMicroseconds(Lt);
}

The light never really gets all the way down to off. You should let Lt get to 0 before resetting updown.

Well when Lt is zero it means Ht is 1000 so the led is actually full on. See with Lt ==0 I get the flash when full on. but with L1 == 1 the led doesn't flash at full on. but it still flashes at full off. It's like a real quick flicker before it starts fading on again.

I think delayMicroseconds misbehaves when zero is passed. Skip the delayMicroseconds if the parameter is zero...

  digitalWrite(13, HIGH);
  if ( Ht != 0 )
    delayMicroseconds(Ht);
  digitalWrite(13, LOW);
  if ( Lt != 0 )
    delayMicroseconds(Lt);

That did it! :smiley:
Thank you all so much for the help!

So is there a way to calculate the frequency of the rep routine and to adjust for the overhead of the calculation/if code?

Thanks!

Thank you all so much for the help!

You are welcome.

So is there a way to calculate the frequency of the rep routine and to adjust for the overhead of the calculation/if code?

There is but the process is a bit painful. You'll have to dig through an assembly listing and sum clock cycles for each instruction.

If you're willing to dedicate one of the two timers, it's possible to measure the frequency in the Sketch. Or, you can measure the frequency using the external interrupt. Because you're generating the waveform in software, measuring the frequency will also reduce the maximum possible frequency.