DIY floating turn signal made from Arduino. Dynamic turn signals - we make running lights from the KIT kit. Work sequence

Let's consider creating a running turn signal like on an Audi, using the example of a headlight from a Renault Clio car. Let's make turn signals and DRLs in one device.

What you will need for this: LED strip consisting of ws2812b LEDs Arduino nano controller(can be used in any other form factor) Automotive charger For mobile phones With USB output. Since the Arduino controller needs a voltage of 5V, we will use this charger as a voltage converter from 12V to 5V. Voltage stabilizer for 5V KR142EN5V (KREN5V) or any other imported analogue. 3 10 kOhm resistors as pull-up resistance.

Connection diagram

The Arduino controller must be connected to the car's network via a 12V -> 5V converter so that the voltage to the circuit comes from turning on the ignition. You need to connect the positive wire from the existing turn signal to the KREN5V voltage stabilizer. This article discusses the connection and firmware of only one turn signal; to make a second turn signal, you need to connect the second one in the same way LED strip to any free digital output Arduino (for example 7), and also add code for it in the firmware according to our example.

Controller firmware

To work with pixel LEDs you will need a library . You can install it as follows: Sketch -> Connect library -> Manage libraries. Next, enter the name of the library Adafruit_NeoPixel.h in the search menu and click the install button. After that, insert the sketch into the program and replace the number of LEDs in the code (we use 22 diodes):

#include // connect the library
Adafruit_NeoPixel strip = Adafruit_NeoPixel(22, 8, NEO_GRB + NEO_KHZ800);
int t,t1,t2,t3,t4,p2,p1 = 0;// time variable
void setup() (
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
digitalWrite(2, LOW);
digitalWrite(3, LOW);
digitalWrite(4, LOW);

strip.begin();
strip.show();

}
void loop() (
if (digitalRead(2) == LOW) ( //If the turn signal is off
for(int i = 0; i< 23; i++) {
strip.setPixelColor(i, strip.Color(255,255,255)); // R=255, G=255, B=255 - white color of the LED, when turned on we turn on the running lights
}
strip.show();
}

if ((digitalRead(2) == HIGH) & (t == 1)) ( // check if the turn signal is on
for(int i = 0; i< 23; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0)); // extinguish all diodes
}
strip.show();
for(int k = 0; k< 3; k++){ // цикл до трех - сигнал «перестроения» , при кратковременном включении мигает 3 раза,

for(int i = 0; i< 23; i++){

if (digitalRead(2) == HIGH) (k = 0;) // if while the turn signal is blinking we receive another positive signal, then reset the counter so that the turn signal blinks at least 3 more times
strip.setPixelColor(i, strip.Color(255, 69, 0)); // R=255, G=69, B=0 - LED color

delay((t4)/22);
strip.show();

}
if (digitalRead(2) == HIGH) (t4=t4+20;) // if all the diodes are lit yellow, but the signal from the relay is still coming, then we increase the burning time
if (digitalRead(2) == LOW) (t4=t4-20;) // if all the diodes are lit yellow, but the signal from the relay is still coming, then we increase the burning time

for(int i = 0; i< 23; i++){

strip.setPixelColor(i, strip.Color(0, 0, 0)); // R=0, G=0, B=0 - LED color

delay((t3)/22);
strip.show();

}
if ((digitalRead(2) == LOW)) (t3=t3+20;)
if ((digitalRead(2) == HIGH)) (t3=t3-20;)
}

if ((digitalRead(2) == HIGH) & (t == 0)) ( // check if the turn signal is on

t1 = millis(); //remember what time you turned on
for(int i = 0; i< 22; i++) {
strip.setPixelColor(i, strip.Color(255, 69, 0)); // when you turn on the turn signal for the first time, turn on all the diodes yellow
}
strip.show();
while (digitalRead(2) == HIGH) ()
t2 = millis(); // remember what time the turn signal turned off
t4=t2-t1;

for(int i = 0; i< 22; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0)); // extinguish the diodes when the signal from the turn relay disappears
}
strip.show();
while (digitalRead(2) == LOW) (
if ((millis()-t2)>2000)(break;)
}
if ((millis()-t2)<2000) {
t3 = millis()-t2; // time for which the turn signals go off
t = 1; // flag, we know that the time value has been saved.
}
}

