Here's a sketch I wrote to do what OP @secretreeve requires.
It's all delayless, so that if the sketch needs to do other things (maybe eery storm noises or whatever) they can be handled too.
It's a state machine with 4 states, viz new, main flash, 2nd flash and 3rd flash. In new, a few functions are run: they initialise the sequence of the leds for the next run of 3 flashes, and initialise the flash lengths and inter-flash intervals. The flash lengths and interflash intervals are given minima and maxima at the top of the sketch: experiment with those for the right effect.
All the led pins and timings are in arrays. Remember to use ~ PWM pins, since you need to use analogWrite to get the dim effect less than full bright.
Once the initialisation functions have run at the start of the new case, it moves to the case main flash once the interval has elapsed (all delayless with millis) where the main flash fires up. It stays on delaylessly for the time set during the randomisation process, then hangs around (delaylessly) for the randomised interval before it goes to the case for the second flash. Then does the same for that and third flash.
It gets back to the new case once the "strike" is done, rinse and repeat. (The pin sequence and timings are re-randomised each time.)
All you need to do is put the pin numbers in the ledPins array, and mess around with the min an max timings. The analogWrite() intensities are hard-coded into variables, not randomised, but can of course be edited to get the right effect.
Give this a try.... Run it with serial monitor open and see the debug messages.
// random lightning on 3 leds
// one "main" flash followed by two "secondary" flashes
// includes blink-without-delay pulse on built-in led as proof-of-life
// probably overkill but this code uses a state machine managed in a switch..case
//states
enum {state_new, state_main_flash, state_second_flash, state_third_flash} currentState = state_new;
bool justEnteredThisState = true;
unsigned long currentMillis;
unsigned long previousPulse;
int pulseInterval = 500;
bool pulseState;
//led array (use ~pwm pins to cater for brightness less than full)
byte ledPins[] = {9, 10, 11}; //index from 0 to 2 for 3 leds
const byte howManyLEDs = sizeof(ledPins) / sizeof(ledPins[0]);
int flashLengths[howManyLEDs];// will be populated each time, between the min and max
int flashLengthsMin[] = {500, 500, 500}; //experiment with these
int flashLengthsMax[] = {1000, 1000, 1000};
int intervals[howManyLEDs]; // will be populated each time, between the min and max
int intervalsMin[] = {3000, 500, 500}; //between 3nd flash and new main flash, main and 2nd, 2nd and 3rd
int intervalsMax[] = {5000, 1000, 1000};
byte secondFlashIntensity = 800; //experiment with these
byte thirdFlashIntensity = 300;
bool flashIsDone = false;
byte ledSequence[howManyLEDs]; //this gets populated later, in random sequence
unsigned long enteredThisStateAtMillis;
unsigned long flashEndedAtMillis;
void setup()
{
Serial.begin(9600);
Serial.println("https://forum.arduino.cc/t/lightning-effect-with-3-leds/1010662");
Serial.print("Compiler: ");
Serial.print(__VERSION__);
Serial.print(", Arduino IDE: ");
Serial.println(ARDUINO);
Serial.print("Created: ");
Serial.print(__TIME__);
Serial.print(", ");
Serial.println(__DATE__);
Serial.println(__FILE__);
pinMode(LED_BUILTIN, OUTPUT);
Serial.print("Initialising and testing ");
Serial.print(howManyLEDs);
Serial.print(" leds: ");
for (int i = 0; i < howManyLEDs; i++)
{
pinMode(ledPins[i], OUTPUT);
Serial.print(i);
Serial.print("/");
Serial.print(ledPins[i]);
Serial.print(", ");
digitalWrite(ledPins[i], HIGH);
delay(500);
digitalWrite(ledPins[i], LOW);
}
Serial.println(" ");
Serial.println("Leds initialised");
randomSeed(analogRead(0));
delay(1000);
Serial.print("setup() is done, starting.... "); Serial.println(millis());
}//setup
void loop()
{
currentMillis = millis();
pulse();
doLightning();
}//loop
void doLightning()
{
switch (currentState) //state_new, state_main_flash, state_second_flash, state_third_flash
{
case state_new:
if (justEnteredThisState)
{
Serial.println("state_new");
randomiseSequence();
randomiseIntervals();
randomiseFlashLengths();
justEnteredThisState = false;
enteredThisStateAtMillis = currentMillis;
}
if (currentMillis - enteredThisStateAtMillis >= intervals[0]) //interval from idle to 1st flash
{
currentState = state_main_flash;
justEnteredThisState = true;
}
break;
case state_main_flash:
if (justEnteredThisState)
{
Serial.println("state_main_flash");
enteredThisStateAtMillis = currentMillis;
digitalWrite(ledPins[ledSequence[0]], HIGH); //main flash is always fully bright
Serial.print(" main_flash ON "); Serial.println(currentMillis);
//while (1) {} //temp stop for testing
flashIsDone = false;
justEnteredThisState = false;
}
//this is the flash:
if (!flashIsDone && currentMillis - enteredThisStateAtMillis >= flashLengths[0])
{
flashIsDone = true;
flashEndedAtMillis = currentMillis;
digitalWrite(ledPins[ledSequence[0]], LOW);
Serial.print(" main_flash OFF "); Serial.println(currentMillis);
}
//this is the inter-flash interval:
if (flashIsDone && currentMillis - flashEndedAtMillis >= intervals[1])
{
currentState = state_second_flash;
justEnteredThisState = true;
}
break;
case state_second_flash:
if (justEnteredThisState)
{
Serial.println(" state_second_flash");
enteredThisStateAtMillis = currentMillis;
analogWrite(ledPins[ledSequence[1]], secondFlashIntensity);
Serial.print(" 2nd_flash ON "); Serial.println(currentMillis);
flashIsDone = false;
justEnteredThisState = false;
}
//this is the flash:
if (!flashIsDone && currentMillis - enteredThisStateAtMillis >= flashLengths[1])
{
flashIsDone = true;
flashEndedAtMillis = currentMillis;
digitalWrite(ledPins[ledSequence[1]], LOW);
Serial.print(" 2nd_flash OFF "); Serial.println(currentMillis);
}
//this is the inter-flash interval:
if (flashIsDone && currentMillis - flashEndedAtMillis >= intervals[2])
{
currentState = state_third_flash;
justEnteredThisState = true;
}
break;
case state_third_flash:
if (justEnteredThisState)
{
Serial.println(" state_third_flash ");
enteredThisStateAtMillis = currentMillis;
analogWrite(ledPins[ledSequence[2]], thirdFlashIntensity);
Serial.print(" 3rd_flash ON "); Serial.println(currentMillis);
flashIsDone = false;
justEnteredThisState = false;
}
//this is the flash:
if (!flashIsDone && currentMillis - enteredThisStateAtMillis >= flashLengths[2])
{
flashIsDone = true;
flashEndedAtMillis = currentMillis;
digitalWrite(ledPins[ledSequence[2]], LOW);
Serial.print(" 3rd_flash OFF "); Serial.println(currentMillis);
}
if (flashIsDone)
{
currentState = state_new;
justEnteredThisState = true;
Serial.println("*** Heading back to the start... ***");
//while (1) {} //temp stop for testing
}
break;
}//switch
}//doLightning()
void randomiseSequence()
{
Serial.print(" Sequence: ");
ledSequence[0] = random(0, 3); //can be 0, 1 or 2
Serial.print(ledSequence[0]);
do
{
ledSequence[1] = random(0, 3);
}
while (ledSequence[1] == ledSequence[0]); //can't reuse
Serial.print(ledSequence[1]);
do
{
ledSequence[2] = random(0, 3);
}
while (ledSequence[2] == ledSequence[0] || ledSequence[2] == ledSequence[1]); //can't reuse
Serial.println(ledSequence[2]);
//while(1){} //temp stop for testing
}//randomiseSequence
void randomiseIntervals()
{
intervals[0] = random(intervalsMin[0], intervalsMax[0]);
Serial.print(" Main interval: "); Serial.println(intervals[0]);
intervals[1] = random(intervalsMin[1], intervalsMax[1]);
Serial.print(" 2nd interval: "); Serial.println(intervals[1]);
intervals[2] = random(intervalsMin[2], intervalsMax[2]);
Serial.print(" 3rd interval: "); Serial.println(intervals[2]);
//while (1) {} //temp stop for testing
}//randomiseIntervals
void randomiseFlashLengths()
{
flashLengths[0] = random(flashLengthsMin[0], flashLengthsMax[0]);
Serial.print(" Main flash: "); Serial.println(flashLengths[0]);
flashLengths[1] = random(flashLengthsMin[1], flashLengthsMax[1]);
Serial.print(" 2nd flash: "); Serial.println(flashLengths[1]);
flashLengths[2] = random(flashLengthsMin[2], flashLengthsMax[2]);
Serial.print(" 3rd flash: "); Serial.println(flashLengths[2]);
//while (1) {} //temp stop for testing
}//randomisFlashLengths
void pulse()
{
if (currentMillis - previousPulse >= pulseInterval)
{
pulseState = !pulseState;
digitalWrite(LED_BUILTIN, pulseState);
previousPulse = currentMillis;
}
}//pulse