user1335: I'm beginning to do kind of sophisticated things (well.. for my entry level skill) and I have to control a display with 3 LED and 4/5 types of events and status.
I'm using the BlinkWithoutDelay example duplicating all the variables for different status/events but the code is really messy, full of puzzling nested if statements.
How to simplify the things? I don't know what to choose, because OOP could be a choice but I think it will hurt the low-memory thing inside the Arduino Uno/Leonardo. Interrupts could be another choice but I think they are like threads, and following the KISS principle I'd like to stay away from them.
So, can someone advice me some article/tutorial/code-to-read/whatever to understand how to use a lot of LEDs and keep a lot internal status without screw my brain?
EDIT:
It is a little bit hard to reproduce a simple skelton of my messy code, but it looks like this (in pseudocode maybe)
void loop() {
    if(state==0) handleState0();
    if(state==1) handleState1();
    if(state==2) handleState2();
    if(state==3) handleState3();
    readButtons();
    readSensors();
    …
}

// this is a block of variables that I have to copy-and-paste 
// every time I have to blink a led (hoping that there is 
// nothing blocking that can skrew up everything)
unsigned long previousMillis_1 = 0;
const long interval_1 = 1000;
int ledState_1 = LOW;

void handleState1() {
  // Green led blinking, yellow is fixed
  // this is a copy-and-paste code hard to maintain, 
  // easily broken from any blocking call (like also I2C)
  // and hard to refactor or isolate
  unsigned long currentMillis_1 = millis();
  if(currentMillis_1 - previousMillis_1 >= interval_1) {
    previousMillis_1 = currentMillis_1;   
    if (ledState_1 == LOW) ledState_1 = HIGH;
    else ledState_1 = LOW;
    digitalWrite(pinGreen, ledState_1);
    digitalWrite(pinYellow, LOW);
}

unsigned long previousMillis_2 = 0;
const long interval_2 = 1000;
int ledState_2 = LOW;

void handleState2() {
  // Yellow led blinking, green is fixed
  // same as before
  unsigned long currentMillis_2 = millis();
  if(currentMillis_2 - previousMillis_2 >= interval_2) {
    previousMillis_2 = currentMillis_2;   
    if (ledState_2 == LOW) ledState_2 = HIGH;
    else ledState_2 = LOW;
    digitalWrite(pinYellow, ledState_2);
    digitalWrite(pinGreen, LOW);
}

void handleButtonPressed() {
  // this skrew everything and because is blocking 
  // and should be inserted in the main loop with 
  // some global variables: active/disable, counter, 
  // and non-blocking vars like previousMills, interval, etc etc
  Serial.println("\ndisplayAccessDenied");
  for(int i=0; i<3; i++) {
    digitalWrite(pinRed, LOW);
    delay(100);
    digitalWrite(pinRed, HIGH);
    delay(100);
  } digitalWrite(pinRed, LOW);
}

I feel a little bit lost but all the Arduino example arounds are super simple and to make a middle-level LED interface I have to screw my minds with something that is not working as 100% and other than Arduino I find only super-hard articles on microprocessors with low-level C code. But the pasted example is not working at 100% AND super hard to read, maintain, etc.

user13432: Cosa supports a large number of mechanisms for multi-tasking. The latest addition is an abstract class for Jobs (delayed or periodic functions) and Job Schedulers. This abstraction allows functions to be scheduled on micro-, milli- and seconds level. 
To get started please see the Cosa example sketches. If you have an Logic Analyzer (Salea Logic for instance) there are a number of example sketches that show pulse generation. 
There is also a binding of the Job Scheduler to a seconds tick level. This is abstracted to Clock and Alarms. 
For higher abstraction of multi-tasking Cosa also implements FSM, Proto-threads, Threads (multi-stacks), UML Capsules, and more.

user10794: Here's an example of blinking two LEDs independently:
// Which pins are connected to which LED
const byte greenLED = 12;
const byte redLED = 13;

// Time periods of blinks in milliseconds (1000 to a second).
const unsigned long greenLEDinterval = 500;
const unsigned long redLEDinterval = 1000;

// Variable holding the timer value so far. One for each "Timer"
unsigned long greenLEDtimer;
unsigned long redLEDtimer;

void setup () 
  {
  pinMode (greenLED, OUTPUT);
  pinMode (redLED, OUTPUT);
  }  // end of setup

void toggleLED (const byte which, unsigned long & whenToggled)
  {
   if (digitalRead (which) == LOW)
      digitalWrite (which, HIGH);
   else
      digitalWrite (which, LOW);
  // remember when we toggled it
  whenToggled = millis ();  
  }  // end of toggleLED

void loop ()
  {
  // Handling the blink of one LED.
  if ( (millis () - greenLEDtimer) >= greenLEDinterval)
     toggleLED (greenLED, greenLEDtimer);

  // The other LED is controlled the same way. Repeat for more LEDs
  if ( (millis () - redLEDtimer) >= redLEDinterval) 
    toggleLED (redLED, redLEDtimer);

/* Other code that needs to execute goes here.
   It will be called many thousand times per second because the above code
   does not wait for the LED blink interval to finish. */

  }  // end of loop

Note that instead of copying and pasting the blinking code, I made a generic function. That way any bugs are easily fixed.

For more LEDs you could use an array:
const int NUMBER_OF_LEDS = 5;
// Which pins are connected to which LED
const byte LED_PINS [NUMBER_OF_LEDS] = { 8, 9, 10, 11, 12 };
// Time periods of blinks in milliseconds (1000 to a second).
const unsigned long LED_INTERVALS [NUMBER_OF_LEDS] = { 200, 400, 100, 1000, 2000};
// Variable holding the timer value so far. One for each "Timer"
unsigned long timeLEDtoggled [NUMBER_OF_LEDS];

void setup () 
  {
  for (int i = 0; i < NUMBER_OF_LEDS; i++)
    pinMode (LED_PINS [i], OUTPUT);
  }  // end of setup

void toggleLED (const byte which, unsigned long & whenToggled)
  {
   if (digitalRead (which) == LOW)
      digitalWrite (which, HIGH);
   else
      digitalWrite (which, LOW);
  // remember when we toggled it
  whenToggled = millis ();  
  }  // end of toggleLED

void loop ()
  {
  // see if it is time to toggle the LEDs    
  for (int i = 0; i < NUMBER_OF_LEDS; i++)
    if ( (millis () - timeLEDtoggled [i]) >= LED_INTERVALS [i])
       toggleLED (LED_PINS [i], timeLEDtoggled [i]);

  /* Other code that needs to execute goes here. */
  }  // end of loop

If anything, the above code is simpler, but it blinks 5 LEDs at different rates. Now you can have more sophisticated tests than that, but the general concept is the same.

References

How to do multiple things at once ... like cook bacon and eggs
State machines


user-1: Following the KISS principle, I have recently published the Instructable "Simple Multi-tasking in Arduino on any board"
It covers non-blocking delays, non-blocking serial output, non-blocking user input, removing delays from third party libraries, and loop timers, so you can see and adjust the response/latency of your tasks.  
Here is some example code
void loop() {
 callTask_1(); // do something
 callTask_2(); // do something else
 callTask_1(); // check the first task again as it needs to be more responsive than the others.
 callTask_3(); // do something else
}

The trick is that each callTask..() method must return quickly so that the other tasks in the loop get called promptly and often. The rest of the instructable covers how to keep your tasks running quickly and not holding everything up, using a temperature controlled, stepper motor driven damper with a user interface as a concrete example.
Finally the instructable moves the code, unchanged, to an ESP32 to add remote control via Wifi, Bluetooth or BLE, to the temperature controlled, stepper motor driven damper.
Drop me a message/email via Instructables or my website, if you are unclear about anything in the instructable.

user4531: It is not really clear what you want here...
If you want to execute things in a certain time, then take a look at http://playground.arduino.cc/Code/Scheduler
Or, if you want more than just that (multiple tasks, preemptive multitasking) https://launchpad.net/arduos (arduOS can also just serve to run things in a certain time, but without having to use a function all the time)
While OOP MIGHT take more program memory, an object without virtual functions only takes the RAM the variables in it take (if you have a byte (1 byte) and an int (2 bytes) in an object it would take 3 bytes)
On the AVR-architecture (the one most Arduinos use) the program is directly executed from a flash-memory and only the variables are in the RAM
The if-state-handling you are doing there can be done easier using arrays like:
typedef void(*handler)(void)
handler stateHandlers[STATES] = {&handle1, &handle2, &handle3 ...
// handle? are functions without the () !
void handleState(int state)
{
    if(state >= STATES)
        return;
    stateHandlers[state]();
}

Obviously, you can also use arrays to store the states of the LEDs.
Also note that HIGH is just 1 and LOW is 0, so technically a bit would be enough to store the states.

1335: <p>I'm beginning to do kind of sophisticated things (well.. for my entry level skill) and I have to control a display with 3 LED and 4/5 types of events and status.</p>
<p>I'm using the BlinkWithoutDelay example duplicating all the variables for different status/events but the code is really messy, full of puzzling nested <code>if</code> statements.</p>
<p>How to simplify the things? I don't know what to choose, because OOP could be a choice but I think it will hurt the low-memory thing inside the Arduino Uno/Leonardo. Interrupts could be another choice but I think they are like threads, and following the <a href="http://en.wikipedia.org/wiki/KISS_principle" rel="nofollow noreferrer">KISS principle</a> I'd like to stay away from them.</p>
<p>So, can someone advice me some article/tutorial/code-to-read/whatever to understand how to use a lot of LEDs and keep a lot internal status without screw my brain?</p>
<h2>EDIT:</h2>
<p>It is a little bit hard to reproduce a simple skelton of my messy code, but it looks like this (in pseudocode maybe)</p>
<pre><code>void loop() {
    if(state==0) handleState0();
    if(state==1) handleState1();
    if(state==2) handleState2();
    if(state==3) handleState3();
    readButtons();
    readSensors();
    …
}

// this is a block of variables that I have to copy-and-paste 
// every time I have to blink a led (hoping that there is 
// nothing blocking that can skrew up everything)
unsigned long previousMillis_1 = 0;
const long interval_1 = 1000;
int ledState_1 = LOW;

void handleState1() {
  // Green led blinking, yellow is fixed
  // this is a copy-and-paste code hard to maintain, 
  // easily broken from any blocking call (like also I2C)
  // and hard to refactor or isolate
  unsigned long currentMillis_1 = millis();
  if(currentMillis_1 - previousMillis_1 &gt;= interval_1) {
    previousMillis_1 = currentMillis_1;   
    if (ledState_1 == LOW) ledState_1 = HIGH;
    else ledState_1 = LOW;
    digitalWrite(pinGreen, ledState_1);
    digitalWrite(pinYellow, LOW);
}

unsigned long previousMillis_2 = 0;
const long interval_2 = 1000;
int ledState_2 = LOW;

void handleState2() {
  // Yellow led blinking, green is fixed
  // same as before
  unsigned long currentMillis_2 = millis();
  if(currentMillis_2 - previousMillis_2 &gt;= interval_2) {
    previousMillis_2 = currentMillis_2;   
    if (ledState_2 == LOW) ledState_2 = HIGH;
    else ledState_2 = LOW;
    digitalWrite(pinYellow, ledState_2);
    digitalWrite(pinGreen, LOW);
}

void handleButtonPressed() {
  // this skrew everything and because is blocking 
  // and should be inserted in the main loop with 
  // some global variables: active/disable, counter, 
  // and non-blocking vars like previousMills, interval, etc etc
  Serial.println(&quot;\ndisplayAccessDenied&quot;);
  for(int i=0; i&lt;3; i++) {
    digitalWrite(pinRed, LOW);
    delay(100);
    digitalWrite(pinRed, HIGH);
    delay(100);
  } digitalWrite(pinRed, LOW);
}
</code></pre>
<p>I feel a little bit lost but all the Arduino example arounds are super simple and to make a middle-level LED interface I have to screw my minds with something that is not working as 100% and other than Arduino I find only super-hard articles on microprocessors with low-level C code. But the pasted example is not working at 100% AND super hard to read, maintain, etc.</p>
 13432: <p><a href="https://github.com/mikaelpatel/Cosa" rel="nofollow">Cosa</a> supports a large number of mechanisms for multi-tasking. The latest addition is an abstract class for <a href="https://dl.dropboxusercontent.com/u/993383/Cosa/doc/html/da/d10/classJob.html" rel="nofollow">Jobs</a> (delayed or periodic functions) and Job Schedulers. This abstraction allows functions to be scheduled on micro-, milli- and seconds level. </p>

<p>To get started please see the Cosa example sketches. If you have an Logic Analyzer (Salea Logic for instance) there are a number of example sketches that show pulse generation. </p>

<p>There is also a binding of the Job Scheduler to a seconds tick level. This is abstracted to Clock and Alarms. </p>

<p>For higher abstraction of multi-tasking Cosa also implements FSM, Proto-threads, Threads (multi-stacks), UML Capsules, and more.</p>
 10794: 

<p>Here's an example of blinking two LEDs independently:</p>

<pre class="lang-C++ prettyprint-override"><code>// Which pins are connected to which LED
const byte greenLED = 12;
const byte redLED = 13;

// Time periods of blinks in milliseconds (1000 to a second).
const unsigned long greenLEDinterval = 500;
const unsigned long redLEDinterval = 1000;

// Variable holding the timer value so far. One for each "Timer"
unsigned long greenLEDtimer;
unsigned long redLEDtimer;

void setup () 
  {
  pinMode (greenLED, OUTPUT);
  pinMode (redLED, OUTPUT);
  }  // end of setup

void toggleLED (const byte which, unsigned long &amp; whenToggled)
  {
   if (digitalRead (which) == LOW)
      digitalWrite (which, HIGH);
   else
      digitalWrite (which, LOW);
  // remember when we toggled it
  whenToggled = millis ();  
  }  // end of toggleLED

void loop ()
  {
  // Handling the blink of one LED.
  if ( (millis () - greenLEDtimer) &gt;= greenLEDinterval)
     toggleLED (greenLED, greenLEDtimer);

  // The other LED is controlled the same way. Repeat for more LEDs
  if ( (millis () - redLEDtimer) &gt;= redLEDinterval) 
    toggleLED (redLED, redLEDtimer);

/* Other code that needs to execute goes here.
   It will be called many thousand times per second because the above code
   does not wait for the LED blink interval to finish. */

  }  // end of loop
</code></pre>

<p>Note that instead of copying and pasting the blinking code, I made a generic function. That way any bugs are easily fixed.</p>

<hr>

<p>For more LEDs you could use an array:</p>

<pre class="lang-C++ prettyprint-override"><code>const int NUMBER_OF_LEDS = 5;
// Which pins are connected to which LED
const byte LED_PINS [NUMBER_OF_LEDS] = { 8, 9, 10, 11, 12 };
// Time periods of blinks in milliseconds (1000 to a second).
const unsigned long LED_INTERVALS [NUMBER_OF_LEDS] = { 200, 400, 100, 1000, 2000};
// Variable holding the timer value so far. One for each "Timer"
unsigned long timeLEDtoggled [NUMBER_OF_LEDS];

void setup () 
  {
  for (int i = 0; i &lt; NUMBER_OF_LEDS; i++)
    pinMode (LED_PINS [i], OUTPUT);
  }  // end of setup

void toggleLED (const byte which, unsigned long &amp; whenToggled)
  {
   if (digitalRead (which) == LOW)
      digitalWrite (which, HIGH);
   else
      digitalWrite (which, LOW);
  // remember when we toggled it
  whenToggled = millis ();  
  }  // end of toggleLED

void loop ()
  {
  // see if it is time to toggle the LEDs    
  for (int i = 0; i &lt; NUMBER_OF_LEDS; i++)
    if ( (millis () - timeLEDtoggled [i]) &gt;= LED_INTERVALS [i])
       toggleLED (LED_PINS [i], timeLEDtoggled [i]);

  /* Other code that needs to execute goes here. */
  }  // end of loop
</code></pre>

<p>If anything, the above code is simpler, but it blinks 5 LEDs at different rates. Now you can have more sophisticated tests than that, but the general concept is the same.</p>

<hr>

<h2>References</h2>

<ul>
<li><p><a href="http://www.gammon.com.au/blink" rel="nofollow">How to do multiple things at once ... like cook bacon and eggs</a></p></li>
<li><p><a href="http://www.gammon.com.au/statemachine" rel="nofollow">State machines</a></p></li>
</ul>
 -1: <p>Following the KISS principle, I have recently published the Instructable "<a href="https://www.instructables.com/id/Simple-Multi-tasking-in-Arduino-on-Any-Board/" rel="nofollow noreferrer">Simple Multi-tasking in Arduino on any board</a>"</p>

<p>It covers non-blocking delays, non-blocking serial output, non-blocking user input, removing delays from third party libraries, and loop timers, so you can see and adjust the response/latency of your tasks.  </p>

<p>Here is some example code</p>

<pre><code>void loop() {
 callTask_1(); // do something
 callTask_2(); // do something else
 callTask_1(); // check the first task again as it needs to be more responsive than the others.
 callTask_3(); // do something else
}
</code></pre>

<p>The trick is that each callTask..() method must return quickly so that the other tasks in the loop get called promptly and often. The rest of the instructable covers how to keep your tasks running quickly and not holding everything up, using a temperature controlled, stepper motor driven damper with a user interface as a concrete example.</p>

<p>Finally the instructable moves the code, unchanged, to an ESP32 to add remote control via Wifi, Bluetooth or BLE, to the temperature controlled, stepper motor driven damper.</p>

<p>Drop me a message/email via Instructables or <a href="https://www.forward.com.au/pfod/ArduinoProgramming/RealTimeArduino/index.html" rel="nofollow noreferrer">my website</a>, if you are unclear about anything in the instructable.</p>
 4531: <p>It is not really clear what you want here...</p>

<p>If you want to execute things in a certain time, then take a look at <a href="http://playground.arduino.cc/Code/Scheduler" rel="nofollow">http://playground.arduino.cc/Code/Scheduler</a></p>

<p>Or, if you want more than just that (multiple tasks, preemptive multitasking) <a href="https://launchpad.net/arduos" rel="nofollow">https://launchpad.net/arduos</a> (arduOS can also just serve to run things in a certain time, but without having to use a function all the time)</p>

<p>While OOP MIGHT take more program memory, an object without virtual functions only takes the RAM the variables in it take (if you have a byte (1 byte) and an int (2 bytes) in an object it would take 3 bytes)</p>

<p>On the AVR-architecture (the one most Arduinos use) the program is directly executed from a flash-memory and only the variables are in the RAM</p>

<p>The if-state-handling you are doing there can be done easier using arrays like:</p>

<pre><code>typedef void(*handler)(void)
handler stateHandlers[STATES] = {&amp;handle1, &amp;handle2, &amp;handle3 ...
// handle? are functions without the () !
void handleState(int state)
{
    if(state &gt;= STATES)
        return;
    stateHandlers[state]();
}
</code></pre>

<p>Obviously, you can also use arrays to store the states of the LEDs.</p>

<p>Also note that <code>HIGH</code> is just 1 and <code>LOW</code> is 0, so technically a bit would be enough to store the states.</p>
