AP_ToshibaCAN.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. #include <AP_HAL/AP_HAL.h>
  14. #if HAL_WITH_UAVCAN
  15. #include <AP_HAL/utility/sparse-endian.h>
  16. #include <AP_BoardConfig/AP_BoardConfig.h>
  17. #include <AP_BoardConfig/AP_BoardConfig_CAN.h>
  18. #include <AP_Common/AP_Common.h>
  19. #include <AP_Scheduler/AP_Scheduler.h>
  20. #include <AP_HAL/utility/sparse-endian.h>
  21. #include <SRV_Channel/SRV_Channel.h>
  22. #include <GCS_MAVLink/GCS.h>
  23. #include "AP_ToshibaCAN.h"
  24. #include <AP_Logger/AP_Logger.h>
  25. extern const AP_HAL::HAL& hal;
  26. #define debug_can(level_debug, fmt, args...) do { if ((level_debug) <= AP::can().get_debug_level_driver(_driver_index)) { printf(fmt, ##args); }} while (0)
  27. // data format for messages from flight controller
  28. static const uint8_t COMMAND_STOP = 0x0;
  29. static const uint8_t COMMAND_LOCK = 0x10;
  30. static const uint8_t COMMAND_REQUEST_DATA = 0x20;
  31. static const uint8_t COMMAND_MOTOR3 = 0x3B;
  32. static const uint8_t COMMAND_MOTOR2 = 0x3D;
  33. static const uint8_t COMMAND_MOTOR1 = 0x3F;
  34. // data format for messages from ESC
  35. static const uint8_t MOTOR_DATA1 = 0x40;
  36. static const uint8_t MOTOR_DATA2 = 0x50;
  37. static const uint8_t MOTOR_DATA3 = 0x60;
  38. static const uint8_t MOTOR_DATA5 = 0x80;
  39. // processing definitions
  40. static const uint16_t TOSHIBACAN_OUTPUT_MIN = 6300;
  41. static const uint16_t TOSHIBACAN_OUTPUT_MAX = 32000;
  42. static const uint16_t TOSHIBACAN_SEND_TIMEOUT_US = 500;
  43. static const uint8_t CAN_IFACE_INDEX = 0;
  44. // telemetry definitions
  45. static const uint32_t TOSHIBA_CAN_ESC_UPDATE_MS = 100;
  46. AP_ToshibaCAN::AP_ToshibaCAN()
  47. {
  48. debug_can(2, "ToshibaCAN: constructed\n\r");
  49. }
  50. AP_ToshibaCAN *AP_ToshibaCAN::get_tcan(uint8_t driver_index)
  51. {
  52. if (driver_index >= AP::can().get_num_drivers() ||
  53. AP::can().get_protocol_type(driver_index) != AP_BoardConfig_CAN::Protocol_Type_ToshibaCAN) {
  54. return nullptr;
  55. }
  56. return static_cast<AP_ToshibaCAN*>(AP::can().get_driver(driver_index));
  57. }
  58. // initialise ToshibaCAN bus
  59. void AP_ToshibaCAN::init(uint8_t driver_index, bool enable_filters)
  60. {
  61. _driver_index = driver_index;
  62. debug_can(2, "ToshibaCAN: starting init\n\r");
  63. if (_initialized) {
  64. debug_can(1, "ToshibaCAN: already initialized\n\r");
  65. return;
  66. }
  67. AP_HAL::CANManager* can_mgr = hal.can_mgr[driver_index];
  68. if (can_mgr == nullptr) {
  69. debug_can(1, "ToshibaCAN: no mgr for this driver\n\r");
  70. return;
  71. }
  72. if (!can_mgr->is_initialized()) {
  73. debug_can(1, "ToshibaCAN: mgr not initialized\n\r");
  74. return;
  75. }
  76. _can_driver = can_mgr->get_driver();
  77. if (_can_driver == nullptr) {
  78. debug_can(1, "ToshibaCAN: no CAN driver\n\r");
  79. return;
  80. }
  81. // start calls to loop in separate thread
  82. if (!hal.scheduler->thread_create(FUNCTOR_BIND_MEMBER(&AP_ToshibaCAN::loop, void), _thread_name, 4096, AP_HAL::Scheduler::PRIORITY_MAIN, 1)) {
  83. debug_can(1, "ToshibaCAN: couldn't create thread\n\r");
  84. return;
  85. }
  86. _initialized = true;
  87. debug_can(2, "ToshibaCAN: init done\n\r");
  88. return;
  89. }
  90. // loop to send output to ESCs in background thread
  91. void AP_ToshibaCAN::loop()
  92. {
  93. uavcan::MonotonicTime timeout;
  94. const uint32_t timeout_us = MIN(AP::scheduler().get_loop_period_us(), TOSHIBACAN_SEND_TIMEOUT_US);
  95. while (true) {
  96. if (!_initialized) {
  97. // if not initialised wait 2ms
  98. debug_can(2, "ToshibaCAN: not initialized\n\r");
  99. hal.scheduler->delay_microseconds(2000);
  100. continue;
  101. }
  102. // check for updates
  103. if (update_count == update_count_sent) {
  104. hal.scheduler->delay_microseconds(50);
  105. continue;
  106. }
  107. // prepare commands and frames
  108. if (send_stage == 0) {
  109. motor_lock_cmd_t unlock_cmd = {};
  110. motor_rotation_cmd_t mot_rot_cmd1;
  111. motor_rotation_cmd_t mot_rot_cmd2;
  112. motor_rotation_cmd_t mot_rot_cmd3;
  113. {
  114. // take semaphore to read scaled motor outputs
  115. WITH_SEMAPHORE(_rc_out_sem);
  116. // prepare command to lock or unlock motors
  117. unlock_cmd.motor1 = (_scaled_output[0] == 0) ? 2 : 1;
  118. unlock_cmd.motor2 = (_scaled_output[1] == 0) ? 2 : 1;
  119. unlock_cmd.motor3 = (_scaled_output[2] == 0) ? 2 : 1;
  120. unlock_cmd.motor4 = (_scaled_output[3] == 0) ? 2 : 1;
  121. unlock_cmd.motor5 = (_scaled_output[4] == 0) ? 2 : 1;
  122. unlock_cmd.motor6 = (_scaled_output[5] == 0) ? 2 : 1;
  123. unlock_cmd.motor7 = (_scaled_output[6] == 0) ? 2 : 1;
  124. unlock_cmd.motor8 = (_scaled_output[7] == 0) ? 2 : 1;
  125. unlock_cmd.motor9 = (_scaled_output[8] == 0) ? 2 : 1;
  126. unlock_cmd.motor10 = (_scaled_output[9] == 0) ? 2 : 1;
  127. unlock_cmd.motor11 = (_scaled_output[10] == 0) ? 2 : 1;
  128. unlock_cmd.motor12 = (_scaled_output[11] == 0) ? 2 : 1;
  129. // prepare command to spin motors in bank1
  130. mot_rot_cmd1.motor1 = htobe16(_scaled_output[0]);
  131. mot_rot_cmd1.motor2 = htobe16(_scaled_output[1]);
  132. mot_rot_cmd1.motor3 = htobe16(_scaled_output[2]);
  133. mot_rot_cmd1.motor4 = htobe16(_scaled_output[3]);
  134. // prepare message to spin motors in bank2
  135. mot_rot_cmd2.motor1 = htobe16(_scaled_output[4]);
  136. mot_rot_cmd2.motor2 = htobe16(_scaled_output[5]);
  137. mot_rot_cmd2.motor3 = htobe16(_scaled_output[6]);
  138. mot_rot_cmd2.motor4 = htobe16(_scaled_output[7]);
  139. // prepare message to spin motors in bank3
  140. mot_rot_cmd3.motor1 = htobe16(_scaled_output[8]);
  141. mot_rot_cmd3.motor2 = htobe16(_scaled_output[9]);
  142. mot_rot_cmd3.motor3 = htobe16(_scaled_output[10]);
  143. mot_rot_cmd3.motor4 = htobe16(_scaled_output[11]);
  144. // copy update time
  145. update_count_buffered = update_count;
  146. }
  147. unlock_frame = {(uint8_t)COMMAND_LOCK, unlock_cmd.data, sizeof(unlock_cmd.data)};
  148. mot_rot_frame1 = {((uint8_t)COMMAND_MOTOR1 & uavcan::CanFrame::MaskStdID), mot_rot_cmd1.data, sizeof(mot_rot_cmd1.data)};
  149. mot_rot_frame2 = {((uint8_t)COMMAND_MOTOR2 & uavcan::CanFrame::MaskStdID), mot_rot_cmd2.data, sizeof(mot_rot_cmd2.data)};
  150. mot_rot_frame3 = {((uint8_t)COMMAND_MOTOR3 & uavcan::CanFrame::MaskStdID), mot_rot_cmd3.data, sizeof(mot_rot_cmd3.data)};
  151. // advance to next stage
  152. send_stage++;
  153. }
  154. // send unlock command
  155. if (send_stage == 1) {
  156. timeout = uavcan::MonotonicTime::fromUSec(AP_HAL::micros64() + timeout_us);
  157. if (!write_frame(unlock_frame, timeout)) {
  158. continue;
  159. }
  160. send_stage++;
  161. }
  162. // send output to motor bank3
  163. if (send_stage == 2) {
  164. timeout = uavcan::MonotonicTime::fromUSec(AP_HAL::micros64() + timeout_us);
  165. if (!write_frame(mot_rot_frame3, timeout)) {
  166. continue;
  167. }
  168. send_stage++;
  169. }
  170. // send output to motor bank2
  171. if (send_stage == 3) {
  172. timeout = uavcan::MonotonicTime::fromUSec(AP_HAL::micros64() + timeout_us);
  173. if (!write_frame(mot_rot_frame2, timeout)) {
  174. continue;
  175. }
  176. send_stage++;
  177. }
  178. // send output to motor bank1
  179. if (send_stage == 4) {
  180. timeout = uavcan::MonotonicTime::fromUSec(AP_HAL::micros64() + timeout_us);
  181. if (!write_frame(mot_rot_frame1, timeout)) {
  182. continue;
  183. }
  184. send_stage++;
  185. }
  186. // check if we should request update from ESCs
  187. if (send_stage == 5) {
  188. uint32_t now_ms = AP_HAL::millis();
  189. uint32_t diff_ms = now_ms - _telemetry_req_ms;
  190. // check if 100ms has passed since last update request
  191. if (diff_ms >= TOSHIBA_CAN_ESC_UPDATE_MS) {
  192. // set _telem_req_ms to time we ideally should have requested update
  193. if (diff_ms >= 2 * TOSHIBA_CAN_ESC_UPDATE_MS) {
  194. _telemetry_req_ms = now_ms;
  195. } else {
  196. _telemetry_req_ms += TOSHIBA_CAN_ESC_UPDATE_MS;
  197. }
  198. // prepare command to request data1 (rpm and voltage) from all ESCs
  199. motor_request_data_cmd_t request_data_cmd = {};
  200. request_data_cmd.motor1 = 1;
  201. request_data_cmd.motor2 = 1;
  202. request_data_cmd.motor3 = 1;
  203. request_data_cmd.motor4 = 1;
  204. request_data_cmd.motor5 = 1;
  205. request_data_cmd.motor6 = 1;
  206. request_data_cmd.motor7 = 1;
  207. request_data_cmd.motor8 = 1;
  208. request_data_cmd.motor9 = 1;
  209. request_data_cmd.motor10 = 1;
  210. request_data_cmd.motor11 = 1;
  211. request_data_cmd.motor12 = 1;
  212. uavcan::CanFrame request_data_frame;
  213. request_data_frame = {(uint8_t)COMMAND_REQUEST_DATA, request_data_cmd.data, sizeof(request_data_cmd.data)};
  214. // send request data command
  215. timeout = uavcan::MonotonicTime::fromUSec(AP_HAL::micros64() + timeout_us);
  216. if (!write_frame(request_data_frame, timeout)) {
  217. continue;
  218. }
  219. // increment count to request temperature
  220. _telemetry_temp_req_counter++;
  221. }
  222. send_stage++;
  223. }
  224. // check if we should request temperature from ESCs
  225. if (send_stage == 6) {
  226. if (_telemetry_temp_req_counter > 10) {
  227. _telemetry_temp_req_counter = 0;
  228. // prepare command to request data2 (temperature) from all ESCs
  229. motor_request_data_cmd_t request_data_cmd = {};
  230. request_data_cmd.motor1 = 2;
  231. request_data_cmd.motor2 = 2;
  232. request_data_cmd.motor3 = 2;
  233. request_data_cmd.motor4 = 2;
  234. request_data_cmd.motor5 = 2;
  235. request_data_cmd.motor6 = 2;
  236. request_data_cmd.motor7 = 2;
  237. request_data_cmd.motor8 = 2;
  238. request_data_cmd.motor9 = 2;
  239. request_data_cmd.motor10 = 2;
  240. request_data_cmd.motor11 = 2;
  241. request_data_cmd.motor12 = 2;
  242. uavcan::CanFrame request_data_frame;
  243. request_data_frame = {(uint8_t)COMMAND_REQUEST_DATA, request_data_cmd.data, sizeof(request_data_cmd.data)};
  244. // send request data command
  245. timeout = uavcan::MonotonicTime::fromUSec(AP_HAL::micros64() + timeout_us);
  246. if (!write_frame(request_data_frame, timeout)) {
  247. continue;
  248. }
  249. }
  250. send_stage++;
  251. }
  252. // check for replies from ESCs
  253. if (send_stage == 7) {
  254. uavcan::CanFrame recv_frame;
  255. while (read_frame(recv_frame, timeout)) {
  256. // decode rpm and voltage data
  257. if ((recv_frame.id >= MOTOR_DATA1) && (recv_frame.id <= MOTOR_DATA1 + 12)) {
  258. // copy contents to our structure
  259. motor_reply_data1_t reply_data;
  260. memcpy(reply_data.data, recv_frame.data, sizeof(reply_data.data));
  261. // store response in telemetry array
  262. const uint8_t esc_id = recv_frame.id - MOTOR_DATA1;
  263. if (esc_id < TOSHIBACAN_MAX_NUM_ESCS) {
  264. WITH_SEMAPHORE(_telem_sem);
  265. _telemetry[esc_id].rpm = be16toh(reply_data.rpm);
  266. _telemetry[esc_id].millivolts = be16toh(reply_data.millivolts);
  267. _telemetry[esc_id].count++;
  268. _telemetry[esc_id].new_data = true;
  269. _esc_present_bitmask |= ((uint32_t)1 << esc_id);
  270. }
  271. }
  272. // decode temperature data
  273. if ((recv_frame.id >= MOTOR_DATA2) && (recv_frame.id <= MOTOR_DATA2 + 12)) {
  274. // motor data2 data format is 8 bytes (64 bits)
  275. // 10 bits: U temperature
  276. // 10 bits: V temperature
  277. // 10 bits: W temperature
  278. // 10 bits: motor temperature
  279. // remaining 24 bits: reserved
  280. const uint16_t u_temp = ((uint16_t)recv_frame.data[0] << 2) | ((uint16_t)recv_frame.data[1] >> 6);
  281. const uint16_t v_temp = (((uint16_t)recv_frame.data[1] & (uint16_t)0x3F) << 4) | (((uint16_t)recv_frame.data[2] & (uint16_t)0xF0) >> 4);
  282. const uint16_t w_temp = (((uint16_t)recv_frame.data[2] & (uint16_t)0x0F) << 6) | (((uint16_t)recv_frame.data[3] & (uint16_t)0xFC) >> 2);
  283. const uint16_t temp_max = MAX(u_temp, MAX(v_temp, w_temp));
  284. // store repose in telemetry array
  285. uint8_t esc_id = recv_frame.id - MOTOR_DATA2;
  286. if (esc_id < TOSHIBACAN_MAX_NUM_ESCS) {
  287. WITH_SEMAPHORE(_telem_sem);
  288. _telemetry[esc_id].temperature = temp_max < 20 ? 0 : temp_max / 5 - 20;
  289. _esc_present_bitmask |= ((uint32_t)1 << esc_id);
  290. }
  291. }
  292. }
  293. }
  294. // success!
  295. send_stage = 0;
  296. // record success so we don't send this frame again
  297. update_count_sent = update_count_buffered;
  298. }
  299. }
  300. // write frame on CAN bus
  301. bool AP_ToshibaCAN::write_frame(uavcan::CanFrame &out_frame, uavcan::MonotonicTime timeout)
  302. {
  303. // wait for space in buffer to send command
  304. uavcan::CanSelectMasks inout_mask;
  305. do {
  306. inout_mask.read = 0;
  307. inout_mask.write = 1 << CAN_IFACE_INDEX;
  308. _select_frames[CAN_IFACE_INDEX] = &out_frame;
  309. _can_driver->select(inout_mask, _select_frames, timeout);
  310. // delay if no space is available to send
  311. if (!inout_mask.write) {
  312. hal.scheduler->delay_microseconds(50);
  313. }
  314. } while (!inout_mask.write);
  315. // send frame and return success
  316. return (_can_driver->getIface(CAN_IFACE_INDEX)->send(out_frame, timeout, uavcan::CanIOFlagAbortOnError) == 1);
  317. }
  318. // read frame on CAN bus, returns true on success
  319. bool AP_ToshibaCAN::read_frame(uavcan::CanFrame &recv_frame, uavcan::MonotonicTime timeout)
  320. {
  321. // wait for space in buffer to read
  322. uavcan::CanSelectMasks inout_mask;
  323. inout_mask.read = 1 << CAN_IFACE_INDEX;
  324. inout_mask.write = 0;
  325. _select_frames[CAN_IFACE_INDEX] = &recv_frame;
  326. _can_driver->select(inout_mask, _select_frames, timeout);
  327. // return false if no data is available to read
  328. if (!inout_mask.read) {
  329. return false;
  330. }
  331. uavcan::MonotonicTime time;
  332. uavcan::UtcTime utc_time;
  333. uavcan::CanIOFlags flags {};
  334. // read frame and return success
  335. return (_can_driver->getIface(CAN_IFACE_INDEX)->receive(recv_frame, time, utc_time, flags) == 1);
  336. }
  337. // called from SRV_Channels
  338. void AP_ToshibaCAN::update()
  339. {
  340. // take semaphore and update outputs
  341. {
  342. WITH_SEMAPHORE(_rc_out_sem);
  343. const bool armed = hal.util->get_soft_armed();
  344. for (uint8_t i = 0; i < MIN(TOSHIBACAN_MAX_NUM_ESCS, 16); i++) {
  345. const SRV_Channel *c = SRV_Channels::srv_channel(i);
  346. if (!armed || (c == nullptr)) {
  347. _scaled_output[i] = 0;
  348. } else {
  349. const uint16_t pwm_out = c->get_output_pwm();
  350. if (pwm_out <= 1000) {
  351. _scaled_output[i] = 0;
  352. } else if (pwm_out >= 2000) {
  353. _scaled_output[i] = TOSHIBACAN_OUTPUT_MAX;
  354. } else {
  355. _scaled_output[i] = TOSHIBACAN_OUTPUT_MIN + (pwm_out - 1000) * 0.001f * (TOSHIBACAN_OUTPUT_MAX - TOSHIBACAN_OUTPUT_MIN);
  356. }
  357. }
  358. }
  359. update_count++;
  360. }
  361. // log ESCs telemetry info
  362. AP_Logger *logger = AP_Logger::get_singleton();
  363. if (logger && logger->logging_enabled()) {
  364. WITH_SEMAPHORE(_telem_sem);
  365. // log if any new data received. Logging only supports up to 8 ESCs
  366. const uint64_t time_us = AP_HAL::micros64();
  367. for (uint8_t i = 0; i < MIN(TOSHIBACAN_MAX_NUM_ESCS, 8); i++) {
  368. if (_telemetry[i].new_data) {
  369. logger->Write_ESC(i, time_us,
  370. _telemetry[i].rpm * 100U,
  371. _telemetry[i].millivolts * 0.1f,
  372. 0,
  373. _telemetry[i].temperature * 100.0f,
  374. 0);
  375. _telemetry[i].new_data = false;
  376. }
  377. }
  378. }
  379. }
  380. // send ESC telemetry messages over MAVLink
  381. void AP_ToshibaCAN::send_esc_telemetry_mavlink(uint8_t mav_chan)
  382. {
  383. // compile time check this method handles the correct number of motors
  384. static_assert(TOSHIBACAN_MAX_NUM_ESCS == 12, "update AP_ToshibaCAN::send_esc_telemetry_mavlink only handles 12 motors");
  385. // return immediately if no ESCs have been found
  386. if (_esc_present_bitmask == 0) {
  387. return;
  388. }
  389. // return if no space in output buffer to send mavlink messages
  390. if (!HAVE_PAYLOAD_SPACE((mavlink_channel_t)mav_chan, ESC_TELEMETRY_1_TO_4)) {
  391. return;
  392. }
  393. // output telemetry messages
  394. {
  395. // take semaphore to access telemetry data
  396. WITH_SEMAPHORE(_telem_sem);
  397. // loop through 3 groups of 4 ESCs
  398. for (uint8_t i = 0; i < 3; i++) {
  399. // skip this group of ESCs if no data to send
  400. if ((_esc_present_bitmask & ((uint32_t)0x0F << i*4)) == 0) {
  401. continue;
  402. }
  403. // arrays to hold output
  404. uint8_t temperature[4] {};
  405. uint16_t voltage[4] {};
  406. uint16_t rpm[4] {};
  407. uint16_t count[4] {};
  408. uint16_t nosup[4] {}; // single empty array for unsupported current and current_tot
  409. // fill in output arrays
  410. for (uint8_t j = 0; j < 4; j++) {
  411. uint8_t esc_id = i * 4 + j;
  412. temperature[j] = _telemetry[esc_id].temperature;
  413. voltage[j] = _telemetry[esc_id].millivolts * 0.1f;
  414. rpm[j] = _telemetry[esc_id].rpm;
  415. count[j] = _telemetry[esc_id].count;
  416. }
  417. // send messages
  418. switch (i) {
  419. case 0:
  420. mavlink_msg_esc_telemetry_1_to_4_send((mavlink_channel_t)mav_chan, temperature, voltage, nosup, nosup, rpm, count);
  421. break;
  422. case 1:
  423. mavlink_msg_esc_telemetry_5_to_8_send((mavlink_channel_t)mav_chan, temperature, voltage, nosup, nosup, rpm, count);
  424. break;
  425. case 2:
  426. mavlink_msg_esc_telemetry_9_to_12_send((mavlink_channel_t)mav_chan, temperature, voltage, nosup, nosup, rpm, count);
  427. break;
  428. default:
  429. break;
  430. }
  431. }
  432. }
  433. }
  434. #endif // HAL_WITH_UAVCAN