Skip to content
Christian edited this page Jun 15, 2026 · 3 revisions

Every cycle in the control loop, all machines implement the MachineAct trait which exposes the act function. In the act function the machine executes its control logic, reading and writing IOs synchronously.

The MachineAct trait is defined in machines/src/lib.rs:

pub trait MachineAct {
    fn act_machine_message(&mut self, msg: MachineMessage);
    fn act(&mut self, now: Instant);
}

In this example a machine toggles a digital output every cycle:

#[derive(Debug)]
pub struct DigitalOutputToggler {
    output: DigitalOutputDevice,
    state: bool,
}

impl MachineAct for DigitalOutputToggler {
    fn act_machine_message(&mut self, _msg: MachineMessage) {}
    
    fn act(&mut self, _now: Instant) {
        self.state = !self.state;
        self.output.write(self.state.into());
    }
}

Machines can contain other machines, calling their act in sequence:

struct Machine1 {
    toggler1: DigitalOutputToggler,
    toggler2: DigitalOutputToggler,
}

impl MachineAct for Machine1 {
    fn act_machine_message(&mut self, _msg: MachineMessage) {}
    
    fn act(&mut self, now: Instant) {
        self.toggler1.act(now);
        self.toggler2.act(now);
    }
}

The act function should be as fast as possible, because delays slow down the control loop.

Clone this wiki locally