BusIO.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2017, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package ArmarX
19  * @author Stefan Reither( stefan dot reither at kit dot edu)
20  * @date 2021
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
25 
26 #pragma once
27 
28 #include <atomic>
29 #include <cstdint>
30 #include <mutex>
31 #include <thread>
32 #include <array>
33 
34 #include "ESI.h"
35 #include "RequestQueue.h"
36 #include "SlaveRegisters.h"
37 #include "Timeouts.h"
38 
40 {
41  class ChangeStateRequest;
42  class ReadStatesRequest;
43  class SDOUpdateRequest;
44  class RegisterResetRequest;
45  class RegisterReadRequest;
46 
47  struct EtherCATFrame;
48  struct EtherCATFrameList;
49 
50  /**
51  * @class BusIO
52  * @ingroup Library-ethercat
53  * @brief Brief description of class BusIO.
54  *
55  * Detailed description of class BusIO.
56  */
57  class BusIO : public ESIHandler
58  {
59  public:
60  virtual ~BusIO();
61 
62  /**
63  * Performs a SDO write to a single entry to the slave with the give slaveIndex
64  * and returns true if it succeeds.
65  * Fails if the bus has not been started yet.
66  *
67  * Blocking until the write has been performed or a timeout is reached.
68  *
69  * @param [IN] slaveIndex the slavenumber of the slave on the bus
70  * @param [IN] index the index of the entry where the value is written to
71  * @param [IN] subIndex the subindex of the entry
72  * @param [IN] value the value that will be written to the slave
73  * @param [IN] completeAccess with this flag you can activate writing in complete access
74  * mode
75  * @return true when write was successful otherwise false
76  */
77  template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
78  bool
79  writeSDOEntry(std::uint16_t slaveIndex,
80  std::uint16_t index,
81  std::uint8_t subIndex,
82  T value,
83  bool completeAccess = false)
84  {
85  return generalSDOWrite(
86  slaveIndex, index, subIndex, sizeof(value), &value, completeAccess);
87  }
88 
89  /**
90  * Performs a SDO write to the slave with the given slaveIndex and returns true if it
91  * succeeds.
92  * Fails if the bus has not been started yet.
93  *
94  * Blocking until the write has been performed or a timeout is reached.
95  *
96  * @param [IN] slaveIndex the slavenumber of the slave on the bus
97  * @param [IN] index the index of the entry where the value is written to
98  * @param [IN] subIndex the subindex of the entry
99  * @param [IN] buflen length of the buffer containing the data
100  * @param [IN] buf buffer containing the data to write
101  * @param [IN] completeAccess with this flag you can activate writing in complete access
102  * mode
103  * @return true when write was successful otherwise false
104  */
105  bool
106  writeSDOByteBuffer(std::uint16_t slaveIndex,
107  std::uint16_t index,
108  std::uint8_t subIndex,
109  int buflen,
110  const unsigned char* buf,
111  bool completeAccess = false)
112  {
113  return generalSDOWrite(slaveIndex, index, subIndex, buflen, buf, completeAccess);
114  }
115 
116  /**
117  * Performs a SDO read of an single entry from the slave and returns true if it
118  * succeeds.
119  * Fails if the bus has not been started yet.
120  *
121  * Blocking until the write has been performed or a timeout is reached.
122  *
123  * @param [IN] slaveIndex the index of the slave it will read from
124  * @param [IN] index the index of the object dictonary it will read from
125  * @param [IN] subIndex the sub index of the entry
126  * @param [OUT] result the read data
127  * @param [IN] completeAccess with this flag you can activate writing in complete access
128  * mode
129  * @return true when write was successful otherwise false
130  */
131  template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
132  bool
133  readSDOEntry(std::uint16_t slaveIndex,
134  std::uint16_t index,
135  std::uint8_t subIndex,
136  T& result,
137  bool completeAccess = false)
138  {
139  int buflen = sizeof(result);
140  return generalSDORead(
141  slaveIndex, index, subIndex, &buflen, &result, completeAccess);
142  }
143 
144  /**
145  * Performs a SDO read from the slave and returns true if it
146  * succeeds.
147  * Fails if the bus has not been started yet.
148  *
149  * Blocking until the write has been performed or a timeout is reached.
150  *
151  * @param [IN] slaveIndex the index of the slave it will read from
152  * @param [IN] index the index of the object dictonary it will read from
153  * @param [IN] subIndex the sub index of the entry
154  * @param [IN] buflen amount of bytes to read
155  * @param [OUT] buf buffer which contains the read data afterwards
156  * @param [IN] completeAccess with this flag you can activate writing in complete access
157  * mode
158  * @return true when write was successful otherwise false
159  */
160  bool
161  readSDOByteBuffer(std::uint16_t slaveIndex,
162  std::uint16_t index,
163  std::uint8_t subIndex,
164  int* buflen,
165  unsigned char* buf,
166  bool completeAccess = false)
167  {
168  return generalSDORead(slaveIndex, index, subIndex, buflen, buf, completeAccess);
169  }
170 
172  changeStateOfSlave(std::uint16_t slaveIndex, EtherCATState state, bool validate = true);
174 
176 
177  bool resetErrorRegisters(std::uint16_t slaveIndex);
178 
179  bool readRegisters(std::vector<RegisterDataList>& registerData);
180  bool readRegisters(EtherCATFrameList* frames, std::uint16_t amountFramesToRead = 0);
181 
182  /**
183  * This deactivates the Complete access mode in CoE for the given slave.
184  * For Elmo's it is necessary to deactivate the CA mode otherwise SOEM isn't able to bring
185  * them into OP-Mode
186  * @param slave the slave for which the CA mode will be deactivated
187  */
188  void deactivateCOECA(std::uint16_t slaveIndex);
189 
190  void setTimeouts(Timeouts const& timeouts);
191 
192  protected:
193  BusIO();
194 
195  /**
196  * @brief Updates the PDO of all slaves.
197  * This function has priority over all other BusIO functions and can only be executed by the
198  * Bus itself.
199  */
200  void rtUpdatePDO();
201 
202  bool sdoAccessAvailable = false;
203  bool pdoAccessAvailable = false;
204 
206 
208 
209  /** @brief IOmap the IO map where the process data are mapped in */
210  using IOMap = std::array<char, 4096>;
211  alignas(alignof(std::max_align_t)) IOMap ioMap;
212 
213 
214  private:
215  bool generalSDOWrite(std::uint16_t slaveIndex,
216  std::uint16_t index,
217  std::uint8_t subIndex,
218  std::uint16_t buflen,
219  const void* buf,
220  bool completeAccess = false);
221 
222  bool generalSDORead(std::uint16_t slaveIndex,
223  std::uint16_t index,
224  std::uint8_t subIndex,
225  int* buflen,
226  void* buf,
227  bool completeAccess = false);
228 
229  bool isSDOAccessAvailable() const;
230 
231  /*!
232  * \brief Sends an EtherCAT frame over the EtherCAT bus, receives it and returns the
233  * index of the SOEM buffer the resulting frame was placed in along with the working
234  * counter returned by SOEM.
235  *
236  * This method will automatically place the given slave address at the given offsets
237  * in the final EtherCAT frame in the buffer. Pass an empty offset vector if you do not
238  * require this.
239  * \param frame the EtherCAT frame to send over the bus
240  * \param frameLength the length of the EtherCAT frame in bytes
241  * \param slaveConfiguredAddress the configured address of the slave to send the frame to,
242  * if it needs to be set in the frame
243  * \param slaveAddressOffsets the offsets in the EtherCAT frame to write the configured
244  * address of the slave to
245  * \return the working counter of the frame as returned by SOEM and the index of the SOEM
246  * rx frame buffer the received frame has been placed in.
247  */
248  std::pair<int, int>
249  sendAndReceiveEtherCATFrame(const EtherCATFrame* frame,
250  size_t frameLength,
251  uint16_t slaveConfiguredAddress,
252  const std::vector<size_t>& slaveAddressOffsets);
253 
254  RequestQueue requestQueues;
255 
256  std::thread requestHandlerThread;
257  std::atomic_bool requestHandlerThreadRunning{true};
258  std::atomic_bool pdoUpdateRequested{false};
259 
260  void requestHandlerLoop();
261 
262  bool handleNextRequest();
263  void handleSDOUpdateRequest(const std::shared_ptr<SDOUpdateRequest>& request);
264  void handleChangeStateRequest(const std::shared_ptr<ChangeStateRequest>& request);
265  void handleReadStatesRequest(const std::shared_ptr<ReadStatesRequest>& request);
266  void handleRegisterResetRequest(const std::shared_ptr<RegisterResetRequest>& request);
267  void handleRegisterReadRequest(const std::shared_ptr<RegisterReadRequest>& request);
268  };
269 } // namespace armarx::control::ethercat
armarx::control::ethercat::BusIO::rtUpdatePDO
void rtUpdatePDO()
Updates the PDO of all slaves.
Definition: BusIO.cpp:113
armarx::control::ethercat::BusIO::changeStateOfBus
EtherCATState changeStateOfBus(EtherCATState state, bool validate=true)
Definition: BusIO.cpp:411
armarx::control::ethercat::BusIO
Brief description of class BusIO.
Definition: BusIO.h:57
armarx::control::ethercat::BusIO::ioMap
IOMap ioMap
Definition: BusIO.h:211
armarx::control::ethercat::EtherCATState
This class is a wrapper around an enum containing the different EtherCAT states.
Definition: EtherCATState.h:25
ESI.h
armarx::control::ethercat::BusIO::BusIO
BusIO()
Definition: BusIO.cpp:25
index
uint8_t index
Definition: EtherCATFrame.h:59
armarx::control::ethercat::BusIO::IOMap
std::array< char, 4096 > IOMap
IOmap the IO map where the process data are mapped in.
Definition: BusIO.h:210
armarx::control::ethercat::BusIO::readSDOEntry
bool readSDOEntry(std::uint16_t slaveIndex, std::uint16_t index, std::uint8_t subIndex, T &result, bool completeAccess=false)
Performs a SDO read of an single entry from the slave and returns true if it succeeds.
Definition: BusIO.h:133
armarx::control::ethercat::BusIO::changeStateOfSlave
EtherCATState changeStateOfSlave(std::uint16_t slaveIndex, EtherCATState state, bool validate=true)
Definition: BusIO.cpp:403
armarx::control::ethercat::BusIO::writeSDOEntry
bool writeSDOEntry(std::uint16_t slaveIndex, std::uint16_t index, std::uint8_t subIndex, T value, bool completeAccess=false)
Performs a SDO write to a single entry to the slave with the give slaveIndex and returns true if it s...
Definition: BusIO.h:79
armarx::control::ethercat::BusIO::pdoAccessAvailable
bool pdoAccessAvailable
Definition: BusIO.h:203
armarx::control::ethercat::ESIHandler
Brief description of class ESIHandler.
Definition: ESI.h:45
armarx::control::ethercat::BusIO::readSDOByteBuffer
bool readSDOByteBuffer(std::uint16_t slaveIndex, std::uint16_t index, std::uint8_t subIndex, int *buflen, unsigned char *buf, bool completeAccess=false)
Performs a SDO read from the slave and returns true if it succeeds.
Definition: BusIO.h:161
armarx::control::ethercat::BusIO::resetErrorRegisters
bool resetErrorRegisters(std::uint16_t slaveIndex)
Definition: BusIO.cpp:427
armarx::control::ethercat::BusIO::deactivateCOECA
void deactivateCOECA(std::uint16_t slaveIndex)
This deactivates the Complete access mode in CoE for the given slave.
Definition: BusIO.cpp:445
armarx::control::ethercat::BusIO::lastWorkCounter
int lastWorkCounter
Definition: BusIO.h:207
armarx::control::ethercat::BusIO::readStates
EtherCATState readStates()
Definition: BusIO.cpp:419
armarx::control::ethercat::BusIO::setTimeouts
void setTimeouts(Timeouts const &timeouts)
Definition: BusIO.cpp:463
SlaveRegisters.h
RequestQueue.h
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::control::ethercat::BusIO::writeSDOByteBuffer
bool writeSDOByteBuffer(std::uint16_t slaveIndex, std::uint16_t index, std::uint8_t subIndex, int buflen, const unsigned char *buf, bool completeAccess=false)
Performs a SDO write to the slave with the given slaveIndex and returns true if it succeeds.
Definition: BusIO.h:106
armarx::control::ethercat::RequestQueue
Brief description of class RequestQueue.
Definition: RequestQueue.h:51
armarx::control::ethercat::EtherCATFrameList
The EtherCATFrameList struct holds a list of EtherCAT frames that can be scheduled in round-robin-sty...
Definition: EtherCATFrame.h:124
armarx::control::ethercat
Definition: Bus.cpp:24
Timeouts.h
armarx::control::ethercat::BusIO::~BusIO
virtual ~BusIO()
Definition: BusIO.cpp:396
armarx::control::ethercat::BusIO::sdoAccessAvailable
bool sdoAccessAvailable
Definition: BusIO.h:202
armarx::navigation::client::validate
void validate(const std::vector< WaypointTarget > &path)
Definition: ice_conversions.h:70
slaveConfiguredAddress
uint16_t slaveConfiguredAddress
Definition: EtherCATFrame.h:60
armarx::control::ethercat::Timeouts
Definition: Timeouts.h:8
armarx::control::ethercat::EtherCATFrame
The EtherCATFrame struct represents an EtherCAT frame according to the EtherCAT spec.
Definition: EtherCATFrame.h:44
T
float T
Definition: UnscentedKalmanFilterTest.cpp:35
armarx::control::ethercat::BusIO::timeouts
Timeouts timeouts
Definition: BusIO.h:205
armarx::control::ethercat::BusIO::readRegisters
bool readRegisters(std::vector< RegisterDataList > &registerData)
Definition: BusIO.cpp:433