neuberfran

onemoresmartdriveCXX

Sep 27th, 2016
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.76 KB | None | 0 0
  1. /*
  2. * Author: Neuber Sousa <neuberfran@gmail.com>
  3. * Below are the terms of usage of this file
  4. *
  5. * This is an upm implementation for SmartDrive from OpenElectrons.Com
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining
  8. * a copy of this software and associated documentation files (the
  9. * "Software"), to deal in the Software without restriction, including
  10. * without limitation the rights to use, copy, modify, merge, publish,
  11. * distribute, sublicense, and/or sell copies of the Software, and to
  12. * permit persons to whom the Software is furnished to do so, subject to
  13. * the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be
  16. * included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  22. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  23. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  24. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25. */
  26.  
  27. #include <iostream>
  28. #include <exception>
  29. #include <stdexcept>
  30. #include <unistd.h>
  31. #include <stdlib.h>
  32.  
  33. #include "smartdrive.h"
  34.  
  35.  
  36. using namespace upm;
  37.  
  38. SmartDrive::SmartDrive(int i2c_bus, int address): m_controlAddr(address), m_i2ControlCtx(i2c_bus)
  39. {
  40. mraa::Result ret = m_i2ControlCtx.address(m_controlAddr);
  41. if (ret != mraa::SUCCESS) {
  42. throw std::invalid_argument(std::string(__FUNCTION__) +
  43. ": mraa_i2c_address() failed");
  44. return;
  45. }
  46. }
  47.  
  48.  
  49. void
  50. SmartDrive::writeByte(uint8_t addr, uint8_t value) {
  51. try {
  52. m_i2ControlCtx.address(m_controlAddr);
  53. m_i2ControlCtx.writeReg(addr, value);
  54. } catch (int e) {
  55. std::cout << "Failed to write " << value << " to address " << addr << " --> " << e << std::endl;
  56. }
  57. }
  58.  
  59. uint8_t
  60. SmartDrive::readByte(uint8_t addr) {
  61. try {
  62. m_i2ControlCtx.address(m_controlAddr);
  63. return m_i2ControlCtx.readReg(addr);
  64. } catch (int e) {
  65. std::cout << "Failed to read byte at address " << addr << " --> " << e << std::endl;
  66. }
  67. return -1;
  68. }
  69.  
  70. void
  71. SmartDrive::writeArray(uint8_t* array, int size) {
  72. try {
  73. m_i2ControlCtx.address(m_controlAddr); //Second : I was not resetting bus adress of device evreytime ebfore acessing it
  74. //I believe we need to do this everytime before accessing bus, because i2c bus may be used by many devices, se we need to tell which device we want to control EVERYTIME
  75. m_i2ControlCtx.write(array, size); //First : Here, i was tryignt o calculate array size dynamically, but it's not supported here, so i have to pass array size statically in variable
  76. } catch (int e) {
  77. std::cout << "Failed to write array values to address " << array[0] << " --> " << e << std::endl;
  78. }
  79. }
  80.  
  81. uint16_t
  82. SmartDrive::readInteger(uint8_t addr) {
  83. try {
  84. m_i2ControlCtx.address(m_controlAddr);
  85. return m_i2ControlCtx.readWordReg(addr);
  86. } catch (int e) {
  87. std::cout << "Failed to read value at address " << addr << " --> " << e << std::endl;
  88. }
  89. return -1;
  90. }
  91.  
  92. uint32_t
  93. SmartDrive::readLongSigned(uint8_t addr) {
  94. uint8_t bytes[4]={0};
  95.  
  96. try {
  97. m_i2ControlCtx.address(m_controlAddr);
  98. m_i2ControlCtx.readBytesReg(addr, bytes, sizeof(bytes)/sizeof(uint8_t));
  99. return (bytes[0]|(bytes[1]<<8)|(bytes[2]<<16)|(bytes[3]<<24));
  100. } catch (int e) {
  101. std::cout << "Failed to read integer value at address " << addr << " --> " << e << std::endl;
  102. }
  103. return -1;
  104. }
  105.  
  106. void
  107. SmartDrive::command(uint8_t cmd) {
  108. std::cout << "Running Command : " << cmd << std::endl;
  109. writeByte(SmartDrive_COMMAND, cmd);
  110. }
  111.  
  112.  
  113. float
  114. SmartDrive::GetBattVoltage() {
  115. uint8_t value = 0;
  116. try {
  117. value = readByte(SmartDrive_BATT_VOLTAGE);
  118. return (value * SmartDrive_VOLTAGE_MULTIPLIER);
  119. } catch (int e) {
  120. std::cout << "Error: Could not read voltage -> " << e << std::endl;
  121. }
  122. return -1.0f;
  123. }
  124.  
  125.  
  126. uint32_t
  127. SmartDrive::ReadTachometerPosition(MotorID_t motor_number) {
  128. try {
  129. if (motor_number == 1 )
  130. return readLongSigned(SmartDrive_POSITION_M1);
  131. else
  132. return readLongSigned(SmartDrive_POSITION_M2);
  133. } catch (int e) {
  134. std::cout << "Error: Could not read encoders" << std::endl;
  135. }
  136. return -1;
  137. }
  138.  
  139.  
  140. void
  141. SmartDrive::Run_Unlimited(MotorID_t motor_number, Direction_t direction, uint8_t speed) {
  142. uint8_t ctrl = 0;
  143. ctrl |= SmartDrive_CONTROL_SPEED;
  144. ctrl |= SmartDrive_CONTROL_BRK;
  145.  
  146. std::cout << "Running with speed : " << (int) speed << std::endl;
  147.  
  148. if ( motor_number != Motor_ID_BOTH )
  149. ctrl |= SmartDrive_CONTROL_GO;
  150. if ( direction != Dir_Forward )
  151. speed = speed * -1;
  152. if ( motor_number != Motor_ID_2) {
  153. uint8_t array [5] = {SmartDrive_SPEED_M1, speed, 0, 0, ctrl};
  154. writeArray(array,5);
  155. }
  156. if ( motor_number != Motor_ID_1) {
  157. uint8_t array [5] = {SmartDrive_SPEED_M2, speed, 0, 0, ctrl};
  158. writeArray(array,5);
  159. }
  160. if ( motor_number == Motor_ID_BOTH )
  161. writeByte(SmartDrive_COMMAND,0x53);
  162. }
  163.  
  164.  
  165. void
  166. SmartDrive::StopMotor(MotorID_t motor_number, MotorAction_t next_action ) {
  167. if ( next_action != Action_Float )
  168. writeByte(SmartDrive_COMMAND, 'A'+motor_number-1);
  169. else
  170. writeByte(SmartDrive_COMMAND, 'a'+motor_number-1);
  171. }
  172.  
  173.  
  174. void
  175. SmartDrive::Run_Seconds(MotorID_t motor_number, Direction_t direction, uint8_t speed, uint8_t duration, bool wait_for_completion, MotorAction_t next_action ) {
  176. uint8_t ctrl = 0;
  177. ctrl |= SmartDrive_CONTROL_SPEED;
  178. ctrl |= SmartDrive_CONTROL_TIME;
  179.  
  180. if ( next_action == Action_Brake )
  181. ctrl |= SmartDrive_CONTROL_BRK;
  182. if ( next_action == Action_BrakeHold ) {
  183. ctrl |= SmartDrive_CONTROL_BRK;
  184. ctrl |= SmartDrive_CONTROL_ON;
  185. }
  186. if ( motor_number != Motor_ID_BOTH )
  187. ctrl |= SmartDrive_CONTROL_GO;
  188. if ( direction != Dir_Forward )
  189. speed = speed * -1;
  190. if ( (motor_number & 0x01) != 0 ) {
  191. uint8_t array[5] = {SmartDrive_SPEED_M1, speed, duration, 0, ctrl};
  192. printf("Motor 1 running | cmd = %2x %2x %2x %2x %2x\n", array[0] ,array[1] ,array[2] ,array[3] , array[4]);
  193. writeArray(array,5);
  194. }
  195. if ( (motor_number & 0x02) != 0 ) {
  196. uint8_t array[5] = {SmartDrive_SPEED_M2, speed, duration, 0, ctrl};
  197. printf("Motor 2 running | cmd = %2x %2x %2x %2x %2x\n", array[0] ,array[1] ,array[2] ,array[3] , array[4]);
  198. writeArray(array,5);
  199. }
  200. if ( motor_number == Motor_ID_BOTH )
  201. writeByte(SmartDrive_COMMAND, 0x53);
  202. printf("Speed Motor 1 : %2x\n", readByte(SmartDrive_SPEED_M1));
  203. printf("Speed Motor 2 : %2x\n", readByte(SmartDrive_SPEED_M2));
  204. printf("Time Motor 1 : %2x\n", readByte(SmartDrive_TIME_M1));
  205. printf("Time Motor 2 : %2x\n", readByte(SmartDrive_TIME_M2));
  206. if ( wait_for_completion ) {
  207. sleep(1); //this delay is required for the status byte to be available for reading.
  208. WaitUntilTimeDone(motor_number);
  209. }
  210. }
  211.  
  212.  
  213. void
  214. SmartDrive::WaitUntilTimeDone(MotorID_t motor_number) {
  215. while (IsTimeDone(motor_number) == false)
  216. sleep(1);
  217. }
  218.  
  219.  
  220. bool
  221. SmartDrive::IsTimeDone(MotorID_t motor_number) {
  222. uint8_t result_1 = 0, result_2 = 0;
  223. if ( motor_number != Motor_ID_2 )
  224. result_1 = readByte(SmartDrive_STATUS_M1);
  225. if ( motor_number != Motor_ID_1 )
  226. result_2 = readByte(SmartDrive_STATUS_M2);
  227. return (((result_1 & 0x40) == 0) && ((result_2 & 0x40) == 0) ); //look for time bits to be zero
  228. }
  229.  
  230.  
  231. void
  232. SmartDrive::Run_Degrees(MotorID_t motor_number, Direction_t direction, uint8_t speed, uint32_t degrees, bool wait_for_completion, MotorAction_t next_action) {
  233. uint8_t ctrl = 0;
  234. ctrl |= SmartDrive_CONTROL_SPEED;
  235. ctrl |= SmartDrive_CONTROL_TACHO;
  236. ctrl |= SmartDrive_CONTROL_RELATIVE;
  237.  
  238. uint32_t d = degrees;
  239. if ( direction != Dir_Forward )
  240. d = degrees * -1 ;
  241.  
  242. uint8_t t4 = (d/0x1000000);
  243. uint8_t t3 = ((d%0x1000000)/0x10000);
  244. uint8_t t2 = (((d%0x1000000)%0x10000)/0x100);
  245. uint8_t t1 = (((d%0x1000000)%0x10000)%0x100);
  246.  
  247. if ( next_action == Action_Brake )
  248. ctrl |= SmartDrive_CONTROL_BRK;
  249. if ( next_action == Action_BrakeHold ) {
  250. ctrl |= SmartDrive_CONTROL_BRK;
  251. ctrl |= SmartDrive_CONTROL_ON;
  252. }
  253. if ( motor_number != Motor_ID_BOTH )
  254. ctrl |= SmartDrive_CONTROL_GO;
  255. if ( motor_number != Motor_ID_2) {
  256. uint8_t array[9] = {SmartDrive_SETPT_M1, t1, t2, t3, t4, speed, 0, 0, ctrl};
  257. writeArray(array,9);
  258. }
  259. if ( motor_number != Motor_ID_1){
  260. uint8_t array[9] = {SmartDrive_SETPT_M2, t1, t2, t3, t4, speed, 0, 0, ctrl};
  261. writeArray(array,9);
  262. }
  263. if ( motor_number == Motor_ID_BOTH )
  264. writeByte(SmartDrive_COMMAND, 0x53);
  265. if ( wait_for_completion ) {
  266. sleep(1);//this delay is required for the status byte to be available for reading.
  267. WaitUntilTachoDone(motor_number);
  268. }
  269. }
  270.  
  271.  
  272. void
  273. SmartDrive::Run_Rotations(MotorID_t motor_number, Direction_t direction, uint8_t speed, uint32_t rotations, bool wait_for_completion, MotorAction_t next_action) {
  274. uint8_t ctrl = 0;
  275. ctrl |= SmartDrive_CONTROL_SPEED;
  276. ctrl |= SmartDrive_CONTROL_TACHO;
  277. ctrl |= SmartDrive_CONTROL_RELATIVE;
  278.  
  279. uint32_t d = rotations * 360;
  280. if ( direction != Dir_Forward )
  281. d = (rotations * 360) * -1;
  282.  
  283. uint8_t t4 = (d/0x1000000);
  284. uint8_t t3 = ((d%0x1000000)/0x10000);
  285. uint8_t t2 = (((d%0x1000000)%0x10000)/0x100);
  286. uint8_t t1 = (((d%0x1000000)%0x10000)%0x100);
  287.  
  288. if ( next_action == Action_Brake )
  289. ctrl |= SmartDrive_CONTROL_BRK;
  290. if ( next_action == Action_BrakeHold ) {
  291. ctrl |= SmartDrive_CONTROL_BRK;
  292. ctrl |= SmartDrive_CONTROL_ON;
  293. }
  294. if ( motor_number != Motor_ID_BOTH )
  295. ctrl |= SmartDrive_CONTROL_GO;
  296. if ( motor_number != Motor_ID_2) {
  297. uint8_t array[9] = {SmartDrive_SETPT_M1, t1, t2, t3, t4, speed, 0, 0, ctrl};
  298. writeArray(array,9);
  299. }
  300. if ( motor_number != Motor_ID_1) {
  301. uint8_t array[9] = {SmartDrive_SETPT_M2, t1, t2, t3, t4, speed, 0, 0, ctrl};
  302. writeArray(array,9);
  303. }
  304. if ( motor_number == Motor_ID_BOTH )
  305. writeByte(SmartDrive_COMMAND, 0x53);
  306. if ( wait_for_completion) {
  307. sleep(1); //this delay is required for the status byte to be available for reading.
  308. WaitUntilTachoDone(motor_number);
  309. }
  310. }
  311.  
  312.  
  313. void
  314. SmartDrive::Run_Tacho(MotorID_t motor_number, uint8_t speed, uint32_t tacho_count, bool wait_for_completion, MotorAction_t next_action) {
  315. uint8_t ctrl = 0;
  316. ctrl |= SmartDrive_CONTROL_SPEED;
  317. ctrl |= SmartDrive_CONTROL_TACHO;
  318.  
  319. uint32_t d = tacho_count;
  320.  
  321. uint8_t t4 = (d/0x1000000);
  322. uint8_t t3 = ((d%0x1000000)/0x10000);
  323. uint8_t t2 = (((d%0x1000000)%0x10000)/0x100);
  324. uint8_t t1 = (((d%0x1000000)%0x10000)%0x100);
  325.  
  326. if ( next_action == Action_Brake )
  327. ctrl |= SmartDrive_CONTROL_BRK;
  328. if ( next_action == Action_BrakeHold ) {
  329. ctrl |= SmartDrive_CONTROL_BRK;
  330. ctrl |= SmartDrive_CONTROL_ON;
  331. }
  332. if ( motor_number != Motor_ID_BOTH )
  333. ctrl |= SmartDrive_CONTROL_GO;
  334. if ( motor_number != Motor_ID_2){
  335. uint8_t array[9]= {SmartDrive_SETPT_M1, t1, t2, t3, t4, speed, 0, 0, ctrl};
  336. writeArray(array,9);
  337. }
  338. if ( motor_number != Motor_ID_1){
  339. uint8_t array[9]= {SmartDrive_SETPT_M2, t1, t2, t3, t4, speed, 0, 0, ctrl};
  340. writeArray(array,9);
  341. }
  342. if ( motor_number == Motor_ID_BOTH )
  343. writeByte(SmartDrive_COMMAND, 0x53);
  344. if ( wait_for_completion )
  345. sleep(1); //this delay is required for the status byte to be available for reading.
  346. WaitUntilTachoDone(motor_number);
  347. }
  348.  
  349.  
  350. void
  351. SmartDrive::WaitUntilTachoDone(MotorID_t motor_number) {
  352. while (IsTachoDone(motor_number) == false)
  353. usleep(30000);
  354. }
  355.  
  356.  
  357. bool
  358. SmartDrive::IsTachoDone(MotorID_t motor_number) {
  359. uint8_t result_1 = 0, result_2 = 0;
  360.  
  361. if ( motor_number != Motor_ID_2 )
  362. result_1 = readByte(SmartDrive_STATUS_M1);
  363. if ( motor_number != Motor_ID_1 )
  364. result_2 = readByte(SmartDrive_STATUS_M2);
  365. //look for both time bits to be zero
  366. return (((result_1 & 0x08) == 0) && ((result_2 & 0x08) == 0) );
  367. }
  368.  
  369.  
  370. void
  371. SmartDrive::SetPerformanceParameters( uint16_t Kp_tacho, uint16_t Ki_tacho, uint16_t Kd_tacho, uint16_t Kp_speed, uint16_t Ki_speed, uint16_t Kd_speed, uint8_t passcount, uint8_t tolerance) {
  372. uint8_t Kp_t1 = Kp_tacho%0x100;
  373. uint8_t Kp_t2 = Kp_tacho/0x100;
  374. uint8_t Ki_t1 = Ki_tacho%0x100;
  375. uint8_t Ki_t2 = Ki_tacho/0x100;
  376. uint8_t Kd_t1 = Kd_tacho%0x100;
  377. uint8_t Kd_t2 = Kd_tacho/0x100;
  378. uint8_t Kp_s1 = Kp_speed%0x100;
  379. uint8_t Kp_s2 = Kp_speed/0x100;
  380. uint8_t Ki_s1 = Ki_speed%0x100;
  381. uint8_t Ki_s2 = Ki_speed/0x100;
  382. uint8_t Kd_s1 = Kd_speed%0x100;
  383. uint8_t Kd_s2 = Kd_speed/0x100;
  384.  
  385. uint8_t array[15] = {SmartDrive_P_Kp, Kp_t1 , Kp_t2 , Ki_t1, Ki_t2, Kd_t1, Kd_t2, Kp_s1, Kp_s2, Ki_s1, Ki_s2, Kd_s1, Kd_s2, passcount, tolerance};
  386. writeArray(array,15);
  387. }
  388.  
  389.  
  390. void
  391. SmartDrive::ReadPerformanceParameters() {
  392. try {
  393. std::cout << "Pkp: " << readInteger(SmartDrive_P_Kp) << std::endl;
  394. std::cout << "Pki: " << readInteger(SmartDrive_P_Ki) << std::endl;
  395. std::cout << "Pkd: " << readInteger(SmartDrive_P_Kd) << std::endl;
  396. std::cout << "Skp: " << readInteger(SmartDrive_S_Kp) << std::endl;
  397. std::cout << "Ski: " << readInteger(SmartDrive_S_Ki) << std::endl;
  398. std::cout << "Skd: " << readInteger(SmartDrive_S_Kd) << std::endl;
  399. std::cout << "Passcount: " << SmartDrive_PASSCOUNT << std::endl; //ToDo : Check if these should actually be Register Reads !!
  400. std::cout << "Tolerance: " << SmartDrive_PASSTOLERANCE << std::endl;
  401. } catch( int e) {
  402. std::cout << "Error: Could not read PID values -> " << e << std::endl;
  403. }
  404. }
  405.  
  406. uint8_t
  407. SmartDrive::GetMotorStatus(MotorID_t motor_id) {
  408. uint8_t status=0;
  409. if (motor_id == Motor_ID_1)
  410. status = readByte(SmartDrive_STATUS_M1);
  411. if (motor_id == Motor_ID_2)
  412. status = readByte(SmartDrive_STATUS_M1);
  413. if (motor_id == Motor_ID_BOTH) {
  414. std::cout << "Please specifiy which motor's status you want to fetch !" << std::endl;
  415. }
  416. return status;
  417. }
  418.  
  419. void
  420. SmartDrive::PrintMotorStatus(MotorID_t motor_id) {
  421. if (motor_id != Motor_ID_BOTH) {
  422. uint8_t status = GetMotorStatus(motor_id);
  423. uint8_t control_on = (status & SmartDrive_MOTOR_CONTROL_ON);
  424. uint8_t is_ramping = (status & SmartDrive_MOTOR_IS_RAMPING);
  425. uint8_t is_powered = (status & SmartDrive_MOTOR_IS_POWERED);
  426. uint8_t pos_control_on = (status & SmartDrive_MOTOR_POS_CTRL_ON);
  427. uint8_t in_brake_mode = (status & SmartDrive_MOTOR_IN_BRAKE_MODE);
  428. uint8_t is_overloaded = (status & SmartDrive_MOTOR_OVERLOADED);
  429. uint8_t in_time_mode = (status & SmartDrive_MOTOR_IN_TIME_MODE);
  430. uint8_t is_stalled = (status & SmartDrive_MOTOR_IS_STALLED);
  431.  
  432. std::cout << "Motor " << motor_id+1 << " is programemd to move at " << ( (control_on == 0) ? "variable" : "fixed") << " speed" << std::endl;
  433. std::cout << "Motor " << motor_id+1 << " is " << ((is_ramping == 0) ? "NOT" : "") << " ramping" << std::endl;
  434. std::cout << "Motor " << motor_id+1 << " is " << ((is_powered == 0) ? "NOT" : "") << " powered" << std::endl;
  435. std::cout << "Motor " << motor_id+1 << " is " << ((pos_control_on == 0) ? "moving towards desired encoder " : "holding it ") << "position" << std::endl;
  436. std::cout << "Motor " << motor_id+1 << " is in " << ((in_brake_mode == 0) ? "brake" : "float") << " mode" << std::endl;
  437. std::cout << "Motor " << motor_id+1 << " is " << ((is_overloaded == 0) ? "NOT" : "") << " overloaded" << std::endl;
  438. std::cout << "Motor " << motor_id+1 << " is " << ((in_time_mode == 0) ? "NOT" : "") << " in time mode" << std::endl;
  439. std::cout << "Motor " << motor_id+1 << " is " << ((is_stalled == 0) ? "NOT" : "") << " stalled" << std::endl;
  440.  
  441. } else {
  442. std::cout << "Please specifiy which motor's status you want to fetch !" << std::endl;
  443. }
  444. }
Add Comment
Please, Sign In to add comment