Beginner questions re: tactile button presses and the main loop()

In preparation for the arrival of my first photo and Internet buttons, I’ve been reading example code as I’ve never played around with hardware before. Two quick questions:

  1. I see lots of examples where loop() has no artificial delays introduced. If I were writing software for my laptop, I would try to avoid any spin loops to minimize CPU utilization and prolong battery life. Is this a consideration in the micro-controller world as well? I realize that loop() is called by the system-level firmware, so perhaps there is an artificial delay in there?

  2. I was looking at same code for button presses on the Internet button. Again, this is going to show my hardware ignorance, but it seems like the pattern here is to read from an input that has been pulled up to see when in goes low. So, the main loop() is doing an if statement with a digitalRead() on the pin. My question is whether or not there can be a race condition where a button is pushed while the code is not executing that statement. What happens if the system loop takes a bit long as it’s checking for new instructions from the cloud? What happens if I introduce an artificial delay (1s) per my question above?

Thanks for entertaining these basic questions from a newbie. I can’t wait for my order to arrive to start testing and experimenting!

Thanks!

It is, but when you write your code you also need to consider that your computer is still running a loop - e.g. the message pump in Windows.
So your code should be non-blocking but loop() can be considered part of the OS.

What do you consider an artificial delay?

To reduce power consumption sleep modes are currently the best option, but other low power modes are planned.

For your point 2. I’d not call this a race condition but rather hit or miss where success rate would be invers proportional to your net delay time.
To catch button presses most reliably going for interrupts would be my choice.

3 Likes

Thank you for your feedback.

By artificial delay, I was thinking of something along the lines of a call to simply pause execution. For example, in application code (not firmware), if I had a loop that ran forever to check the status of something, I’d likely put a sleep() in there so as not to constantly be spinning the CPU. I’m trying to understand if that same concept applies to firmware.

For example, if I had firmware that had an empty loop() function, would that be considered bad form (aside from boring and uninteresting) because it would needlessly cause the CPU to spin? I understand that loop() is really called by some main system loop that runs forever, but I was unsure of how long the system takes in between calls to my loop() function. It would seem variable if the system loop has to check for firmware updates and so forth over the network periodically.

And thus, my original question about button presses. In most example code, I see very few people using interrupts (thanks for pointing those out as I had not seen that feature yet), so I was curious if button presses were a hit or miss thing in the firmware world when one is doing a digitalRead()? If the main system loop takes too long doing its housekeeping, and my firmware’s loop() function is not called frequently enough, is there a chance that button presses would be missed? Presumably no given that most people seem to check for button presses this way.

Thanks for the help in these “basic” questions. My hardware should be arriving in a couple of days! I’m very excited to start tinkering.

The average period loop() is called when connected to the cloud is 1ms - without cloud connection it’s a lot faster.
And sure enough, ongoing OTA updates will impose a lot of extra delay on your loop() (in multithreaded mode) - but since your code will be gone sooner or later with an OTA update, that should not make any difference really :wink:

With SYSTEM_THREAD(ENABLED) you’ll get (at least) two threads that get services via FreeRTOS in 1ms timeslices reducing the impact any system firmware tasks will impose on your application firmware.
In this case you might only be your own enemy when writing blocking code, causing other portions of your code to miss a button press.