Running lights Arduino connection diagram. Running turn signals on WS2812 and Arduino tape

In this tutorial we will continue working with LEDs, but we will increase the number of LEDs to 5. And we will create a running fire effect. To control the LEDs we will use manipulations with Arduino ports. We will directly write data to the Arduino ports. This is better than working with specific controller inputs/outputs. This will allow you to set the values ​​for the LEDs with just one operation.

Arduino UNO has 3 ports:
B (digital inputs/outputs 8 to 13)
C (analog inputs)
D (digital inputs/outputs 0 to 7)

Each port is controlled by 3 registers. DDR register determines whether the leg (pin) will be an input or an output. With help PORT register pin can be set to HIGH or LOW. With help PIN register you can read the state of the Arduino legs when they work as an input.

We will use port B. First, we must set all pins of port B as digital outputs. Port B only has 6 legs. The register bits for the DDRB B-port must be set to 1 if the leg will be used as an OUTPUT, and to 0 if the leg will be used as an INPUT. Port bits are numbered 0 to 7, but do not always contain all 8 bits. Example:
DDRB = B00111110; // set port B pins 1 to 5 as output and 0 as input.

Please note that in Microchip microcontrollers the opposite is true. 0 bit - the leg works as an output, and 1 - as an input.

In our running fire project we will use 5 outputs:
DDRB = B00011111; // set the legs of port B from 0 to 4 as outputs

To write values ​​to port B, you must use the PORTB register. You can light the first LED with the command:
PORTB = B00000001;
first and fourth:
PORTB = B00001001;

Now you can see how easily we can turn LEDs on and off. Now let's tell you about shift operators

There are 2 binary shift operators: the left shift operator >. The left shift operator > shifts bits to the right.

Example:
varA = 1; // 00000001
varA = 1 varA = 1 varA = 1

Now let's go back to our program, which is shown below. We need to enter 2 variables: the first upDown will contain the value of where to move - up or down, and the second cylon which LEDs to light.

In function setup() we determine which legs should work as outputs.

In the main loop() of the program, the LEDs are lit up one by one by incrementing the cylon variable, and when the topmost one is reached, the upDown variable is set to 0 and the LEDs are lit down in order.

/* Running fire. 5 LEDs */ unsigned char upDown=1; // start with an upward movement unsigned char cylon=0; // determines the LED order void setup() ( DDRB = B00011111; // set port B from 0 to 4 as outputs ) void loop() ( if(upDown==1)( // if we go up, then cylon++; if( cylon>=4) upDown=0; // when the highest LED number is reached, then in the next cycle we go down ) else ( cylon--; if(cylon==0) upDown=1; // when the lowest LED number is reached, then in the next cycle we go up) PORTB = 1

In this experiment we make a light run along an LED scale.

LIST OF PARTS FOR THE EXPERIMENT

- 1 Arduino Uno board;

- 1 solderless breadboard;

- 1 LED scale;

- 10 resistors with a nominal value of 220 Ohms;

- 11 male-male wires.

CIRCUIT DIAGRAM

DIAGRAM ON BREADBOARD

SKETCH

download sketch for Arduino IDE
// the LED scale is connected to a group of pins located // in a row. We give clear names to the first and last pins #define FIRST_LED_PIN 2 #define LAST_LED_PIN 11 void setup() ( // there are 10 LEDs in the scale. We could write pinMode 10 // times: for each of the pins, but this would bloat the code and // made changing it more problematic. // So it's better to use a loop. We execute // pinMode for each pin (pin variable) // from the first (= FIRST_LED_PIN) to the last inclusive // ​​(<= LAST_LED_PIN), всякий раз продвигаясь к следующему // (++pin увеличивает значение pin на единицу) // Так все пины от 2-го по 11-й друг за другом станут выходами for (int pin = FIRST_LED_PIN; pin <= LAST_LED_PIN; ++pin) pinMode(pin, OUTPUT); } void loop() { // получаем время в миллисекундах, прошедшее с момента // включения микроконтроллера unsigned int ms = millis(); // нехитрой арифметикой вычисляем, какой светодиод // должен гореть именно сейчас. Смена будет происходить // каждые 120 миллисекунд. Y % X — это остаток от // деления Y на X; плюс, минус, скобки — как в алгебре. int pin = FIRST_LED_PIN + (ms / 120) % 10; // включаем нужный светодиод на 10 миллисекунд, затем — // выключаем. На следующем проходе цикла он снова включится, // если гореть его черёд, и мы вообще не заметим отключения digitalWrite(pin, HIGH); delay(10); digitalWrite(pin, LOW); }

