Skip to content
Snippets Groups Projects
Commit 7e86056f authored by Martin Teichmann's avatar Martin Teichmann
Browse files

write even more documentation

parent d1714cb0
No related branches found
No related tags found
No related merge requests found
Pipeline #135470 passed
...@@ -110,11 +110,11 @@ class DigitalOutput(Device): ...@@ -110,11 +110,11 @@ class DigitalOutput(Device):
self.data = self.value self.data = self.value
class PWM(Device): class RandomOutput(Device):
"""Generic digital output device """Randomized digital output
This device can be linked to an analog output of a terminal. This device randomly switches its linked digital output
It will write the `value` to that terminal. on or off, with a probability given by :attr:`probability`.
""" """
seed = DeviceVar("I", write=True) seed = DeviceVar("I", write=True)
value = DeviceVar("I", write=True) value = DeviceVar("I", write=True)
...@@ -127,8 +127,13 @@ class PWM(Device): ...@@ -127,8 +127,13 @@ class PWM(Device):
self.seed = self.seed * 0xcf019d85 + 1 self.seed = self.seed * 0xcf019d85 + 1
self.data = self.value > self.seed self.data = self.value > self.seed
def update(self): @property
self.data = self.value def probability(self):
return self.value / 0xffffffff
@probability.setter
def probability(self, value):
self.value = int(value * 0xffffffff)
class Counter(Device): class Counter(Device):
...@@ -156,14 +161,67 @@ class Counter(Device): ...@@ -156,14 +161,67 @@ class Counter(Device):
class Motor(Device): class Motor(Device):
"""A simple closed-loop motor
This device implements a closed loop between an encoder and a
velocity-control motor.
.. attribute:: velocity
:type: TerminalVar
link this to the velocity output of a motor terminal
.. attribute:: encoder
:type: TerminalVar
link this to the position input of an encoder
.. attribute:: low_switch
:type: TerminalVar
link to a digital input for a low limit switch
.. attribute:: high_switch
:type: TerminalVar
link to a digital input for a high limit switch
.. attribute:: enable
:type: TerminalVar
link to the enable parameter of the motor terminal
.. attribute:: current_position
:type: TerminalVar
.. attribute:: set_enable
:type: DeviceVar
set to whether the motor should be enabled, i.e. moving
.. attribute:: target
:type: DeviceVar
the current target the motor should move to
.. attribute:: max_velocity
:type: DeviceVar
the maximum allowed velocity for the motor. If the motor is far away
from its target, this is the velocity the motor will go with.
.. attribute:: proportional
:type: DeviceVar
the proportionality factor between the distance from target and the
desired velocity.
"""
velocity = TerminalVar() velocity = TerminalVar()
encoder = TerminalVar() encoder = TerminalVar()
low_switch = TerminalVar() low_switch = TerminalVar()
high_switch = TerminalVar() high_switch = TerminalVar()
enable = TerminalVar() enable = TerminalVar()
current_position = DeviceVar()
set_velocity = DeviceVar(write=True)
set_enable = DeviceVar(write=True) set_enable = DeviceVar(write=True)
max_velocity = DeviceVar(write=True) max_velocity = DeviceVar(write=True)
max_acceleration = DeviceVar(write=True) max_acceleration = DeviceVar(write=True)
...@@ -176,7 +234,6 @@ class Motor(Device): ...@@ -176,7 +234,6 @@ class Motor(Device):
velocity = self.max_velocity velocity = self.max_velocity
elif velocity < -self.max_velocity: elif velocity < -self.max_velocity:
velocity = -self.max_velocity velocity = -self.max_velocity
self.current_position = self.encoder
self.velocity = velocity self.velocity = velocity
self.enable = self.set_enable self.enable = self.set_enable
...@@ -197,6 +254,7 @@ class Motor(Device): ...@@ -197,6 +254,7 @@ class Motor(Device):
with self.high_switch, self.velocity > 0: with self.high_switch, self.velocity > 0:
self.velocity = 0 self.velocity = 0
class Dummy(Device): class Dummy(Device):
"""A placeholder device assuring a terminal is initialized""" """A placeholder device assuring a terminal is initialized"""
def __init__(self, terminals): def __init__(self, terminals):
...@@ -210,6 +268,11 @@ class Dummy(Device): ...@@ -210,6 +268,11 @@ class Dummy(Device):
class RandomDropper(Device): class RandomDropper(Device):
"""Randomly drop packets
This fake device randomly drops EtherCat packets, to simulate bad
connections.
"""
rate = DeviceVar("I", write=True) rate = DeviceVar("I", write=True)
def program(self): def program(self):
......
...@@ -11,12 +11,15 @@ via an ethernet interface. So we create a master object, and connect to that ...@@ -11,12 +11,15 @@ via an ethernet interface. So we create a master object, and connect to that
interface an scan the loop. This takes time, so in a good asyncronous fashion interface an scan the loop. This takes time, so in a good asyncronous fashion
we need to use await, which can only be done in an async function:: we need to use await, which can only be done in an async function::
import asyncio
from ebpfcat.ebpfcat import FastEtherCat from ebpfcat.ebpfcat import FastEtherCat
# later, in an async function: async def main():
master = FastEtherCat("eth0") master = FastEtherCat("eth0")
await master.connect() await master.connect()
await master.scan_bus() await master.scan_bus()
asyncio.run(main())
Next we create an object for each terminal that we want to use. As an example, Next we create an object for each terminal that we want to use. As an example,
take some Beckhoff output terminal:: take some Beckhoff output terminal::
...@@ -39,7 +42,7 @@ instantiation, they are connected to the terminals:: ...@@ -39,7 +42,7 @@ instantiation, they are connected to the terminals::
from ebpfcat.devices import AnalogOutput from ebpfcat.devices import AnalogOutput
ao = AnalogOutput(out.ch1_value) ao = AnalogOutput(out.ch1_value) # use channel 1 of terminal "out"
Devices are grouped into :class:`~ebpfcat.SyncGroup`, which means that their Devices are grouped into :class:`~ebpfcat.SyncGroup`, which means that their
terminals are always read and written at the same time. A device can only terminals are always read and written at the same time. A device can only
...@@ -89,6 +92,7 @@ method of the device is called, in which one can evaluate the ...@@ -89,6 +92,7 @@ method of the device is called, in which one can evaluate the
"""a idiotic speed controller""" """a idiotic speed controller"""
self.speed = (self.position - self.target) * self.pConst self.speed = (self.position - self.target) * self.pConst
Three methods of control Three methods of control
------------------------ ------------------------
...@@ -120,11 +124,11 @@ The meaning of all these parameters can usually be found in the documentation ...@@ -120,11 +124,11 @@ The meaning of all these parameters can usually be found in the documentation
of the terminal. Additionally, terminals often have a self-description, which of the terminal. Additionally, terminals often have a self-description, which
can be read with the command line tool ``ec-info``:: can be read with the command line tool ``ec-info``::
$ ec-info eth0 --terminal -1 --sdo $ ec-info eth0 --terminal 1 --sdo
this reads the first (-1th) terminal's self description (``--sdo``). Add a this reads the first terminal's self description (``--sdo``). Add a ``--value``
``--value`` to also get the current values of the parameters. This prints out to also get the current values of the parameters. This prints out all known
all known self descriptions of CoE parameters. self descriptions of CoE parameters.
Once we know the meaning of parameters, they may be read or written Once we know the meaning of parameters, they may be read or written
asynchronously using :meth:`~ethercat.Terminal.sdo_read` and asynchronously using :meth:`~ethercat.Terminal.sdo_read` and
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment