AMIS30543 library
AMIS30543.h
Go to the documentation of this file.
1 // Copyright Pololu Corporation. For more information, see http://www.pololu.com/
2 
16 #pragma once
17 
18 #include <stdint.h>
19 #include <Arduino.h>
20 #include <SPI.h>
21 
28 {
29 public:
30 
33  void init(uint8_t slaveSelectPin) { ssPin = slaveSelectPin;
34 
35  digitalWrite(ssPin, HIGH);
36  pinMode(ssPin, OUTPUT);
37  }
38 
40  uint8_t readReg(uint8_t address)
41  {
42  selectChip();
43  transfer(address & 0b11111);
44  uint8_t dataOut = transfer(0);
45  deselectChip();
46  return dataOut;
47  }
48 
50  void writeReg(uint8_t address, uint8_t value)
51  {
52  selectChip();
53  transfer(0x80 | (address & 0b11111));
54  transfer(value);
55 
56  // The CS line must go high after writing for the value to actually take
57  // effect.
58  deselectChip();
59  }
60 
61 private:
62 
63  SPISettings settings = SPISettings(500000, MSBFIRST, SPI_MODE0);
64 
65  uint8_t transfer(uint8_t value)
66  {
67  return SPI.transfer(value);
68  }
69 
70  void selectChip()
71  {
72  digitalWrite(ssPin, LOW);
73  SPI.beginTransaction(settings);
74  }
75 
76  void deselectChip()
77  {
78  digitalWrite(ssPin, HIGH);
79  SPI.endTransaction();
80 
81  // The CS high time is specified as 2.5 us in the AMIS-30543 datasheet.
82  delayMicroseconds(3);
83  }
84 
85  uint8_t ssPin;
86 };
87 
93 class AMIS30543
94 {
95 public:
98  {
99  wr = cr0 = cr1 = cr2 = cr3 = 0;
100  }
101 
103  enum stepMode
104  {
105  MicroStep128 = 128,
106  MicroStep64 = 64,
107  MicroStep32 = 32,
108  MicroStep16 = 16,
109  MicroStep8 = 8,
110  MicroStep4 = 4,
111  MicroStep2 = 2,
112  MicroStep1 = 1,
113  CompensatedHalf = MicroStep2,
114  CompensatedFullTwoPhaseOn = MicroStep1,
115  CompensatedFullOnePhaseOn = 200,
116  UncompensatedHalf = 201,
117  UncompensatedFull = 202,
118  };
119 
122  {
123  OPENY = (1 << 2),
124  OPENX = (1 << 3),
125  WD = (1 << 4),
126  CPFAIL = (1 << 5),
127  TW = (1 << 6),
128  };
129 
132  {
133  OVCXNB = (1 << 3),
134  OVCXNT = (1 << 4),
135  OVCXPB = (1 << 5),
136  OVCXPT = (1 << 6),
137  TSD = (1 << 10),
138  OVCYNB = (1 << 11),
139  OVCYNT = (1 << 12),
140  OVCYPB = (1 << 13),
141  OVCYPT = (1 << 14),
142  };
143 
145  enum regAddr
146  {
147  WR = 0x0,
148  CR0 = 0x1,
149  CR1 = 0x2,
150  CR2 = 0x3,
151  CR3 = 0x9,
152  SR0 = 0x4,
153  SR1 = 0x5,
154  SR2 = 0x6,
155  SR3 = 0x7,
156  SR4 = 0xA,
157  };
158 
161  void init(uint8_t slaveSelectPin)
162  {
163  driver.init(slaveSelectPin);
164  }
165 
172  {
173  wr = cr0 = cr1 = cr2 = cr3 = 0;
174  applySettings();
175  }
176 
190  {
191  return driver.readReg(WR) == wr &&
192  driver.readReg(CR0) == cr0 &&
193  driver.readReg(CR1) == cr1 &&
194  driver.readReg(CR2) == cr2 &&
195  driver.readReg(CR3) == cr3;
196  }
197 
206  {
207  // Because of power interruption considerations, the register that
208  // contains the MOTEN bit (CR2) must be written first, and whenever we
209  // write to it we should also write to all the other registers.
210 
211  // CR2 is written first, because it contains the MOTEN bit, and there is
212  // a risk that there might be a power interruption to the driver right
213  // before CR2 is written. This could result in the motor being enabled
214  // with incorrect settings. Also, whenever we do write to CR2, we want to
215  // also write the other registers to make sure they are in the correct state.
216  driver.writeReg(CR2, cr2);
217 
218  writeWR();
219  writeCR0();
220  writeCR1();
221  writeCR3();
222  }
223 
228  {
229  cr2 |= 0b10000000;
230  applySettings();
231  }
232 
237  {
238  cr2 &= ~0b10000000;
239  applySettings();
240  }
241 
247  void setCurrentMilliamps(uint16_t current)
248  {
249  // This comes from Table 13 of the AMIS-30543 datasheet.
250  uint8_t code = 0;
251  if (current >= 3000) { code = 0b11001; }
252  else if (current >= 2845) { code = 0b11000; }
253  else if (current >= 2700) { code = 0b10111; }
254  else if (current >= 2440) { code = 0b10110; }
255  else if (current >= 2240) { code = 0b10101; }
256  else if (current >= 2070) { code = 0b10100; }
257  else if (current >= 1850) { code = 0b10011; }
258  else if (current >= 1695) { code = 0b10010; }
259  else if (current >= 1520) { code = 0b10001; }
260  else if (current >= 1405) { code = 0b10000; }
261  else if (current >= 1260) { code = 0b01111; }
262  else if (current >= 1150) { code = 0b01110; }
263  else if (current >= 1060) { code = 0b01101; }
264  else if (current >= 955) { code = 0b01100; }
265  else if (current >= 870) { code = 0b01011; }
266  else if (current >= 780) { code = 0b01010; }
267  else if (current >= 715) { code = 0b01001; }
268  else if (current >= 640) { code = 0b01000; }
269  else if (current >= 585) { code = 0b00111; }
270  else if (current >= 540) { code = 0b00110; }
271  else if (current >= 485) { code = 0b00101; }
272  else if (current >= 445) { code = 0b00100; }
273  else if (current >= 395) { code = 0b00011; }
274  else if (current >= 355) { code = 0b00010; }
275  else if (current >= 245) { code = 0b00001; }
276 
277  cr0 = (cr0 & 0b11100000) | code;
278  writeCR0();
279  }
280 
295  uint16_t readPosition()
296  {
297  uint8_t sr3 = readStatusReg(SR3);
298  uint8_t sr4 = readStatusReg(SR4);
299  return ((uint16_t)sr3 << 2) | (sr4 & 3);
300  }
301 
308  void setDirection(bool value)
309  {
310  if (value)
311  {
312  cr1 |= 0x80;
313  }
314  else
315  {
316  cr1 &= ~0x80;
317  }
318  writeCR1();
319  }
320 
325  {
326  return cr1 >> 7 & 1;
327  }
328 
340  void setStepMode(uint8_t mode)
341  {
342  // Pick 1/32 micro-step by default.
343  uint8_t esm = 0b000;
344  uint8_t sm = 0b000;
345 
346  // The order of these cases matches the order in Table 12 of the
347  // AMIS-30543 datasheet.
348  switch(mode)
349  {
350  case MicroStep32: sm = 0b000; break;
351  case MicroStep16: sm = 0b001; break;
352  case MicroStep8: sm = 0b010; break;
353  case MicroStep4: sm = 0b011; break;
354  case CompensatedHalf: sm = 0b100; break; /* a.k.a. MicroStep2 */
355  case UncompensatedHalf: sm = 0b101; break;
356  case UncompensatedFull: sm = 0b110; break;
357  case MicroStep128: esm = 0b001; break;
358  case MicroStep64: esm = 0b010; break;
359  case CompensatedFullTwoPhaseOn: esm = 0b011; break; /* a.k.a. MicroStep 1 */
360  case CompensatedFullOnePhaseOn: esm = 0b100; break;
361  }
362 
363  cr0 = (cr0 & ~0b11100000) | (sm << 5);
364  cr3 = (cr3 & ~0b111) | esm;
365  writeCR0();
366  writeCR3();
367  }
368 
377  void sleep()
378  {
379  cr2 |= (1 << 6);
380  applySettings();
381  }
382 
386  void sleepStop()
387  {
388  cr2 &= ~(1 << 6);
389  applySettings();
390  }
391 
396  {
397  cr1 &= ~0b01000000;
398  writeCR1();
399  }
400 
404  {
405  cr1 |= 0b01000000;
406  writeCR1();
407  }
408 
411  {
412  cr1 |= (1 << 3);
413  writeCR1();
414  }
415 
419  {
420  cr1 &= ~(1 << 3);
421  writeCR1();
422  }
423 
427  {
428  cr1 |= (1 << 2);
429  writeCR1();
430  }
431 
436  {
437  cr1 &= ~(1 << 2);
438  writeCR1();
439  }
440 
444  void setPwmSlope(uint8_t emc)
445  {
446  cr1 = (cr1 & ~0b11) | (emc & 0b11);
447  writeCR1();
448  }
449 
455  {
456  cr2 &= ~(1 << 5);
457  applySettings();
458  }
459 
465  {
466  cr2 |= (1 << 5);
467  applySettings();
468  }
469 
475  {
476  cr2 &= ~(1 << 4);
477  applySettings();
478  }
479 
485  {
486  cr2 |= (1 << 4);
487  applySettings();
488  }
489 
514  {
515  return readStatusReg(SR0);
516  }
517 
532  {
533  uint8_t sr1 = readStatusReg(SR1);
534  uint8_t sr2 = readStatusReg(SR2);
535  return (sr2 << 8) | sr1;
536  }
537 
538 protected:
539 
540  uint8_t wr, cr0, cr1, cr2, cr3;
541 
544  uint8_t readStatusReg(uint8_t address)
545  {
546  // Mask off the parity bit.
547  // (Later we might add code here to check the parity
548  // bit and record errors.)
549  return driver.readReg(address) & 0x7F;
550  }
551 
553  void writeWR()
554  {
555  driver.writeReg(WR, wr);
556  }
557 
559  void writeCR0()
560  {
561  driver.writeReg(CR0, cr0);
562  }
563 
565  void writeCR1()
566  {
567  driver.writeReg(CR1, cr1);
568  }
569 
571  void writeCR3()
572  {
573  driver.writeReg(CR3, cr3);
574  }
575 
576 public:
581 };
void setSlaGainHalf()
Definition: AMIS30543.h:464
void stepOnRisingEdge()
Definition: AMIS30543.h:395
void sleepStop()
Definition: AMIS30543.h:386
void writeReg(uint8_t address, uint8_t value)
Definition: AMIS30543.h:50
bool verifySettings()
Definition: AMIS30543.h:189
void setPwmFrequencyDouble()
Definition: AMIS30543.h:410
bool getDirection()
Definition: AMIS30543.h:324
void init(uint8_t slaveSelectPin)
Definition: AMIS30543.h:33
void writeCR1()
Definition: AMIS30543.h:565
uint8_t readStatusReg(uint8_t address)
Definition: AMIS30543.h:544
uint16_t readLatchedStatusFlagsAndClear()
Definition: AMIS30543.h:531
void enableDriver()
Definition: AMIS30543.h:227
nonLatchedStatusFlag
Definition: AMIS30543.h:121
void setPwmJitterOff()
Definition: AMIS30543.h:435
void resetSettings()
Definition: AMIS30543.h:171
void writeCR3()
Definition: AMIS30543.h:571
void setCurrentMilliamps(uint16_t current)
Definition: AMIS30543.h:247
void setSlaGainDefault()
Definition: AMIS30543.h:454
void setStepMode(uint8_t mode)
Definition: AMIS30543.h:340
void setPwmFrequencyDefault()
Definition: AMIS30543.h:418
void disableDriver()
Definition: AMIS30543.h:236
latchedStatusFlag
Definition: AMIS30543.h:131
void setPwmJitterOn()
Definition: AMIS30543.h:426
AMIS30543SPI driver
Definition: AMIS30543.h:580
void writeCR0()
Definition: AMIS30543.h:559
void setSlaTransparencyOff()
Definition: AMIS30543.h:474
void setSlaTransparencyOn()
Definition: AMIS30543.h:484
void setDirection(bool value)
Definition: AMIS30543.h:308
uint8_t readReg(uint8_t address)
Definition: AMIS30543.h:40
void setPwmSlope(uint8_t emc)
Definition: AMIS30543.h:444
uint16_t readNonLatchedStatusFlags()
Definition: AMIS30543.h:513
void applySettings()
Definition: AMIS30543.h:205
void writeWR()
Definition: AMIS30543.h:553
void stepOnFallingEdge()
Definition: AMIS30543.h:403
AMIS30543()
Definition: AMIS30543.h:97
void init(uint8_t slaveSelectPin)
Definition: AMIS30543.h:161
uint16_t readPosition()
Definition: AMIS30543.h:295
void sleep()
Definition: AMIS30543.h:377