Motion Master
Loading...
Searching...
No Matches
soempp.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <functional>
5#include <map>
6#include <memory>
7#include <mutex>
8#include <string>
9#include <type_traits>
10#include <utility>
11#include <variant>
12#include <vector>
13
14#include "common.h"
15#include "ethercat.h"
16#include "loguru.h"
17
18namespace soempp {
19
31std::map<std::string, std::string> mapMacAddressesToInterfaces();
32
48inline std::string uiConfigWithDefaultPdoMapping = R"(
49{
50 "pdoMapping": {
51 "rx": {
52 "0x1600": [
53 "0x60400010",
54 "0x60600008",
55 "0x60710010",
56 "0x607a0020",
57 "0x60ff0020",
58 "0x60b20010",
59 "0x27010020"
60 ],
61 "0x1601": [
62 "0x60fe0120",
63 "0x60fe0220"
64 ],
65 "0x1602": [
66 "0x27030020",
67 "0x60b10020"
68 ]
69 },
70 "tx": {
71 "0x1a00": [
72 "0x60410010",
73 "0x60610008",
74 "0x60640020",
75 "0x606c0020",
76 "0x60770010",
77 "0x60f40020",
78 "0x21110220",
79 "0x21130220"
80 ],
81 "0x1a01": [
82 "0x24010010",
83 "0x24020010",
84 "0x24030010",
85 "0x24040010",
86 "0x27020020"
87 ],
88 "0x1a02": [
89 "0x60fd0020"
90 ],
91 "0x1a03": [
92 "0x27040020",
93 "0x20f00020",
94 "0x60fc0020",
95 "0x606b0020",
96 "0x60740010",
97 "0x60790020",
98 "0x20410120"
99 ]
100 }
101 }
102})";
103
128int setPdoMappingFromUiConfig(ecx_contextt *context, uint16 slave);
129
147void checkPdoMapping(ecx_contextt *context, uint16 slave);
148
172uint16_t getSlaveState(ecx_contextt *context, uint16_t slave,
173 bool forceRefresh);
174
194std::string convertSlaveStateToString(int state);
195
212bool transitionToHigherSlaveState(ecx_contextt *context, uint16_t slave,
213 int targetState);
214
237void updateMailboxSyncManagersOnNextState(ecx_contextt *context, uint16_t slave,
238 int targetState);
239
255void configureDetectedSmmModule(ecx_contextt *context, uint16_t slave);
256
273bool setSlaveState(ecx_contextt *context, uint16_t slave, int targetState);
274
286common::PdoMappings readPdoMappings(ecx_contextt *context, uint16_t slave);
287
302void logPdoMappingEntries(const std::vector<common::PdoMappingEntry> &entries);
303
315void logIoMap(uint8_t *ioMap, size_t totalBytes);
316
331struct Fieldbus {
332 ecx_contextt context;
333 std::string iface;
334 uint8 group;
336
337 /* Used by the context */
338 uint8 map[4096];
339 ecx_portt port;
340 ec_slavet slavelist[EC_MAXSLAVE];
342 ec_groupt grouplist[EC_MAXGROUP];
343 uint8 esibuf[EC_MAXEEPBUF];
344 uint32 esimap[EC_MAXEEPBITMAP];
345 ec_eringt elist;
346 ec_idxstackT idxstack;
347 boolean ecaterror;
348 int64 DCtime;
349 ec_SMcommtypet SMcommtype[EC_MAX_MAPT];
350 ec_PDOassignt PDOassign[EC_MAX_MAPT];
351 ec_PDOdesct PDOdesc[EC_MAX_MAPT];
352 ec_eepromSMt eepSM;
353 ec_eepromFMMUt eepFMMU;
354};
355
373void initFieldbus(std::unique_ptr<Fieldbus> &fieldbus,
374 const std::string &iface);
375
380class Slave {
381 public:
392 explicit Slave(ecx_contextt &context, uint16_t position);
393
402 uint16_t getPosition() const;
403
412 uint32_t getVendorId() const;
413
422 uint32_t getProductCode() const;
423
432 uint32_t getRevisionNumber() const;
433
445 int getState(bool forceRefresh = true) const;
446
466 bool setState(int targetState, int timeoutMs = 0, int intervalMs = 100);
467
489 void loadParameters(bool readValues = false);
490
503 void logParameters() const;
504
521
538
545 void clearParameters();
546
555 std::unordered_map<common::ParameterKey, common::Parameter> &
557
570 common::Parameter &findParameter(uint16_t index, uint8_t subindex);
571
599 template <typename T = std::vector<uint8_t>>
600 T upload(uint16_t index, uint8_t subindex, bool refresh = true) {
601 // Lock the mailbox mutex to ensure thread safety
602 std::lock_guard<std::mutex> lock(mailboxMutex_);
603
604 // Check if the device is in a valid state for uploading
605 auto state = getState(false);
606 if (state == EC_STATE_INIT || state == EC_STATE_BOOT) {
607 throw std::runtime_error(
608 "To upload object dictionary entries, the device must be in the (2) "
609 "PRE-OPERATIONAL, (4) SAFE-OPERATIONAL, or (8) OPERATIONAL state. "
610 "The current state is " +
611 convertSlaveStateToString(state) + ".");
612 }
613
614 // Find the previously loaded parameter
615 auto &parameter = findParameter(index, subindex);
616
617 // Refresh data if needed (SDO read)
618 if (refresh) {
619 const std::unique_ptr<std::uint8_t[]> data =
620 std::make_unique<std::uint8_t[]>(parameter.byteLength);
621 auto wkc = ecx_SDOread(&context_, position_, parameter.index,
622 parameter.subindex, false, &parameter.byteLength,
623 data.get(), EC_TIMEOUTRXM * 3);
624 if (wkc <= 0) {
625 LOG_F(ERROR, "Device %d: SDO read failed for %#04x:%02x! WKC: %d",
626 position_, parameter.index, parameter.subindex, wkc);
627 auto id = common::makeParameterId(parameter.index, parameter.subindex);
628 throw std::runtime_error("Device " + std::to_string(position_) +
629 ": SDO read failed for " + id +
630 "! WKC: " + std::to_string(wkc));
631 } else {
632 std::vector<uint8_t> receivedData(data.get(),
633 data.get() + parameter.byteLength);
634 if (!parameter.trySetValue(receivedData)) {
635 LOG_F(ERROR,
636 "Device %d: Failed to set the value of parameter %#04x:%02x!",
637 position_, parameter.index, parameter.subindex);
638 }
639 }
640 }
641
642 // Return the appropriate type
643 if constexpr (std::is_same_v<T, std::vector<uint8_t>>) {
644 return parameter.data; // parameter.data should be std::vector<uint8_t>
645 } else {
646 // Otherwise, try to get the value as the requested type T
647 auto value = parameter.getValue();
648 if (auto ptr = std::get_if<T>(&value)) {
649 return *ptr;
650 } else {
651 throw std::bad_variant_access(); // Type mismatch
652 }
653 }
654 }
655
680 template <typename T = std::vector<uint8_t>>
681 bool download(uint16_t index, uint8_t subindex, const T &value) {
682 std::lock_guard<std::mutex> lock(mailboxMutex_);
683
684 // Check if device is in valid state for download
685 auto state = getState(false);
686 if (state == EC_STATE_INIT || state == EC_STATE_BOOT) {
687 throw std::runtime_error(
688 "To download object dictionary entries, the device must be in the "
689 "(2) PRE-OPERATIONAL, (4) SAFE-OPERATIONAL, or (8) OPERATIONAL "
690 "state. The current state is " +
691 convertSlaveStateToString(state) + ".");
692 }
693
694 auto &parameter = findParameter(index, subindex);
695
696 // Convert value to raw byte data
697 std::vector<uint8_t> data;
698 if constexpr (std::is_same_v<T, std::vector<uint8_t>>) {
699 data = value;
700 } else {
701 // Set the value in the parameter model
702 if (!parameter.trySetValue(value)) {
703 LOG_F(ERROR,
704 "Device %d: Failed to set the value of parameter %#04x:%02x!",
705 position_, parameter.index, parameter.subindex);
706 return false;
707 }
708 data = parameter.data; // Use the parameter's byte representation
709 }
710
711 // Check if data size matches the expected parameter size
712 if (data.size() != parameter.byteLength) {
713 LOG_F(ERROR, "Data size mismatch: expected %d, got %zu",
714 parameter.byteLength, data.size());
715 throw std::runtime_error("Data size does not match the parameter size!");
716 }
717
718 // Perform the SDO write
719 auto wkc = ecx_SDOwrite(&context_, position_, parameter.index,
720 parameter.subindex, false, parameter.byteLength,
721 data.data(), EC_TIMEOUTRXM * 3);
722
723 // Check write result
724 if (wkc <= 0) {
725 LOG_F(ERROR, "Device %d: SDO write failed for %#04x:%02x! WKC: %d",
726 position_, parameter.index, parameter.subindex, wkc);
727 return false;
728 }
729
730 return true;
731 }
732
742
751 void updatePdoMappings();
752
764 void logPdoMappings() const;
765
772
795 void updateOutputs();
796
819
820 private:
821 ecx_contextt &context_;
822 const uint16_t position_;
825 std::mutex mailboxMutex_;
826 std::unordered_map<common::ParameterKey, common::Parameter>
827 parametersMap_;
829 common::PdoMappings pdoMappings_;
830};
831
832class Master {
833 public:
840 explicit Master();
841
852 explicit Master(const std::string &iface);
853
905 void init(const std::string &iface);
906
917 void deinit();
918
925 ~Master();
926
936 Fieldbus &getFieldbus() const;
937
946 std::string getInterfaceName() const;
947
956 size_t getIoMapSize() const;
957
1020 int initSlaves();
1021
1033 const std::vector<std::unique_ptr<soempp::Slave>> &getSlaves() const;
1034
1044 inline int expectedWkc() const {
1045 return fieldbus_->context.grouplist[fieldbus_->group].outputsWKC * 2 +
1046 fieldbus_->context.grouplist[fieldbus_->group].inputsWKC;
1047 }
1048
1058 int roundtrip();
1059
1089
1100 bool start();
1101
1102 private:
1116 std::unique_ptr<Fieldbus> fieldbus_;
1117
1129 std::vector<std::unique_ptr<Slave>> slaves_;
1130};
1131}; // namespace soempp
Represents a device parameter identified by index and subindex.
Definition: common.h:472
Definition: soempp.h:832
Fieldbus & getFieldbus() const
Returns a reference to the Fieldbus instance.
Definition: soempp.cc:1095
Master()
Default constructor for the Master class.
Definition: soempp.cc:1063
void init(const std::string &iface)
Initializes the fieldbus using the specified network interface.
Definition: soempp.cc:1070
size_t getIoMapSize() const
Returns the total size of the I/O map for the current group.
Definition: soempp.cc:1099
int initSlaves()
Initializes the slave devices on the EtherCAT network.
Definition: soempp.cc:1104
void exchangeProcessDataAndUpdateParameters()
Exchanges process data with slaves and updates parameters based on the response.
Definition: soempp.cc:1136
bool start()
Initializes and starts the fieldbus master.
Definition: soempp.cc:1159
std::string getInterfaceName() const
Retrieves the interface name used by the fieldbus.
Definition: soempp.cc:1097
const std::vector< std::unique_ptr< soempp::Slave > > & getSlaves() const
Returns a reference to the list of slaves.
Definition: soempp.cc:1127
int roundtrip()
Performs a complete send/receive process data cycle on the fieldbus.
Definition: soempp.cc:1131
void deinit()
Deinitializes the fieldbus and releases associated resources.
Definition: soempp.cc:1088
~Master()
Destructor for the Master class.
Definition: soempp.cc:1093
int expectedWkc() const
Calculates the expected working counter (WKC) for the current fieldbus group.
Definition: soempp.h:1044
Represents a slave in the EtherCAT network.
Definition: soempp.h:380
void updatePdoMappings()
Updates the PDO mapping entries for the slave.
Definition: soempp.cc:980
void logTxPdoMappedParameters()
Logs all mapped TxPDO parameters with their current values.
Definition: soempp.cc:942
std::unordered_map< common::ParameterKey, common::Parameter > & getParametersMap()
Returns a reference to the internal parameters map.
Definition: soempp.cc:958
uint32_t getRevisionNumber() const
Gets the Revision Number of the slave device.
Definition: soempp.cc:732
common::PdoMappings readPdoMappings() const
Reads the PDO mappings from the slave device.
Definition: soempp.cc:973
uint32_t getProductCode() const
Gets the Product Code of the slave device.
Definition: soempp.cc:728
void updateParametersFromInputs()
Updates parameters from the received input data.
Definition: soempp.cc:1013
void logPdoMappings() const
Logs the PDO (Process Data Object) mappings for the device.
Definition: soempp.cc:988
T upload(uint16_t index, uint8_t subindex, bool refresh=true)
Uploads a parameter value from the device's object dictionary.
Definition: soempp.h:600
int getState(bool forceRefresh=true) const
Retrieves the current state of the slave.
Definition: soempp.cc:736
bool setState(int targetState, int timeoutMs=0, int intervalMs=100)
Attempts to set the slave to the specified EtherCAT state and optionally waits until it is reached.
Definition: soempp.cc:740
bool download(uint16_t index, uint8_t subindex, const T &value)
Downloads a value to the specified object dictionary entry via SDO.
Definition: soempp.h:681
uint32_t getVendorId() const
Gets the Vendor ID of the slave device.
Definition: soempp.cc:724
void logRxPdoMappedParameters()
Logs all mapped RxPDO parameters with their current values.
Definition: soempp.cc:929
void clearParameters()
Clears all loaded object dictionary parameters.
Definition: soempp.cc:955
common::Parameter & findParameter(uint16_t index, uint8_t subindex)
Finds and returns a reference to a Parameter in the parameters map.
Definition: soempp.cc:962
void logParameters() const
Logs all loaded object dictionary parameters.
Definition: soempp.cc:923
common::PdoMappings & getPdoMappings()
Returns a reference to the cached PDO mappings.
Definition: soempp.cc:994
void updateOutputs()
Updates the outputs for the slave device.
Definition: soempp.cc:996
uint16_t getPosition() const
Gets the position of the slave.
Definition: soempp.cc:722
void loadParameters(bool readValues=false)
Loads the parameters (object dictionary entries) from the EtherCAT slave device.
Definition: soempp.cc:764
uint8_t * value
Definition: co_dictionary.h:9
uint16_t index
Definition: co_dictionary.h:0
std::string makeParameterId(int index, int subindex)
Formats the given index and subindex into a parameter identifier string.
Definition: common.h:1134
Definition: soempp.cc:25
void checkPdoMapping(ecx_contextt *context, uint16 slave)
Diagnoses and prints the PDO mapping for a given slave.
Definition: soempp.cc:224
std::string convertSlaveStateToString(int state)
Converts a numeric EtherCAT state value into a human-readable string.
Definition: soempp.cc:327
void configureDetectedSmmModule(ecx_contextt *context, uint16_t slave)
Reads the detected SMM module ID from the slave device and configures the module identification objec...
Definition: soempp.cc:493
common::PdoMappings readPdoMappings(ecx_contextt *context, uint16_t slave)
Read and parse all mapped PDO entries for a given slave.
Definition: soempp.cc:625
void initFieldbus(std::unique_ptr< Fieldbus > &fieldbus, const std::string &iface)
Initializes a Fieldbus instance for EtherCAT communication.
Definition: soempp.cc:1030
bool setSlaveState(ecx_contextt *context, uint16_t slave, int targetState)
Sets the state of a specified EtherCAT slave.
Definition: soempp.cc:523
std::map< std::string, std::string > mapMacAddressesToInterfaces()
Maps MAC addresses to their corresponding network interface names.
Definition: soempp.cc:27
bool transitionToHigherSlaveState(ecx_contextt *context, uint16_t slave, int targetState)
Transitions a slave to a higher EtherCAT state.
Definition: soempp.cc:356
std::string uiConfigWithDefaultPdoMapping
Default UI configuration used for PDO mapping.
Definition: soempp.h:48
void logPdoMappingEntries(const std::vector< common::PdoMappingEntry > &entries)
Logs PDO mapping entries grouped by PDO index.
Definition: soempp.cc:690
void logIoMap(uint8_t *ioMap, size_t totalBytes)
Logs the I/O map as a formatted hexadecimal string.
Definition: soempp.cc:709
void updateMailboxSyncManagersOnNextState(ecx_contextt *context, uint16_t slave, int targetState)
Updates the mailbox and sync manager (SM) configurations for an EtherCAT slave when transitioning to ...
Definition: soempp.cc:418
uint16_t getSlaveState(ecx_contextt *context, uint16_t slave, bool forceRefresh)
Retrieves the current state of a specific EtherCAT slave.
Definition: soempp.cc:306
int setPdoMappingFromUiConfig(ecx_contextt *context, uint16 slave)
Sets PDO mapping for a specified EtherCAT slave using UI configuration.
Definition: soempp.cc:129
Represents the mapped PDO entries for a slave device.
Definition: common.h:180
Structure representing the Fieldbus configuration and context for EtherCAT communication.
Definition: soempp.h:331
int64 DCtime
Definition: soempp.h:348
ec_slavet slavelist[EC_MAXSLAVE]
Definition: soempp.h:340
boolean ecaterror
Definition: soempp.h:347
ec_PDOdesct PDOdesc[EC_MAX_MAPT]
Definition: soempp.h:351
ec_idxstackT idxstack
Definition: soempp.h:346
ec_groupt grouplist[EC_MAXGROUP]
Definition: soempp.h:342
ec_PDOassignt PDOassign[EC_MAX_MAPT]
Definition: soempp.h:350
ec_eepromFMMUt eepFMMU
Definition: soempp.h:353
ec_eepromSMt eepSM
Definition: soempp.h:352
ecx_portt port
Definition: soempp.h:339
uint8 map[4096]
Definition: soempp.h:338
int slavecount
Definition: soempp.h:341
ecx_contextt context
Definition: soempp.h:332
uint8 esibuf[EC_MAXEEPBUF]
Definition: soempp.h:343
int roundtripTime
Definition: soempp.h:335
uint32 esimap[EC_MAXEEPBITMAP]
Definition: soempp.h:344
uint8 group
Definition: soempp.h:334
ec_eringt elist
Definition: soempp.h:345
std::string iface
Definition: soempp.h:333
ec_SMcommtypet SMcommtype[EC_MAX_MAPT]
Definition: soempp.h:349