HighPowerStepperDriver
Loading...
Searching...
No Matches
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
22enum 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{
42public:
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
93private:
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
119enum 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
133enum 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
148enum 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
173};
174
175
179{
180public:
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 {
198 driver.setChipSelectPin(pin);
199 }
200
207 {
208 ctrl = 0xC10;
209 torque = 0x1FF;
210 off = 0x030;
211 blank = 0x080;
212 decay = 0x110;
213 stall = 0x040;
214 drive = 0xA59;
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 {
362 }
363
381 void setCurrentMilliamps36v4(uint16_t current)
382 {
383 if (current > 8000) { current = 8000; }
384
385 // The 36v4 is just like the 36v8, except Risense is twice as large, so
386 // TORQUE/ISGAIN has to be doubled.
387 setCurrentMilliamps36v8(current * 2);
388 }
389
407 void setCurrentMilliamps36v8(uint16_t current)
408 {
409 if (current > 16000) { current = 16000; }
410
411 // From the DRV8711 datasheet, section 7.3.4, equation 2:
412 //
413 // Ifs = (2.75 V * TORQUE) / (256 * ISGAIN * Risense)
414 //
415 // Rearranged:
416 //
417 // TORQUE = (256 * ISGAIN * Risense * Ifs) / 2.75 V
418 //
419 // The 36v8 has an Risense of 15 milliohms, and "current" is
420 // in milliamps, so:
421 //
422 // TORQUE = (256 * ISGAIN * (15/1000) ohms * (current/1000) A) / 2.75 V
423 // = (3840 * ISGAIN * current) / 2750000
424 // = (384 * (ISGAIN/40) * current) / 6875
425 //
426 // We want to pick the highest gain (5, 10, 20, or 40) that will not
427 // overflow TORQUE (8 bits, 0xFF max), so we start with a gain of 40 and
428 // calculate the TORQUE value needed.
429 uint8_t isgainBits = 0b11;
430 uint16_t torqueBits = ((uint32_t)384 * current) / 6875;
431
432 // Halve the gain and TORQUE until the TORQUE value fits in 8 bits.
433 while (torqueBits > 0xFF)
434 {
435 isgainBits--;
436 torqueBits >>= 1;
437 }
438
439 ctrl = (ctrl & 0b110011111111) | (isgainBits << 8);
440 writeCTRL();
441 torque = (torque & 0b111100000000) | torqueBits;
442 writeTORQUE();
443 }
444
452 {
453 decay = (decay & 0b00011111111) | (((uint8_t)mode & 0b111) << 8);
454 writeDECAY();
455 }
456
472 uint8_t readStatus()
473 {
474 return driver.readReg(HPSDRegAddr::STATUS);
475 }
476
484 {
485 driver.writeReg(HPSDRegAddr::STATUS, 0);
486 }
487
493 uint8_t readFaults()
494 {
495 return readStatus() & 0b00111111;
496 }
497
508 {
509 driver.writeReg(HPSDRegAddr::STATUS, ~0b00111111);
510 }
511
512protected:
513
514 uint16_t ctrl, torque, off, blank, decay, stall, drive;
515
518 {
519 driver.writeReg(HPSDRegAddr::CTRL, ctrl);
520 }
521
524 {
525 driver.writeReg(HPSDRegAddr::TORQUE, torque);
526 }
527
529 void writeOFF()
530 {
531 driver.writeReg(HPSDRegAddr::OFF, off);
532 }
533
536 {
537 driver.writeReg(HPSDRegAddr::BLANK, blank);
538 }
539
542 {
543 driver.writeReg(HPSDRegAddr::DECAY, decay);
544 }
545
548 {
549 driver.writeReg(HPSDRegAddr::STALL, stall);
550 }
551
554 {
555 driver.writeReg(HPSDRegAddr::DRIVE, drive);
556 }
557
558public:
565};
@ OTS
Overtemperature shutdown.
@ APDF
Channel A predriver fault.
@ UVLO
Undervoltage lockout.
@ BOCP
Channel B overcurrent shutdown.
@ STDLAT
Latched stall detect.
@ STD
Stall detected.
@ AOCP
Channel A overcurrent shutdown.
@ BPDF
Channel B predriver fault.
HPSDRegAddr
Addresses of control and status registers.
HPSDStepMode
Possible arguments to setStepMode().
HPSDDecayMode
Possible arguments to setDecayMode().
void writeReg(uint8_t address, uint16_t value)
Writes the specified value to a register.
uint16_t readReg(uint8_t address)
Reads the register at the given address and returns its raw value.
void writeReg(HPSDRegAddr address, uint16_t value)
Writes the specified value to a register.
void setChipSelectPin(uint8_t pin)
uint16_t readReg(HPSDRegAddr address)
Reads the register at the given address and returns its raw value.
void setCurrentMilliamps36v8(uint16_t current)
void setStepMode(uint16_t mode)
void setCurrentMilliamps36v4(uint16_t current)
HighPowerStepperDriver()
The default constructor.
void writeBLANK()
Writes the cached value of the BLANK register to the device.
void disableDriver()
Disables the driver (ENBL = 0).
void enableDriver()
Enables the driver (ENBL = 1).
void setStepMode(HPSDStepMode mode)
void writeDRIVE()
Writes the cached value of the DRIVE register to the device.
void writeSTALL()
Writes the cached value of the STALL register to the device.
void writeOFF()
Writes the cached value of the OFF register to the device.
void writeTORQUE()
Writes the cached value of the TORQUE register to the device.
void writeDECAY()
Writes the cached value of the DECAY register to the device.
void writeCTRL()
Writes the cached value of the CTRL register to the device.
void setDecayMode(HPSDDecayMode mode)