bnjmnp / pysoem

Cython wrapper for the Simple Open EtherCAT Master Library
MIT License
96 stars 37 forks source link

Homing mode #72

Closed Phiraos closed 2 years ago

Phiraos commented 2 years ago

Hi,

I am using a C1250-DS-XC-1S (with standard ASIC ET1100 and CiA402 Protocol). I am trying to use a linear actuator but frankly I understand nothing. So, to begin, I try to realize a home operation.

My code is inspired by the #30 :

import time
import pysoem
import ctypes

class InputPdo(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ('statusword', ctypes.c_uint16),
        ('position_actual_value', ctypes.c_int32),
        ('demand_position', ctypes.c_int32),
        ('demand_current', ctypes.c_int32),
        ('modes_of_operation_display', ctypes.c_int8),
        ('byte_padding', ctypes.c_int8),
    ]

class OutputPdo(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ('controlword', ctypes.c_uint16),
        ('target_position', ctypes.c_int32),
        ('target_velocity', ctypes.c_int32),
        ('modes_of_operation', ctypes.c_int8),
        ('byte_padding', ctypes.c_int8),
    ]

modes_of_operation = {
    'No mode': 0,
    'Profile position mode': 1,
    'Profile velocity mode': 3,
    'Homing mode': 6,
    'Cyclic synchronous position mode': 8,
    'Cyclic synchronous velocity mode': 9,
    'Cyclic synchronous torque mode': 10,
}

SDO_Info_Check = False

master = pysoem.Master()

print('opening connection')
master.open('eno1')

if master.config_init() > 0:
    master.read_state()
    for device in master.slaves:
        print('Found Device: {},'.format(device.name))
        print('Manufacturer id: {}'.format(hex(device.man)))
        print('Id: {}'.format((hex(device.id))))
        print('state: {}'.format(hex(device.state)))

    print('Transition system to SAFEOP_STATE')
    io_map_size = master.config_map()
    print('IOMap Size: {}'.format(io_map_size))

    if master.state_check(pysoem.SAFEOP_STATE, 50000) != pysoem.SAFEOP_STATE:
        master.read_state()
        if not device.state == pysoem.SAFEOP_STATE:
                print('{} did not reach SAFEOP state'.format(device.name))
                print('al status code {} ({})'.format(hex(device.al_status), pysoem.al_status_code_to_string(device.al_status))
                )

        raise Exception('not all slaves reached SAFEOP state')
    else:
            print('Device in SAFEOP state: {}'.format(hex(device.state)))

# Send and receive process data to have valid data at all outputs before transistioning to OP_STATE
    print('Send and receive process data to have valid data at all outputs before transistioning to OP_STATE')
    master.send_processdata()
    actual_wkc = master.receive_processdata(2000)
    if not actual_wkc == master.expected_wkc:
        print('incorrect wkc')

# Transition MASTER to OP_STATE (Slave should follow)
    print('Transitioning system to OP_STATE')
    master.state = pysoem.OP_STATE
    master.write_state()

    if master.state_check(pysoem.OP_STATE, 50000) != pysoem.OP_STATE:
        master.read_state()
        if not device.state == pysoem.OP_STATE:
                print('{} did not reach OP state'.format(device.name))
                print('al status code {} ({})'.format(hex(device.al_status), pysoem.al_status_code_to_string(device.al_status)))
        raise Exception('Not all slaves reached OP state')

        # Read state of all slaves at start-up
    master.read_state()
    print('Device in OP state: {}'.format(hex(device.state)))
    print('{}'.format(device.output))
    output_data = OutputPdo()
    output_data.modes_of_operation = modes_of_operation['Homing mode']
    for control_cmd in [6,7,15]:
        print('{}'.format(control_cmd))
        output_data.controlword = control_cmd
        device.output = bytes(output_data)
        master.send_processdata()
        master.receive_processdata(1000)
        time.sleep(0.01)
        print('{}'.format(device.output))

else:
    print('no device found')

master.close()

The actuator is in OP state but do nothing after send_processdata(). Clearly, there is something I am missing.

bnjmnp commented 2 years ago

Hi,

Maybe you need to write a homing method in the homing method object, and homing speeds accordingly. I also think to trigger the homing you need another control_word command.

    for control_cmd in [6,7,15,31]:
        ...

At least I know it form the position mode, there you also need a transition from 15 to 31 for any position update.

Phiraos commented 2 years ago

Hi @bnjmnp ,

Thanks for your reply.

I solved my problem just before your answer and you are right, a control_word command is missing, it was 63.

Now, time to go to position.