Hello everybody.
Sometimes we need to use multiple digital writes. One classical example is reproducing a LED pattern, like KITT (for older people KITT's Lights from Knight Rider Lights - YouTube) or a modern side-turn LED lamp (using discrete LEDs...not a beautiful LED strip
).
So, imagine 4 LEDs connected to Arduino pins 2 to 5.
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(2, HIGH); // O X X X - 100 ms
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
delay(100);
digitalWrite(2, LOW); // X O X X - 100 ms
digitalWrite(3, HIGH);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
delay(100);
digitalWrite(2, LOW); // X X O X - 100 ms
digitalWrite(3, LOW);
digitalWrite(4, HIGH);
digitalWrite(5, LOW);
delay(100);
digitalWrite(2, LOW); // X X X O - 100 ms
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, HIGH);
delay(100);
}
Now imagine, you have 8 LEDs, the code is long and difficult to change.
So another approach (classical in embedded controllers world) consists in taking an integer and associating each bit to a LED and using bit values (1 or 0) to turn on/off each LED.
For the previous pattern using 4 bits, we could use an array and a function that translate the array value into digitalWrites ![]()
void loop() {
// put your main code here, to run repeatedly:
int LEDS[4] = {1,2,4,8};
for(int i=0; i<4;i++){
emitPins(LEDS[i], 2,5);
delay(100);
}
}
Now, changing the array value, you change the LED lighting pattern.
The complete code for 8 bits is shown below:
// 8 LEDs are connected to pins 2 - 9
void setup() {
// put your setup code here, to run once:
for(int i=2; i<10;i++){
pinMode(i, OUTPUT);
}
}
// LEDS contains an 8-sequence pattern similar to https://www.youtube.com/watch?v=8lS-VvMhDus or to another side turn sequential LEDs
void loop() {
// put your main code here, to run repeatedly:
int LEDS[8] = {1,2,4,8,16,32,64, 128};
for(int i=0; i<8;i++){
emitPins(LEDS[i], 2,9);
delay(100);
}
}
// Basic variant of the function
void emitPins(int val2emit, int pinIni, int pinFinal)
{
int nPins = pinFinal - pinIni + 1;
int pin2emit = pinIni;
for(int i=0; i <nPins; i++){
if(bitRead(val2emit, i) == 1)
digitalWrite(pin2emit, HIGH);
else
digitalWrite(pin2emit, LOW);
pin2emit ++;
}
}
In a previous working thread about this,
TheMemberFormerlyKnownAsAWOL pointed out that sometimes pins are not connected sequentially.
In that case, you can use this code:
// 8 LEDs are connected to a non-ordered set of pins
int pins[8] = {2,7,8,9,3,4,5,6};
void setup() {
// put your setup code here, to run once:
for(int i=0; i<8;i++){
pinMode(pins[i], OUTPUT);
}
}
// LEDS contains an 8-sequence pattern similar to https://www.youtube.com/watch?v=8lS-VvMhDus or to another side turn sequential LEDs
void loop() {
// put your main code here, to run repeatedly:
int LEDS[8] = {1,2,4,8,16,32,64, 128};
for(int i=0; i<8;i++){
emitPinsRandom(LEDS[i], pins, 0, 7);
delay(1000);
}
}
// Emitting for non-ordered pins
void emitPinsRandom(int val2emit, int pins[], int pinIni, int pinFinal)
{
int nPins = pinFinal - pinIni + 1;
int pin2emit = pinIni;
for(int i=0; i <nPins; i++){
if(bitRead(val2emit, i) == 1)
digitalWrite(pins[pin2emit], HIGH);
else
digitalWrite(pins[pin2emit], LOW);
pin2emit ++;
}
}
TheMemberFormerlyKnownAsAWOL and also
aarg suggested optimizing emitPins functions taking into account HIGH and LOW as 1 and 0 or indexing pin directly instead of counting them.
// A second variant of the function - indexing on the number of pins
void emitPins(int val2emit, int pinIni, int pinFinal)
{
int nPins = pinFinal - pinIni + 1;
int pin2emit = pinIni;
for(int i=0; i <nPins; i++){
digitalWrite(pin2emit, bitRead(val2emit, i));
pin2emit ++;
}
}
Their final optimization is:
void emitPins(int val2emit, int pinIni, int pinFinal)
{
for(int i = pinIni; i <= pinFinal; i++) {
digitalWrite(i, bitRead(val2emit, i-pinIni));
}
}
Thank you guys and the rest of the people participating in the working thread.