if (digitalRead(4) == HIGH) ( //special signals
for(int j = 0; j< 16; j++) {
for(int i = 0; i< 22; i++) {
strip.setPixelColor(i, strip.Color(255, 0, 0)); // R=255, G=0, B=0 - LED color
}
strip.show();
delay(20);
for(int i = 0; i< 22; i++){

}
strip.show();
delay(20);
}

for(int j = 0; j< 16; j++) {
for(int i = 0; i< 22; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 255)); // R=0, G=0, B=255 - LED color
}
strip.show();
delay(20);
for(int i = 0; i< 22; i++){
strip.setPixelColor(i, strip.Color(0, 0, 0)); // R=0, G=0, B=0 - LED color
}
strip.show();
delay(20);
}
}

if (digitalRead(3) == HIGH) ( //strobe
for(int j = 0; j< 24; j++) {
for(int i = 0; i< 22; i++) {
strip.setPixelColor(i, strip.Color(255, 255, 255)); // R=255, G=255, B=255 - LED color
}
strip.show();

delay(15);
for(int i = 0; i< 22; i++){
strip.setPixelColor(i, strip.Color(0, 0, 0)); // R=0, G=0, B=0 - LED color
}
strip.show();
delay(15);
}
delay(500);

Do the same for the code for the second turn signal.

Video of how our headlight works

I said “Gop” last year - it’s time to jump :)
Or rather, do the promised review of running turn signals.
I ordered 1 meter of black WS2812B tape (144 LEDs) in a silicone tube, when ordering I chose “Black 1m 144led IP67” (perhaps someone will like the white color of the substrate, there is such a choice).

A word of caution

I received a tape soldered from two half-meter pieces. The downside of this is a vulnerable soldering point (contacts may break over time) and an increased gap between the LEDs.
Before purchasing, check with the seller about this point.

Contact wires were soldered to the tape on both sides to connect several pieces in series, because I didn’t need this, so I unsoldered the wires on one side, sealed everything with a neutral sealant and wrapped a little more black electrical tape.



Attached to the glass using double-sided transparent adhesive tape, for example.

Installation details

I degreased the surfaces, first glued adhesive tape to the tube (I’ll call it that, even though the cross-section is rectangular), cut off the protruding excess of the wider tape, pushed the edges of the tube into the cracks between the ceiling and the upper parts of the decorative panels of the rear pillars (the contact wires with the connector were hidden behind one panel ), centered it and began to press it against the glass, slowly pulling out the protective layer of the tape.
Unfortunately, there is no video - there were no free hands for filming, and everyone’s car is different.
If anything is unclear, ask in the comments.
The test in the summer heat was successful - nothing came off or floated.
The only negative is that the angle of the glass is gentle, the LEDs shine more upward. On a sunny day it’s hard to see, but since these are duplicate signals,

Now let's move on to the electronic stuffing.
I used it, but discovered it not long ago

For about the same cost we get more goodies

The sketch will work without any special modifications on Wemos when programming in the Arduino IDE, and if you implement a small web server, then when connected to it via Wi-Fi, you can change the values ​​of such variables as the delay time between blinks, the amount of deceleration during emergency braking etc.
Here in the future, if someone is interested in implementing a project on the ESP8266, I can post an example for changing the settings via the web interface, saving them in EEPROM, and then reading them.
The web server can be launched, for example, through the turn signal being turned on and the brake pedal being pressed when the ignition is turned on (in the setup procedure, poll the status of the corresponding inputs).

To implement a flashing mode during heavy braking, I purchased
The sketch monitors the level of deceleration when pressing the brake pedal; if it exceeds 0.5G (sharp deceleration, but without squealing brakes), then a flashing mode is turned on for a few seconds to attract additional attention.
Control signals to the Arduino inputs from the “plus” of stops, turn signals and reverse are supplied through galvanic isolation - optocouplers with current-limiting resistors, which ultimately form the LOW level at the Arduino inputs (constantly pulled to positive through 10 kOhm resistors).
Power supply - 5 volts via a DC-DC step-down converter.
The whole thing is folded into a sandwich and packed in a suitable box, on which the installation direction is marked with an arrow for the correct orientation of the gravity sensor

Diagram and photo



The nominal value of pull-up (to positive) resistors is standard - 10 kOhm, limiting the current of the optocoupler resistors - 1 kOhm. I removed the optocouplers from old boards, two were PC123, two were PC817.


In the first photo you can see two additional terminals; I made them for the turn signals. Since in my car, when the steering column lever is turned on, there is a short to ground, I connected the wires to the lever block and the Arduino inputs. If the steering column lever switches the plus or you take the signal from the “+” of the left/right turn signal lamps, then connect them through galvanic isolation.



Well, now the sketch itself (Arduino IDE)

