Skip to content

Arduino: Fade and pulse a LED with just using a DigitalPort

2009 May 17
by tobi

This is a nice experiment I did to fade and pulse a LED by just using a digital port. Digital? On/Off, 1/0 – how can this work? Well it does, check this out:

The key is, I’m switching the LED on & off very fast which appears the human eye as it’s on all the time (similar to a LED Matrix). Now, I change the time period between switching the LED on and off. Is the off period time longer, the LED lights low, is the off period time short, the LED lights high. Fading the period time, makes the LED pulse… nice!

Check this (still quite ugly) code:
[c]
int ledPin = 13; // LED connected to digital pin 13
int value = LOW; // previous value of the LED
long cnt = 0; // will store last time LED was updated
long low = 0; // interval at which to blink (milliseconds)
long high = 1000; // interval at which to blink (milliseconds)
int op = 3;
long a = 0;

void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}

void loop()
{
a += op;
blinkl( a+30, 10 );
if( a > 200 || a < 0 ) op *= -1;
}

void blinkl(long low, long high )
{
int c = 5;
while ( c > 0 ) {
blink( low, high );
c-=1;
}
}

void blink( long low, long high )
{
long period = 4000;
long pt = period * high / (low + high );
int value = LOW;
digitalWrite(ledPin, value);

while( period > 0 ) {
if (period < pt && value == LOW ) {
value = HIGH;
digitalWrite(ledPin, value);
}
period -= 1;
}
}
[/c]

Flattr this!