EXPLANATIONS FOR THE CODE

  • Using the expression for we will organize loop with counter . In this case, to configure output ports. To make such a loop, you need:
    • Initialize a counter variable by assigning it an initial value. In our case: int pin = FIRST_LED_ PIN ;
    • Specify the condition until which the loop will repeat. In our case: pin<= LAST_LED_ PIN ;
    • Determine the rule by which the counter will change. In our case ++pin(see below about the operator ++ ).
  • For example, you can make a loop for (int i = 10; i > 0; i = i - 1). In this case:
    • The variable i is assigned the value 10 ;
    • This value satisfies the condition i > 0 ;
    • Therefore, a block of code placed in a loop is executed the first time;
    • Meaning i decreases by one, according to a given rule, and takes the value 9 ;
    • The code block is executed a second time;
    • Everything is repeated again and again until the meaning i equal 0 ;
    • When i will become equal 0 , condition i > 0 will fail and the loop will end;
    • The controller will jump to the code following the loop for ;
  • Place the code you want to loop between the pair curly braces {} , if it contains more than one instruction;
  • Counter variable declared in statement for, can be used inside a loop. For example, in this experiment pin sequentially takes values ​​from 2 to 11 and, when passed to pinMode, allows you to configure 10 ports with one line placed in a loop;
  • Counter variables are only visible inside a loop. Those. if you turn to pin before or after the loop, the compiler will generate an error about an undeclared variable;
  • Design i = i - 1 in the explanation above is not an equation! We use the assignment operator = to assign to a variable i put value equal to current value i, reduced by 1 ;
  • Expression ++pin- this is the so-called operator increment , applied to a variable pin. This instruction will produce the same result as pin = pin + 1 ;
  • The operator works similarly to increment decrement - - , which decreases the value by one. Read more about this in the article about arithmetic operations;
  • Data type unsigned int used to store unsigned integers, i.e. only non-negative . Due to the extra bit, which is no longer used to store the sign, we can store values ​​up to 65 535 ;
  • Function millis returns the number of milliseconds that have passed since the microcontroller was turned on or rebooted. Here we use it to count the time between LED switches;
  • Using the expression (ms / 120) % 10 we determine which of the 10 LEDs should be lit now. To paraphrase, we determine which 120 ms segment is currently running and what its number is within the current ten. We add the sequence number of the segment to the number of the port that appears first in the current set;
  • What we do is extinguish the LED with digitalWrite(pin, LOW) just 10 ms after switching on it is not noticeable to the eye, because very soon it will be calculated again which LED to turn on, and it will be turned on - the one just turned off or the next one.

QUESTIONS TO TEST YOURSELF

  1. Why in this experiment we connect the LED scale without using a transistor?
  2. If we only turned on the LEDs on ports 5, 6, 7, 8, 9, what would need to be changed in the program?
  3. What other instruction can be used to perform an action equivalent to ++pin ?
  4. What's the difference between type variables int And unsigned int ?
  5. What does the function return? millis() ?
  6. In this experiment, how do we calculate the port number on which to turn on the LED?

TASKS FOR INDEPENDENT SOLUTION

  1. Change the code so that the LEDs switch once per second.
  2. Without turning off the ports, make sure that the light runs only along the middle four divisions of the scale.
  3. Rework the program so that instead int pin = FIRST_LED_ PIN + (ms / 120) % 10 the movement of the light was controlled by a cycle for .
  4. Without swapping the wires, change the program so that the light runs in the opposite direction.

In this tutorial we will continue working with LEDs, but we will increase the number of LEDs to 5. And we will create a running fire effect. To control the LEDs we will use manipulations with Arduino ports. We will directly write data to the Arduino ports. This is better than working with specific controller inputs/outputs. This will allow you to set the values ​​for the LEDs with just one operation.

Arduino UNO has 3 ports:

  • B (digital inputs/outputs 8 to 13)
  • C (analog inputs)
  • D (digital inputs/outputs 0 to 7)

Each port is controlled by 3 registers. The DDR register determines whether the pin will be an input or an output. Using the PORT register, you can set the pin to HIGH or LOW. Using the PIN register, you can read the state of the Arduino pins when they are working as an input.