#include #include //a few general comments // I turned off one of the outermost LEDs, because... they reflected on the decorative panels of the racks //visible in the example of this cycle for (int i=1; i<143; i++) //если отключать не нужно, заменяем на for (int i=0; i<144; i++) //задний ход и аварийка у меня не используются, т.к. в первом случае яркость никакая, во втором надо подключать входы к лампам поворотников //поворотники и стоп-сигнал одновременно не включаются, чтобы это реализовать, нужно переписывать соответствующий код скетча (делить ленту на три секции, подбирать тайминги миганий, менять диапазон переменных циклов). //Дерзайте - все в ваших руках // Пин для подключения управляющего сигнала светодной ленты const int PinLS = 2; //Пины для подключения датчиков //если более удобно будет подключать контакты в другом порядке - просто поменяйте значения переменных const int buttonPinL = 3; const int buttonPinR = 4; const int buttonPinS = 6; const int buttonPinD = 5; //начальные статусы входов (подтянуты к плюсу) int buttonStateS = HIGH; int buttonStateD = HIGH; int buttonStateL = HIGH; int buttonStateR = HIGH; // пауза pause_pov1 (в миллисекундах) нужна, чтобы синхронизировать циклы "пробегания" полоски и включения лампочки поворотника // такое может быть, если используется меньше половины светодиодов // в моем случае паузы нет (pause_pov1 = 0) int pause_pov1 = 1; // этой паузой регулируем длительность состояния, когда все светодиоды выключены //я определял опытным путем - включал поворотник, засекал по отдельности время ста мыргов лампочкой и ста беганий полоски, разницу делил на 100, на полученное время увеличивал или уменьшал значение переменной (в зависимости от того, отставали или убегали вперед лампочки) int pause_pov2 = 62; // переменная для получения значения ускорения int ix; Adafruit_NeoPixel strip = Adafruit_NeoPixel(144, PinLS, NEO_GRB + NEO_KHZ800); Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345); void setup() { pinMode(buttonPinS, INPUT); pinMode(buttonPinD, INPUT); pinMode(buttonPinL, INPUT); pinMode(buttonPinR, INPUT); strip.begin(); // гасим ленту for (int i=0; i<144; i++) strip.setPixelColor(i, strip.Color(0,0,0)); strip.show(); accel.begin(); // ограничиваем измеряемый диапазон четырьмя G (этого хватит с большим запасом) accel.setRange(ADXL345_RANGE_4_G); accel.setDataRate(ADXL345_DATARATE_100_HZ); } void loop() { // СТОПЫ: если включены - высший приоритет //Чтобы сделать меняющуюся по ширине полоску в зависимости от интенсивности торможения //(уточнение - никакой светомузыки, ширина полосы после нажатия на тормоз не меняется!) //от плавного торможения до тапки в пол. //Добавляем еще одну переменную, например, ix2, //присваиваем ей значение ix с коэффициентом умножения, //заодно инвертируем и округляем до целого //ix = event.acceleration.x; //ix2 = -round(ix*10); //ограничиваем для плавного торможения в пробках //(чтобы не менялась при каждом продвижении на 5 метров) //if (ix2<10) ix2 = 0; //и для резкого торможения. //Реальный диапазон изменения переменной ix - от 0 до -5 //для максимальной ширины полосы при G равном или большем 0.5 //if (ix2 >50) ix2 = 50; //then change the cycles in the STOP block for (int i=1; i<143; i++) на for (int i=51-ix2; i<93+ix2; i++) //Получаем минимальную ширину полоски ~30 см (для стояния в пробке) и максимальную для резкого торможения //конец комментария buttonStateS = digitalRead(buttonPinS); if (buttonStateS == LOW) { sensors_event_t event; accel.getEvent(&event); ix = event.acceleration.x; // проверка резкого торможения - мигающий режим // значение 5 - это 0,5G, минус - торможение if (ix < -5) { for (int is=0; is<15; is++) { for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(240,0,0)); strip.show(); delay(10 + is*10); for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(0,0,0)); strip.show(); delay(10 + is*3); buttonStateS = digitalRead(buttonPinS); if (buttonStateS == HIGH) return; } } // помигали - и хватит, включаем постоянный режим, если педаль тормоза еще нажата // или если не было резкого торможения и предыдущее условие не сработало if (buttonStateS == LOW) { for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(200,0,0)); strip.show(); while(buttonStateS == LOW){ buttonStateS = digitalRead(buttonPinS); delay(50); } // плавно гасим for (int is=0; is<20; is++) { for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(190 - is*10,0,0)); strip.show(); delay(10); } // СТОПЫ конец } } else // если СТОПЫ выключены { // ЗАДНИЙ ХОД: если включен - средний приоритет buttonStateD = digitalRead(buttonPinD); if (buttonStateD == LOW) { for (int i=1; i<37; i++) strip.setPixelColor(i, strip.Color(63,63,63)); for (int i=107; i<143; i++) strip.setPixelColor(i, strip.Color(63,63,63)); strip.show(); while(buttonStateD == LOW){ buttonStateD = digitalRead(buttonPinD); delay(50); } //плавно гасим for (int is=0; is<16; is++) { for (int i=1; i<37; i++) strip.setPixelColor(i, strip.Color(60 - is*4,60 - is*4,60 - is*4)); for (int i=107; i<143; i++) strip.setPixelColor(i, strip.Color(60 - is*4,60 - is*4,60 - is*4)); strip.show(); delay(10); } } buttonStateL = digitalRead(buttonPinL); buttonStateR = digitalRead(buttonPinR); // если включена аварийка if (buttonStateL == LOW && buttonStateR == LOW) { for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(63,31,0)); strip.setPixelColor(il+72, strip.Color(63,31,0)); strip.show(); delay(pause_pov1); } for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(0,0,0)); strip.setPixelColor(il+72, strip.Color(0,0,0)); strip.show(); delay(pause_pov1); } delay(pause_pov2); } // если включен ЛЕВЫЙ ПОВОРОТНИК if (buttonStateL == LOW && buttonStateR == HIGH) { for (int il=0; il<71; il++) { strip.setPixelColor(il+72, strip.Color(220,120,0)); strip.show(); delay(pause_pov1); } for (int il=0; il<71; il++) { strip.setPixelColor(il+72, strip.Color(0,0,0)); strip.show(); delay(pause_pov1); } delay(pause_pov2); } // если включен ПРАВЫЙ ПОВОРОТНИК if (buttonStateL == HIGH && buttonStateR == LOW) { for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(220,120,0)); strip.show(); delay(pause_pov1); } for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(0,0,0)); strip.show(); delay(pause_pov1); } delay(pause_pov2); } //правый поворотник конец } //конец условия else Стоп // задержка для следующего опроса датчиков delay(10); }