15 Responses
  1. Bartek permalink
    November 5, 2013

    Compact version.

    unsigned int i=1;
    boolean rise=false;
    int period=1000;

    void setup() {
    }

    void loop() {
    if(i == period-1 || i == 1) {
    rise=!rise;
    }
    if(rise == true) {
    i++;
    } else {
    i–;
    }
    digitalWrite(13, LOW);
    delayMicroseconds(period-i);
    digitalWrite(13, HIGH);
    delayMicroseconds(i);
    }

  2. December 22, 2012

    Standing on the shoulder of giant Marc:

    int ledPin = 13;
    unsigned int i=0;
    boolean rise=true;
    int period=1000;

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

    void loop() {

    digitalWrite(13, LOW);
    delayMicroseconds(i);
    digitalWrite(13, HIGH);
    delayMicroseconds(period-i);

    if (rise) {
    i++;
    }
    else {
    i–;
    }

    if (i == period || i == 0) {
    rise != rise;
    }
    }

  3. tobi permalink*
    March 31, 2011

    nice

  4. March 31, 2011

    This is easier:

    int ledPin = 13;
    unsigned int i=0;
    boolean rise=true;
    int period=1000;

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

    void loop()
    {
    if(i == period)
    {
    i=1;
    rise= !rise;
    }
    if(rise == false)
    {
    digitalWrite(13, LOW);
    delayMicroseconds(i);
    digitalWrite(13, HIGH);
    delayMicroseconds(period-i);
    i=i+1;
    }

    if(rise == true)
    {
    digitalWrite(13, LOW);
    delayMicroseconds(period-i);
    digitalWrite(13, HIGH);
    delayMicroseconds(i);
    i=i+1;
    }

    }

  5. Andri permalink
    December 10, 2010

    No problem Tobi…I’ve found another code and with a little bit “patiece”…it works 😀
    I post the code that I’ve modified…have a nice day!! Thanks!

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

    void fade(int pin, int start, int finish, int milliseconds)
    {
    uint32_t startMillis = millis(); // remember when we started
    while (true) // we will ‘break’ when we are done
    {
    uint32_t elapsedTime = millis() – startMillis; // track the time

    // convert the elapsed time into a brightness range
    int brightness = map(elapsedTime, 0, milliseconds, start, finish);
    analogWrite(pin, brightness);

    // exit when milliseconds have elapsed
    if (elapsedTime >= milliseconds)
    {
    break;
    }
    delay(1);
    }
    }

    void loop()
    {
    fade(9, 0, 255, 1000); // fade led on pin 9 from min to max over one second
    delay(2000); // hold for 2 seconds
    fade(9, 255, 0, 2000); // fade pin 9 from max to min over 2 seconds
    delay(1000); // hold for 1 second
    }

  6. tobi permalink*
    December 10, 2010

    sorry no updated code and not quite sure about the math formula, neither its name 🙂 it was just a quick hack to get prepared controlling the 8×8 LED Matrix… happy u like it 🙂

  7. Marco permalink
    December 9, 2010

    Hi Tobi!
    Very nice trick! I am prototyping my thesis project, which involves 24 LEDs fading in and out according to the 24 photoresistors used as on/off switches. I am using n. 3 4051 for the INPUTS and probably I’ll use TLC 5940 for OUTPUTS. Do you think your code it’s suitable for my project? Did you came up with a newer version of the code? That would be awesome and extremely helpful! Please let me know

  8. Andri permalink
    December 9, 2010

    Hi tobi,

    very nice code!! Fabulous…
    but I have a question…which mathematical formula “pt = period * high / (low + high )” is??
    Has it a name? Or do you know where I can find it?
    I want to work with it to get one cycle of fading-in led…then a piezo works…and finally one cycle of fading-out led…WHITOUT DELAY 😀

  9. July 24, 2010

    Comment system totally butchered my code. Is using htmlspecialchars really that hard? Replace ~ with less than sign.

    int data = 2;
    int clock = 3;
    int latch = 4;

    boolean Pins[8];

    int Count = 0;

    int Brightness = 0;
    int BrightnessInc = 1;

    void setup() {
    pinMode(data, OUTPUT);
    pinMode(clock, OUTPUT);
    pinMode(latch, OUTPUT);
    }

    void loop() {
    digitalWrite(latch, 0);
    digitalWrite(clock, 0);
    digitalWrite(data, 0);

    for(int i = 0;i ~ 8;i++) {
    if(Count ~ Brightness) {
    Pins[i] = 1;
    }else{
    Pins[i] = 0;
    }
    }

    Count++;

    if(Count >= 50) {
    Count = 0;
    Brightness += BrightnessInc;
    }

    if(Brightness > 50) {
    BrightnessInc = -1;
    }else
    if(Brightness ~ 0) {
    BrightnessInc = 1;
    }

    for(int i = 0;i ~ 8;i++) {
    digitalWrite(clock, 0);

    digitalWrite(data, Pins[i]);

    digitalWrite(clock, 1);
    digitalWrite(data, 0);
    }

    digitalWrite(clock, 0);
    digitalWrite(latch, 1);
    }

  10. July 24, 2010

    Simple example, using a shift register – makes all 8 LEDs pulsate together (from complete brightness, to nothing):

    int data = 2;
    int clock = 3;
    int latch = 4;

    boolean Pins[8];

    int Count = 0;

    int Brightness = 0;
    int BrightnessInc = 1;

    void setup() {
    pinMode(data, OUTPUT);
    pinMode(clock, OUTPUT);
    pinMode(latch, OUTPUT);
    }

    void loop() {
    digitalWrite(latch, 0);
    digitalWrite(clock, 0);
    digitalWrite(data, 0);

    for(int i = 0;i < 8;i++) {
    if(Count = 50) {
    Count = 0;
    Brightness += BrightnessInc;
    }

    if(Brightness > 50) {
    BrightnessInc = -1;
    }else
    if(Brightness < 0) {
    BrightnessInc = 1;
    }

    for(int i = 0;i < 8;i++) {
    digitalWrite(clock, 0);

    digitalWrite(data, Pins[i]);

    digitalWrite(clock, 1);
    digitalWrite(data, 0);
    }

    digitalWrite(clock, 0);
    digitalWrite(latch, 1);
    }

  11. March 10, 2010

    Excellent solution for the digital write. I’ve been trying to find a good solution for button input to LED lights using the analogwrite, but the delay function would always null my button input until the loop was complete. This works very well.
    Thanks for giving me new ideas.

  12. jason permalink
    February 12, 2010

    What about having one LED fade into another? For example, a red LED fading into a blue LED?

  13. BiLL permalink
    December 31, 2009

    Nice work m8, im try to do samething for a project for my university. i work with pic 18F1320 ( c programming ) . Could u want to send me a code in this pic or something like that in order to fix it to work . Im already thank u for this idea a read.

  14. tobi permalink*
    November 5, 2009

    well sure! I admit, this code was first version and is kind of crap, I should come up with an updated one. But to solve your problem turing off the LED, just change the low/high interval ratio to a maximum of low. Try playing around with the values in line 17, e.g. change them into: blinkl( a+100, 200 – a );

  15. November 5, 2009

    What line would I modify to make the LED completely turn off then fade on? Or is that even possible w/ the digital channels? Thanks though this code is the shizzle fo rizzle…

Comments are closed.