List of Events for Modules in Smoothie

This is a list of all the events that a Module can register for in Smoothieware V1.

These events allow modules to respond to various system activities and communicate with each other.

This reference is essential for developers creating custom modules for Smoothieware V1. Each event provides a hook into specific system activities.

Smoothieware V2 does not use the event-based module system. Instead, V2 uses FreeRTOS with configuration-based modules that communicate via direct lookup and request methods.

This page documents the V1 event system only. V2 modules are configured dynamically and use a registry-based approach with the Module::lookup() and request() interface rather than global events.
Name Called from Description How to cast the argument
ON_MAIN_LOOP /main.cpp Called in a loop in main(), all G/M commands must be executed or issued in this event. no argument
ON_CONSOLE_LINE_RECEIVED /modules/communication/SerialConsole.cpp Called every time a new line is received on the default Serial Console, with the line as a parameter SerialMessage new_message = *static_cast<SerialMessage*>(argument); string received = new_message.message;
ON_GCODE_RECEIVED /modules/communication/GcodeDispatch.cpp Called every time a new G code is received, with the Gcode object as a parameter Gcode* gcode = static_cast<Gcode*>(argument);
ON_IDLE /main.cpp Called in the main loop immediately after ON_MAIN_LOOP. Used by modules for periodic tasks that need to run frequently. Many modules use this for polling or checking states that need quick response times. no argument
ON_SECOND_TICK /libs/SlowTicker.cpp Called once per second by the SlowTicker timer. Used for periodic tasks that don’t need to run as frequently as ON_IDLE, such as temperature monitoring, status updates, watchdog checks, etc. no argument
ON_GET_PUBLIC_DATA /libs/PublicData.cpp Allow communication of data between modules. Module A can get data from B by providing checksums identifying Module B and the desired data. PublicDataRequest *pdr = static_cast<PublicDataRequest *>(argument)
ON_SET_PUBLIC_DATA /libs/PublicData.cpp Allow communication of data between modules. Module A can set data from B by providing checksums identifying Module B and the data to set up. PublicDataRequest *pdr = static_cast<PublicDataRequest *>(argument);
ON_HALT Multiple sources: /modules/communication/GcodeDispatch.cpp (M112 emergency stop), /modules/tools/endstops/Endstops.cpp, /modules/tools/temperaturecontrol/TemperatureControl.cpp, etc. Called when the system enters or exits HALT state (emergency stop). This disables heaters and motors, ignores further incoming Gcode and clears block queue. Used by modules to safely shut down or restart after emergency conditions. if(argument == nullptr) - entering halt state; if(argument == (void*)1) - clearing halt state (M999 or unkill button)
ON_ENABLE /modules/robot/Robot.cpp (M17/M18 commands), /modules/robot/Conveyor.cpp Called to enable or disable stepper motors. Triggered by M17 (enable), M18 (disable), or when motion starts. Modules handling motor drivers should respond to this event. uint32_t bm = (uint32_t)argument;
if(bm == 0x01) - enable all motors
if(bm == 0 or nullptr) - disable all motors
Otherwise: bit 0 = enable/disable, bits 1-6 = axis mask (bit1=X, bit2=Y, bit3=Z, bit4=A, bit5=B, bit6=C)
NUMBER_OF_DEFINED_EVENTS n/a Only used to enumerate the events. Not an actual event that gets called. no argument

Event System Architecture

The Smoothieware V1 event system provides a publish-subscribe pattern for module communication. Events are defined in /libs/Module.h as an enumeration, and the kernel dispatches these events to all registered modules.

This section describes Smoothieware V1 only. V2 uses FreeRTOS with a module registry and request-based communication instead of the event system.

How Events Work

  1. Event Definition: All events are defined in the _EVENT_ENUM enumeration in /libs/Module.h
  2. Registration: Modules register for specific events using register_for_event(EVENT_NAME) in their constructor or on_module_loaded() method
  3. Dispatching: The kernel calls events via THEKERNEL->call_event(EVENT_NAME, argument)
  4. Handling: Registered modules receive the event through their corresponding callback method (e.g., on_idle(), on_gcode_received(), etc.)

Registering for Events

To register your module for an event, add the registration call in your module’s constructor or on_module_loaded() method (V1 only):

This section applies to Smoothieware V1 only. V2 modules use configuration-based registration instead.

void MyModule::on_module_loaded() {
    this->register_for_event(ON_GCODE_RECEIVED);
    this->register_for_event(ON_IDLE);
    this->register_for_event(ON_HALT);
}

Then implement the corresponding callback methods:

void MyModule::on_gcode_received(void *argument) {
    Gcode *gcode = static_cast<Gcode*>(argument);
    if(gcode->has_m && gcode->m == 123) {
        // Handle M123 command
    }
}

void MyModule::on_idle(void *argument) {
    // Periodic tasks that need frequent execution
}

void MyModule::on_halt(void *argument) {
    if(argument == nullptr) {
        // System is entering halt state - disable outputs
    } else {
        // System is clearing halt state - can re-enable
    }
}

Event Usage Examples

Common Module Patterns

Temperature Control registers for:

  • ON_IDLE - PID calculations and sensor reading
  • ON_SECOND_TICK - Temperature reporting and monitoring
  • ON_HALT - Emergency heater shutdown
  • ON_GCODE_RECEIVED - M104/M109 temperature commands

Endstops registers for:

  • ON_IDLE - Checking endstop states during moves
  • ON_GCODE_RECEIVED - M119 endstop status, homing commands

Laser registers for:

  • ON_HALT - Immediately disable laser for safety
  • ON_GCODE_RECEIVED - Laser power control commands

Motor Driver Control registers for:

  • ON_ENABLE - Enable/disable motor drivers
  • ON_HALT - Disable motors on emergency stop
  • ON_SECOND_TICK - Monitor driver alarm conditions
  • ON_IDLE - Process enable/disable events safely (SPI communication)

Best Practices

These best practices apply to Smoothieware V1 module development using the event system.

This section applies to Smoothieware V1 only. V2 modules use a different architecture.

Do:
  • Keep event handlers short and fast - other modules are waiting
  • Use ON_IDLE for time-critical polling operations
  • Use ON_SECOND_TICK for less frequent periodic tasks
  • Always check if system is halted before executing commands: if(THEKERNEL->is_halted()) return;
  • Register for ON_HALT if your module controls hardware that needs emergency shutdown
Don't:
  • Don't perform lengthy operations in event handlers - they block other modules
  • Don't perform SPI or I2C transactions directly in interrupt-called events (use ON_IDLE to schedule)
  • Don't ignore ON_HALT events if you control heaters, lasers, or other potentially dangerous hardware
  • Don't assume event order - events may be called in any sequence

Event Call Frequency

Event Frequency Context
ON_MAIN_LOOP ~1000+ Hz Main loop
ON_IDLE ~1000+ Hz Main loop (immediately after ON_MAIN_LOOP)
ON_CONSOLE_LINE_RECEIVED On demand When serial data received
ON_GCODE_RECEIVED On demand When G-code parsed
ON_SECOND_TICK 1 Hz SlowTicker timer interrupt
ON_HALT On demand Emergency or error conditions
ON_ENABLE On demand Motor enable/disable commands
ON_GET_PUBLIC_DATA On demand Inter-module data requests
ON_SET_PUBLIC_DATA On demand Inter-module data updates

See Also

This page is for Smoothieware V1 module development. For V2, see the V2 module documentation (coming soon).

This is a wiki! If you'd like to improve this page, you can edit it on GitHub.