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 <array>
29 #include <atomic>
30 #include <cstdint>
31 #include <mutex>
32 #include <thread>
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(slaveIndex, index, subIndex, &buflen, &result, completeAccess);
141  }
142 
143  /**
144  * Performs a SDO read from the slave and returns true if it
145  * succeeds.
146  * Fails if the bus has not been started yet.
147  *
148  * Blocking until the write has been performed or a timeout is reached.
149  *
150  * @param [IN] slaveIndex the index of the slave it will read from
151  * @param [IN] index the index of the object dictonary it will read from
152  * @param [IN] subIndex the sub index of the entry
153  * @param [IN] buflen amount of bytes to read
154  * @param [OUT] buf buffer which contains the read data afterwards
155  * @param [IN] completeAccess with this flag you can activate writing in complete access
156  * mode
157  * @return true when write was successful otherwise false
158  */
159  bool
160  readSDOByteBuffer(std::uint16_t slaveIndex,
161  std::uint16_t index,
162  std::uint8_t subIndex,
163  int* buflen,
164  unsigned char* buf,
165  bool completeAccess = false)
166  {
167  return generalSDORead(slaveIndex, index, subIndex, buflen, buf, completeAccess);
168  }
169 
171  changeStateOfSlave(std::uint16_t slaveIndex, EtherCATState state, bool validate = true);
173 
175 
176  bool resetErrorRegisters(std::uint16_t slaveIndex);
177 
178  bool readRegisters(std::vector<RegisterDataList>& registerData);
179  bool readRegisters(EtherCATFrameList* frames, std::uint16_t amountFramesToRead = 0);
180 
181  /**
182  * This deactivates the Complete access mode in CoE for the given slave.
183  * For Elmo's it is necessary to deactivate the CA mode otherwise SOEM isn't able to bring
184  * them into OP-Mode
185  * @param slave the slave for which the CA mode will be deactivated
186  */
187  void deactivateCOECA(std::uint16_t slaveIndex);
188 
189  void setTimeouts(Timeouts const& timeouts);
190 
191  protected:
192  BusIO();
193 
194  /**
195  * @brief Updates the PDO of all slaves.
196  * This function has priority over all other BusIO functions and can only be executed by the
197  * Bus itself.
198  */
199  void rtUpdatePDO();
200 
201  bool sdoAccessAvailable = false;
202  bool pdoAccessAvailable = false;
203 
205 
207 
208  /** @brief IOmap the IO map where the process data are mapped in */
209  using IOMap = std::array<char, 4096>;
210  alignas(alignof(std::max_align_t)) IOMap ioMap;
211 
212 
213  private:
214  bool generalSDOWrite(std::uint16_t slaveIndex,
215  std::uint16_t index,
216  std::uint8_t subIndex,
217  std::uint16_t buflen,
218  const void* buf,
219  bool completeAccess = false);
220 
221  bool generalSDORead(std::uint16_t slaveIndex,
222  std::uint16_t index,
223  std::uint8_t subIndex,
224  int* buflen,
225  void* buf,
226  bool completeAccess = false);
227 
228  bool isSDOAccessAvailable() const;
229 
230  /*!
231  * \brief Sends an EtherCAT frame over the EtherCAT bus, receives it and returns the
232  * index of the SOEM buffer the resulting frame was placed in along with the working
233  * counter returned by SOEM.
234  *
235  * This method will automatically place the given slave address at the given offsets
236  * in the final EtherCAT frame in the buffer. Pass an empty offset vector if you do not
237  * require this.
238  * \param frame the EtherCAT frame to send over the bus
239  * \param frameLength the length of the EtherCAT frame in bytes
240  * \param slaveConfiguredAddress the configured address of the slave to send the frame to,
241  * if it needs to be set in the frame
242  * \param slaveAddressOffsets the offsets in the EtherCAT frame to write the configured
243  * address of the slave to
244  * \return the working counter of the frame as returned by SOEM and the index of the SOEM
245  * rx frame buffer the received frame has been placed in.
246  */
247  std::pair<int, int>
248  sendAndReceiveEtherCATFrame(const EtherCATFrame* frame,
249  size_t frameLength,
250  uint16_t slaveConfiguredAddress,
251  const std::vector<size_t>& slaveAddressOffsets);
252 
253  RequestQueue requestQueues;
254 
255  std::thread requestHandlerThread;
256  std::atomic_bool requestHandlerThreadRunning{true};
257  std::atomic_bool pdoUpdateRequested{false};
258 
259  void requestHandlerLoop();
260 
261  bool handleNextRequest();
262  void handleSDOUpdateRequest(const std::shared_ptr<SDOUpdateRequest>& request);
263  void handleChangeStateRequest(const std::shared_ptr<ChangeStateRequest>& request);
264  void handleReadStatesRequest(const std::shared_ptr<ReadStatesRequest>& request);
265  void handleRegisterResetRequest(const std::shared_ptr<RegisterResetRequest>& request);
266  void handleRegisterReadRequest(const std::shared_ptr<RegisterReadRequest>& request);
267  };
268 } // namespace armarx::control::ethercat
armarx::control::ethercat::BusIO::rtUpdatePDO
void rtUpdatePDO()
Updates the PDO of all slaves.
Definition: BusIO.cpp:115
armarx::control::ethercat::BusIO::changeStateOfBus
EtherCATState changeStateOfBus(EtherCATState state, bool validate=true)
Definition: BusIO.cpp:417
armarx::control::ethercat::BusIO
Brief description of class BusIO.
Definition: BusIO.h:57
armarx::control::ethercat::BusIO::ioMap
IOMap ioMap
Definition: BusIO.h:210
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:209
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:409
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:202
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:160
armarx::control::ethercat::BusIO::resetErrorRegisters
bool resetErrorRegisters(std::uint16_t slaveIndex)
Definition: BusIO.cpp:433
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:451
armarx::control::ethercat::BusIO::lastWorkCounter
int lastWorkCounter
Definition: BusIO.h:206
armarx::control::ethercat::BusIO::readStates
EtherCATState readStates()
Definition: BusIO.cpp:425
armarx::control::ethercat::BusIO::setTimeouts
void setTimeouts(Timeouts const &timeouts)
Definition: BusIO.cpp:470
SlaveRegisters.h
RequestQueue.h
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
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:402
armarx::control::ethercat::BusIO::sdoAccessAvailable
bool sdoAccessAvailable
Definition: BusIO.h:201
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:38
armarx::control::ethercat::BusIO::timeouts
Timeouts timeouts
Definition: BusIO.h:204
armarx::control::ethercat::BusIO::readRegisters
bool readRegisters(std::vector< RegisterDataList > &registerData)
Definition: BusIO.cpp:439