Knight Rider

Like the bouncing ball the Knight Rider effect is something that just has to be done with the Blinkenlight Shield. I will not demonstrate a boring version that switches just some LEDs on and off. I want to have this original style glowing effect. Some of the LEDs must not be fully on but „glow“. This requires so called „pulse width modulation“. That is some of the LEDs will be toggled on and off in rapid succession. If this is done fast enough the eye is does not see a flicker but some dimmer light.

//
//  www.blinkenlight.net
//
//  Copyright 2011 Udo Klein
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program. If not, see http://www.gnu.org/licenses/


void setup() {
    for (uint8_t pin=0; pin<20; ++pin) {
        pinMode(pin, OUTPUT);
    }
}

uint8_t brightness(const int8_t led, const int8_t pos) {    
    switch (abs(led-pos)) {
        case 0:     return 32;
        case 1:     return 16;
        case 2:     return 6;
        case 3:     return 2;
        default:    return 1;
    }
}

void pulse_width_modulation(const uint8_t pos) {
    for(uint8_t times=0; times<10; ++times) {
        for (uint8_t pass=0; pass<32; ++pass) {
            for (int8_t led=0; led<20; ++led) {
                digitalWrite(led, (brightness(led, pos) > pass));
            }
        }
    }
}

void loop() {
    static uint8_t pos=0;

    while(pos<20) {
        pulse_width_modulation(pos);
        ++pos;
    }

    while(pos>0) {
        --pos;
        pulse_width_modulation(pos);
    }
}

Let’s analyze the sketch. The underlying idea is that the glowing effect is some kind of cursor that has a position that moves back and forth. This is what the main loop takes care of. The brightness function will compute the desired brightness of an LED depending on the LED’s number and the position of the cursor. In between is the pulse_width_modulation. This function will cycle 10 times through 32 phases. For each phase it will cycle through all LEDs. Depending on any LED’s desired brightness and the phase it will switch the LED on and off. For example suppose the brightness function returns 16 for an LED. In this case the LED will be on for phase in 0..15 and off for phase in 16..31. Thus the LED would be on half of the time. Accordingly it will be visibly on but dimmer as an LED that is always on.


Follow me here to other similar effects.