I tried to comment on it as much as possible, but if there are questions, I will try to add comments (that’s why I’m placing it in the text of the review, and not as an attached file). This, by the way, also applies to other points of the review - I will also supplement it if there are significant questions in the comments.

And finally, a demonstration of the work (for the video I used a sketch with demo mode).

Upd. I made the sketch with the demo mode specifically to fit everything into one short video.
The brake light flashes only during hard braking (this was discussed above); during slow braking and when standing in traffic jams, it simply lights up, without irritating the drivers behind.
The brightness at night is not excessive, because... Due to the tilt of the glass, the lights are directed more upward than backward.
The standard lights work as usual, this strip duplicates them.

I'm planning to buy +97 Add to favorites I liked the review +89 +191

Many car enthusiasts, in order to improve the appearance of their car, tune their “Swallow” with LED lights. One of the tuning options is a running turn signal, which draws the attention of other road users. The article provides instructions for installing and configuring turn signals with running lights.

[Hide]

Assembly instructions

LED lamps are semiconductor elements that glow when exposed to electric current. The main element in them is silicon. Depending on what impurities are used, the color of the light bulbs changes.

Photo gallery “Possible options for dynamic direction indicators”

Tools and materials

To make a running turn signal with your own hands, you will need the following tools:

  • soldering iron;
  • side cutters or pliers;
  • soldering iron and soldering material;
  • tester.

You need to prepare fiberglass laminate from consumables. It is needed for the manufacture of a printed circuit board on which the semiconductor element will be placed. The required LEDs are selected. Depending on the characteristics of the LEDs and the current and voltage values ​​of the on-board network, the characteristics of the protective resistors are calculated. Using calculations, the remaining components of the network are selected (the author of the video is Evgeny Zadvornov).

Work sequence

Before making turn signals, you need to choose a suitable scheme.

Then, based on the diagram, make a printed circuit board and apply markings on it to place future elements.

The assembly consists of a sequence of actions:

  1. First, you should turn off the power to the car by disconnecting the negative terminal from the battery.
  2. Next, you need to remove the old turn signals and carefully disassemble them.
  3. Old light bulbs should be unscrewed.
  4. The joints should be cleaned of glue, degreased, washed and allowed to dry.
  5. In place of each old element, a new running light turn signal is installed.
  6. Next, assembly and installation of the lights is done in the reverse order.
  7. After installation, the wires are connected.

