0

Why does this code not function in a similar way to the example fade sketch? I have had to resort to using bit-banging as a way to implement PWM onto non PWM pins due to a lack of available free pins on my arduino pro mini. I am using a sketch that supposedly should fade an LED ranging from maximum brightness to minimum brightness. My code however does not work. Can anyone figure out why my code does not operate in the same way the fade sketch does?

My current code is:

int brightness = 0;
int fadeAmount = 50;  
void setup()
{
  pinMode(12, OUTPUT);
}
void loop()
{    brightness = brightness + fadeAmount;
    if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }
  digitalWrite(13, HIGH);
  delayMicroseconds(brightness); // Approximately 10% duty cycle @ 1KHz
  digitalWrite(13, LOW);
  delayMicroseconds(1000 - 100);
}

And i want it to work in the same way as:

int led = 9;
int brightness = 0;
int fadeAmount = 5;
void setup() {
  pinMode(led, OUTPUT);
}
void loop() {
  analogWrite(led, brightness);
  brightness = brightness + fadeAmount;
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }
  delay(30);
}

If possible could anyone provide a correct version to help me with my project.

0

You seem to have a typo on the pin number: you are configuring pin 12 and driving pin 13.

In other words: pinMode(12, OUTPUT); and digitalWrite(13, HIGH); do not match.

1

Your code here is not quite right:

digitalWrite(13, HIGH);
delayMicroseconds(brightness);
digitalWrite(13, LOW);
delayMicroseconds(1000 - 100);

Your two delays should add up to the total period (wavelength), or the reciprocal of the frequency (scaled to microseconds).

Hence the - 100 in the second delay - that is subtracting the "on" time from the total time to give the "off" time. It should be replaced with - brightness as such:

digitalWrite(13, HIGH);
delayMicroseconds(brightness);
digitalWrite(13, LOW);
delayMicroseconds(1000 - brightness);

And of course the brightness is in the range 0 - 1000 not 0 - 255 like analogWrite(). To make it 0-255 you should replace the 1000 with 255, which of course makes it all run at a much higher frequency. (1 / 0.000255 = 3922Hz).

digitalWrite(13, HIGH);
delayMicroseconds(brightness);
digitalWrite(13, LOW);
delayMicroseconds(255 - brightness);

Mind you, all this is not good regardless of your calculations. This is a blocking system in which you are unable to do anything else at all in your program whilst generating PWM. Instead you should be using a timer (like the tone() command does) and switch between two different time periods each interrupt for "on" and "off" time periods. That way it can function asynchronously ("in the background") like analogWrite() does.

0

It's not strongly related to your question but i suggest you to use external library as SoftPWM.h

You can find the whole documentation on https://github.com/bhagman/SoftPWM

0

A more generic version of your approach would be like this.

  1. Set the output pin - don't hardwire the pin number but instead use a macro for it.

  2. Delay for it's duty cycles.

  3. Clear the output pin.

  4. Delay for period - duty cycles used in step 2 above.

You can put that in a routine and call it.

With that said the routine has limited use in a real application as it can drive one output pin and ties up the whole mcu needlessly.

A better approach is to use an interrupt and test for duty cycles in the interrupt . This can drive multiple pins with independent duty cycles. All without tying up the mcu.

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.