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()?

3
  • have you tried different values in cycle? – jsotola Mar 21 '20 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. :) – Vinícius Peixoto Mar 21 '20 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 – jsotola Mar 21 '20 at 3:27
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.