tecki / ebpfcat

A Python-base EBPF code generator
GNU General Public License v2.0
17 stars 5 forks source link

How to read or write custom ethercat slave ? #7

Open jinyistudio534 opened 7 months ago

jinyistudio534 commented 7 months ago

EasyCAT HAT is a ethercat slave for raspberry pi. this slave is here EasyCAT and its ESI/XML this slave can share 32 bytes for output(from slave, master read only) , 32byte for input(from master,slave read only).

I have try to define a slave into terminals.py :

class EASYCAT3232(EBPFTerminal): compatibility = {(0x0000079A, 0x00DEFEDE)} byte0 = ProcessDesc(0x0005, 1, 'B') byte1 = ProcessDesc(0x0005, 2, 'B') byte2 = ProcessDesc(0x0005, 3, 'B') byte3 = ProcessDesc(0x0005, 4, 'B') byte4 = ProcessDesc(0x0005, 5, 'B') byte5 = ProcessDesc(0x0005, 6, 'B') byte6 = ProcessDesc(0x0005, 7, 'B') byte7 = ProcessDesc(0x0005, 8, 'B') byte8 = ProcessDesc(0x0005, 9, 'B') byte9 = ProcessDesc(0x0005, 10, 'B') byte10 = ProcessDesc(0x0005, 11, 'B') byte11 = ProcessDesc(0x0005, 12, 'B') byte12 = ProcessDesc(0x0005, 13, 'B') byte13 = ProcessDesc(0x0005, 14, 'B') byte14 = ProcessDesc(0x0005, 15, 'B') byte15 = ProcessDesc(0x0005, 16, 'B') byte16 = ProcessDesc(0x0005, 17, 'B') byte17 = ProcessDesc(0x0005, 18, 'B') byte18 = ProcessDesc(0x0005, 19, 'B') byte19 = ProcessDesc(0x0005, 20, 'B') byte20 = ProcessDesc(0x0005, 21, 'B') byte21 = ProcessDesc(0x0005, 22, 'B') byte22 = ProcessDesc(0x0005, 23, 'B') byte23 = ProcessDesc(0x0005, 24, 'B') byte24 = ProcessDesc(0x0005, 25, 'B') byte25 = ProcessDesc(0x0005, 26, 'B') byte26 = ProcessDesc(0x0005, 27, 'B') byte27 = ProcessDesc(0x0005, 28, 'B') byte28 = ProcessDesc(0x0005, 29, 'B') byte29 = ProcessDesc(0x0005, 30, 'B') byte30 = ProcessDesc(0x0005, 31, 'B') byte31 = ProcessDesc(0x0005, 32, 'B')

Refer to your devices.py, I don't know what kind of device it should be. As following code. Please tell me how to modify the following program to read the value of byte0 and write the value to byte1? 😵 DigitalOutput -> ???

easycat = EASYCAT3232(master) await easycat.initialize(-5,21) do1 = DigitalOutput(out1.channel1) # use channel 1 of terminal "out" do2 = DigitalOutput(out2.channel3) # use channel 1 of terminal "out"

tecki commented 7 months ago

There are weird devices out there, fortunately I also had stumbled over such a wannabe-ethercat device. Usually the problem is that their self description is useless, so ProcessDesc doesn't work. But there is hope: this is what PacketDesc is for, replacing ProcessDesc. It takes three parameters: first, SyncManager.IN or .OUT to show whether you want to read or write, then the byte position in your custom device, lastly either a format character like in the struct module (eg "H" for two bytes), or an integer denoting which bit is meant if the byte is a bit field.

Anyways your code should read something like this:

do1 = DigitalOutput(easycat.byte21)

The byte21 is one of the fields you defined in your terminal definition.

tecki commented 7 months ago

Looking again at it, if you want to read and write entire bytes, you should not use DigitalOutput, which is for single bits, but AnalogOutput. So something like

in1 = AnalogInput(easycat.byte7)
out1 = AnalogOutput(easycat.byte5)

Once the sync group has been started, you can do things like out1.value = in1.value. Note that this makes only sense for reading or setting values once in a while. If you want to read and write values all the time, like in a control loop, you should write your own device, like the Motor device in the documentation.

jinyistudio534 commented 7 months ago

class EASYCAT3232(EBPFTerminal): compatibility = {(0x0000079A, 0x00DEFEDE)} byte0 = ProcessDesc(0x0005, 1, 'B') byte1 = ProcessDesc(0x0005, 2, 'B') byte2 = ProcessDesc(0x0005, 3, 'B') byte3 = ProcessDesc(0x0005, 4, 'B') byte4 = ProcessDesc(0x0005, 5, 'B') byte5 = ProcessDesc(0x0005, 6, 'B') byte6 = ProcessDesc(0x0005, 7, 'B') byte7 = ProcessDesc(0x0005, 8, 'B')

I use ProcessDesc(). I try ob0 = AnalogOutput(easycat.byte1) ok. slave side has received value with any byte0,byte1,, do1,do2 are ok too. But ib0 = AnalogInput(easycat.byte0) not ok. master side cann't received any value.😅 Is there something wrong with my program? 😅

terminal massage:

WARNING:root:EtherCAT datagram was processe 4 times, should be 3
ib0:  0    ob0: 112
WARNING:root:EtherCAT datagram was processe 4 times, should be 3

async def main(): master = FastEtherCat("eth0") await master.connect() print("Number of terminals:", await master.count())
out1 = EL2088(master)
await out1.initialize(-3,3) out2 = EL2088(master)
await out2.initialize(-4,4) easycat = EASYCAT3232(master)
await easycat.initialize(-5,5) do1 = DigitalOutput(out1.channel1) # use channel 1 of terminal "out" do2 = DigitalOutput(out2.channel3) # use channel 1 of terminal "out" ob0 = AnalogOutput(easycat.byte1) ib0 = AnalogInput(easycat.byte0) sg = SyncGroup(master, [do1,do2,ib0,ob0]) # this sync group only contains one terminal task = sg.start() # start operating the terminals ox = 0 ix = 0 for i in range(5000):
do1.value = 1 if do1.value==0 else 0 do2.value = 1 if do2.value==0 else 0 ob0.value = ox ox = ox+1 if ox<255 else 0
print('ib0: ',ib0.value,' ob0:',ob0.value) await asyncio.sleep(0.1) task.cancel()