Setting the PWM period and resolution

Arduino forum,
I need a PWM with a period of 20ms (50Hz) with a T1 of 0 and a T2 of 450us. But every thing I've read says there are only two periods, 490Hz and 980Hz for pins 5 and 6. I haven't found a way to set the period time and resolution bits?

With other hardware I have written code that toggles the clocks and uses delays to simulate the PWM that I need and it has worked. I wrote the following Nano program to do the same but with the limitations to the delayMicroseconds() command I had to stack two delays back to back to get a 20ms. That worked but check out the scope photos attached to see the fall time problem.

#define Pin 4

void setup()
{

}

void loop()
{
 digitalWrite(Pin, HIGH);
 delayMicroseconds(450);
 digitalWrite(Pin, LOW);
 delay(19);
 delayMicroseconds(550);
 // total delay of 19550us which the datasheet didn't guarantee with delayMiroseconds()
 digitalWrite(Pin, LOW);
}

I got the 20ms period alright and the pulse begins to fall at 450us but with the lag in the fall time it doesn't get to half level until about 575us. Do these pins need pull downs? I tried several different ports but all were the same.

Maybe there's a completely different way to do this.

jerdon


If I wasn't going to use a low-level timer, I'd use something BlinkWithoutDelay-related:

#define Pin 4

void setup()
{
  pinMode(Pin, OUTPUT);
}

void loop()
{
  blink(19550UL+450,450);
}

void blink(uint32_t period, uint32_t onTime) {
  static uint32_t lastUs = 0;
  static bool pinHigh = false;
  uint32_t nowUs = micros();
  uint32_t HighUs = onTime, LowUs = period - onTime;
  if (pinHigh == false && nowUs - lastUs >= LowUs) {
    digitalWrite(Pin, HIGH);
    lastUs += LowUs;
    pinHigh = true;
  } else if (pinHigh == true && nowUs - lastUs >= HighUs) {
    digitalWrite(Pin, LOW);
    lastUs += HighUs;
    pinHigh = false;
  }
}
1 Like

This guy was timing in tenths of microseconds using Assembly... (seek 4m34s)

The description:

The code:

2 Likes

either:

const byte Pin = 4;

void setup(){
pinMode(Pin,OUTPUT);
}

void loop(){
 digitalWrite(Pin, HIGH);
 delayMicroseconds(446);
 digitalWrite(Pin, LOW);
 delay(19);
 delayMicroseconds(546);
}

or

void setup(){
  DDRD|=B1000;
}

void loop(){
 PORTD |=(1<<3);
 delayMicroseconds(446);
 PORTD &=~(1<<3);
 delay(19);
 delayMicroseconds(546);
}

@jerdon you forgot pinMode(Pin,OUTPUT);, that is why you fall flank is so shallow.
also you may read this

2 Likes

Well you have not read much have you?
What type of Arduino do you have?
The resolution setting is fixed on most Arduinos as 8 Bits.

The PWM speed can be set by setting the Pre-scalier register, but where this is depends again on what sort of Arduino you are using.

Google is your friend.

1 Like

kolaha,
Those are the exact numbers I use in my program with the other hardware but in

it says:
"This function works very accurately in the range 3 microseconds and up to 16383. We cannot assure that delayMicroseconds will perform precisely for smaller delay-times. Larger delay times may actually delay for an extremely brief time."

so I was hesitant to use delayMicroseconds(19546);

What about the falling edge in the scope photo?

jerdon

I think it is not a software issue. Do you have anything connected to the pin?

1 Like

Did you read this?

1 Like

ah, my fault, corrected.
as i already 3 times showed: falling flank was not strait down because you forgot pinMode

1 Like

Arduino forum,
Thanks to those who pointed out that I forgot to declare "Pin" as an output.
Don't know how much longer I can continue to use the excuse that I'm new to Arduino.

The waveform is now as it should be.

Still concerned about using delayMicroseconds(19546) since Arduino doesn't guarantee values above 16383. I'll use the back to back delays which gave me the correct period.
jerdon

1 Like

Arduino forum,
Since I need a period of 20ms and the limit of delayMicroseconds is 16383 I always include a delay of 10ms so I never need to exceed the max microseconds.

Thanks to all who contributed.
jerdon

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.