We will use port B. First, we must set all pins of port B as digital outputs. Port B only has 6 legs. The register bits for the DDRB B-port must be set to 1 if the leg will be used as an OUTPUT, and to 0 if the leg will be used as an INPUT. Port bits are numbered 0 to 7, but do not always contain all 8 bits.

Example:

DDRB = B00111110; // set port B pins 1 to 5 as output and 0 as input.

Please note that in Microchip microcontrollers the opposite is true. 0 bit - the leg works as an output, and 1 - as an input.

In our running fire project we will use 5 outputs:

DDRB = B00011111; // set the legs of port B from 0 to 4 as outputs

To write values ​​to port B, you must use the PORTB register. You can light the first LED with the command:

PORTB = B00000001;
first and fourth:
PORTB = B00001001;

Now you can see how easily we can turn LEDs on and off. Now let's tell you about shift operators

There are 2 binary shift operators: left shift operator<< и оператор сдвига вправо >>. Left shift operator<< заставляет все биты сдвигаться влево, соответственно оператор сдвига вправо >> shifts bits to the right.

Example:

VarA = 1; // 00000001
varA = 1<< 0; // 00000001
varA = 1<< 1; // 00000010
varA = 1<< 2; // 00000100

Now let's go back to our program, which is shown below. We need to enter 2 variables: the first upDown will contain the value of where to move - up or down, and the second cylon which LEDs to light.

In function setup() we determine which legs should work as outputs.

In the main program loop loop(), the LEDs light up in turn by increasing the variable cylon, and when it comes to the very top, then the variable upDown is assigned 0 and the LEDs light up in sequence.

Schematic diagram

Scheme on the breadboard

note

    Note that in this experiment the resistors are placed between the cathodes and ground, unlike in the pulsar experiment.

    We connect the LEDs to the digital ports, starting with port 2. We can use ports 0 and 1, but they are serial port data channels and for each board flashing we will have to disconnect the devices connected to them.

Sketch

The unsigned int data type is used to store unsigned integers, i.e. only non-negative. Due to the extra bit, which is no longer used to store the sign, we can store values ​​up to 65,535 in a variable of this type.

Using the expression (ms / 120) % 10 we determine which of the 10 LEDs should be lit now. To paraphrase, we determine which 120 ms segment is currently running and what its number is within the current ten. We add the sequence number of the segment to the number of the port that appears first in the current set.

The fact that we extinguish the LED using digitalWrite(pin, LOW) just 10 ms after turning it on is not noticeable to the eye, because very soon it will be calculated again which LED to turn on, and it will be turned on - the one just turned off or the next one.

Questions to test yourself

    Why in this experiment we connect the LED scale without using a transistor?

    If we only turned on the LEDs on ports 5, 6, 7, 8, 9, what would need to be changed in the program?

    What other instruction can perform an action equivalent to ++pin ?

    What is the difference between int and unsigned int variables?

    What does the millis() function return?

    In this experiment, how do we calculate the port number on which to turn on the LED?

Making running lights from LEDs using Arduino. In this case, an Arduino Mega 2560 is used, which is potentially capable of controlling a treadmill of 54 LEDs. But the circuit and program will not change if you use other controllers from the Arduino platform of this type (UNO, Leonardo...)

Diagram for connecting LEDs to Arduino Mega 2560.

This is what the sketch looks like in the window of a standard Arduino programming application.

Text of the program for implementing running lights on the Arduino platform.

int first_out = 11; //first discrete output

int last_out = 13; //last discrete output

//block for initializing inputs-outputs and other initial data

last_out = last_out + 1; //add a unit for correct use in loops

//defining the 11th, 12th and 13th discrete pins of the Arduino board as outputs

for (i = first_out; i< last_out; i++) { pinMode(i, OUTPUT); }

for (t = first_out; t< last_out; t++) { //перебираем номера дискретных выходов 11,12,13 поочереди

digitalWrite(t, HIGH); //lighting the next LED

delay(500); //delay 500ms

for (i = first_out; i< last_out; i++) { digitalWrite(i, LOW); }//гасим все светодиоды

To increase the number of controllable LEDs in a garland, in the program you will simply need to replace the values ​​of the first_out and last_out. The first variable stores the initial discrete output of the controller, and the second is the last of a group of outputs that come in a row. For example, if we want to connect 10 LEDs in a garland, we enter the following values: first_out = 4, last_out = 13. And LEDs to pins in order from 4th to 13th. It is better not to touch the first and second pins of discrete inputs and outputs, since they are interfered with by the USB port connected to the computer.