At the next stage, an additional stabilized power source is connected to the network. Its input receives power from the intermediate relay, and the output is connected to a diode. It is better to place it in the instrument panel.

When connecting LEDs, you must ensure that the anode is connected to the plus of the power source, and the cathode to the minus. If the connection is not made correctly, the semiconductor elements will not light up and may even burn out.


Features of installation and configuration of running direction indicators

You can install dynamic turn signals instead of conventional LEDs. To do this, the board with LEDs and current-limiting resistors is removed and dismantled. On the repeater you need to tear the glass away from the body. Then you should carefully cut out the reflector and remove it.

In place of the remote reflector, an SMD 5730 board is installed, on which yellow LEDs are located. Since the repeater has a curved shape, the board will have to be delaminated and bent a little. You need to cut off the part with the connector from the old board and solder it to connect the controller. Then all components are returned to their place.

To adjust the timing of the running LED lights, a switch is soldered to the microcontroller. When a suitable speed is found, jumpers are soldered in place of the switch. When connecting two pins to ground, the minimum time between LED flashes will be 20 ms. When the contacts are closed, this time will be 30 ms.


Price issue

You can make a running light turn signal from daytime running lights. Their cost is 600 rubles. In this case, you can use “pixel” RGB LEDs as light sources in the amount of 7 pieces for each running turn signal. The cost of one element is 19 rubles. To control the LEDs, you need to purchase an Arduino UNO costing 250 rubles. Thus, the total cost will be 1060 rubles.

All those who have seen a more or less modern car not for the second time, and even if it was a matter of driving, have long noted for themselves one of the useful options... People call it a lazy turn signal or a polite turn signal. Its whole essence boils down to the fact that when turning right or left, the driver only touches the turn signal lever once, without fixing it. That is, it simply makes the turn signal circuits work, but does not turn on this very switch. As a result, after the lever is released, the direction indicators are activated 3-4 more times, and at this time the driver can already go about “his business,” that is, devote himself entirely to the road. The option is very useful when you have to change lanes. After all, when the turn signal lever is fully turned on, automatic shutdown will not occur, due to the insignificant angle of rotation of the steering wheel, which means you will have to poke back and forth with the pointer itself or constantly support it with your hand on the verge of turning on in order to imitate the operation of the turn signal. And if there is such an option, then I just slightly touched the lever and forgot. In general, we think that the essence of the work has been fully revealed, but now it’s worth mentioning the possibility of implementing such an option on your machine.

For which electrical circuits is a polite turn signal on Arduino suitable?

Before you go into all serious troubles about the production of a polite turn signal, you need to understand what electrical connection diagrams it will be suitable for without modifying the electrical circuit in the car.
Here we are presented with two main options that differ in principle. The first is when the turn signals turn on when they are connected as a load. That is, switching on occurs due to switching the circuit of turn signal lamps, in which the turn signal lever itself is located, it is this that closes the circuit, after which the operation occurs. In this case, it will not be possible to use our option, since when the lever opens the circuit with the lamps, we immediately disable the possibility of light indication, even if a signal arrives at the lever itself, it simply will not go any further.
The second option is ours, when there are control signals and there are output power signals. In this case, instead of the standard relay, you can install exactly the circuit that we would like to bring to your attention.

Relay power module that can be purchased on the Internet to control the power load

Sketch and circuit of a lazy (polite) turn signal on Arduino

So, one can argue about using Arduino as a head unit for lazy turn signals, since this is also not an ideal solution, which has its drawbacks. For example, it will be necessary to have constant power after turning on the ignition; in order to ensure performance, it will be necessary to connect power circuits. At the same time, the harness itself of extra radio components is basically useless here, because in this case you can simply program a microcontroller and use only it. But this minus is also a plus, because anyone who has one can program Arduino, and for microcontrollers you will also need a programmer.
Writing a program will be one of the most difficult tasks. Here a beginner will have to spend more than one hour of his free time and studying the work of algorithms, but fortunately there is the Internet and there is us. So here's the sketch.

