RSeries astromech firmware
TB9051FTGMotorCarrier.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "ReelTwo.h"
4 
13 public:
14  static constexpr uint8_t kPinNotUsed{255};
15  // static constexpr uint8_t kPWM1_Timer0{5};
16  // static constexpr uint8_t kPWM2_Timer0{6};
17  // static constexpr uint8_t kPWM1_Timer1{9};
18  // static constexpr uint8_t kPWM2_Timer1{10};
19  // static constexpr uint8_t kPWM1_Timer2{3};
20  // static constexpr uint8_t kPWM2_Timer2{11};
21 
35  uint8_t pwm1,
36  uint8_t pwm2,
37  uint8_t en = kPinNotUsed,
38  uint8_t enb = kPinNotUsed,
39  uint8_t ocm = kPinNotUsed,
40  uint8_t diag = kPinNotUsed,
41  uint8_t occ = kPinNotUsed) :
42  fPWM1(pwm1),
43  fPWM2(pwm2),
44  fOCM(ocm),
45  fDiag(diag),
46  fOCC(occ),
47  fEN(en),
48  fENB(enb)
49  {
50  pinMode(fPWM1, OUTPUT);
51  pinMode(fPWM2, OUTPUT);
52  pinMode(fOCM, INPUT);
53  pinMode(fDiag, INPUT);
54  pinMode(fOCC, OUTPUT);
55  pinMode(fEN, OUTPUT);
56  pinMode(fENB, OUTPUT);
57  // if (fPWM1 == kPWM1_Timer0 && fPWM2 == kPWM2_Timer0)
58  // {
59  // /* Enable fast PWM mode */
60  // TCCR0A |= (1<<WGM00);
61  // TCCR0A |= (1<<WGM01);
62  // TCCR0B &= ~(1<<WGM02);
63 
64  // /* Enable non-inverting mode on OC0A */
65  // TCCR0A |= (1<<COM0A1);
66  // TCCR0A &= ~(1<<COM0A0);
67 
68  // /* Enable non-inverting mode on OC0B */
69  // TCCR0A |= (1<<COM0B1);
70  // TCCR0A &= ~(1<<COM0B0);
71 
72  // /* Disable Force Output Compare A */
73  // TCCR0B &= ~(1<<FOC0A);
74 
75  // /* Disable Force Output Compare B */
76  // TCCR0B &= ~(1<<FOC0B);
77 
78  // /* Disable all Counter0 interrupts */
79  // TIMSK0 = 0;
80 
81  // auto CS_bits = getPrescaleCSBits(0);
82 
83  // /* Use dummy variable to set the right CS02:0 bits */
84  // TCCR0B |= CS_bits;
85 
86  // /* Use dummy variable to clear the right CS02:0 bits, masking out the other bits */
87  // TCCR0B &= (0b11111000 | CS_bits);
88  // }
89  // else if (fPWM1 == kPWM1_Timer1 && fPWM2 == kPWM2_Timer1)
90  // {
91  // /* Enable fast PWM mode */
92  // TCCR1A |= (1<<WGM10);
93  // TCCR1A |= (1<<WGM11);
94  // TCCR1B &= ~(1<<WGM12);
95 
96  // /* Enable non-inverting mode on OC1A */
97  // TCCR1A |= (1<<COM1A1);
98  // TCCR1A &= ~(1<<COM1A0);
99 
100  // /* Enable non-inverting mode on OC1B */
101  // TCCR1A |= (1<<COM1B1);
102  // TCCR1A &= ~(1<<COM1B0);
103 
104  // /* Disable Force Output Compare A */
105  // TCCR1B &= ~(1<<FOC1A);
106 
107  // /* Disable Force Output Compare B */
108  // TCCR1B &= ~(1<<FOC1B);
109 
110  // /* Disable all Counter1 interrupts */
111  // TIMSK1 = 0;
112 
113  // ICR1 = 799;
114 
115  // // prescale 0
116  // auto CS_bits = getPrescaleCSBits(0);
117 
118  // /* Use dummy variable to set the right CS02:0 bits */
119  // TCCR1B |= CS_bits;
120 
121  // /* Use dummy variable to clear the right CS02:0 bits, masking out the other bits */
122  // TCCR1B &= (0b11111000 | CS_bits);
123  // }
124  // else if (fPWM1 == kPWM1_Timer2 && fPWM2 == kPWM2_Timer2)
125  // {
126  // /* Enable fast PWM mode */
127  // TCCR2A |= (1<<WGM20);
128  // TCCR2A |= (1<<WGM21);
129  // TCCR2B &= ~(1<<WGM22);
130 
131  // /* Enable non-inverting mode on OC2A */
132  // TCCR2A |= (1<<COM2A1);
133  // TCCR2A &= ~(1<<COM2A0);
134 
135  // /* Enable non-inverting mode on OC2B */
136  // TCCR2A |= (1<<COM2B1);
137  // TCCR2A &= ~(1<<COM2B0);
138 
139  // /* Disable Force Output Compare A */
140  // TCCR2B &= ~(1<<FOC2A);
141 
142  // /* Disable Force Output Compare B */
143  // TCCR2B &= ~(1<<FOC2B);
144 
145  // /* Disable all Counter2 interrupts */
146  // TIMSK2 = 0;
147 
148  // // prescale 0
149  // auto CS_bits = getPrescaleCSBits(0);
150 
151  // /* Use dummy variable to set the right CS02:0 bits */
152  // TCCR1B |= CS_bits;
153 
154  // /* Use dummy variable to clear the right CS02:0 bits, masking out the other bits */
155  // TCCR1B &= (0b11111000 | CS_bits);
156  // }
157  }
158 
166  float getCurrent(void) const
167  {
168  // 4.9 mV per analog unit (for Arduino Uno)
169  // 500 mV per A on TB9051FTG current sense
170  // 1000 mA per A
171  return (analogRead(fOCM) * 4.9) / 500 * 1000;
172  }
173 
181  uint8_t getDiagnostic(void) const
182  {
183  return digitalRead(fDiag, HIGH);
184  }
185 
193  void setDeadband(float lower, float upper)
194  {
195  fDeadBandLower = lower;
196  fDeadBandUpper = upper;
197  }
198 
207  void setBrakeMode(bool mode)
208  {
209  fBrakeMode = mode;
210  }
211 
218  void setOutput(float percent) const
219  {
220  if (withinDeadband(percent))
221  {
222  if (fBrakeMode)
223  {
224  dualAnalogWrite(fPWM1, 0, fPWM2, 0);
225  }
226  else
227  {
228  disableOutputs();
229  }
230  }
231  else if (fEnabled && percent < 0)
232  {
233  enableOutputs();
234  dualAnalogWrite(fPWM1, 0, fPWM2, fabs(percent));
235  }
236  else if (fEnabled)
237  {
238  enableOutputs();
239  dualAnalogWrite(fPWM1, fabs(percent), fPWM2, 0);
240  }
241  }
242 
251  void setOccResponse(bool automatic) const
252  {
253  digitalWrite(fOCC, automatic ? 1 : 0);
254  }
255 
260  void enable(void)
261  {
262  fEnabled = true;
263  enableOutputs();
264  }
265 
269  void disable(void)
270  {
271  fEnabled = false;
272  disableOutputs();
273  }
274 
275 private:
276  static constexpr uint8_t getPrescaleCSBits(unsigned prescale)
277  {
278  return (prescale == 0) ? 0b00000001 :
279  (prescale == 8) ? 0b00000010 :
280  (prescale == 64) ? 0b00000011 :
281  (prescale == 256) ? 0b00000100 :
282  (prescale == 1024) ? 0b00000101 : 0;
283  }
284 
285  static inline void pinMode(uint8_t pin, uint8_t mode)
286  {
287  if (pin != kPinNotUsed)
288  {
289  ::pinMode(pin, mode);
290  }
291  }
292 
293  static inline void digitalWrite(uint8_t pin, uint8_t val)
294  {
295  if (pin != kPinNotUsed)
296  {
297  Serial.println("digitalWrite");
298  ::digitalWrite(pin, val);
299  }
300  }
301 
302  static inline uint8_t digitalRead(uint8_t pin, uint8_t defaultValue = 0)
303  {
304  return (pin != kPinNotUsed) ? ::digitalRead(pin) : defaultValue;
305  }
306 
307  static inline int analogRead(uint8_t pin)
308  {
309  return (pin != kPinNotUsed) ? ::analogRead(pin) : 0;
310  }
311 
312  static inline void dualAnalogWrite(uint8_t m1, float v1, uint8_t m2, float v2)
313  {
314  const auto output1{static_cast<uint16_t>(abs(v1) * 1023)};
315  const auto output2{static_cast<uint16_t>(abs(v2) * 1023)};
316  // if (m1 == kPWM1_Timer0 && m2 == kPWM2_Timer0)
317  // {
318  // OCR0A = output1;
319  // OCR0B = output2;
320  // }
321  // else if (m1 == kPWM1_Timer1 && m2 == kPWM2_Timer1)
322  // {
323  // const auto output1{static_cast<uint16_t>(abs(v1) * 799)};
324  // const auto output2{static_cast<uint16_t>(abs(v2) * 799)};
325  // OCR1A = output1;
326  // OCR1B = output2;
327  // }
328  // else if (m1 == kPWM1_Timer2 && m2 == kPWM2_Timer2)
329  // {
330  // OCR2A = output1;
331  // OCR2B = output2;
332  // }
333  // else
334  {
335  Serial.print("dualAnalogWrite "); Serial.print(output1); Serial.print(", "); Serial.println(output2);
336  ::analogWrite(m1, output1, 1023);
337  ::analogWrite(m2, output2, 1023);
338  }
339  Serial.println();
340  }
341 
342  bool withinDeadband(float value) const
343  {
344  return value < fDeadBandUpper && value > fDeadBandLower;
345  }
346 
347  void enableOutputs(void) const
348  {
349  digitalWrite(fEN, 1);
350  digitalWrite(fENB, 0);
351  }
352 
353  void disableOutputs(void) const
354  {
355  digitalWrite(fEN, 0);
356  digitalWrite(fENB, 1);
357  }
358 
359  float fDeadBandLower = 0;
360  float fDeadBandUpper = 0;
361 
362  bool fBrakeMode = false; // true if motor in brake mode
363  bool fEnabled = false; // true if driver enabled
364 
365  // Pin values
366  uint8_t fPWM1; // PWM for OUT1 (PWM1)
367  uint8_t fPWM2; // PWM for OUT2 (PWM2)
368  uint8_t fOCM; // Output current monitor (OCM)
369  uint8_t fDiag; // Diagnostic error (DIAG)
370  uint8_t fOCC; // Over current (OCC) response
371  uint8_t fEN; // Enable (EN)
372  uint8_t fENB; // Inverted enable (ENB)
373 };
ReelTwo.h
TB9051FTGMotorCarrier::disable
void disable(void)
Disable the motor driver carrier's outputs.
Definition: TB9051FTGMotorCarrier.h:269
TB9051FTGMotorCarrier
Implements support for the Pololu TB9051FTG MotorCarrier (https://www.pololu.com/product/2997)
Definition: TB9051FTGMotorCarrier.h:12
TB9051FTGMotorCarrier::TB9051FTGMotorCarrier
TB9051FTGMotorCarrier(uint8_t pwm1, uint8_t pwm2, uint8_t en=kPinNotUsed, uint8_t enb=kPinNotUsed, uint8_t ocm=kPinNotUsed, uint8_t diag=kPinNotUsed, uint8_t occ=kPinNotUsed)
Constructor.
Definition: TB9051FTGMotorCarrier.h:34
TB9051FTGMotorCarrier::setBrakeMode
void setBrakeMode(bool mode)
Sets the brake mode for the motor driver carrier.
Definition: TB9051FTGMotorCarrier.h:207
TB9051FTGMotorCarrier::kPinNotUsed
static constexpr uint8_t kPinNotUsed
Definition: TB9051FTGMotorCarrier.h:14
TB9051FTGMotorCarrier::enable
void enable(void)
Enable the motor driver carrier's outputs.
Definition: TB9051FTGMotorCarrier.h:260
TB9051FTGMotorCarrier::setDeadband
void setDeadband(float lower, float upper)
Sets the dead band range.
Definition: TB9051FTGMotorCarrier.h:193
TB9051FTGMotorCarrier::setOccResponse
void setOccResponse(bool automatic) const
Sets the over-current response.
Definition: TB9051FTGMotorCarrier.h:251
TB9051FTGMotorCarrier::getDiagnostic
uint8_t getDiagnostic(void) const
Reads the DIAG pin on the motor driver carrier.
Definition: TB9051FTGMotorCarrier.h:181
TB9051FTGMotorCarrier::setOutput
void setOutput(float percent) const
Sets the throttle output percentage [-1, 1], which is the percentage of the driver carrier's input vo...
Definition: TB9051FTGMotorCarrier.h:218
TB9051FTGMotorCarrier::getCurrent
float getCurrent(void) const
Reads an estimate of the motor current from the motor driver carrier.
Definition: TB9051FTGMotorCarrier.h:166