Lucky Resistor
Menu
  • Home
  • Learn
    • Learn C++
    • Product Photography for Electronics
      • Required Equipment and Software
    • Soldering for Show
  • Projects
  • Libraries
  • Applications
  • Shop
  • About
    • About Me
    • Contact
    • Stay Informed
  •  
Menu

Handling of the Loop

If there is a single signal to monitor, the implementation of the loop is simple. But if you have several different things to monitor and control, and would like to keep your code extensible, you need a good pattern for the main loop of your application.

Game developer face the same problem.Actually game developers face a similar situation. Probably not complex 3D games, where many tasks running in separate threads, but small simple 2D games. They are usually build around a simple main loop. This loop works basically in two parts: A. Display the current scene, B. react to controls, collisions, etc. and calculate the next scene.

For the game, a key factor is the time. You try to reach a high “frame rate”, therefore the code in your loop should run enough fast to allow 60 frames per second. Usually the loop is synchronised with the display, to make animations look smooth. But, you never know if your code get interrupted by other high priority processes (e.g. on a phone), so you have to write your code flexible. If for once you do not reach the 60 frames per second, the animation should nevertheless process in the same speed, just not same smooth as possible.

Introducing the Loop Time

To reach this goal, each loop has an absolute time, which is used for all calculations in this loop. For the Arduino, we can use the same principle. Depending on your requirements for precision, you can use a time in microseconds, or in milliseconds. In my case, the time in milliseconds is precise enough.

The loop in my case is starting always with the time measurement.

void loop()
{
    const uint32_t currentTime = millis();
    // The logic.
}

The Logic

Each component in the system usually has two important methods. The first is a setup or initialize method, which has to be called in the setup() method, and a loop(const uint32_t currentTime) method, which has to be called in the loop().

The loop in this project looks like this:

void loop() {
    const unsigned long currentTime = millis();
    ledController.loop(currentTime);
    if (logicState != ErrorState) {
        motionSensor.loop(currentTime);
        if (logicState == AlarmState) {
            if (!audioPlayer.play("voice.snd")) {
                return;
            }
            logicState = IdleState;
        }
    }
}

You can see, there is a LED controller which just handles the “display” of the multicolour LED. This controller can let this LED display different colours, and let the LED blink in different patterns and intervals. Everything is done in the loop method of this controller.

There is also a motion sensor component, which handles the state of the motion sensor. This motion sensor component uses a callback method, which is always called when the state of the sensor changes. This works similar to an interrupt, but is more like the traditional event handling from user interface applications.

The callback method is registered in the setup() method like this:

void setup() {
    // Set the initial state.
    logicState = WaitForSensor;

    // setup the LED controller
    ledController.setup();

    // setup the motion sensor.
    motionSensor.setup();
    motionSensor.setCallback(&onMotion);

And the callback itself looks like this:

void onMotion(const unsigned long currentTime, MotionSensor::Status status)
{
    if (status == MotionSensor::WaitStablilize) {
        ledController.setState(LEDController::Orange, LEDController::BlinkSlow);
    } else if (status == MotionSensor::Idle) {
        ledController.setState(LEDController::Green, LEDController::FlashVerySlow);
        logicState = IdleState; // Ready to observe.
    } else if (status == MotionSensor::Alarm) {
        ledController.setState(LEDController::Red, LEDController::On);
        logicState = AlarmState; // Activate the alarm and play a sound.
    }
}

Internally the components are using two classes Timer and TimeDelta to measure the time and internally working with callbacks and events. I will explain this two classes on the next pages.

Conclusion

The shown loop pattern is very flexible and extensible. You can add any number of components in the loop, which each can work independent from each other. You can implement complex logic, using callbacks or just by providing other methods on the components where one can read or change the status.

One of the biggest benefit is its simplicity. There are no interrupts, everything runs at a defined place, so you can always access all variables without any precautions. You even know the exact order of the calls, and know from which loop() call the callbacks are started.

The only disadvantage is the controller is always busy. You can for example put the controller into a low energy state, by disabling many features and let it been wake up from a signal. If energy preservation is important for you, this is not the right pattern for you.

Continue with: Time Events

Leave a Reply Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Stay Updated

Join me on Mastodon!

Top Posts & Pages

  • Storage Boxes System for 3D Print
  • Use Enum with More Class!
  • Simple Box with Lid for 3D-Print
  • Fan Controller
  • Shop
  • Real Time Counter and Integer Overflow
  • How and Why to use Namespaces
  • The Hinges and its Secrets for Perfect PETG Print
  • Extreme Integers – Doom from Below
  • Build a 3D Printer Enclosure

Latest Posts

  • The Importance of Wall Profiles in 3D Printing2023-02-12
  • The Hinges and its Secrets for Perfect PETG Print2023-02-07
  • Better Bridging with Slicer Guides2023-02-04
  • Stronger 3D Printed Parts with Vertical Perimeter Linking2023-02-02
  • Logic Gates Puzzle 1012023-02-02
  • Candlelight Emulation – Complexity with Layering2023-02-01
  • Three Ways to Integrate LED Light Into the Modular Lantern2023-01-29
  • The 3D Printed Modular Lantern2023-01-17

Categories

  • 3D Printing
  • Build
  • Common
  • Fail
  • Fun
  • Learn
  • Projects
  • Puzzle
  • Recommendations
  • Request for Comments
  • Review
  • Software
Copyright (c)2022 by Lucky Resistor. All rights reserved.