2

Going through resources such as several things at the same time and with some greatly appreciated assistance on here I'm finally getting a grasp on how to multitask a microcontroller.

Most examples use the millis() approach to nonblocking programming. However, even in the link above the button state is being polled every loop (from what I understood).

So what confuses me is: is it bad practice to write functions, which poll sensor(s) and input(s) without timing constraints, i.e. at every iteration of loop?

Is this still consider nonblocking programming?

I've written some mock code to better illustrate what I mean. Thank you very much for reading through.

void loop() {
    Button();
    Sensor();
    LED();
    // ...
}

void Button() {
  // Read button(s)
  button_state = digitalRead(button_pin);
  if (button_state == LOW) {
    // ...
  };
};

void Sensor() {
  // Read sensor
  int sensor_state = analogRead(sensor_pin);
  if (sensor_state >= 150) {
    // ...
  };
};
1
  • Everything blocks a little bit, right? The point is that a delay() is (usually) a pointless blocking that could be better handled. It's better to use interrupts to monitor sensors, when practical. That gets by some of the "single thread" limitations of a sketch and lets the MCU do >1 things at a time.
    – dandavis
    Feb 18 at 18:50
4

Like often, the answer is: It depends.

Generally it is non-blocking programming, when you do only short things on each loop. What exactly can be considered short depends on the situation, meaning, what else you want to do.

For example: You are reading an analog value on every loop. The analogRead() will take about 100us (reference). I assume, that your sensor value is rather slow (so the time of signal above 150 would be rather long). Also you are reading a button with digitalRead(). The read takes about 3.6us (reference). So in total you have a loop of - lets say - 150us (with overhead and loop() iteration included). But the event, that you want to catch - the button press - will be in the ballpark of 100ms, which is a factor 667 greater, than the total time of your loop() (when no event happened). So in relation to the shortest event (the button press) all the reads can be considered non-blocking. (Though you could still get blocking through the code inside the if statements. Thats on you to investigate)

Non assume, that you don't have a button, but a digital signal, and you want to sense pulses down to 80us. Then your analogRead() would take too long and you could miss a pulse event. In this case analogRead() might be considered blocking.

So, to check if you are really using non-blocking code, you would need to ask yourself: Am I giving every code part enough time to execute right and to catch all the intended events? If yes, then you are non-blocking. If no, then you are blocking.


As a side note: Often polling is described as bad, but it really depends on the situation. In your case you poll the inputs sequentially, so every input gets polled at the same (total) rate at which your loop() runs. You are doing nothing else, so why should you lower the processing time by not use polling? The saved time cannot be used better on a microcontroller (in contrast to a PC, where the saved CPU time could be given to a different program).

1
  • Hi Chris, thank you for the answer. It was very clear and helped me understand the thought process behind the decision-making so now I have a better framework to work off of. Feb 18 at 18:46
1

If you are running off battery, then you should consider having the microcontroller sleep as much as possible, and not poll the sensors more often than needed. AFAIK, the Arduino core library provides no facility for managing sleep, but some third-party libraries are available for that purpose.

If you project runs off mains power, then there is no point in adding the complexity of sleep management. Unless your sensors are really slow, polling them at each loop iteration is generally fine. Specifically, for a push button, the documentation of the Bounce2 library states that the button update method should be called on every loop iteration.

3
  • Hi Edgar, thanks for responding again. It's going to be running off of a battery so I will have a think about how to implement. Feb 18 at 18:48
  • 1
    @ZhelyazkoGrudov: Achieving low power consumption is a vast subject. I suggest you start by reading Power saving techniques for microprocessors, by Nick Gammon. Feb 18 at 19:07
  • Oh sweet! Thanks for the pointer, I'm sure I would have had another great moment just starting in the middle of nowhere otherwise. Feb 18 at 19:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.