Int switchPinR=8; int switchPinL=7; int ledPinR=11; int ledPinL=12; boolean ledOn = false; int i=0; int z=0; void setup() ( // put your setup code here, to run once: pinMode(switchPinR, INPUT); pinMode(switchPinL, INPUT); pinMode(ledPinR, OUTPUT); pinMode(ledPinL, OUTPUT); Serial.begin(9600 ); ) void loop() ( // put your main code here, to run repeatedly: //2 label: if (digitalRead(switchPinR) == HIGH && digitalRead(switchPinL) == HIGH) ( digitalWrite(ledPinR, HIGH) ; digitalWrite(ledPinL, HIGH);<7) { ledOn = !ledOn; digitalWrite(ledPinR, ledOn); digitalWrite(ledPinL, ledOn); delay(400); i++; z++; if (digitalRead(switchPinL) == LOW && digitalRead(switchPinR) == LOW && z>=7) ( break; ) ) ) else ( digitalWrite(ledPinR, LOW); digitalWrite(ledPinL, LOW); z=0; ) //cycling the emergency signal if (digitalRead(switchPinR) == HIGH && digitalRead(switchPinL) == HIGH) (goto label;) //Right turn signal. if (digitalRead(switchPinR) == HIGH) ( digitalWrite(ledPinR, HIGH); i=0; while (i<7) { ledOn = !ledOn; digitalWrite(ledPinR, ledOn); delay(400); i++; z++; if (digitalRead(switchPinR) == LOW && z>=7) ( break; ) ) ) else ( digitalWrite(ledPinR, LOW); z=0; ) //Left turn signal. if (digitalRead(switchPinL) == HIGH) ( digitalWrite(ledPinL, HIGH); i=0; while (i<7) { ledOn = !ledOn; digitalWrite(ledPinL, ledOn); delay(400); i++; z++; if (digitalRead(switchPinL) == LOW && z>=7) ( break; ) ) ) else ( digitalWrite(ledPinL, LOW); z=0; ) ) )

To briefly summarize, the sketch has 2 inputs and 2 outputs. In this case, when a positive, that is, high-level signal is input at the input (8,7), we receive a certain number of blinks (z or i) at the corresponding output (11,12). In short, something like this. That is, if you want to change something in the sketch regarding the number of blinks and input outputs, then pay attention to these variables. If you need to change the length of blinks, then your attention should be focused on the delay function.
Another feature of the program is a somewhat unusual alarm output. First, the left and right indicators are processed, then the hazard warning lights turn on. This is due to the fact that it can only turn on if the input is high at the same time at inputs 8 and 7. And this condition will only be fulfilled in the second cycle, because pressing two buttons at once is physically impossible. The speed of the microcontroller will allow you to read the high output from a button faster and decide that this is, after all, a condition for triggering the turn signal, and not an alarm. Although you shouldn’t worry about it, unless saying thank you on the road will be problematic.

Features of connecting a lazy (polite) turn signal in a car using Arduino

You should not use pin 13 as an output, since every time you turn the power on and off, the indicators that will be connected to this output may flicker.
When moving from control signals to power signals, use appropriate blocks purchased on the Internet or assembled by yourself. We have already talked about such blocks - modules.
When receiving signal 1 from a voltage of 12 volts, place a 10 Kom resistor in front of the input.

That's all the instructions for making a lazy turn signal for a car using an Arduino microcontroller, and now about the same thing in the video...

I said “Gop” last year - it’s time to jump :)
Or rather, do the promised review of running turn signals.
I ordered 1 meter of black WS2812B tape (144 LEDs) in a silicone tube, when ordering I chose “Black 1m 144led IP67” (perhaps someone will like the white color of the substrate, there is such a choice).

A word of caution

I received a tape soldered from two half-meter pieces. The downside of this is a vulnerable soldering point (contacts may break over time) and an increased gap between the LEDs.
Before purchasing, check with the seller about this point.

Contact wires were soldered to the tape on both sides to connect several pieces in series, because I didn’t need this, so I unsoldered the wires on one side, sealed everything with a neutral sealant and wrapped a little more black electrical tape.



Attached to the glass using double-sided transparent adhesive tape, for example.

Installation details

I degreased the surfaces, first glued adhesive tape to the tube (I’ll call it that, even though the cross-section is rectangular), cut off the protruding excess of the wider tape, pushed the edges of the tube into the cracks between the ceiling and the upper parts of the decorative panels of the rear pillars (the contact wires with the connector were hidden behind one panel ), centered it and began to press it against the glass, slowly pulling out the protective layer of the tape.
Unfortunately, there is no video - there were no free hands for filming, and everyone’s car is different.
If anything is unclear, ask in the comments.
The test in the summer heat was successful - nothing came off or floated.
The only negative is that the angle of the glass is gentle, the LEDs shine more upward. On a sunny day it’s hard to see, but since these are duplicate signals,

Now let's move on to the electronic stuffing.
I used it, but discovered it not long ago

For about the same cost we get more goodies