21 Responses to Knight Rider

  1. Paul says:

    These sketches return many compilation errors. e.g:
    for (uint8_t pin=0; pin<20; ++pin) {

    Same happened with the bounce sketch.

    Could someone refer me to debugged sketches for al theose Blinken lights

    Thanks

  2. Paul says:

    All Blinken sketches here return compilation errors e.g.

    for (uint8_t pin=0; pin<20; ++pin) {
    above

    Would appreciate a reference to sketches that work

    Thanks

  3. Paul says:

    On basic as copied and pasted:

    Error Message:
    Sorry I could not copy and paste the error message. But if you copy and paste the sketch above that I copied and pasted from:

    Counting Resets


    you will see the errors. ( after removing line numbers)

    In particular the syntax pin<20, and pos&lt, seem to be repeating in all sketches.

    Also the sketches on your web have line numbers that copy along with the code and have to be removed. This too is a pain unless there is an easier way to to copy the sketches
    Hope you’ll be able to replicate my sketch and errors per my sketch above .

    Thanks for your help.

    • You copied the markup instead of the sketch. Hover the mouse in the upper right corner to get the plain text file. This should do it.

      • Paul says:

        Indeed that helped eliminate the line numbers. However at the top of the “markup” when I move the mouse at the top right, four icons appear: View source, Copy to Clip board, Print, and “help”. When I click View Source I get a sketch without line numbers which is OK. however, there are some characters in the markup sketch such as “pin<20;” that reappear verbatum that the compiler flags as error. If I correct “pin<20;” to “pin>20;” the error clears and the compiler passes. however the following line 40 still gives error:
        40 digitalWrite(led, (brightness(led, pos) > pass));
        I’m using UNO 022 on Vista.

  4. Paul says:

    I’m still not able to show you the characters giving errors. When I type them as in the sketch, I note in the reply panel, they get corrected. there is something dynamic between the sketch either markedup or as viewed that converts these characters. Once again the character stream in question is ( pin & 1 t ; 20 ) that translate in the transmission to you as pin>20. Same applies wherever this expression is used as in pos, pass, times etc

    Hope this help clarify the issue

    • You are still copying markup instead of code. Please do not click “view source” to copy the sketch. Click “Copy to Clipboard”. Then copy the contents of the clipboard into the editor. This should fix it.

      • By now I figured out that some of the sketches (3 in total) actually had improper markup. All others were fine. I fixed the 3 affected sketched. Thanks for pointing out this issue to me. I was somewhat thrown off track because you stated that all of my sketches had this issue.

  5. Bert says:

    Copy to clipboard works for me with no problems 🙂 I don’t have the shield yet (soon as I can afford it!) but the code copies/pastes clean.

  6. rontab says:

    Worked perfectly well on my system!

  7. Peter says:

    Udo I would just like to thank you for your interesting LED coding for examples, like the Knightrider with PWM. I am finding it useful as a learning exercise modifying your code and just using the eight LED’s in a line that I tend to use for trying and modifying peoples code as an aid to developing my very basic coding skills. I just declared an eight element array so I could change the 20 in the setup for loop down to the 8 required for my minimal setup. It runs perfectly on my Windows XP system. Anyway thanks again and hopefully I’ll see you on the Arduino forum.
    Peter Newman / Pedro147 on Arduino forum.

  8. Ashley says:

    I got the uno today and tried this out as my first experiment it worked a treat. Thanks 😀

  9. hockeyrink says:

    Clever code. Really, really clever. Took me a bit of time to figure out your fake PWM function, which I do by trying to comment code (forces me to analyse it thoroughly). I adapted it to my own nefarious purposes, but thought perhaps my comments may be handy to those who want to learn from your example. Pardon my conversion of uint8_t to Arduino shorthand – it was an extra level of distraction I didn’t need while parsing out your logic.

    //Assign ring levels to appropriate I/O line
    #define r1 13
    #define r2 12
    #define r3 11
    #define r4 10
    #define r5 9
    #define r6 8
    #define r7 7
    const int ledRings[] = {r1, r2, r3, r4, r5, r6, r7}; //Set me up the list of pins to be used with the LEDs
    int ringCount = 7; // Number of elements we’re USING in array (0 to 5 = 6)

    void setup()
    {
    for (int thisRing = 0; thisRing < ringCount; thisRing++) {
    pinMode(ledRings[thisRing], OUTPUT);
    }
    }

    byte brightness(const int led, const int pos) { //Test each LED for distance from focused position. The further way it is, ramp the brightness down
    switch (abs(led-pos)) {
    case 0: return 32; // LED IS the Pos'n? Make it full bright (32/32)
    case 1: return 16; // 1 LED away from Pos'n? Make it 1/2 bright (16/32)
    case 2: return 6; // 2 LEDs away? 6/32 (19% bright)
    case 3: return 1; // 3 LEDs away? 1/32 on (3% bright)
    default: return 1; // Even further away? Just make it barely on (3%)
    }
    }

    void pulse_width_modulation(const byte position) { //Position is the present focused LED location
    for(byte times=0; times<80; ++times) { // Loop "times" higher for a slower action
    for (byte brightLevel=0; brightLevel<32; ++brightLevel) { // Start of "fake" PWM. Looping thru all 32 levels of brightness that are available, from off (0) to full on (32)
    for (int led=0; led brightLevel)); //If tested brightness value is greater than brightLevel, turn it on
    }
    }
    }
    }

    void loop() {
    static int pos=0;

    while(pos0) {
    –pos;
    pulse_width_modulation(pos);
    }
    */
    }

    /*
    Let’s analyze the sketch.
    The underlying idea is that the glowing effect is some kind of cursor that has a position that moves back and forth.
    This is what the main loop takes care of.

    The brightness function will compute the desired brightness of an LED depending on the LED’s number and the position
    of the cursor.

    In between is the pulse_width_modulation. This function will cycle 10 times through 32 phases.
    For each phase it will cycle through all LEDs.
    Depending on any LED’s desired brightness and the phase it will switch the LED on and off.

    For example: Suppose the brightness function returns 16 for an LED.
    In this case the LED will be on for phase in 0..15 and off for phase in 16..31.
    Thus the LED would be on half of the time. Accordingly it will be visibly on but dimmer as an LED that is always on.
    */

  10. pedro14755 says:

    I modified your code lightly to terms I was more familiar with as well as declaring an eight element array so I could change the 20 in the setup for loop down to the 8 required for my minimal setup. I have posted this code at
    http://www.mediafire.com/download/dsfwmiu844r428d/_8_LED_Blinkenlight.ino

  11. Shereef Hisham says:

    Hello Sir,

    After reading this, I took the liberty of creating a visual representation of how the code loops work using Microsoft Excel in the following link:
    https://www.dropbox.com/s/nn9ltsphrnzgxjp/Knight%20Rider%20code%20visualization.xlsm?dl=0

    I’m hoping that this might be an added value to anyone who finds this interesting or finds the code a little bit confusing to follow.

    I would be more than glad if you could put this sheet here as a helping tool 🙂

    Many thanks for sharing your great experiments.


    Shereef

    • Hi Shereef,

      cool work and thanks for sharing. I would prefer to upload it to my site instead of having some dropbox link. Please add your copyright and a license note to your excel and I will upload it. For example GPL would be a very suitable license because my stuff is GPLed as well.

      Best regards,
      Udo

  12. wasteinc says:

    very njce implementation of software pwm , thanks for the very smart code. we have made a knight rider 15LED with my son on an arduino mini (pin2 until pin16 AKA A2).

    for the others that find the code a bit kryptic , the times value sets the speed, and if you want the LEDs to fade completely on the right side use a higher value than the number of LEDs you have here while(pos<20) {
    Unfortuntaley doing the same on the left side is not so easy, as negative numbers don't work well 🙂

    thanks again for the fishes

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.