### Install festo-cpx-io from git repo with all extras Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/index.md Install the package from the git repository with all optional dependencies using uv. ```bash uv sync --all-extras ``` -------------------------------- ### Setup CPX-E system with Python context manager Source: https://github.com/festo-se/festo-cpx-io/blob/main/README.md Import CpxE and use a context manager to set up the system. The order of modules must match the hardware setup. ```python with CpxE(, ip_address=) as myCPX: print(myCPX.modules) ``` -------------------------------- ### CPX-E Digital Output Example Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md This snippet demonstrates basic setup for a CPX-E digital output module. ```python from cpx_io.cpx_system.cpx_e.cpx_e import CpxE from cpx_io.cpx_system.cpx_e.eep import CpxEEp from cpx_io.cpx_system.cpx_e.e8do import CpxE8Do ``` -------------------------------- ### Install festo-cpx-io from git repo Source: https://github.com/festo-se/festo-cpx-io/blob/main/README.md Clone the repository, navigate to the directory, and use 'uv' to sync dependencies and install. ```bash git clone ``` ```bash cd ``` ```bash uv sync ``` ```bash uv sync --all-extras ``` -------------------------------- ### Install festo-cpx-io from PyPI Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/index.md Install the latest release of the package from the public PyPi repository using pip. ```bash pip install festo-cpx-io ``` -------------------------------- ### Install festo-cpx-io with pip Source: https://github.com/festo-se/festo-cpx-io/blob/main/README.md Install the latest release from PyPi. Use optional dependencies for CLI or logging. ```bash pip install festo-cpx-io ``` ```bash pip install festo-cpx-io[cli] ``` ```bash pip install festo-cpx-io --group dev ``` -------------------------------- ### Setup CPX-E with a List of Modules Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Initialize the CPX-E system by providing a list of module objects. Modules are named automatically and can be accessed by index or name. ```python from cpx_io.cpx_system.cpx_e.cpx_e import CpxE from cpx_io.cpx_system.cpx_e.eep import CpxEEp from cpx_io.cpx_system.cpx_e.e16di import CpxE16Di modules = [CpxEEp(), CpxE16Di()] with CpxE(ip_address="192.168.1.1", modules=modules) as myCPX: module_list = myCPX.modules module_0 = myCPX.modules[0] module_1 = myCPX.cpxe16di myCPX.modules[0].name = "ep_module" myCPX.cpxe16di.name = "digital_input_module" ``` -------------------------------- ### Example: Read from CPX-AP device via CLI Source: https://github.com/festo-se/festo-cpx-io/blob/main/README.md Example demonstrating how to read a specific channel from a module on a CPX-AP device using the CLI. ```bash festo-cpx-io -i 192.178.0.10 cpx-ap read -m 3 -c 2 ``` -------------------------------- ### Initialize CPX-E system with context manager Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/index.md Import and initialize the CpxE class using a context manager in Python. This example shows how to set up the system with a typecode and IP address, and then print the attached modules. ```python from cpx_io.cpx_system.cpx_e.cpx_e import CpxE with CpxE(, ip_address=) as myCPX: print(myCPX.modules) ``` -------------------------------- ### Install festo-cpx-io with optional CLI dependencies Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/index.md Install the package with optional dependencies for CLI and logging features. ```bash pip install festo-cpx-io[cli] ``` -------------------------------- ### Install festo-cpx-io with development dependencies Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/index.md Install the package including development dependencies using pip with the --group flag. ```bash pip install festo-cpx-io --group dev ``` -------------------------------- ### Setup CPX-E Modules by Typecode Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Initialize the CPX-E system using typecodes to automatically set up attached modules. Modules can be accessed by index or auto-generated names. ```python from cpx_io.cpx_system.cpx_e.cpx_e import CpxE with CpxE("60E-EP-MLNINO", ip_address="192.168.1.1") as myCPX: module_list = myCPX.modules module_0 = myCPX.modules[0] module_1 = myCPX.cpxe8do myCPX.modules[0].name = "ep_module" myCPX.cpxe8do.name = "digital_output_module" ``` -------------------------------- ### Use CPX-E with Context Manager Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Utilize the CPX-E system with a context manager for automatic connection management. This example shows reading module count and accessing the module list. ```python with CpxE("60E-EP-MLNINO", ip_address="192.168.1.1") as myCPX: # read system information module_count = myCPX.read_module_count() module_list = myCPX.modules ``` -------------------------------- ### Control EHPS Gripper with CPX-E IO-Link Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md This example shows how to initialize and control an EHPS gripper connected to a CPX-E module using IO-Link. It covers setting operating modes, reading line states, and sending open/close commands. Ensure the necessary imports and helper functions like `read_process_data_in` are available. ```python from cpx_io.cpx_system.cpx_e.cpx_e import CpxE from cpx_io.cpx_system.cpx_e.cpx_e_iolink import CpxE4Iol import time import struct # Placeholder for the actual read_process_data_in function def read_process_data_in(raw_data): # This function would parse the raw data based on the EHPS datasheet # For demonstration, returning a dummy dictionary return {"OpenedPositionFlag": False, "ClosedPositionFlag": False} with CpxE( ip_address="192.168.1.1", modules=[CpxE4Iol(8)], ) as myCPX: # read system information module_list = myCPX.modules # example EHPS-20-A-LK on port 1 EHPS_CHANNEL = 1 # (optional) get the module and assign it to a new variable for easy access e4iol = myCPX.cpxe4iol # (optional) you can reset the power for each channel e4iol.configure_pl_supply(False, EHPS_CHANNEL) e4iol.configure_ps_supply(False) time.sleep(0.05) e4iol.configure_pl_supply(True, EHPS_CHANNEL) e4iol.configure_ps_supply(True) time.sleep(0.05) # set operating mode of channel 0 to "IO-Link communication" e4iol.configure_operating_mode(3, channel=EHPS_CHANNEL) time.sleep(0.05) # (optional) read line-state, should now be "OPERATE" for the channel param = e4iol.read_line_state() # read process data raw_data = e4iol.read_channel(EHPS_CHANNEL) # interpret it according to datasheet process_data_in = read_process_data_in(raw_data) # demo of process data out needed to initialize EHPS control_word_msb = 0x00 control_word_lsb = 0x01 # latch gripping_mode = 0x46 # universal workpiece_no = 0x00 gripping_position = 0x03E8 gripping_force = 0x03 # ca. 85% gripping_tolerance = 0x0A data = [ control_word_lsb + (control_word_msb << 8), workpiece_no + (gripping_mode << 8), gripping_position, gripping_tolerance + (gripping_force << 8), ] # init # pack the 4*16bit values to bytes process_data_out = struct.pack(">HHHH", *data) e4iol.write_channel(EHPS_CHANNEL, process_data_out) time.sleep(0.05) # Open command: 0x0100 data[0] = 0x0100 # Directly modify the list element process_data_out = struct.pack(">HHHH", *data) e4iol.write_channel(EHPS_CHANNEL, process_data_out) # wait for the process data in to change to "opened" while not process_data_in["OpenedPositionFlag"]: process_data_in = read_process_data_in(e4iol.read_channel(EHPS_CHANNEL)) time.sleep(0.05) # Close command 0x 0200 data[0] = 0x0200 # Directly modify the list element process_data_out = struct.pack(">HHHH", *data) e4iol.write_channel(EHPS_CHANNEL, process_data_out) # wait for the process data in to change to "closed" while not process_data_in["ClosedPositionFlag"]: process_data_in = read_process_data_in(e4iol.read_channel(EHPS_CHANNEL)) time.sleep(0.05) ``` -------------------------------- ### CPX-AP IO-Link with SDAS Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md This is a placeholder for IO-Link examples with SDAS on the CPX-AP system. The provided code imports the necessary library. ```python from cpx_io.cpx_system.cpx_ap.cpx_ap import CpxAp ``` -------------------------------- ### CPX-E Object with Typecode Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Basic example showing the import of the CpxE class for use with CPX-E systems, specifically when dealing with typecodes. ```python """Example code for CPX-E with typecode""" # import the library from cpx_io.cpx_system.cpx_e.cpx_e import CpxE ``` -------------------------------- ### Cyclic Access with Python Threading Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md This snippet is a placeholder for examples related to cyclic data access using Python threading. ```python """Example code for cyclic access with python threading""" import time import threading ``` -------------------------------- ### I/O-Link Manual Connection and Diagnosis with CPX-AP Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Example of diagnosing an I/O-Link device connected to a CPX-AP module. It demonstrates writing validation settings, device IDs, and port modes, then reading status and diagnosis information. ```python """Example code for diagnosis with CPX-AP""" import time # Import the library from cpx_io.cpx_system.cpx_ap.cpx_ap import CpxAp with CpxAp(ip_address="192.168.1.1") as myCPX: # optional: for easy access, assign the IO-Link module to an object myIOL = myCPX.cpx_ap_a_4iol_m12_variant_16 SDAS_CHANNEL = 2 # this assumes you have a SDAS sensor on channel 2 # Write the validation setting myIOL.write_module_parameter( "Validation & Backup", "Type compatible Device V1.1", SDAS_CHANNEL ) # Write the IO-Link device ID and Vendor ID to the IO-Link module # You can read these with read_fieldbus_parameters()[SDAS_CHANNEL] # In this example, we write a wrong ID on purpose (it should be 12) # So that an error occures and we can read it out. myIOL.write_module_parameter("DeviceID", 13, SDAS_CHANNEL) myIOL.write_module_parameter("Nominal Vendor ID", 333, SDAS_CHANNEL) # Set the Port Mode to IOL_MANUAL. This will compare the written DeviceID # with the actual device ID and the Nominal Vendor ID with the actual vendor # ID. If they do not match, the "Port status information" of the fieldbus # parameters will change to "PORT_DIAG" myIOL.write_module_parameter("Port Mode", "IOL_MANUAL", SDAS_CHANNEL) time.sleep(0.05) # give it some time to set everything param = myIOL.read_fieldbus_parameters() print(param[SDAS_CHANNEL]) # If everything works, this loop will run until the port goes into OPERATE # mode. But in our example it will go to PORT_DIAG. We catch this with the # following if statement and print the diagnosis information from the module while param[SDAS_CHANNEL]["Port status information"] != "OPERATE": param = myIOL.read_fieldbus_parameters() if param[SDAS_CHANNEL]["Port status information"] == "PORT_DIAG": print(myIOL.read_diagnosis_information()) break ``` -------------------------------- ### Read IO-Link Sensor (SDAS) Data on CPX-E Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Example for using the CPX-E IO-Link master to communicate with an SDAS sensor. Configure the operating mode and read process data, including SSC bits and PDV. ```python with CpxE( ip_address="192.168.1.1", modules=[CpxEEp(), CpxE4Iol()], ) as myCPX: # read system information module_list = myCPX.modules SDAS_CHANNEL = 0 # set operating mode of channel 0 to "IO-Link communication" myCPX.cpxe4iol.configure_operating_mode(3, SDAS_CHANNEL) # read line-state, should now be "OPERATE" param = myCPX.cpxe4iol.read_line_state() # read the channel 0 process data sdas_data = myCPX.cpxe4iol.read_channel(SDAS_CHANNEL) # the process data consists of 4 ssc bits and 12 bit pdv (see datasheet sdas) # you can convert the bytes data to integer first and then do bitwise operations process_data_int = int.from_bytes(sdas_data, byteorder="big") ssc1 = bool(process_data_int & 0x1) ssc2 = bool(process_data_int & 0x2) ssc3 = bool(process_data_int & 0x4) ssc4 = bool(process_data_int & 0x8) pdv = (process_data_int & 0xFFF0) >> 4 # you can also read the device error or other parameters myCPX.cpxe4iol.read_device_error(0) ``` -------------------------------- ### Control Digital Output on CPX-AP Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Provides examples for controlling digital output channels on a CPX-AP module. This includes setting, resetting, toggling individual channels, writing to all channels simultaneously, and reading back channel states. Module parameters can also be configured. ```python from cpx_io.cpx_system.cpx_ap.cpx_ap import CpxAp with CpxAp(ip_address="192.168.1.1") as myCPX: print(myCPX.docu_path) dido = myCPX.modules[1] dido.set_channel(0) dido.reset_channel(0) dido.toggle_channel(0) dido.write_channels([True, True, False, False]) dido.read_channels() dido.read_channel(0) dido.read_output_channel(0) for parameter in dido.module_dicts.parameters.values(): print(parameter) dido.write_module_parameter("Input Debounce Time", "10ms") dido.write_module_parameter(20022, "Load supply monitoring inactive") dido.write_module_parameter(20052, 1) ``` -------------------------------- ### Cyclic Fault Detection with Threading Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md This example demonstrates how to implement cyclic fault detection for CPX-E modules using Python threading. It utilizes a lock for Modbus transmissions and an event for signaling errors. The `ThreadedCpx` class inherits from `CpxE` and runs a continuous thread to monitor module statuses. ```python import time import threading # import the library from cpx_io.cpx_system.cpx_e.cpx_e import CpxE from cpx_io.cpx_system.cpx_e.e16di import CpxE16Di class ThreadedCpx(CpxE): """Class for threaded CpxE""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # lock for modbus transmissions self.lock = threading.Lock() # error flag for error handling outside this thread self.status_error = threading.Event() self.exit_event = threading.Event() # start the thread self.continous_thread = threading.Thread(target=self.status_update) self.continous_thread.start() def __exit__(self, exc_type, exc_value, traceback): # exit the thread and then close the connection self.exit_event.set() return super().__exit__(exc_type, exc_value, traceback) def status_update(self): """continous thread to read faults in a cyclic access""" counter = 0 while not self.exit_event.is_set(): # lock the thread when accessing the connection with self.lock: module_status = self.read_fault_detection() if any(module_status): print( f"Status Error in module(s): " f"{ [i for i, s in enumerate(module_status) if s]}" ) self.status_error.set() time.sleep(0.05) # a counter to show that the thread is running print(counter) counter += 1 ``` -------------------------------- ### Instantiate CPX-E System and Add Modules Later Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Instantiate an empty CPX-E system and add modules subsequently. Ensure to import the specific module class first. ```python from cpx_io.cpx_system.cpx_e.e8do import CpxE8Do myCPX = CpxE(ip_address="192.168.1.1") e8do = myCPX.add_module(CpxE8Do()) ``` -------------------------------- ### CPX-AP Startup and System Information Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Initializes the CpxAp object, prints the documentation path, and displays system information. The attached modules are automatically detected. ```python """Example code for CPX-AP startup and system information""" # import the library from cpx_io.cpx_system.cpx_ap.cpx_ap import CpxAp # for cpx_ap, the attached modules are found automatically with CpxAp(ip_address="192.168.1.1") as myCPX: # view the system documentation by going to the apdd path on your system directory # this documentation is updated everytime the CpxAp Object with this ip address is # instanciated. It gives an overview of all parameters and functions of each module print(myCPX.docu_path) # alternatively you can print out the system information in the console myCPX.print_system_information() # to get an overview of all available parameters, there is a function that iterates # over every module and reads out the parameters and channels if available myCPX.print_system_state() ``` -------------------------------- ### CPX System Composition with Custom Class Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Illustrates creating a custom class to abstract a CPX system, demonstrating the use of context managers for initialization and cleanup, and implementing custom functions like 'pressurize'. ```python # Import the library from cpx_io.cpx_system.cpx_ap.cpx_ap import CpxAp # This is your personal class. It doesn't inherit from anything! class PersonalClass: # Initialize your CpxAp System and configure it with your (default) parameters def __init__( self, ip_address="192.168.1.1" ): # you can pass down the arguments that you want. print("initialize the personal class") self.cpx = CpxAp(ip_address=ip_address) # to be used in a context manager, add the enter and exit function (leave the enter as it is) def __enter__(self): print("enter the personal class") return self # be sure to shutdown the cpx object in the exit function. def __exit__(self, *args): print("clean up CpxAp") # clean up everything self.cpx.shutdown() # implement your personal functions. For example a pressurize function with VTUX def pressurize(self, valve_number: int): # do some complex computation and evaluation of different # ap modules self.cpx.modules[1].set_channel(valve_number) # Demo to show that everything works correctly # if you run this script it will create a personal class but then raise a ZeroDivisionError. # You can see from the prints in the console how it behaves and that the use of the context # manager of PersonalClass is working and shutting down the cpx correctly if __name__ == "__main__": # simply use the pressurize command with PersonalClass() as personal: personal.pressurize(1) with PersonalClass() as personal: i = 1 / 0 print("This is never reached") ``` -------------------------------- ### Instantiate CPX-E with Modules via Constructor Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Instantiate a CPX-E system by providing modules directly in the constructor. The bus module (e.g., CpxEEp) should typically be listed first. ```python from cpx_io.cpx_system.cpx_e.e8do import CpxE8Do from cpx_io.cpx_system.cpx_e.eep import CpxEEp # add via constructor. Here you should always provide the -EP module first eep = CpxEEp() e8do = CpxE8Do() myCPX = CpxE(ip_address="192.168.1.1", modules=[eep, e8do]) ``` -------------------------------- ### Main Task with Acyclic Access Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Demonstrates setting up a threaded CPX connection, adding modules, and performing acyclic read operations with locking. Includes basic error checking and a loop for repeated access. ```python def main(): """main thread with acyclic access""" with ThreadedCpx(ip_address="192.168.1.1") as myCPX: myCPX.add_module(CpxE16Di()) # your main application here... for _ in range(3): # acyclic communication with locking with myCPX.lock: information = myCPX.read_device_identification() channels = myCPX.modules[1].read_channels() # error handling if myCPX.status_error.is_set(): print("ERROR handling ...") # jobs outside the cpx access can go here so they don't block the cyclic thread print(information) print(channels) time.sleep(10) print("End of main") if __name__ == "__main__": main() ``` -------------------------------- ### Read and Control EHPS Gripper with IO-Link Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Demonstrates reading process data from and writing control commands to an EHPS gripper via an IO-Link master. Includes initialization, opening, and closing sequences. ```python def read_process_data_in(data): """Read the process data and return as dict""" # ehps provides 3 x UIntegerT16 "process data in" according to datasheet. # you can unpack the data easily with stuct ehps_data = struct.unpack(">HHH", data) process_data_dict = {} process_data_dict["Error"] = bool((ehps_data[0] >> 15) & 1) process_data_dict["DirectionCloseFlag"] = bool((ehps_data[0] >> 14) & 1) process_data_dict["DirectionOpenFlag"] = bool((ehps_data[0] >> 13) & 1) process_data_dict["LatchDataOk"] = bool((ehps_data[0] >> 12) & 1) process_data_dict["UndefinedPositionFlag"] = bool((ehps_data[0] >> 11) & 1) process_data_dict["ClosedPositionFlag"] = bool((ehps_data[0] >> 10) & 1) process_data_dict["GrippedPositionFlag"] = bool((ehps_data[0] >> 9) & 1) process_data_dict["OpenedPositionFlag"] = bool((ehps_data[0] >> 8) & 1) process_data_dict["Ready"] = bool((ehps_data[0] >> 6) & 1) process_data_dict["ErrorNumber"] = ehps_data[1] process_data_dict["ActualPosition"] = ehps_data[2] return process_data_dict # list of some connected modules. IO-Link module is specified with 8 bytes per port: # Datasheet: Per port: 8 E / 8 A Module: 32 E / 32 A. This has to be set up with the # switch on the module. with CpxAp(ip_address="192.168.1.1") as myCPX: # example EHPS-20-A-LK on port 1 EHPS_CHANNEL = 1 # (optional) get the module and assign it to a new variable for easy access io_link_master = myCPX.modules[5] # set operating mode of channel 0 to "IO-Link communication" io_link_master.write_module_parameter("Port Mode", "IOL_AUTOSTART", EHPS_CHANNEL) time.sleep(0.05) # (optional) read line-state, should now be "OPERATE" for the channel param = io_link_master.read_fieldbus_parameters() while param[EHPS_CHANNEL]["Port status information"] != "OPERATE": param = io_link_master.read_fieldbus_parameters() # read process data raw_data = io_link_master.read_channel(EHPS_CHANNEL) # interpret it according to datasheet process_data_in = read_process_data_in(raw_data) # demo of process data out needed to initialize EHPS control_word = 0x0001 # latch gripping_mode = 0x46 # universal workpiece_no = 0x00 gripping_position = 0x03E8 gripping_force = 0x03 # ca. 85% gripping_tolerance = 0x0A pd_list = [ control_word, gripping_mode, workpiece_no, gripping_position, gripping_force, gripping_tolerance, ] # init process_data_out = struct.pack(">HBBHBB", *pd_list) io_link_master.write_channel(EHPS_CHANNEL, process_data_out) time.sleep(0.05) # Open command: 0x0100 pd_list[0] = 0x0100 process_data_out = struct.pack(">HBBHBB", *pd_list) io_link_master.write_channel(EHPS_CHANNEL, process_data_out) # wait for the process data in to change to "opened" while not process_data_in["OpenedPositionFlag"]: process_data_in = read_process_data_in(io_link_master.read_channel(EHPS_CHANNEL)) time.sleep(0.05) # Close command: 0x 0200 pd_list[0] = 0x0200 process_data_out = struct.pack(">HBBHBB", *pd_list) io_link_master.write_channel(EHPS_CHANNEL, process_data_out) # wait for the process data in to change to "closed" while not process_data_in["ClosedPositionFlag"]: process_data_in = read_process_data_in(io_link_master.read_channel(EHPS_CHANNEL)) time.sleep(0.05) io_link_master.write_module_parameter("Port Mode", "DEACTIVATED", EHPS_CHANNEL) # wait for inactive param = io_link_master.read_fieldbus_parameters() while param[EHPS_CHANNEL]["Port status information"] != "DEACTIVATED": param = io_link_master.read_fieldbus_parameters() ``` -------------------------------- ### Instantiate CPX-E and Add Modules via add_module Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Instantiate a CPX-E system and add modules later using the add_module method. An empty CpxE constructor will automatically include a CpxEEp module at position 0. ```python from cpx_io.cpx_system.cpx_e.e8do import CpxE8Do from cpx_io.cpx_system.cpx_e.eep import CpxEEp eep = CpxEEp() e8do = CpxE8Do() myCPX = CpxE(ip_address="192.168.1.1") # this will already put an CpxEEp module at position 0 myCPX.add_module(e8Do) ``` -------------------------------- ### Instantiate CPX-E System by Typecode Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Instantiate a CPX-E system using its typecode and IP address. The typecode determines the correct modules and their order. ```python myCPX = CpxE("60E-EP-MLNINO", ip_address="192.168.1.1") ``` -------------------------------- ### Initialize and Print CPX-AP System Information Source: https://github.com/festo-se/festo-cpx-io/blob/main/README.md Use this snippet to establish a connection to the CPX-AP system via its IP address and print detailed system information. The library automatically handles module discovery and documentation generation. ```python from cpx_io.cpx_system.cpx_ap.cpx_ap import CpxAp with CpxAp(ip_address=) as myCPX: myCPX.print_system_information() ``` -------------------------------- ### Festo CPX IO CLI Help Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/index.md Display the main help message for the festo-cpx-io CLI, showing available options and subcommands. ```bash usage: festo-cpx-io [-h] [-v] [-i IP_ADDRESS] [-q] {cpx-e,cpx-ap} ... options: -h, --help show this help message and exit -v, --version print current version -i IP_ADDRESS, --ip-address IP_ADDRESS IP address to connect to (default: 192.168.0.1). -q, --quiet remove output verbosity subcommands: {cpx-e,cpx-ap} Subcommand that should be called ``` -------------------------------- ### Connect and Print System Information Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Use a context manager to establish a connection and print system information. The context manager ensures the connection is properly closed. ```python with CpxAp(ip_address="192.168.1.1") as myCPX: # print system information myCPX.print_system_information() ``` -------------------------------- ### Festo CPX IO CLI Usage Source: https://github.com/festo-se/festo-cpx-io/blob/main/README.md Main entry point for the CLI. Use the help flag for detailed options and subcommands. ```bash usage: festo-cpx-io [-h] [-v] [-i IP_ADDRESS] [-q] {cpx-e,cpx-ap} ... ``` -------------------------------- ### Festo CPX IO CLI cpx-e subcommand help Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/index.md Display help for the cpx-e subcommand, used for executing commands on CPX-E devices. Shows available options and actions. ```bash usage: festo-cpx-io cpx-e [-h] -t TYPECODE [-m MODULE_INDEX] {read,write} ... options: -h, --help show this help message and exit -t TYPECODE, --typecode TYPECODE Typecode of the cpx setup -m MODULE_INDEX, --module-index MODULE_INDEX Module index to read (default: 1). action commands: Action to perform {read,write} ``` -------------------------------- ### Set Custom Documentation Path Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Initialize the CpxAp object with a custom documentation path if the default path is not suitable. ```python CpxAp(ip_address="192.168.1.1", docu_path="user/docu") ``` -------------------------------- ### Festo CPX IO CLI cpx-ap subcommand help Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/index.md Display help for the cpx-ap subcommand, used for executing commands on CPX-AP devices. Shows available options and actions. ```bash usage: festo-cpx-io cpx-ap [-h] [-si] [-ss] {read,write} ... options: -h, --help show this help message and exit -si, --system-information Print system information -ss, --system-state Print system state -mt, --modbus-timeout Set a modbus timeout in seconds. Minimum timeout is 0.1s (100 ms). Exception: setting timeout to 0.0s means an infinite timeout (no timeout). If you don't specify a timeout we set it internally to None and the default timeout on the device itself remains active! action commands: Action to perform {read,write} ``` -------------------------------- ### CPX-AP Parameter Read/Write Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Demonstrates reading and writing individual parameters of a CPX-AP module. It shows how to iterate through parameters, read their values (including enum strings), and write new values, checking writability and data types. ```python """Example code for CPX-AP parameter read and write""" # import the library from cpx_io.cpx_system.cpx_ap.cpx_ap import CpxAp # for cpx_ap, the attached modules are found automatically with CpxAp(ip_address="192.168.1.1") as myCPX: # Read the automatically generated documentation on your system folder # It gives an overview of all parameters and functions of each module print(myCPX.docu_path) print("-------------------- ") # to get an overview of all available parameters, there is a function that iterates # over every module and reads out the parameters and channels if available myCPX.print_system_state() print("-------------------- ") # to read or write an individual parameter, you can either call it by ID or name, # ID is a bit faster. You can get both ID and name from the print_system_state function # or from the documentation or print the available parameters from each module. If the # value has enums as value, it will return the enum strings instead of the integer. module = myCPX.modules[1] for parameter in module.module_dicts.parameters.values(): # if you want to read it and print the correct unit of the value, you can get the unit # from the parameter. If you want to get the (if available) enum string, use # read_module_parameter_enum_str() instead. print( parameter.name, module.read_module_parameter(parameter.parameter_id), parameter.unit, ) print("-------------------- ") # writing a parameter is almost the same, you can check if the parameter is writable by # the R/W tag or get it from the parameter. You should also check the datatype of the # parameter to reduce unwanted behaviours. If the parameter allows enums as value you can # either use the enum strings (you can get them by printing them from the parameter) # try this example with a cpx-ap digital input module on index 1 or adapt VALUE to the # correct value for your module parameter module = myCPX.modules[1] PARAM_VALUE = "3ms" PARAM_ID = 20014 for parameter in module.module_dicts.parameters.values(): print( parameter.parameter_id, parameter.name, "\tIs writeable: ", parameter.is_writable, "\tData type: ", parameter.data_type, "\tEnums: ", parameter.enums, ) # adapt this to your found parameter module.write_module_parameter(PARAM_ID, PARAM_VALUE) ``` -------------------------------- ### Import CPX-AP System Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Import the necessary CpxAp class for the CPX-AP system. ```python from cpx_io.cpx_system.cpx_ap.cpx_ap import CpxAp ``` -------------------------------- ### Import CPX-E System Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Import the necessary CpxE class for the CPX-E system. ```python from cpx_io.cpx_system.cpx_e.cpx_e import CpxE ``` -------------------------------- ### Print System State (cpx-ap) Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cli.md Prints the system state of a cpx-ap module to the console. Requires the module's IP address. ```bash festo-cpx-io -i 192.168.0.2 -q cpx-ap -ss ``` -------------------------------- ### CPX-E Module Naming and Access Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Demonstrates automatic module naming in CPX-E systems, including handling multiple modules of the same type. Modules can be accessed by their auto-generated or custom names. ```python from cpx_io.cpx_system.cpx_e.cpx_e import CpxE from cpx_io.cpx_system.cpx_e.eep import CpxEEp from cpx_io.cpx_system.cpx_e.e16di import CpxE16Di with CpxE(ip_address="192.168.1.1", modules = [CpxEEp(), CpxE16Di()]) as myCPX: # assuming you have one CpxE16Di in your system print(myCPX.modules[1]) # will return "cpxe16di (idx: 1, type: CpxE16Di)" where cpxe16di is the automatically generated name # you can access the module by its name print(myCPX.cpxe16di) # will also return "cpxe16di (idx: 1, type: CpxE16Di)" # rename the module myCPX.cpxe16di.name = "my16di" # you can access the module with the new name cpx.my16di # and the myCPX.modules[1] will return the new name "my16di (idx: 1, type: CpxE16Di)" ``` -------------------------------- ### Instantiate CPX-AP System Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Instantiate a CPX-AP system with an optional Modbus timeout. Modules are generated automatically upon instantiation. Remember to close the connection. ```python myCPX = CpxAp(ip_address="192.168.1.1", timeout=1.5) ``` -------------------------------- ### Read SDAS Process Data with CPX-AP Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Demonstrates how to read process data from an IO-Link master module connected to a CPX-AP. It includes setting the port mode to IO-Link, waiting for the device to be operational, and then reading and interpreting the channel's process data. ```python from cpx_io.cpx_system.cpx_ap.cpx_ap import CpxAp with CpxAp(ip_address="192.168.1.1") as myCPX: print(myCPX.docu_path) SDAS_CHANNEL = 0 io_link_master = myCPX.modules[4] io_link_master.write_module_parameter("Port Mode", "IOL_AUTOSTART", SDAS_CHANNEL) param = io_link_master.read_fieldbus_parameters() while param[SDAS_CHANNEL]["Port status information"] != "OPERATE": param = io_link_master.read_fieldbus_parameters() sdas_data = io_link_master.read_channel(SDAS_CHANNEL) process_data_int = int.from_bytes(sdas_data, byteorder="big") ssc1 = bool(process_data_int & 0x1) ssc2 = bool(process_data_int & 0x2) ssc3 = bool(process_data_int & 0x4) ssc4 = bool(process_data_int & 0x8) pdv = (process_data_int & 0xFFF0) >> 4 ``` -------------------------------- ### Add Modules to CPX-E Dynamically Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Initialize an empty CPX-E object and add modules later using the `add_module` method. Modules are named automatically and can be renamed. ```python from cpx_io.cpx_system.cpx_e.cpx_e import CpxE from cpx_io.cpx_system.cpx_e.e16di import CpxE16Di from cpx_io.cpx_system.cpx_e.e8do import CpxE8Do with CpxE(ip_address="192.168.1.1") as myCPX: myCPX.add_module(CpxE16Di()) myCPX.add_module(CpxE8Do()) module_list = myCPX.modules module_0 = myCPX.modules[0] module_1 = myCPX.cpxe16di module_2 = myCPX.cpxe8do myCPX.modules[0].name = "ep_module" myCPX.cpxe16di.name = "digital_input_module" myCPX.cpxe8do.name = "digital_output_module" myCPX.modules[0].name = "my_ep_module" myCPX.digital_input_module.name = "my_digital_input_module" myCPX.digital_output_module.name = "my_digital_output_module" ``` -------------------------------- ### Acyclic Access with CpxAp Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Demonstrates acyclic access to a CPX-AP device, including reading diagnostic status and using a custom performance IO class. ```python from cpx_io.cpx_system.cpx_ap.cpx_ap import CpxAp from cpx_io.custom_perfom_io import CustomPerfomIo import time def main(): """main thread with acyclic access""" with CpxAp(ip_address="192.168.1.1", timeout=0.5, cycle_time=0.05) as myCPX: print(myCPX.read_diagnostic_status()) # the modbus connection does not timeout although we wait 10 seconds time.sleep(2) print(myCPX.read_diagnostic_status()) # It is possible to overwrite the function is called in the thread cyclicly with CustomPerfomIo( ip_address="192.168.1.1", timeout=0.5, cycle_time=0.05 ) as myCPX: time.sleep(2) if __name__ == "__main__": main() ``` -------------------------------- ### Read Digital Input on CPX-AP Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Demonstrates how to read digital input channels on a CPX-AP module. Modules can be accessed by index or by their automatically generated or custom names. It also shows how to read all channels at once and retrieve module parameters. ```python from cpx_io.cpx_system.cpx_ap.cpx_ap import CpxAp with CpxAp(ip_address="192.168.1.1") as myCPX: print(myCPX.docu_path) myCPX.modules[1].read_channel(0) myCPX.modules[1].name = "cpxap8di" myCPX.cpxap8di.read_channel(0) myIO = myCPX.modules[1] myIO.read_channel(0) myIO.read_channels() debounce_time = myIO.read_module_parameter_enum_str("Input Debounce Time") ``` -------------------------------- ### Print System Information (cpx-ap) Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cli.md Prints the system information of a cpx-ap module to the console. Does not require an IP address. ```bash festo-cpx-io cpx-ap -si ``` -------------------------------- ### Connection with Timeout and Cycle Time Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/features/cpx_io.md Establish a connection with a specified timeout and cycle time to prevent connection loss during periods of inactivity. The cycle time keeps the connection alive. ```python with CpxAp(ip_address="192.168.1.1", timeout=0.5, cycle_time=0.1) as myCPX: myCPX.print_system_information() time.sleep(2) # this command would timeout without the cycle_time parameter myCPX.print_system_information() ``` -------------------------------- ### Clone festo-cpx-io repository Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/index.md Clone the repository from a git URL to a specified destination directory. ```bash git clone ``` -------------------------------- ### Control Digital Outputs on CPX-E Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Demonstrates reading and writing to digital output channels on a CPX-E module. Ensure the CpxE8Do module is correctly configured in the modules list. ```python with CpxE(ip_address="192.168.1.1", modules=[CpxEEp(), CpxE8Do()]) as myCPX: # the modules are all named automatically and one can access them by their name or index # read all channels myCPX.cpxe8do.read_channels() # read one channel myCPX.cpxe8do.read_channel(0) # write all channels at once data = [False] * 8 myCPX.cpxe8do.write_channels(data) # set and reset or toggle the state of one channel myCPX.cpxe8do.set_channel(0) myCPX.cpxe8do.reset_channel(0) myCPX.cpxe8do.toggle_channel(0) # configure the diagnostics of the module myCPX.cpxe8do.configure_diagnostics(short_circuit=False, undervoltage=False) # configure the power reset myCPX.cpxe8do.configure_power_reset(True) ``` -------------------------------- ### Configure CPX-E Digital Input Module Source: https://github.com/festo-se/festo-cpx-io/blob/main/doc/source/examples.md Interact with a CPX-E digital input module, including reading channels, configuring diagnostics, power reset, and debounce time. ```python from cpx_io.cpx_system.cpx_e.cpx_e import CpxE from cpx_io.cpx_system.cpx_e.eep import CpxEEp from cpx_io.cpx_system.cpx_e.e16di import CpxE16Di with CpxE(ip_address="192.168.1.1", modules=[CpxEEp(), CpxE16Di()]) as myCPX: myCPX.cpxe16di.read_channels() myCPX.cpxe16di.read_channel(0) myCPX.cpxe16di.configure_diagnostics(True) myCPX.cpxe16di.configure_power_reset(True) myCPX.cpxe16di.configure_debounce_time(2) ```