Adding a simulation¶
A simulation is two classes: a model (the physics, no UI) and a view (the drawing).
The model¶
plcyard/sims/my_machine.py. Its module docstring documents the I/O: it becomes the
simulation reference.
"""Conveyor with a photo-eye.
Digital (slot words):
%I0.0 Start (NO) %I0.1 Stop (NC) %I0.2 Photo-eye
%Q0.0 Motor
"""
@dataclass
class ConveyorModel:
name = "Conveyor"
position: float = 0.0
start_pressed: bool = False
stop_pressed: bool = False
outputs: int = 0
events: list[str] = field(default_factory=list)
def input_words(self) -> dict[int, int]: # slot → 16-bit word, read every input scan
return {1: int(self.start_pressed) | int(not self.stop_pressed) << 1}
def set_output_words(self, words: dict[int, int]) -> None: # written every output scan
self.outputs = words.get(2, 0) & 0xFFFF
def step(self, dt_ms: float) -> None: # advance the physics after each scan
...
- Slot 1 is
%I0.x, slot 2 is%Q0.x. - Analog:
analog_inputs()returns{channel: volts}(0-10 V, channel 0 is%IW64);set_analog_outputs(volts)receives the outputs. - Append a line to
eventsfor misuse (a crash, an overflow).
Register it in MODELS in plcyard/sims/__init__.py: "conveyor": ("Conveyor", ConveyorModel).
The view¶
A QWidget that takes the model and repaints it (see plcyard/ui/sim_views3.py for examples
built on the shared canvas and control panel), registered in VIEWS. Give every labelled device
its address so it can be dragged onto a program.
The example and the tests¶
Add a working example in plcyard/data/samples/ and a test that runs it on the model and checks the
machine does its job. Then regenerate the reference:
python -m plcyard.docgen