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

Combine Everything

All the different parts are easily combined in the main file of the Arduino sketch. It starts with some includes and declarations.

#include <SPI.h>

#include "AudioPlayer.h"
#include "SDCard.h"
#include "Timer.h"
#include "LEDController.h"
#include "MotionSensor.h"

using namespace lr;

// Motion callback.
void onMotion(const unsigned long currentTime, MotionSensor::Status status);

/// The logic state.
enum LogicState : uint8_t {
	/// If the board is waiting for the sensor.
	WaitForSensor,
	/// If the board is idle
	IdleState,
	/// If the board is in error state, only the LED is controlled.
	ErrorState,
	/// If the board is in alarm state, the voice is played.
	AlarmState,
} logicState;

/// The controller for the LED
LEDController ledController; 

/// The motion sensor.
MotionSensor motionSensor;

There is the include #include : The SPI class is not used in the main file, but the include also makes sure the files for the SPI libraries are compiled and linked into the project.

Next I include all headers of my classes into the project and import everything from my own namespace lr into the global namespace.

I have to declare the method onMotion here (forward declaration), because I use them as callback in the setup() method which is defined before the onMotion method.

The enumeration LogicState is the overall logic state of my project. This states are similar to the sensor states, but represent it in a more general way.

Next there are two global variables to create instances of the LED controller and motion sensor.

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

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

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

	// Initialize the serial interface
	Serial.begin(115200);
	Serial.println(F("Starting..."));

	// Initialize the audio player
	if (!audioPlayer.initialize()) {
		Serial.println(F("Error on initialize."));
		Serial.flush();
		signalError();
		return;
	}

	Serial.println(F("Success!"));
	Serial.flush();
}

The setup() method initializes all components and writes messages to the serial interface.

void loop() {
	// Get the current time for this loop iteration.
	const unsigned long currentTime = millis();
	// Control the LED
	ledController.loop(currentTime);
	// Deactivate everything if there is an error.
	if (logicState != ErrorState) {
		// Check the motion sensor.
		motionSensor.loop(currentTime);
		// If the board goes into alarm state, play the sound.
		// This will block the loop, until the sound finishes.
		if (logicState == AlarmState) {
			if (!audioPlayer.play("voice.snd")) {
				Serial.println(F("Error on play."));
				Serial.flush();
				return;
			}
			// Go back into idle state after the sound.
			// The sensor might stay in alarm state for a while.
			logicState = IdleState;
		}
	}
}

The loop calls the loop methods of my components, depending on the state. In the Error state, only the loop method of the LED controller is called to keep the red LED blinking. Everything else is ignored.

If the overall logic switches into the alarm state, the voice audio is played. This is a blocking call. After playing the voice, the loop goes back into idle state.

void onMotion(const unsigned long currentTime, MotionSensor::Status status)
{
	if (status == MotionSensor::WaitStablilize) {
		Serial.println(F("Wait until the sensor is ready."));
		Serial.flush();
		ledController.setState(LEDController::Orange, LEDController::BlinkSlow);
	} else if (status == MotionSensor::Idle) {
		Serial.println(F("Sensor is in idle state."));
		Serial.flush();
		ledController.setState(LEDController::Green, LEDController::FlashVerySlow);
		logicState = IdleState; // Ready to observe.
	} else if (status == MotionSensor::Alarm) {
		Serial.println(F("Sensor alarm."));
		Serial.flush();
		ledController.setState(LEDController::Red, LEDController::On);
		logicState = AlarmState; // Activate the alarm and play a sound.
	}
}

The onMotion callback is called if the state of the motion sensor changes. Depending on the state, the LED color and state is changed and the overall state of the controller is changed too.

void signalError() {
	ledController.setState(LEDController::Red, LEDController::BlinkFast);
	logicState = ErrorState; // Deactivate everything except the LED blinking.
}

The signalError() method is called to put the controller into the error state. The LED is changed into red blinking, and the logic state is set to ErrorState. Only a reset of the board can end the error state.

Conclusion

Because all the complexity is wrapped into components with simple interfaces, the main file of the project looks very clean and should be easy to understand. Imagine the chaos if every detail from these classes would be put into one single file.

Continue here: From the Prototype to the Final Device

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.