HighPowerStepperDriver
HighPowerStepperDriver.h
Go to the documentation of this file.
1 // Copyright Pololu Corporation. For more information, see http://www.pololu.com/
2 
14 
15 #pragma once
16 
17 #include <Arduino.h>
18 #include <SPI.h>
19 
20 
22 enum class HPSDRegAddr : uint8_t
23 {
24  CTRL = 0x00,
25  TORQUE = 0x01,
26  OFF = 0x02,
27  BLANK = 0x03,
28  DECAY = 0x04,
29  STALL = 0x05,
30  DRIVE = 0x06,
31  STATUS = 0x07,
32 };
33 
34 
41 {
42 public:
46  void setChipSelectPin(uint8_t pin)
47  {
48  csPin = pin;
49  digitalWrite(csPin, LOW);
50  pinMode(csPin, OUTPUT);
51  }
52 
54  uint16_t readReg(uint8_t address)
55  {
56  // Read/write bit and register address are the first 4 bits of the first
57  // byte; data is in the remaining 4 bits of the first byte combined with
58  // the second byte (12 bits total).
59 
60  selectChip();
61  uint16_t dataOut = transfer((0x8 | (address & 0b111)) << 12);
62  deselectChip();
63  return dataOut & 0xFFF;
64  }
65 
67  uint16_t readReg(HPSDRegAddr address)
68  {
69  return readReg((uint8_t)address);
70  }
71 
73  void writeReg(uint8_t address, uint16_t value)
74  {
75  // Read/write bit and register address are the first 4 bits of the first
76  // byte; data is in the remaining 4 bits of the first byte combined with
77  // the second byte (12 bits total).
78 
79  selectChip();
80  transfer(((address & 0b111) << 12) | (value & 0xFFF));
81 
82  // The CS line must go low after writing for the value to actually take
83  // effect.
84  deselectChip();
85  }
86 
88  void writeReg(HPSDRegAddr address, uint16_t value)
89  {
90  writeReg((uint8_t)address, value);
91  }
92 
93 private:
94 
95  SPISettings settings = SPISettings(500000, MSBFIRST, SPI_MODE0);
96 
97  uint16_t transfer(uint16_t value)
98  {
99  return SPI.transfer16(value);
100  }
101 
102  void selectChip()
103  {
104  digitalWrite(csPin, HIGH);
105  SPI.beginTransaction(settings);
106  }
107 
108  void deselectChip()
109  {
110  SPI.endTransaction();
111  digitalWrite(csPin, LOW);
112  }
113 
114  uint8_t csPin;
115 };
116 
117 
119 enum class HPSDStepMode : uint16_t
120 {
121  MicroStep256 = 256,
122  MicroStep128 = 128,
123  MicroStep64 = 64,
124  MicroStep32 = 32,
125  MicroStep16 = 16,
126  MicroStep8 = 8,
127  MicroStep4 = 4,
128  MicroStep2 = 2,
129  MicroStep1 = 1,
130 };
131 
133 enum class HPSDDecayMode : uint8_t
134 {
135  Slow = 0b000,
136  SlowIncMixedDec = 0b001,
137  Fast = 0b010,
138  Mixed = 0b011,
139  SlowIncAutoMixedDec = 0b100,
140  AutoMixed = 0b101,
141 };
142 
148 enum class HPSDStatusBit : uint8_t
149 {
151  OTS = 0,
152 
154  AOCP = 1,
155 
157  BOCP = 2,
158 
160  APDF = 3,
161 
163  BPDF = 4,
164 
166  UVLO = 5,
167 
169  STD = 6,
170 
172  STDLAT = 7,
173 };
174 
175 
179 {
180 public:
183  {
184  // All settings set to power-on defaults
185  ctrl = 0xC10;
186  torque = 0x1FF;
187  off = 0x030;
188  blank = 0x080;
189  decay = 0x110;
190  stall = 0x040;
191  drive = 0xA59;
192  }
193 
196  void setChipSelectPin(uint8_t pin)
197  {
199  }
200 
207  {
208  ctrl = 0xC10;
209  torque = 0x1FF;
210  off = 0x030;
211  blank = 0x080;
212  decay = 0x110;
213  stall = 0x040;
214  drive = 0xA59;
215  applySettings();
216  }
217 
228  {
229  // Bit 10 in TORQUE is write-only and will always read as 0.
230  return driver.readReg(HPSDRegAddr::CTRL) == ctrl &&
231  driver.readReg(HPSDRegAddr::TORQUE) == (torque & ~(1 << 10)) &&
232  driver.readReg(HPSDRegAddr::OFF) == off &&
233  driver.readReg(HPSDRegAddr::BLANK) == blank &&
234  driver.readReg(HPSDRegAddr::DECAY) == decay &&
235  driver.readReg(HPSDRegAddr::STALL) == stall &&
236  driver.readReg(HPSDRegAddr::DRIVE) == drive;
237  }
238 
247  {
248  writeTORQUE();
249  writeOFF();
250  writeBLANK();
251  writeDECAY();
252  writeDRIVE();
253  writeSTALL();
254 
255  // CTRL is written last because it contains the ENBL bit, and we want to try
256  // to have all the other settings correct first. (For example, TORQUE
257  // defaults to 0xFF (the maximum value), so it would be better to set a more
258  // appropriate value if necessary before enabling the motor.)
259  writeCTRL();
260  }
261 
264  {
265  ctrl |= (1 << 0);
266  writeCTRL();
267  }
268 
271  {
272  ctrl &= ~(1 << 0);
273  writeCTRL();
274  }
275 
282  void setDirection(bool value)
283  {
284  if (value)
285  {
286  ctrl |= (1 << 1);
287  }
288  else
289  {
290  ctrl &= ~(1 << 1);
291  }
292  writeCTRL();
293  }
294 
299  {
300  return ctrl >> 1 & 1;
301  }
302 
309  void step()
310  {
311  driver.writeReg(HPSDRegAddr::CTRL, ctrl | (1 << 2));
312  }
313 
328  {
329  // Pick 1/4 micro-step by default.
330  uint8_t sm = 0b0010;
331 
332  switch (mode)
333  {
334  case HPSDStepMode::MicroStep1: sm = 0b0000; break;
335  case HPSDStepMode::MicroStep2: sm = 0b0001; break;
336  case HPSDStepMode::MicroStep4: sm = 0b0010; break;
337  case HPSDStepMode::MicroStep8: sm = 0b0011; break;
338  case HPSDStepMode::MicroStep16: sm = 0b0100; break;
339  case HPSDStepMode::MicroStep32: sm = 0b0101; break;
340  case HPSDStepMode::MicroStep64: sm = 0b0110; break;
341  case HPSDStepMode::MicroStep128: sm = 0b0111; break;
342  case HPSDStepMode::MicroStep256: sm = 0b1000; break;
343  }
344 
345  ctrl = (ctrl & 0b111110000111) | (sm << 3);
346  writeCTRL();
347  }
348 
359  void setStepMode(uint16_t mode)
360  {
361  setStepMode((HPSDStepMode)mode);
362  }
363 
381  void setCurrentMilliamps36v4(uint16_t current)
382  {
383  if (current > 8000) { current = 8000; }
384 
385  // From the DRV8711 datasheet, section 7.3.4, equation 2:
386  //
387  // Ifs = (2.75 V * TORQUE) / (256 * ISGAIN * Risense)
388  //
389  // Rearranged:
390  //
391  // TORQUE = (256 * ISGAIN * Risense * Ifs) / 2.75 V
392  //
393  // The 36v4 has an Risense of 30 milliohms, and "current" is in milliamps,
394  // so:
395  //
396  // TORQUE = (256 * ISGAIN * (30/1000) ohms * (current/1000) A) / 2.75 V
397  // = (7680 * ISGAIN * current) / 2750000
398  //
399  // We want to pick the highest gain (5, 10, 20, or 40) that will not
400  // overflow TORQUE (8 bits, 0xFF max), so we start with a gain of 40 and
401  // calculate the TORQUE value needed.
402  uint8_t isgainBits = 0b11;
403  uint16_t torqueBits = ((uint32_t)768 * current) / 6875;
404 
405  // Halve the gain and TORQUE until the TORQUE value fits in 8 bits.
406  while (torqueBits > 0xFF)
407  {
408  isgainBits--;
409  torqueBits >>= 1;
410  }
411 
412  ctrl = (ctrl & 0b110011111111) | (isgainBits << 8);
413  writeCTRL();
414  torque = (torque & 0b111100000000) | torqueBits;
415  writeTORQUE();
416  }
417 
425  {
426  decay = (decay & 0b00011111111) | (((uint8_t)mode & 0b111) << 8);
427  writeDECAY();
428  }
429 
445  uint8_t readStatus()
446  {
447  return driver.readReg(HPSDRegAddr::STATUS);
448  }
449 
456  void clearStatus()
457  {
458  driver.writeReg(HPSDRegAddr::STATUS, 0);
459  }
460 
466  uint8_t readFaults()
467  {
468  return readStatus() & 0b00111111;
469  }
470 
480  void clearFaults()
481  {
482  driver.writeReg(HPSDRegAddr::STATUS, ~0b00111111);
483  }
484 
485 protected:
486 
487  uint16_t ctrl, torque, off, blank, decay, stall, drive;
488 
490  void writeCTRL()
491  {
492  driver.writeReg(HPSDRegAddr::CTRL, ctrl);
493  }
494 
496  void writeTORQUE()
497  {
498  driver.writeReg(HPSDRegAddr::TORQUE, torque);
499  }
500 
502  void writeOFF()
503  {
504  driver.writeReg(HPSDRegAddr::OFF, off);
505  }
506 
508  void writeBLANK()
509  {
510  driver.writeReg(HPSDRegAddr::BLANK, blank);
511  }
512 
514  void writeDECAY()
515  {
516  driver.writeReg(HPSDRegAddr::DECAY, decay);
517  }
518 
520  void writeSTALL()
521  {
522  driver.writeReg(HPSDRegAddr::STALL, stall);
523  }
524 
526  void writeDRIVE()
527  {
528  driver.writeReg(HPSDRegAddr::DRIVE, drive);
529  }
530 
531 public:
538 };
void setChipSelectPin(uint8_t pin)
uint16_t readReg(uint8_t address)
Reads the register at the given address and returns its raw value.
void writeDECAY()
Writes the cached value of the DECAY register to the device.
uint16_t readReg(HPSDRegAddr address)
Reads the register at the given address and returns its raw value.
Latched stall detect.
void writeCTRL()
Writes the cached value of the CTRL register to the device.
void writeOFF()
Writes the cached value of the OFF register to the device.
void enableDriver()
Enables the driver (ENBL = 1).
Channel A predriver fault.
void writeReg(HPSDRegAddr address, uint16_t value)
Writes the specified value to a register.
void disableDriver()
Disables the driver (ENBL = 0).
void writeTORQUE()
Writes the cached value of the TORQUE register to the device.
Channel A overcurrent shutdown.
Channel B overcurrent shutdown.
void setChipSelectPin(uint8_t pin)
Undervoltage lockout.
Stall detected.
Channel B predriver fault.
HPSDStepMode
Possible arguments to setStepMode().
void setStepMode(HPSDStepMode mode)
void writeBLANK()
Writes the cached value of the BLANK register to the device.
void writeDRIVE()
Writes the cached value of the DRIVE register to the device.
void setStepMode(uint16_t mode)
void writeReg(uint8_t address, uint16_t value)
Writes the specified value to a register.
void setDecayMode(HPSDDecayMode mode)
HighPowerStepperDriver()
The default constructor.
Overtemperature shutdown.
void writeSTALL()
Writes the cached value of the STALL register to the device.
HPSDDecayMode
Possible arguments to setDecayMode().
HPSDRegAddr
Addresses of control and status registers.
void setCurrentMilliamps36v4(uint16_t current)