The sketch will work without any special modifications on Wemos when programming in the Arduino IDE, and if you implement a small web server, then when connected to it via Wi-Fi, you can change the values ​​of such variables as the delay time between blinks, the amount of deceleration during emergency braking etc.
Here in the future, if someone is interested in implementing a project on the ESP8266, I can post an example for changing the settings via the web interface, saving them in EEPROM, and then reading them.
The web server can be launched, for example, through the turn signal being turned on and the brake pedal being pressed when the ignition is turned on (in the setup procedure, poll the status of the corresponding inputs).

To implement a flashing mode during heavy braking, I purchased
The sketch monitors the level of deceleration when pressing the brake pedal; if it exceeds 0.5G (sharp deceleration, but without squealing brakes), then a flashing mode is turned on for a few seconds to attract additional attention.
Control signals to the Arduino inputs from the “plus” of stops, turn signals and reverse are supplied through galvanic isolation - optocouplers with current-limiting resistors, which ultimately form the LOW level at the Arduino inputs (constantly pulled to positive through 10 kOhm resistors).
Power supply - 5 volts via a DC-DC step-down converter.
The whole thing is folded into a sandwich and packed in a suitable box, on which the installation direction is marked with an arrow for the correct orientation of the gravity sensor

Diagram and photo



The nominal value of pull-up (to positive) resistors is standard - 10 kOhm, limiting the current of the optocoupler resistors - 1 kOhm. I removed the optocouplers from old boards, two were PC123, two were PC817.


In the first photo you can see two additional terminals; I made them for the turn signals. Since in my car, when the steering column lever is turned on, there is a short to ground, I connected the wires to the lever block and the Arduino inputs. If the steering column lever switches the plus or you take the signal from the “+” of the left/right turn signal lamps, then connect them through galvanic isolation.



Well, now the sketch itself (Arduino IDE)

