My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

L6470.cpp 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. ////////////////////////////////////////////////////////////
  2. //ORIGINAL CODE 12/12/2011- Mike Hord, SparkFun Electronics
  3. //LIBRARY Created by Adam Meyer of bildr Aug 18th 2012
  4. //Released as MIT license
  5. ////////////////////////////////////////////////////////////
  6. #include <Arduino.h>
  7. #include "L6470.h"
  8. #include <SPI.h>
  9. #define ENABLE_RESET_PIN 0
  10. #define K_VALUE 100
  11. L6470::L6470(int SSPin){
  12. _SSPin = SSPin;
  13. // Serial.begin(9600);
  14. }
  15. void L6470::init(int k_value){
  16. // This is the generic initialization function to set up the Arduino to
  17. // communicate with the dSPIN chip.
  18. // set up the input/output pins for the application.
  19. pinMode(SLAVE_SELECT_PIN, OUTPUT); // The SPI peripheral REQUIRES the hardware SS pin-
  20. // pin 10- to be an output. This is in here just
  21. // in case some future user makes something other
  22. // than pin 10 the SS pin.
  23. pinMode(_SSPin, OUTPUT);
  24. digitalWrite(_SSPin, HIGH);
  25. pinMode(MOSI, OUTPUT);
  26. pinMode(MISO, INPUT);
  27. pinMode(SCK, OUTPUT);
  28. pinMode(BUSYN, INPUT);
  29. #if (ENABLE_RESET_PIN == 1)
  30. pinMode(RESET, OUTPUT);
  31. // reset the dSPIN chip. This could also be accomplished by
  32. // calling the "L6470::ResetDev()" function after SPI is initialized.
  33. digitalWrite(RESET, HIGH);
  34. delay(10);
  35. digitalWrite(RESET, LOW);
  36. delay(10);
  37. digitalWrite(RESET, HIGH);
  38. delay(10);
  39. #endif
  40. // initialize SPI for the dSPIN chip's needs:
  41. // most significant bit first,
  42. // SPI clock not to exceed 5MHz,
  43. // SPI_MODE3 (clock idle high, latch data on rising edge of clock)
  44. SPI.begin();
  45. SPI.setBitOrder(MSBFIRST);
  46. SPI.setClockDivider(SPI_CLOCK_DIV16); // or 2, 8, 16, 32, 64
  47. SPI.setDataMode(SPI_MODE3);
  48. // First things first: let's check communications. The CONFIG register should
  49. // power up to 0x2E88, so we can use that to check the communications.
  50. if (GetParam(CONFIG) == 0x2E88){
  51. //Serial.println('good to go');
  52. }
  53. else{
  54. //Serial.println('Comm issue');
  55. }
  56. #if (ENABLE_RESET_PIN == 0)
  57. resetDev();
  58. #endif
  59. // First, let's set the step mode register:
  60. // - SYNC_EN controls whether the BUSY/SYNC pin reflects the step
  61. // frequency or the BUSY status of the chip. We want it to be the BUSY
  62. // status.
  63. // - STEP_SEL_x is the microstepping rate- we'll go full step.
  64. // - SYNC_SEL_x is the ratio of (micro)steps to toggles on the
  65. // BUSY/SYNC pin (when that pin is used for SYNC). Make it 1:1, despite
  66. // not using that pin.
  67. //SetParam(STEP_MODE, !SYNC_EN | STEP_SEL_1 | SYNC_SEL_1);
  68. SetParam(KVAL_RUN, k_value);
  69. SetParam(KVAL_ACC, k_value);
  70. SetParam(KVAL_DEC, k_value);
  71. SetParam(KVAL_HOLD, k_value);
  72. // Set up the CONFIG register as follows:
  73. // PWM frequency divisor = 1
  74. // PWM frequency multiplier = 2 (62.5kHz PWM frequency)
  75. // Slew rate is 290V/us
  76. // Do NOT shut down bridges on overcurrent
  77. // Disable motor voltage compensation
  78. // Hard stop on switch low
  79. // 16MHz internal oscillator, nothing on output
  80. SetParam(CONFIG, CONFIG_PWM_DIV_1 | CONFIG_PWM_MUL_2 | CONFIG_SR_290V_us| CONFIG_OC_SD_DISABLE | CONFIG_VS_COMP_DISABLE | CONFIG_SW_HARD_STOP | CONFIG_INT_16MHZ);
  81. // Configure the RUN KVAL. This defines the duty cycle of the PWM of the bridges
  82. // during running. 0xFF means that they are essentially NOT PWMed during run; this
  83. // MAY result in more power being dissipated than you actually need for the task.
  84. // Setting this value too low may result in failure to turn.
  85. // There are ACC, DEC, and HOLD KVAL registers as well; you may need to play with
  86. // those values to get acceptable performance for a given application.
  87. //SetParam(KVAL_RUN, 0xFF);
  88. // Calling GetStatus() clears the UVLO bit in the status register, which is set by
  89. // default on power-up. The driver may not run without that bit cleared by this
  90. // read operation.
  91. getStatus();
  92. hardStop(); //engage motors
  93. }
  94. boolean L6470::isBusy(){
  95. int status = getStatus();
  96. return !((status >> 1) & 0b1);
  97. }
  98. void L6470::setMicroSteps(int microSteps){
  99. byte stepVal = 0;
  100. for(stepVal = 0; stepVal < 8; stepVal++){
  101. if(microSteps == 1) break;
  102. microSteps = microSteps >> 1;
  103. }
  104. SetParam(STEP_MODE, !SYNC_EN | stepVal | SYNC_SEL_1);
  105. }
  106. void L6470::setThresholdSpeed(float thresholdSpeed){
  107. // Configure the FS_SPD register- this is the speed at which the driver ceases
  108. // microstepping and goes to full stepping. FSCalc() converts a value in steps/s
  109. // to a value suitable for this register; to disable full-step switching, you
  110. // can pass 0x3FF to this register.
  111. if(thresholdSpeed == 0.0){
  112. SetParam(FS_SPD, 0x3FF);
  113. }
  114. else{
  115. SetParam(FS_SPD, FSCalc(thresholdSpeed));
  116. }
  117. }
  118. void L6470::setCurrent(int current){}
  119. void L6470::setMaxSpeed(int speed){
  120. // Configure the MAX_SPEED register- this is the maximum number of (micro)steps per
  121. // second allowed. You'll want to mess around with your desired application to see
  122. // how far you can push it before the motor starts to slip. The ACTUAL parameter
  123. // passed to this function is in steps/tick; MaxSpdCalc() will convert a number of
  124. // steps/s into an appropriate value for this function. Note that for any move or
  125. // goto type function where no speed is specified, this value will be used.
  126. SetParam(MAX_SPEED, MaxSpdCalc(speed));
  127. }
  128. void L6470::setMinSpeed(int speed){
  129. // Configure the MAX_SPEED register- this is the maximum number of (micro)steps per
  130. // second allowed. You'll want to mess around with your desired application to see
  131. // how far you can push it before the motor starts to slip. The ACTUAL parameter
  132. // passed to this function is in steps/tick; MaxSpdCalc() will convert a number of
  133. // steps/s into an appropriate value for this function. Note that for any move or
  134. // goto type function where no speed is specified, this value will be used.
  135. SetParam(MIN_SPEED, MinSpdCalc(speed));
  136. }
  137. void L6470::setAcc(float acceleration){
  138. // Configure the acceleration rate, in steps/tick/tick. There is also a DEC register;
  139. // both of them have a function (AccCalc() and DecCalc() respectively) that convert
  140. // from steps/s/s into the appropriate value for the register. Writing ACC to 0xfff
  141. // sets the acceleration and deceleration to 'infinite' (or as near as the driver can
  142. // manage). If ACC is set to 0xfff, DEC is ignored. To get infinite deceleration
  143. // without infinite acceleration, only hard stop will work.
  144. unsigned long accelerationBYTES = AccCalc(acceleration);
  145. SetParam(ACC, accelerationBYTES);
  146. }
  147. void L6470::setDec(float deceleration){
  148. unsigned long decelerationBYTES = DecCalc(deceleration);
  149. SetParam(DEC, decelerationBYTES);
  150. }
  151. long L6470::getPos(){
  152. unsigned long position = GetParam(ABS_POS);
  153. return convert(position);
  154. }
  155. float L6470::getSpeed(){
  156. /*
  157. SPEED
  158. The SPEED register contains the current motor speed, expressed in step/tick (format unsigned fixed point 0.28).
  159. In order to convert the SPEED value in step/s the following formula can be used:
  160. Equation 4
  161. where SPEED is the integer number stored into the register and tick is 250 ns.
  162. The available range is from 0 to 15625 step/s with a resolution of 0.015 step/s.
  163. Note: The range effectively available to the user is limited by the MAX_SPEED parameter.
  164. */
  165. return (float) GetParam(SPEED);
  166. //return (float) speed * pow(8, -22);
  167. //return FSCalc(speed); NEEDS FIX
  168. }
  169. void L6470::setOverCurrent(unsigned int ma_current){
  170. // Configure the overcurrent detection threshold.
  171. byte OCValue = floor(ma_current / 375);
  172. if(OCValue > 0x0F)OCValue = 0x0F;
  173. SetParam(OCD_TH, OCValue);
  174. }
  175. void L6470::setStallCurrent(float ma_current){
  176. byte STHValue = (byte)floor(ma_current / 31.25);
  177. if(STHValue > 0x80)STHValue = 0x80;
  178. if(STHValue < 0)STHValue = 0;
  179. SetParam(STALL_TH, STHValue);
  180. }
  181. void L6470::SetLowSpeedOpt(boolean enable){
  182. // Enable or disable the low-speed optimization option. If enabling,
  183. // the other 12 bits of the register will be automatically zero.
  184. // When disabling, the value will have to be explicitly written by
  185. // the user with a SetParam() call. See the datasheet for further
  186. // information about low-speed optimization.
  187. Xfer(SET_PARAM | MIN_SPEED);
  188. if (enable) Param(0x1000, 13);
  189. else Param(0, 13);
  190. }
  191. void L6470::run(byte dir, float spd){
  192. // RUN sets the motor spinning in a direction (defined by the constants
  193. // FWD and REV). Maximum speed and minimum speed are defined
  194. // by the MAX_SPEED and MIN_SPEED registers; exceeding the FS_SPD value
  195. // will switch the device into full-step mode.
  196. // The SpdCalc() function is provided to convert steps/s values into
  197. // appropriate integer values for this function.
  198. unsigned long speedVal = SpdCalc(spd);
  199. Xfer(RUN | dir);
  200. if (speedVal > 0xFFFFF) speedVal = 0xFFFFF;
  201. Xfer((byte)(speedVal >> 16));
  202. Xfer((byte)(speedVal >> 8));
  203. Xfer((byte)(speedVal));
  204. }
  205. void L6470::Step_Clock(byte dir){
  206. // STEP_CLOCK puts the device in external step clocking mode. When active,
  207. // pin 25, STCK, becomes the step clock for the device, and steps it in
  208. // the direction (set by the FWD and REV constants) imposed by the call
  209. // of this function. Motion commands (RUN, MOVE, etc) will cause the device
  210. // to exit step clocking mode.
  211. Xfer(STEP_CLOCK | dir);
  212. }
  213. void L6470::move(long n_step){
  214. // MOVE will send the motor n_step steps (size based on step mode) in the
  215. // direction imposed by dir (FWD or REV constants may be used). The motor
  216. // will accelerate according the acceleration and deceleration curves, and
  217. // will run at MAX_SPEED. Stepping mode will adhere to FS_SPD value, as well.
  218. byte dir;
  219. if(n_step >= 0){
  220. dir = FWD;
  221. }
  222. else{
  223. dir = REV;
  224. }
  225. long n_stepABS = abs(n_step);
  226. Xfer(MOVE | dir); //set direction
  227. if (n_stepABS > 0x3FFFFF) n_step = 0x3FFFFF;
  228. Xfer((byte)(n_stepABS >> 16));
  229. Xfer((byte)(n_stepABS >> 8));
  230. Xfer((byte)(n_stepABS));
  231. }
  232. void L6470::goTo(long pos){
  233. // GOTO operates much like MOVE, except it produces absolute motion instead
  234. // of relative motion. The motor will be moved to the indicated position
  235. // in the shortest possible fashion.
  236. Xfer(GOTO);
  237. if (pos > 0x3FFFFF) pos = 0x3FFFFF;
  238. Xfer((byte)(pos >> 16));
  239. Xfer((byte)(pos >> 8));
  240. Xfer((byte)(pos));
  241. }
  242. void L6470::goTo_DIR(byte dir, long pos){
  243. // Same as GOTO, but with user constrained rotational direction.
  244. Xfer(GOTO_DIR);
  245. if (pos > 0x3FFFFF) pos = 0x3FFFFF;
  246. Xfer((byte)(pos >> 16));
  247. Xfer((byte)(pos >> 8));
  248. Xfer((byte)(pos));
  249. }
  250. void L6470::goUntil(byte act, byte dir, unsigned long spd){
  251. // GoUntil will set the motor running with direction dir (REV or
  252. // FWD) until a falling edge is detected on the SW pin. Depending
  253. // on bit SW_MODE in CONFIG, either a hard stop or a soft stop is
  254. // performed at the falling edge, and depending on the value of
  255. // act (either RESET or COPY) the value in the ABS_POS register is
  256. // either RESET to 0 or COPY-ed into the MARK register.
  257. Xfer(GO_UNTIL | act | dir);
  258. if (spd > 0x3FFFFF) spd = 0x3FFFFF;
  259. Xfer((byte)(spd >> 16));
  260. Xfer((byte)(spd >> 8));
  261. Xfer((byte)(spd));
  262. }
  263. void L6470::releaseSW(byte act, byte dir){
  264. // Similar in nature to GoUntil, ReleaseSW produces motion at the
  265. // higher of two speeds: the value in MIN_SPEED or 5 steps/s.
  266. // The motor continues to run at this speed until a rising edge
  267. // is detected on the switch input, then a hard stop is performed
  268. // and the ABS_POS register is either COPY-ed into MARK or RESET to
  269. // 0, depending on whether RESET or COPY was passed to the function
  270. // for act.
  271. Xfer(RELEASE_SW | act | dir);
  272. }
  273. void L6470::goHome(){
  274. // GoHome is equivalent to GoTo(0), but requires less time to send.
  275. // Note that no direction is provided; motion occurs through shortest
  276. // path. If a direction is required, use GoTo_DIR().
  277. Xfer(GO_HOME);
  278. }
  279. void L6470::goMark(){
  280. // GoMark is equivalent to GoTo(MARK), but requires less time to send.
  281. // Note that no direction is provided; motion occurs through shortest
  282. // path. If a direction is required, use GoTo_DIR().
  283. Xfer(GO_MARK);
  284. }
  285. void L6470::setMark(long value){
  286. Xfer(MARK);
  287. if (value > 0x3FFFFF) value = 0x3FFFFF;
  288. if (value < -0x3FFFFF) value = -0x3FFFFF;
  289. Xfer((byte)(value >> 16));
  290. Xfer((byte)(value >> 8));
  291. Xfer((byte)(value));
  292. }
  293. void L6470::setMark(){
  294. long value = getPos();
  295. Xfer(MARK);
  296. if (value > 0x3FFFFF) value = 0x3FFFFF;
  297. if (value < -0x3FFFFF) value = -0x3FFFFF;
  298. Xfer((byte)(value >> 16));
  299. Xfer((byte)(value >> 8));
  300. Xfer((byte)(value));
  301. }
  302. void L6470::setAsHome(){
  303. // Sets the ABS_POS register to 0, effectively declaring the current
  304. // position to be "HOME".
  305. Xfer(RESET_POS);
  306. }
  307. void L6470::resetDev(){
  308. // Reset device to power up conditions. Equivalent to toggling the STBY
  309. // pin or cycling power.
  310. Xfer(RESET_DEVICE);
  311. }
  312. void L6470::softStop(){
  313. // Bring the motor to a halt using the deceleration curve.
  314. Xfer(SOFT_STOP);
  315. }
  316. void L6470::hardStop(){
  317. // Stop the motor right away. No deceleration.
  318. Xfer(HARD_STOP);
  319. }
  320. void L6470::softFree(){
  321. // Decelerate the motor and disengage
  322. Xfer(SOFT_HIZ);
  323. }
  324. void L6470::free(){
  325. // disengage the motor immediately with no deceleration.
  326. Xfer(HARD_HIZ);
  327. }
  328. int L6470::getStatus(){
  329. // Fetch and return the 16-bit value in the STATUS register. Resets
  330. // any warning flags and exits any error states. Using GetParam()
  331. // to read STATUS does not clear these values.
  332. int temp = 0;
  333. Xfer(GET_STATUS);
  334. temp = Xfer(0)<<8;
  335. temp |= Xfer(0);
  336. return temp;
  337. }
  338. unsigned long L6470::AccCalc(float stepsPerSecPerSec){
  339. // The value in the ACC register is [(steps/s/s)*(tick^2)]/(2^-40) where tick is
  340. // 250ns (datasheet value)- 0x08A on boot.
  341. // Multiply desired steps/s/s by .137438 to get an appropriate value for this register.
  342. // This is a 12-bit value, so we need to make sure the value is at or below 0xFFF.
  343. float temp = stepsPerSecPerSec * 0.137438;
  344. if( (unsigned long) long(temp) > 0x00000FFF) return 0x00000FFF;
  345. else return (unsigned long) long(temp);
  346. }
  347. unsigned long L6470::DecCalc(float stepsPerSecPerSec){
  348. // The calculation for DEC is the same as for ACC. Value is 0x08A on boot.
  349. // This is a 12-bit value, so we need to make sure the value is at or below 0xFFF.
  350. float temp = stepsPerSecPerSec * 0.137438;
  351. if( (unsigned long) long(temp) > 0x00000FFF) return 0x00000FFF;
  352. else return (unsigned long) long(temp);
  353. }
  354. unsigned long L6470::MaxSpdCalc(float stepsPerSec){
  355. // The value in the MAX_SPD register is [(steps/s)*(tick)]/(2^-18) where tick is
  356. // 250ns (datasheet value)- 0x041 on boot.
  357. // Multiply desired steps/s by .065536 to get an appropriate value for this register
  358. // This is a 10-bit value, so we need to make sure it remains at or below 0x3FF
  359. float temp = stepsPerSec * .065536;
  360. if( (unsigned long) long(temp) > 0x000003FF) return 0x000003FF;
  361. else return (unsigned long) long(temp);
  362. }
  363. unsigned long L6470::MinSpdCalc(float stepsPerSec){
  364. // The value in the MIN_SPD register is [(steps/s)*(tick)]/(2^-24) where tick is
  365. // 250ns (datasheet value)- 0x000 on boot.
  366. // Multiply desired steps/s by 4.1943 to get an appropriate value for this register
  367. // This is a 12-bit value, so we need to make sure the value is at or below 0xFFF.
  368. float temp = stepsPerSec * 4.1943;
  369. if( (unsigned long) long(temp) > 0x00000FFF) return 0x00000FFF;
  370. else return (unsigned long) long(temp);
  371. }
  372. unsigned long L6470::FSCalc(float stepsPerSec){
  373. // The value in the FS_SPD register is ([(steps/s)*(tick)]/(2^-18))-0.5 where tick is
  374. // 250ns (datasheet value)- 0x027 on boot.
  375. // Multiply desired steps/s by .065536 and subtract .5 to get an appropriate value for this register
  376. // This is a 10-bit value, so we need to make sure the value is at or below 0x3FF.
  377. float temp = (stepsPerSec * .065536)-.5;
  378. if( (unsigned long) long(temp) > 0x000003FF) return 0x000003FF;
  379. else return (unsigned long) long(temp);
  380. }
  381. unsigned long L6470::IntSpdCalc(float stepsPerSec){
  382. // The value in the INT_SPD register is [(steps/s)*(tick)]/(2^-24) where tick is
  383. // 250ns (datasheet value)- 0x408 on boot.
  384. // Multiply desired steps/s by 4.1943 to get an appropriate value for this register
  385. // This is a 14-bit value, so we need to make sure the value is at or below 0x3FFF.
  386. float temp = stepsPerSec * 4.1943;
  387. if( (unsigned long) long(temp) > 0x00003FFF) return 0x00003FFF;
  388. else return (unsigned long) long(temp);
  389. }
  390. unsigned long L6470::SpdCalc(float stepsPerSec){
  391. // When issuing RUN command, the 20-bit speed is [(steps/s)*(tick)]/(2^-28) where tick is
  392. // 250ns (datasheet value).
  393. // Multiply desired steps/s by 67.106 to get an appropriate value for this register
  394. // This is a 20-bit value, so we need to make sure the value is at or below 0xFFFFF.
  395. float temp = stepsPerSec * 67.106;
  396. if( (unsigned long) long(temp) > 0x000FFFFF) return 0x000FFFFF;
  397. else return (unsigned long)temp;
  398. }
  399. unsigned long L6470::Param(unsigned long value, byte bit_len){
  400. // Generalization of the subsections of the register read/write functionality.
  401. // We want the end user to just write the value without worrying about length,
  402. // so we pass a bit length parameter from the calling function.
  403. unsigned long ret_val=0; // We'll return this to generalize this function
  404. // for both read and write of registers.
  405. byte byte_len = bit_len/8; // How many BYTES do we have?
  406. if (bit_len%8 > 0) byte_len++; // Make sure not to lose any partial byte values.
  407. // Let's make sure our value has no spurious bits set, and if the value was too
  408. // high, max it out.
  409. unsigned long mask = 0xffffffff >> (32-bit_len);
  410. if (value > mask) value = mask;
  411. // The following three if statements handle the various possible byte length
  412. // transfers- it'll be no less than 1 but no more than 3 bytes of data.
  413. // L6470::Xfer() sends a byte out through SPI and returns a byte received
  414. // over SPI- when calling it, we typecast a shifted version of the masked
  415. // value, then we shift the received value back by the same amount and
  416. // store it until return time.
  417. if (byte_len == 3) {
  418. ret_val |= long(Xfer((byte)(value>>16))) << 16;
  419. //Serial.println(ret_val, HEX);
  420. }
  421. if (byte_len >= 2) {
  422. ret_val |= long(Xfer((byte)(value>>8))) << 8;
  423. //Serial.println(ret_val, HEX);
  424. }
  425. if (byte_len >= 1) {
  426. ret_val |= Xfer((byte)value);
  427. //Serial.println(ret_val, HEX);
  428. }
  429. // Return the received values. Mask off any unnecessary bits, just for
  430. // the sake of thoroughness- we don't EXPECT to see anything outside
  431. // the bit length range but better to be safe than sorry.
  432. return (ret_val & mask);
  433. }
  434. byte L6470::Xfer(byte data){
  435. // This simple function shifts a byte out over SPI and receives a byte over
  436. // SPI. Unusually for SPI devices, the dSPIN requires a toggling of the
  437. // CS (slaveSelect) pin after each byte sent. That makes this function
  438. // a bit more reasonable, because we can include more functionality in it.
  439. byte data_out;
  440. digitalWrite(_SSPin,LOW);
  441. // SPI.transfer() both shifts a byte out on the MOSI pin AND receives a
  442. // byte in on the MISO pin.
  443. data_out = SPI.transfer(data);
  444. digitalWrite(_SSPin,HIGH);
  445. return data_out;
  446. }
  447. void L6470::SetParam(byte param, unsigned long value){
  448. Xfer(SET_PARAM | param);
  449. ParamHandler(param, value);
  450. }
  451. unsigned long L6470::GetParam(byte param){
  452. // Realize the "get parameter" function, to read from the various registers in
  453. // the dSPIN chip.
  454. Xfer(GET_PARAM | param);
  455. return ParamHandler(param, 0);
  456. }
  457. long L6470::convert(unsigned long val){
  458. //convert 22bit 2s comp to signed long
  459. int MSB = val >> 21;
  460. val = val << 11;
  461. val = val >> 11;
  462. if(MSB == 1) val = val | 0b11111111111000000000000000000000;
  463. return val;
  464. }
  465. unsigned long L6470::ParamHandler(byte param, unsigned long value){
  466. // Much of the functionality between "get parameter" and "set parameter" is
  467. // very similar, so we deal with that by putting all of it in one function
  468. // here to save memory space and simplify the program.
  469. unsigned long ret_val = 0; // This is a temp for the value to return.
  470. // This switch structure handles the appropriate action for each register.
  471. // This is necessary since not all registers are of the same length, either
  472. // bit-wise or byte-wise, so we want to make sure we mask out any spurious
  473. // bits and do the right number of transfers. That is handled by the dSPIN_Param()
  474. // function, in most cases, but for 1-byte or smaller transfers, we call
  475. // Xfer() directly.
  476. switch (param)
  477. {
  478. // ABS_POS is the current absolute offset from home. It is a 22 bit number expressed
  479. // in two's complement. At power up, this value is 0. It cannot be written when
  480. // the motor is running, but at any other time, it can be updated to change the
  481. // interpreted position of the motor.
  482. case ABS_POS:
  483. ret_val = Param(value, 22);
  484. break;
  485. // EL_POS is the current electrical position in the step generation cycle. It can
  486. // be set when the motor is not in motion. Value is 0 on power up.
  487. case EL_POS:
  488. ret_val = Param(value, 9);
  489. break;
  490. // MARK is a second position other than 0 that the motor can be told to go to. As
  491. // with ABS_POS, it is 22-bit two's complement. Value is 0 on power up.
  492. case MARK:
  493. ret_val = Param(value, 22);
  494. break;
  495. // SPEED contains information about the current speed. It is read-only. It does
  496. // NOT provide direction information.
  497. case SPEED:
  498. ret_val = Param(0, 20);
  499. break;
  500. // ACC and DEC set the acceleration and deceleration rates. Set ACC to 0xFFF
  501. // to get infinite acceleration/decelaeration- there is no way to get infinite
  502. // deceleration w/o infinite acceleration (except the HARD STOP command).
  503. // Cannot be written while motor is running. Both default to 0x08A on power up.
  504. // AccCalc() and DecCalc() functions exist to convert steps/s/s values into
  505. // 12-bit values for these two registers.
  506. case ACC:
  507. ret_val = Param(value, 12);
  508. break;
  509. case DEC:
  510. ret_val = Param(value, 12);
  511. break;
  512. // MAX_SPEED is just what it says- any command which attempts to set the speed
  513. // of the motor above this value will simply cause the motor to turn at this
  514. // speed. Value is 0x041 on power up.
  515. // MaxSpdCalc() function exists to convert steps/s value into a 10-bit value
  516. // for this register.
  517. case MAX_SPEED:
  518. ret_val = Param(value, 10);
  519. break;
  520. // MIN_SPEED controls two things- the activation of the low-speed optimization
  521. // feature and the lowest speed the motor will be allowed to operate at. LSPD_OPT
  522. // is the 13th bit, and when it is set, the minimum allowed speed is automatically
  523. // set to zero. This value is 0 on startup.
  524. // MinSpdCalc() function exists to convert steps/s value into a 12-bit value for this
  525. // register. SetLowSpeedOpt() function exists to enable/disable the optimization feature.
  526. case MIN_SPEED:
  527. ret_val = Param(value, 12);
  528. break;
  529. // FS_SPD register contains a threshold value above which microstepping is disabled
  530. // and the dSPIN operates in full-step mode. Defaults to 0x027 on power up.
  531. // FSCalc() function exists to convert steps/s value into 10-bit integer for this
  532. // register.
  533. case FS_SPD:
  534. ret_val = Param(value, 10);
  535. break;
  536. // KVAL is the maximum voltage of the PWM outputs. These 8-bit values are ratiometric
  537. // representations: 255 for full output voltage, 128 for half, etc. Default is 0x29.
  538. // The implications of different KVAL settings is too complex to dig into here, but
  539. // it will usually work to max the value for RUN, ACC, and DEC. Maxing the value for
  540. // HOLD may result in excessive power dissipation when the motor is not running.
  541. case KVAL_HOLD:
  542. ret_val = Xfer((byte)value);
  543. break;
  544. case KVAL_RUN:
  545. ret_val = Xfer((byte)value);
  546. break;
  547. case KVAL_ACC:
  548. ret_val = Xfer((byte)value);
  549. break;
  550. case KVAL_DEC:
  551. ret_val = Xfer((byte)value);
  552. break;
  553. // INT_SPD, ST_SLP, FN_SLP_ACC and FN_SLP_DEC are all related to the back EMF
  554. // compensation functionality. Please see the datasheet for details of this
  555. // function- it is too complex to discuss here. Default values seem to work
  556. // well enough.
  557. case INT_SPD:
  558. ret_val = Param(value, 14);
  559. break;
  560. case ST_SLP:
  561. ret_val = Xfer((byte)value);
  562. break;
  563. case FN_SLP_ACC:
  564. ret_val = Xfer((byte)value);
  565. break;
  566. case FN_SLP_DEC:
  567. ret_val = Xfer((byte)value);
  568. break;
  569. // K_THERM is motor winding thermal drift compensation. Please see the datasheet
  570. // for full details on operation- the default value should be okay for most users.
  571. case K_THERM:
  572. ret_val = Xfer((byte)value & 0x0F);
  573. break;
  574. // ADC_OUT is a read-only register containing the result of the ADC measurements.
  575. // This is less useful than it sounds; see the datasheet for more information.
  576. case ADC_OUT:
  577. ret_val = Xfer(0);
  578. break;
  579. // Set the overcurrent threshold. Ranges from 375mA to 6A in steps of 375mA.
  580. // A set of defined constants is provided for the user's convenience. Default
  581. // value is 3.375A- 0x08. This is a 4-bit value.
  582. case OCD_TH:
  583. ret_val = Xfer((byte)value & 0x0F);
  584. break;
  585. // Stall current threshold. Defaults to 0x40, or 2.03A. Value is from 31.25mA to
  586. // 4A in 31.25mA steps. This is a 7-bit value.
  587. case STALL_TH:
  588. ret_val = Xfer((byte)value & 0x7F);
  589. break;
  590. // STEP_MODE controls the microstepping settings, as well as the generation of an
  591. // output signal from the dSPIN. Bits 2:0 control the number of microsteps per
  592. // step the part will generate. Bit 7 controls whether the BUSY/SYNC pin outputs
  593. // a BUSY signal or a step synchronization signal. Bits 6:4 control the frequency
  594. // of the output signal relative to the full-step frequency; see datasheet for
  595. // that relationship as it is too complex to reproduce here.
  596. // Most likely, only the microsteps per step value will be needed; there is a set
  597. // of constants provided for ease of use of these values.
  598. case STEP_MODE:
  599. ret_val = Xfer((byte)value);
  600. break;
  601. // ALARM_EN controls which alarms will cause the FLAG pin to fall. A set of constants
  602. // is provided to make this easy to interpret. By default, ALL alarms will trigger the
  603. // FLAG pin.
  604. case ALARM_EN:
  605. ret_val = Xfer((byte)value);
  606. break;
  607. // CONFIG contains some assorted configuration bits and fields. A fairly comprehensive
  608. // set of reasonably self-explanatory constants is provided, but users should refer
  609. // to the datasheet before modifying the contents of this register to be certain they
  610. // understand the implications of their modifications. Value on boot is 0x2E88; this
  611. // can be a useful way to verify proper start up and operation of the dSPIN chip.
  612. case CONFIG:
  613. ret_val = Param(value, 16);
  614. break;
  615. // STATUS contains read-only information about the current condition of the chip. A
  616. // comprehensive set of constants for masking and testing this register is provided, but
  617. // users should refer to the datasheet to ensure that they fully understand each one of
  618. // the bits in the register.
  619. case STATUS: // STATUS is a read-only register
  620. ret_val = Param(0, 16);
  621. break;
  622. default:
  623. ret_val = Xfer((byte)(value));
  624. break;
  625. }
  626. return ret_val;
  627. }