1

I've been trying, just out of curiosity, to write my own function that generates a PWM signal, just like analogWrite(), and to make it light up an LED. Here's my attempt so far:

const int pin = 3;
int cycle = 2; // analogWrite() outputs a 498 Hz signal, so each cycle has approximately 2ms
int duty = 0.5; // for a 50% duty cycle
void setup() {
 Serial.begin(9600);
 pinMode(pin,OUTPUT);
}
void loop() {
 digitalWrite(pin,HIGH);
 delay(cycle*duty);
 digitalWrite(pin,LOW);
 delay(cycle*(1-duty));
}

The LED does light up, but very dimly, as shown below:

LED brightness with my code

However, when using analogWrite() with a 50% duty cycle to achieve the same result, the LED shines much brighter:

LED brightness with analogWrite(pin,128)

Is there something wrong with my code, or is there a special reason why more power is dissipated with analogWrite()?

asked Mar 21, 2020 at 2:07
3
  • have you tried different values in cycle? Commented Mar 21, 2020 at 2:33
  • I've just tried that, and indeed the brightness increases as the cycle values get smaller. However, I had to use cycle values as low as 2 microseconds in order to get a brightness comparable to the one provided by analogWrite(). I can't really understand why, though, so I'd really appreciate it if you could provide some clarification. :) Commented Mar 21, 2020 at 3:24
  • i do not know ... i suspect that the signal waveform is not what you and I expect it to be ... only way to check is to put a scope or a logic analyzer on the output Commented Mar 21, 2020 at 3:27

1 Answer 1

4

You need to review your code and also the capabilities of the Arduino UNO.

  • int declares an integer. So int duty = 0.5; is going to get rounded to either 0 1.
  • delay(0); also will not work. The instruction will simply get skipped. Likely the reason why you get a brighter LED. Try to use delayMicroseconds(); if you need shorter time but the minimum delay you can have is 4 us for Arduino UNO.
  • If you are using times as short as 2 us, then from the above comment the delayMicroseconds(); function is not going to be sufficient. Also, you should consider the loop overhead, which will be a few microseconds.

All in all this is not a great method. If you do want to create your own PWM signals, it is much better to use the hardware timers. For example this tutorial on the Arduino website. You should also be able to find posts about hardware timers on Arduino SE.

answered Mar 21, 2020 at 6:25

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.