#include #include //a few general comments // I turned off one of the outermost LEDs, because... they reflected on the decorative panels of the racks //visible in the example of this cycle for (int i=1; i<143; i++) //если отключать не нужно, заменяем на for (int i=0; i<144; i++) //задний ход и аварийка у меня не используются, т.к. в первом случае яркость никакая, во втором надо подключать входы к лампам поворотников //поворотники и стоп-сигнал одновременно не включаются, чтобы это реализовать, нужно переписывать соответствующий код скетча (делить ленту на три секции, подбирать тайминги миганий, менять диапазон переменных циклов). //Дерзайте - все в ваших руках // Пин для подключения управляющего сигнала светодной ленты const int PinLS = 2; //Пины для подключения датчиков //если более удобно будет подключать контакты в другом порядке - просто поменяйте значения переменных const int buttonPinL = 3; const int buttonPinR = 4; const int buttonPinS = 6; const int buttonPinD = 5; //начальные статусы входов (подтянуты к плюсу) int buttonStateS = HIGH; int buttonStateD = HIGH; int buttonStateL = HIGH; int buttonStateR = HIGH; // пауза pause_pov1 (в миллисекундах) нужна, чтобы синхронизировать циклы "пробегания" полоски и включения лампочки поворотника // такое может быть, если используется меньше половины светодиодов // в моем случае паузы нет (pause_pov1 = 0) int pause_pov1 = 1; // этой паузой регулируем длительность состояния, когда все светодиоды выключены //я определял опытным путем - включал поворотник, засекал по отдельности время ста мыргов лампочкой и ста беганий полоски, разницу делил на 100, на полученное время увеличивал или уменьшал значение переменной (в зависимости от того, отставали или убегали вперед лампочки) int pause_pov2 = 62; // переменная для получения значения ускорения int ix; Adafruit_NeoPixel strip = Adafruit_NeoPixel(144, PinLS, NEO_GRB + NEO_KHZ800); Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345); void setup() { pinMode(buttonPinS, INPUT); pinMode(buttonPinD, INPUT); pinMode(buttonPinL, INPUT); pinMode(buttonPinR, INPUT); strip.begin(); // гасим ленту for (int i=0; i<144; i++) strip.setPixelColor(i, strip.Color(0,0,0)); strip.show(); accel.begin(); // ограничиваем измеряемый диапазон четырьмя G (этого хватит с большим запасом) accel.setRange(ADXL345_RANGE_4_G); accel.setDataRate(ADXL345_DATARATE_100_HZ); } void loop() { // СТОПЫ: если включены - высший приоритет //Чтобы сделать меняющуюся по ширине полоску в зависимости от интенсивности торможения //(уточнение - никакой светомузыки, ширина полосы после нажатия на тормоз не меняется!) //от плавного торможения до тапки в пол. //Добавляем еще одну переменную, например, ix2, //присваиваем ей значение ix с коэффициентом умножения, //заодно инвертируем и округляем до целого //ix = event.acceleration.x; //ix2 = -round(ix*10); //ограничиваем для плавного торможения в пробках //(чтобы не менялась при каждом продвижении на 5 метров) //if (ix2<10) ix2 = 0; //и для резкого торможения. //Реальный диапазон изменения переменной ix - от 0 до -5 //для максимальной ширины полосы при G равном или большем 0.5 //if (ix2 >50) ix2 = 50; //then change the cycles in the STOP block for (int i=1; i<143; i++) на for (int i=51-ix2; i<93+ix2; i++) //Получаем минимальную ширину полоски ~30 см (для стояния в пробке) и максимальную для резкого торможения //конец комментария buttonStateS = digitalRead(buttonPinS); if (buttonStateS == LOW) { sensors_event_t event; accel.getEvent(&event); ix = event.acceleration.x; // проверка резкого торможения - мигающий режим // значение 5 - это 0,5G, минус - торможение if (ix < -5) { for (int is=0; is<15; is++) { for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(240,0,0)); strip.show(); delay(10 + is*10); for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(0,0,0)); strip.show(); delay(10 + is*3); buttonStateS = digitalRead(buttonPinS); if (buttonStateS == HIGH) return; } } // помигали - и хватит, включаем постоянный режим, если педаль тормоза еще нажата // или если не было резкого торможения и предыдущее условие не сработало if (buttonStateS == LOW) { for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(200,0,0)); strip.show(); while(buttonStateS == LOW){ buttonStateS = digitalRead(buttonPinS); delay(50); } // плавно гасим for (int is=0; is<20; is++) { for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(190 - is*10,0,0)); strip.show(); delay(10); } // СТОПЫ конец } } else // если СТОПЫ выключены { // ЗАДНИЙ ХОД: если включен - средний приоритет buttonStateD = digitalRead(buttonPinD); if (buttonStateD == LOW) { for (int i=1; i<37; i++) strip.setPixelColor(i, strip.Color(63,63,63)); for (int i=107; i<143; i++) strip.setPixelColor(i, strip.Color(63,63,63)); strip.show(); while(buttonStateD == LOW){ buttonStateD = digitalRead(buttonPinD); delay(50); } //плавно гасим for (int is=0; is<16; is++) { for (int i=1; i<37; i++) strip.setPixelColor(i, strip.Color(60 - is*4,60 - is*4,60 - is*4)); for (int i=107; i<143; i++) strip.setPixelColor(i, strip.Color(60 - is*4,60 - is*4,60 - is*4)); strip.show(); delay(10); } } buttonStateL = digitalRead(buttonPinL); buttonStateR = digitalRead(buttonPinR); // если включена аварийка if (buttonStateL == LOW && buttonStateR == LOW) { for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(63,31,0)); strip.setPixelColor(il+72, strip.Color(63,31,0)); strip.show(); delay(pause_pov1); } for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(0,0,0)); strip.setPixelColor(il+72, strip.Color(0,0,0)); strip.show(); delay(pause_pov1); } delay(pause_pov2); } // если включен ЛЕВЫЙ ПОВОРОТНИК if (buttonStateL == LOW && buttonStateR == HIGH) { for (int il=0; il<71; il++) { strip.setPixelColor(il+72, strip.Color(220,120,0)); strip.show(); delay(pause_pov1); } for (int il=0; il<71; il++) { strip.setPixelColor(il+72, strip.Color(0,0,0)); strip.show(); delay(pause_pov1); } delay(pause_pov2); } // если включен ПРАВЫЙ ПОВОРОТНИК if (buttonStateL == HIGH && buttonStateR == LOW) { for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(220,120,0)); strip.show(); delay(pause_pov1); } for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(0,0,0)); strip.show(); delay(pause_pov1); } delay(pause_pov2); } //правый поворотник конец } //конец условия else Стоп // задержка для следующего опроса датчиков delay(10); }

I tried to comment on it as much as possible, but if there are questions, I will try to add comments (that’s why I’m placing it in the text of the review, and not as an attached file). This, by the way, also applies to other points of the review - I will also supplement it if there are significant questions in the comments.

And finally, a demonstration of the work (for the video I used a sketch with demo mode).

Upd. I made the sketch with the demo mode specifically to fit everything into one short video.
The brake light flashes only during hard braking (this was discussed above); during slow braking and when standing in traffic jams, it simply lights up, without irritating the drivers behind.
The brightness at night is not excessive, because... Due to the tilt of the glass, the lights are directed more upward than backward.
The standard lights work as usual, this strip duplicates them.

Operation