00001 #ifndef CANOPEN_H
00002 #define CANOPEN_H
00003
00004 #include <iostream>
00005 #include <map>
00006 #include <vector>
00007 #include <string>
00008 #include <chrono>
00009 #include <unordered_map>
00010 #include <functional>
00011 #include <cstdlib>
00012 #include <thread>
00013 #include <math.h>
00014 #include <libpcan.h>
00015 #include <utility>
00016 #include <fcntl.h>
00017 #include <stdint.h>
00018 #include <inttypes.h>
00019
00020 namespace canopen {
00021
00022 extern std::chrono::milliseconds syncInterval;
00023 extern bool atFirstInit;
00024
00025
00026 extern HANDLE h;
00027
00028
00029
00030 struct SDOkey {
00031 uint16_t index;
00032 uint8_t subindex;
00033 inline SDOkey(TPCANRdMsg m) : index((m.Msg.DATA[2] << 8) + m.Msg.DATA[1]),
00034 subindex(m.Msg.DATA[3]) {}
00035 inline SDOkey(uint16_t i, uint8_t s) : index(i), subindex(s) {};
00036 };
00037 inline bool operator<(const SDOkey &a, const SDOkey&b) {
00038 return a.index < b.index || (a.index == b.index && a.subindex < b.subindex); }
00039
00040 extern std::map<SDOkey, std::function<void (uint8_t CANid, BYTE data[8])> >
00041 incomingDataHandlers;
00042 extern std::map<uint16_t, std::function<void (const TPCANRdMsg m)> >
00043 incomingPDOHandlers;
00044
00045 void incomingNodeguardHandler(uint8_t CANid, BYTE data[8]);
00046 void statusword_incoming(uint8_t CANid, BYTE data[8]);
00047 void modes_of_operation_display_incoming(uint8_t CANid, BYTE data[8]);
00048
00049
00050
00051 class Device {
00052 public:
00053 Device() {};
00054 Device(uint8_t CANid) : CANid_(CANid), desiredVel_(0), actualVel_(0),
00055 actualPos_(0), desiredPos_(0), initialized(false), motorState_("not initialized") {};
00056 Device(uint8_t CANid, std::string name, std::string group, std::string bus) :
00057 CANid_(CANid), name_(name), group_(group), deviceFile_(bus),
00058 desiredVel_(0), actualVel_(0),
00059 actualPos_(0), desiredPos_(0), initialized(false) {};
00060
00061 std::string motorState_;
00062
00063
00064 inline void setVel(double vel) { desiredVel_ = vel; }
00065 inline void updateDesiredPos() {
00066 desiredPos_ += desiredVel_ * (syncInterval.count() / 1000.0); }
00067
00068 uint8_t CANid_;
00069
00070 std::string deviceFile_;
00071 std::string group_;
00072 std::string name_;
00073 bool initialized;
00074 bool voltage_enabled_;
00075 bool driveReferenced_;
00076 double actualPos_;
00077 double desiredPos_;
00078 double actualVel_;
00079 double desiredVel_;
00080 std::chrono::milliseconds timeStamp_msec_;
00081 std::chrono::microseconds timeStamp_usec_;
00082 };
00083
00084 extern std::map<uint8_t, Device> devices;
00085
00086 class DeviceGroup {
00087 public:
00088 DeviceGroup() {};
00089 DeviceGroup(std::vector<uint8_t> CANids) : CANids_(CANids) {};
00090 DeviceGroup(std::vector<uint8_t> CANids, std::vector<std::string> names) :
00091 CANids_(CANids), names_(names) {};
00092
00093 inline std::vector<double> getActualPos() {
00094 std::vector<double> actualPos;
00095 for (uint8_t CANid : CANids_)
00096 actualPos.push_back(devices[CANid].actualPos_);
00097 return actualPos;
00098 }
00099 inline std::vector<double> getDesiredPos() {
00100 std::vector<double> desiredPos;
00101 for (auto CANid : CANids_)
00102 desiredPos.push_back(devices[CANid].desiredPos_);
00103 return desiredPos;
00104 }
00105 inline std::vector<double> getActualVel() {
00106 std::vector<double> actualVel;
00107 for (auto CANid : CANids_)
00108 actualVel.push_back(devices[CANid].actualVel_);
00109 return actualVel;
00110 }
00111 inline std::vector<double> getDesiredVel() {
00112 std::vector<double> desiredVel;
00113 for (auto CANid : CANids_)
00114 desiredVel.push_back(devices[CANid].desiredVel_);
00115 return desiredVel;
00116 }
00117 inline void setVel(std::vector<double> velocities) {
00118 for (int i=0; i<velocities.size(); i++) {
00119 devices[CANids_[i]].desiredVel_ = velocities[i];
00120 std::cout << "setVel CANID " << (int) CANids_[i]
00121 << " name: " << names_[i] << " vel: " << velocities[i] << std::endl;
00122 }
00123 }
00124
00125 std::vector<uint8_t> CANids_;
00126 std::vector<std::string> names_;
00127 };
00128
00129
00130 extern std::map<std::string, DeviceGroup> deviceGroups;
00131
00132
00133
00134
00135 const uint8_t NMT_stop = 0x02;
00136 const uint8_t NMT_start = 0x01;
00137 const uint8_t NMT_reset = 0x81;
00138
00139 const SDOkey statusword(0x6041, 0x0);
00140 const SDOkey controlword(0x6040, 0x0);
00141 const SDOkey sync_timeout_factor(0x200e, 0x0);
00142 const SDOkey ip_time_units(0x60C2, 0x1);
00143 const SDOkey ip_time_index(0x60C2, 0x2);
00144 const int8_t ip_time_index_milliseconds = 0xFD;
00145 const int8_t ip_time_index_hundredmicroseconds = 0xFC;
00146 const uint8_t sync_timeout_factor_disable_timeout = 0;
00147
00148 const SDOkey modes_of_operation(0x6060, 0x0);
00149 const SDOkey modes_of_operation_display(0x6061, 0x0);
00150 const uint8_t modes_of_operation_homing_mode = 0x6;
00151 const uint8_t modes_of_operation_profile_position_mode = 0x1;
00152 const uint8_t modes_of_operation_velocity_mode = 0x2;
00153 const uint8_t modes_of_operation_profile_velocity_mode = 0x3;
00154 const uint8_t modes_of_operation_torque_profile_mode = 0x4;
00155 const uint8_t modes_of_operation_interpolated_position_mode = 0x7;
00156
00157 const uint16_t controlword_shutdown = 6;
00158 const uint16_t controlword_switch_on = 7;
00159 const uint16_t controlword_start_homing = 16;
00160 const uint16_t controlword_enable_operation = 15;
00161 const uint16_t controlword_enable_ip_mode = 16;
00162 const uint16_t controlword_fault_reset_0 = 0x00;
00163 const uint16_t controlword_fault_reset_1 = 0x80;
00164
00165
00166
00167 bool openConnection(std::string devName);
00168 void init(std::string deviceFile, std::chrono::milliseconds syncInterval);
00169 void initListenerThread(std::function<void ()> const& listener);
00170 void defaultListener();
00171 void initDeviceManagerThread(std::function<void ()> const& deviceManager);
00172 void deviceManager();
00173 void setMotorState(uint16_t CANid, std::string targetState);
00174
00175 void sendSDO(uint8_t CANid, SDOkey sdo);
00176 void sendSDO(uint8_t CANid, SDOkey sdo, uint32_t value);
00177 void sendSDO(uint8_t CANid, SDOkey sdo, int32_t value);
00178 void sendSDO(uint8_t CANid, SDOkey sdo, uint16_t value);
00179 void sendSDO(uint8_t CANid, SDOkey sdo, uint8_t value);
00180
00181 extern std::function< void (uint16_t CANid, double positionValue) > sendPos;
00182
00183
00184
00185 void schunkDefaultPDO_incoming(uint8_t CANid, const TPCANRdMsg m);
00186 void schunkDefaultPDOOutgoing(uint16_t CANid, double positionValue);
00187
00188
00189
00190 extern TPCANMsg syncMsg;
00191 extern TPCANMsg NMTmsg;
00192 extern TPCANMsg nodeguardMsg;
00193 inline void sendSync() {
00194 CAN_Write(h, &syncMsg);
00195 }
00196 inline void sendNMT(uint8_t command, uint8_t CANid) {
00197 NMTmsg.DATA[1] = command;
00198 NMTmsg.DATA[0] = CANid;
00199 CAN_Write(h, &NMTmsg);
00200 }
00201 inline void sendNodeguard(uint8_t CANid) {
00202 nodeguardMsg.ID = 0x700 + CANid;
00203 CAN_Write(h, &nodeguardMsg);
00204 }
00205
00206
00207
00208 inline int32_t rad2mdeg(double phi) {
00209 return static_cast<int32_t>( round( phi/(2*M_PI)*360000.0 ) ); }
00210 inline double mdeg2rad(int32_t alpha) {
00211 return static_cast<double>( static_cast<double>(alpha)/360000.0*2*M_PI ); }
00212
00213 }
00214
00215 #endif