Ever wished you had your own Knight Industries Two Thousand (KITT) car -- you know, from Knight Rider? Make your dream one step closer to reality by building an LED scanner! Here's the end result:

What You Need

There's not a lot of parts needed for this project, and you may have many of them already:

  • 1 x Arduino UNO or similar
  • 1 x Breadboard
  • 8 x red LEDs
  • 8 x 220 ohm resistors
  • 1 x 10k ohm potentiometer
  • Male to male hook up wires

If you have an Arduino starter kit it's likely you have all of these parts (what can you make with a starter kit?).

Almost any Arduino will work, providing it has eight available pins (Never used an Arduino before? Get started here). You could use a Shift Register to control the LEDs, although this is not needed for this project, as the Arduino has enough pins.

Build Plan

Arduino-Knight-Rider-Led-Scanner-Complete

This is a very simple project. Whilst it may look complex from the large number of wires, each individual part is very simple. Each Light Emitting Diode (LED) is connected to it's own Arduino pin. This means each LED can be individually turned on and off. A potentiometer is connected to the Arduino analog in pins, which will be used to adjust the speed of the scanner.

The Circuit

Arduino-Knight-Rider-Circuit

Connect the outer left pin (looking at the front, with the pins at the bottom) of the potentiometer to ground. Connect the opposite outer pin to +5v. If it does not work correctly, reverse these pins. Connect the middle pin to Arduino analog in 2.

Connect the anode (long leg) of each LED to digital pins one through eight. Connect the cathodes (short leg) to Arduino ground.

The Code

Create a new sketch and save it as "knightRider". Here's the code:

        const int leds[] = {1,2,3,4,5,6,7,8}; // Led pins
const int totalLeds = 8;
int time = 50; // Default speed

void setup() {
    // Initialize all outputs
    for(int i = 0; i <= totalLeds; ++i) {
        pinMode(leds[i], OUTPUT);
    }
}

void loop() {
    for(int i = 0; i < totalLeds - 1; ++i) {
        // Scan left to right
        time = analogRead(2);
        digitalWrite(leds[i], HIGH);
        delay(time);
        digitalWrite(leds[i + 1], HIGH);
        delay(time);
        digitalWrite(leds[i], LOW);
    }
    for(int i = totalLeds; i > 0; --i) {
        // Scan right to left
        time = analogRead(2);
        digitalWrite(leds[i], HIGH);
        delay(time);
        digitalWrite(leds[i - 1], HIGH);
        delay(time);
        digitalWrite(leds[i], LOW);
    }
}

Let's break it down. Each LED pin is stored in an array:

        const int leds[] = {1,2,3,4,5,6,7,8};
    

An array is essentially a collection of related items. These elements are defined as constant ("const"), which means they cannot be changed later on. You do not have to use a constant (the code will work perfectly if you remove "const"), although it is recommended.

Elements of an array are accessed by using square brackets ("[ ]") and an integer called an index. Indexes start at zero, so "leds[2]" would return the third element in the array -- pin 3. Arrays make code quicker to write and easier to read, they make the computer do the hard work!

A for loop is used to setup each pin as an output:

        for(int i = 0; i <= totalLeds; ++i) {
        pinMode(leds[i], OUTPUT);
}

This code is inside the "setup()" function, as it only needs to run once at the start of the program. For loops are very useful. They allow you to run the same code over and over again, with a different value each time. They are perfect for working with arrays. An integer "i" is declared, and only code inside the loop can access this variable (this is known as "scope"). The value of i starts at zero, and for each iteration of the loop, i is increased by one. Once the value of i is less than or equal to the "totalLeds" variable, the loop "breaks" (stops).

The value of i is used to access the "leds" array. This loop accesses every element in the array and configures it as an output. You could manually type "pinMode(pin, OUTPUT)" eight times, but why write eight lines when you can write three?

Whilst some programming languages can tell you how many elements are in an array (usually with syntax like array.length), Arduino does not make it so simple (it involves a bit more maths). As the number of elements in the array is already known, it's not a problem.

Arduino-Knight-Rider-LEDS
Multiple LEDs are lit up at the same time.

Inside the main loop (void loop()) are two further for loops. The first sets the LEDs ON and then OFF from 1 - 8. The second loop sets the LEDs ON and then OFF from 8 - 1. Notice how the current pin is set on, and the current pin plus one is set on as well. This ensures that there are always two LEDS on at the same time, making the scanner look more realistic.

At the start of each loop, the value of the pot is read into the "time" variable:

        time = analogRead(2);
    

This is done twice, once inside each loop. This needs to be constantly checked and updated. If this was outside of the loops, it would still work, however there would be a small delay -- it would only run once a loop has finished executing. Pots are analog, hence why "analogRead(pin)" is used. This returns values between zero (minimum) and 1023 (maximum). Arduino is capable of converting these values to something more useful, however they are perfect for this use case.

The delay between changing LEDs (or the speed of the scanner) is set in milliseconds (1/1000 second), so the maximum time is just over 1 second.

Advanced Scanner

Arduino-LEDs-Outside-Pairs
Outside pairs lit-up

Now that you know the basics, let's look at something more complex. This scanner will light the LEDs in pairs starting from the outside and working in. It will then reverse this and go from inside to outside pairs. Here's the code:

        const int leds[] = {1,2,3,4,5,6,7,8}; // Led pins
const int totalLeds = 8;
const int halfLeds = 4;
int time = 50; // Default speed

void setup() {
    // Initialize all outputs
    for(int i = 0; i <= totalLeds; ++i) {
        pinMode(leds[i], OUTPUT);
    }
}

void loop() {
    for(int i = 0; i < (halfLeds - 1); ++i) {
        // Scan outside pairs in
        time = analogRead(2);
        digitalWrite(leds[i], HIGH);
        digitalWrite(leds[(totalLeds - i) - 1], HIGH);
        delay(time);
        digitalWrite(leds[i], LOW);
        digitalWrite(leds[(totalLeds - i) - 1], LOW);
        delay(time);
    }
    for(int i = (halfLeds - 1); i > 0; --i) {
        // Scan inside pairs out
        time = analogRead(2);
        digitalWrite(leds[i], HIGH);
        digitalWrite(leds[(totalLeds - i) - 1], HIGH);
        delay(time);
        digitalWrite(leds[i], LOW);
        digitalWrite(leds[(totalLeds - i) - 1], LOW);
        delay(time);
    }
}

This code is slightly more complex. Notice how both loops go from zero to "halfLeds - 1" (3). This makes a better scanner. If both loops went from 4 - 0 and 0 - 4 then the same LEDs would flash twice in the same sequence -- this would not look very good.

You should now own a working Knight Rider LED scanner! It would be easy to modify this to use more or larger LEDs, or implement your own pattern. This circuit is very easy to port to a Raspberry Pi (new to Pi? Start here) or ESP8266.

Are you building a replica KITT? I'd love to see all things Knight Rider in the comments.