CORC Project
CANOpen Robot Controller Software Documentation
Drive.cpp
Go to the documentation of this file.
1 #include "Drive.h"
2 
3 #include "DebugMacro.h"
4 
6  statusWord = 0;
7  error = 0;
8  this->NodeID = -1;
9 }
10 
12  statusWord = 0;
13  error = 0;
14  this->NodeID = NodeID;
15 }
16 
18  return NodeID;
19 }
20 
21 bool Drive::setPos(int position) {
22  DEBUG_OUT("Drive " << this->NodeID << " Writing " << position << " to 0x607A");
23  *(&CO_OD_RAM.targetMotorPositions.motor1 + ((this->NodeID - 1))) = position;
24  return true;
25 }
26 
27 bool Drive::setVel(int velocity) {
28  DEBUG_OUT("Drive " << NodeID << " Writing " << velocity << " to 0x60FF");
29  *(&CO_OD_RAM.targetMotorVelocities.motor1 + ((this->NodeID - 1))) = velocity;
30  return true;
31 }
32 
33 bool Drive::setTorque(int torque) {
34  /*\todo add setTorque to object dictionary*/
35  DEBUG_OUT("Drive " << NodeID << " Writing " << torque << " to 0x6071");
36  return true;
37 }
38 
40  /*\todo change to actual motor Position when running on real robot*/
41  int q = *(&CO_OD_RAM.targetMotorPositions.motor1 + ((this->NodeID - 1)));
42  return q;
43 }
44 
46  if (this->NodeID < 5) {
47  return (*(&CO_OD_RAM.actualMotorVelocities.motor1 + ((this->NodeID - 1))));
48  } else {
49  return 0;
50  }
51 }
52 
54  if (this->NodeID < 5) {
55  return (*(&CO_OD_RAM.actualMotorTorques.motor1 + ((this->NodeID - 1))));
56  } else {
57  return 0;
58  }
59 }
60 
62  *(&CO_OD_RAM.controlWords.motor1 + ((this->NodeID - 1))) = 0x06;
64 }
65 
66 bool Drive::enable() {
67  *(&CO_OD_RAM.controlWords.motor1 + ((this->NodeID - 1))) = 0x0F;
69 }
70 
72  *(&CO_OD_RAM.controlWords.motor1 + ((this->NodeID - 1))) = 0x00;
74 }
75 
77  return driveState;
78 }
79 
81  statusWord = *(&CO_OD_RAM.statusWords.motor1 + ((this->NodeID - 1)));
82  return statusWord;
83 }
84 
86  int controlWord = *(&CO_OD_RAM.controlWords.motor1 + ((this->NodeID - 1)));
87  *(&CO_OD_RAM.controlWords.motor1 + ((this->NodeID - 1))) = controlWord ^ 0x10;
88  if ((controlWord & 0x10) > 0) {
89  return false;
90  } else {
91  return true;
92  }
93 }
94 
96  DEBUG_OUT("Drive::initPDOs")
97  //DEBUG_OUT("Set up STATUS_WORD TPDO")
99 
100  //DEBUG_OUT("Set up ACTUAL_POS and ACTUAL_VEL TPDO")
102 
103  //DEBUG_OUT("Set up ACTUAL_TOR TPDO")
105 
106  //DEBUG_OUT("Set up TARGET_POS RPDO")
108 
109  //DEBUG_OUT("Set up TARGET_VEL RPDO")
111 
112  return true;
113 }
114 
115 std::vector<std::string> Drive::generateTPDOConfigSDO(std::vector<OD_Entry_t> items, int PDO_Num, int SyncRate) {
116  // TODO: Do a check to make sure that the OD_Entry_t items can be transmitted.
117 
118  // Calculate COB_ID. If TPDO:
119  int COB_ID = 0x100 * PDO_Num + 0x80 + NodeID;
120 
121  // Define Vector to be returned as part of this method
122  std::vector<std::string> CANCommands;
123 
124  // Define stringstream for ease of constructing hex strings
125  std::stringstream sstream;
126 
127  // Disable PDO
128  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1800 + PDO_Num - 1 << " 1 u32 0x" << std::hex << 0x800000000 + COB_ID;
129  CANCommands.push_back(sstream.str());
130  sstream.str(std::string());
131 
132  // Set so that there no PDO items, enable mapping change
133  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1A00 + PDO_Num - 1 << " 0 u8 0";
134  CANCommands.push_back(sstream.str());
135  sstream.str(std::string());
136 
137  // Set the PDO so that it triggers every SYNC Message
138  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1800 + PDO_Num - 1 << " 2 u8 0x" << SyncRate;
139  CANCommands.push_back(sstream.str());
140  sstream.str(std::string());
141 
142  for (int i = 1; i <= items.size(); i++) {
143  // Set transmit parameters
144  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1A00 + PDO_Num - 1 << " " << i << " u32 0x" << std::hex << OD_Addresses[items[i - 1]] * 0x10000 + OD_Data_Size[items[i - 1]];
145  CANCommands.push_back(sstream.str());
146  sstream.str(std::string());
147  }
148 
149  // Sets Number of PDO items to reenable
150  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1A00 + PDO_Num - 1 << " 0 u8 " << items.size();
151  CANCommands.push_back(sstream.str());
152  sstream.str(std::string());
153 
154  // Enable PDO
155  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1800 + PDO_Num - 1 << " 1 u32 0x" << std::hex << COB_ID;
156  CANCommands.push_back(sstream.str());
157  sstream.str(std::string());
158 
159  return CANCommands;
160 }
161 
162 std::vector<std::string> Drive::generateRPDOConfigSDO(std::vector<OD_Entry_t> items, int PDO_Num, int UpdateTiming) {
163  /* \todo Do a check to make sure that the OD_Entry_t items can be Received.*/
164 
165  // Calculate COB_ID. If TPDO:
166  int COB_ID = 0x100 * PDO_Num + NodeID;
167 
168  // Define Vector to be returned as part of this method
169  std::vector<std::string> CANCommands;
170 
171  // Define stringstream for ease of constructing hex strings
172 
173  std::stringstream sstream;
174  // Disable PDO
175  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1400 + PDO_Num - 1 << " 1 u32 0x" << std::hex << 0x800000000 + COB_ID;
176  CANCommands.push_back(sstream.str());
177  sstream.str(std::string());
178 
179  // Set so that there no PDO items, enable mapping change
180  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1600 + PDO_Num - 1 << " 0 u8 0";
181  CANCommands.push_back(sstream.str());
182  sstream.str(std::string());
183 
184  // Set the PDO so that it triggers every SYNC Message
185  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1400 + PDO_Num - 1 << " 2 u8 0x" << UpdateTiming;
186  CANCommands.push_back(sstream.str());
187  sstream.str(std::string());
188 
189  for (int i = 1; i <= items.size(); i++) {
190  // Set transmit parameters
191  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1600 + PDO_Num - 1 << " " << i << " u32 0x" << std::hex << OD_Addresses[items[i - 1]] * 0x10000 + OD_Data_Size[items[i - 1]];
192  CANCommands.push_back(sstream.str());
193  sstream.str(std::string());
194  }
195 
196  // Sets Number of PDO items to reenable
197  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1600 + PDO_Num - 1 << " 0 u8 " << items.size();
198  CANCommands.push_back(sstream.str());
199  sstream.str(std::string());
200 
201  // Enable PDO
202  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x1400 + PDO_Num - 1 << " 1 u32 0x" << std::hex << COB_ID;
203  CANCommands.push_back(sstream.str());
204  sstream.str(std::string());
205 
206  return CANCommands;
207 }
208 
209 std::vector<std::string> Drive::generatePosControlConfigSDO(motorProfile positionProfile) {
210  // Define Vector to be returned as part of this method
211  std::vector<std::string> CANCommands;
212  // Define stringstream for ease of constructing hex strings
213  std::stringstream sstream;
214  // start drive
215  sstream << "[1] " << NodeID << " start";
216  CANCommands.push_back(sstream.str());
217  sstream.str(std::string());
218  //enable profile position mode
219  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x6060 << " 0 i8 1";
220  CANCommands.push_back(sstream.str());
221  sstream.str(std::string());
222 
223  //Set velocity profile
224  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x6081 << " 0 i32 " << positionProfile.profileVelocity;
225  CANCommands.push_back(sstream.str());
226  sstream.str(std::string());
227 
228  //Set acceleration profile
229  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x6083 << " 0 i32 " << positionProfile.profileAccelration;
230  CANCommands.push_back(sstream.str());
231  sstream.str(std::string());
232 
233  //Set deceleration profile
234  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x6084 << " 0 i32 " << positionProfile.profileDeceleration;
235  CANCommands.push_back(sstream.str());
236  sstream.str(std::string());
237 
238  return CANCommands;
239 }
240 std::vector<std::string> Drive::generateVelControlConfigSDO(motorProfile velocityProfile) {
241  // Define Vector to be returned as part of this method
242  std::vector<std::string> CANCommands;
243  // Define stringstream for ease of constructing hex strings
244  std::stringstream sstream;
245  // start drive
246  sstream << "[1] " << NodeID << " start";
247  CANCommands.push_back(sstream.str());
248  sstream.str(std::string());
249  //enable profile Velocity mode
250  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x6060 << " 0 i8 3";
251  CANCommands.push_back(sstream.str());
252  sstream.str(std::string());
253 
254  //Set velocity profile
255  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x6081 << " 0 i32 " << velocityProfile.profileVelocity;
256  CANCommands.push_back(sstream.str());
257  sstream.str(std::string());
258 
259  //Set acceleration profile
260  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x6083 << " 0 i32 " << velocityProfile.profileAccelration;
261  CANCommands.push_back(sstream.str());
262  sstream.str(std::string());
263 
264  //Set deceleration profile
265  sstream << "[1] " << NodeID << " write 0x" << std::hex << 0x6084 << " 0 i32 " << velocityProfile.profileDeceleration;
266  CANCommands.push_back(sstream.str());
267  sstream.str(std::string());
268 
269  return CANCommands;
270 }
271 
272 int Drive::sendSDOMessages(std::vector<std::string> messages) {
273  char *returnMessage;
274  DEBUG_OUT("sendSDOMessages");
275  // change to = 0 when testing with real network or something which responds. and uncomment
276  // return message check
277  int successfulMessages = 1;
278  for (auto strCommand : messages) {
279  // explicitly cast c++ string to from const char* to char* for use by cancomm function
280  char *SDO_Message = (char *)(strCommand.c_str());
281  // DEBUG_OUT(SDO_Message);
282 
283 #ifndef NOROBOT
284  cancomm_socketFree(SDO_Message, returnMessage);
285 #endif
286 
287  // TODO: in cancomm_socketFree -> return message correctly.
288  // std::string retMsg = returnMessage;
289  // DEBUG_OUT(retMsg);
290  /*if (strcmp(returnMessage, "OK") == 0)
291  {
292  successfulMessages++;
293  }*/
294  }
295  return successfulMessages;
296 }
DriveState driveState
State of the drive.
Definition: Drive.h:190
int profileAccelration
Definition: Drive.h:96
Definition: Drive.h:44
virtual bool setPos(int position)
Definition: Drive.cpp:21
int getNodeID()
Get returns the CanNode ID.
Definition: Drive.cpp:17
Defines some macros for debugging output.
virtual DriveState getDriveState()
Get the current state of the drive.
Definition: Drive.cpp:76
Definition: Drive.h:46
std::vector< std::string > generateVelControlConfigSDO(motorProfile velocityProfile)
Generates the list of commands required to configure Velocity control in CANopen motor drive...
Definition: Drive.cpp:240
virtual bool enable()
Sets the state of the drive to "enabled".
Definition: Drive.cpp:66
virtual int updateDriveStatus()
Definition: Drive.cpp:80
virtual bool disable()
sets the state of the drive to "disabled"
Definition: Drive.cpp:71
int error
Current error state of the drive.
Definition: Drive.h:184
virtual bool setTorque(int torque)
Definition: Drive.cpp:33
virtual bool initPDOs()
Initialises a standard set of PDOs for the use of the drive. These are:
Definition: Drive.cpp:95
virtual int getPos()
Definition: Drive.cpp:39
int profileDeceleration
Definition: Drive.h:97
int NodeID
The CAN Node ID used to address this particular drive on the CAN bus.
Definition: Drive.h:111
int profileVelocity
Definition: Drive.h:95
std::vector< std::string > generateTPDOConfigSDO(std::vector< OD_Entry_t > items, int PDO_Num, int SyncRate)
Generates the list of commands required to configure TPDOs on the drives.
Definition: Drive.cpp:115
virtual bool readyToSwitchOn()
Changes the state of the drive to "ready to switch on".
Definition: Drive.cpp:61
Drive()
Construct a new Drive object.
Definition: Drive.cpp:5
struct to hold desired velocity, acceleration and deceleration values for a drives motor controller p...
Definition: Drive.h:94
virtual bool setVel(int velocity)
Definition: Drive.cpp:27
int sendSDOMessages(std::vector< std::string > messages)
messages Properly formatted SDO Messages
Definition: Drive.cpp:272
virtual int getTorque()
Definition: Drive.cpp:53
The Drive class is used to interface with a CANOpen motor drive. According to the CiA402 standard...
#define DEBUG_OUT(x)
Definition: DebugMacro.h:19
virtual int getVel()
Definition: Drive.cpp:45
DriveState
Definition: Drive.h:43
std::vector< std::string > generateRPDOConfigSDO(std::vector< OD_Entry_t > items, int PDO_Num, int UpdateTiming)
Generates the list of commands required to configure RPDOs on the drives.
Definition: Drive.cpp:162
virtual bool posControlConfirmSP()
Flips Bit 4 of Control Word (0x6041) - A new set point is only confirmed if the transition is from 0 ...
Definition: Drive.cpp:85
void cancomm_socketFree(char *command, char *ret)
Definition: CO_command.c:559
int statusWord
Current status word of the drive.
Definition: Drive.h:178
std::vector< std::string > generatePosControlConfigSDO(motorProfile positionProfile)
Generates the list of commands required to configure Position control in CANopen motor drive...
Definition: Drive.cpp:209