TMCStepper
Library supporting Trinamic Stepper Drivers for Arduino platforms
Loading...
Searching...
No Matches
TMC2240Stepper.cpp
Go to the documentation of this file.
1
5#include "../TMCStepper.h"
6#include "TMC_MACROS.h"
7
9uint32_t TMC2240Stepper::spi_speed = 16000000/8;
10
11TMC2240Stepper::TMC2240Stepper(uint16_t pinCS, int8_t link) :
12 _pinCS(pinCS),
13 link_index(link)
14 {
15 defaults();
16
17 if (link > chain_length)
18 chain_length = link;
19 }
20
21TMC2240Stepper::TMC2240Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link) :
22 _pinCS(pinCS),
23 link_index(link)
24 {
25 SW_SPIClass *SW_SPI_Obj = new SW_SPIClass(pinMOSI, pinMISO, pinSCK);
26 TMC_SW_SPI = SW_SPI_Obj;
27 defaults();
28
29 if (link > chain_length)
30 chain_length = link;
31 }
32
34 GCONF_register.multistep_filt = 1;
35
36 IHOLD_IRUN_register.iholddelay = 1;
37 TPOWERDOWN_register.sr = 20;
38
39 // CHOPCONF_register.sr = 0x10010150;
40 CHOPCONF_register.toff = 0;
41 CHOPCONF_register.hstrt = 5;
42 CHOPCONF_register.hend = 2;
43 CHOPCONF_register.fd3 = false;
44 CHOPCONF_register.disfdcc = false;
45 CHOPCONF_register.chm = false;
46 CHOPCONF_register.TBL = 0b10;
47 CHOPCONF_register.vhighfs = false;
48 CHOPCONF_register.vhighchm = false;
49 CHOPCONF_register.tpfd = 0; // leave 0 ?
50 CHOPCONF_register.mres = 0;
51 CHOPCONF_register.intpol = true;
52 CHOPCONF_register.dedge = false;
53 CHOPCONF_register.diss2g = false;
54 CHOPCONF_register.diss2vs = false;
55
56 //PWMCONF_register.sr = 0xC40C001E;
57 PWMCONF_register.pwm_ofs = 30;
58 PWMCONF_register.pwm_grad = 0;
59 PWMCONF_register.pwm_freq = 0;
60 PWMCONF_register.pwm_autoscale = true;
61 PWMCONF_register.pwm_autograd = true;
62 PWMCONF_register.freewheel = 0;
63 PWMCONF_register.pwm_meas_sd_enable = false;
64 PWMCONF_register.pwm_dis_reg_stst = false;
65 PWMCONF_register.pwm_reg = 4;
66 PWMCONF_register.pwm_lim = 12;
67}
68
70void TMC2240Stepper::setSPISpeed(uint32_t speed) {
71 spi_speed = speed;
72}
73
74__attribute__((weak))
75void TMC2240Stepper::switchCSpin(bool state) {
76 digitalWrite(_pinCS, state);
77}
78
79__attribute__((weak))
81 if (TMC_SW_SPI == nullptr) {
83 }
84}
85__attribute__((weak))
87 if (TMC_SW_SPI == nullptr) {
89 }
90}
91
92__attribute__((weak))
93uint8_t TMC2240Stepper::transfer(const uint8_t data) {
94 uint8_t out = 0;
95 if (TMC_SW_SPI != nullptr) {
96 out = TMC_SW_SPI->transfer(data);
97 }
98 else {
99 out = SPI.transfer(data);
100 }
101 return out;
102}
103
105 for (uint8_t i = 0; i < n; i++) {
106 transfer(0x00);
107 }
108}
109
110__attribute__((weak))
111uint32_t TMC2240Stepper::read(uint8_t addressByte) {
112 uint32_t out = 0UL;
113 int8_t i = 1;
114
116 switchCSpin(LOW);
117 transfer(addressByte);
118 // Clear SPI
120
121 // Shift the written data to the correct driver in chain
122 // Default link_index = -1 and no shifting happens
123 while(i < link_index) {
125 i++;
126 }
127
128 switchCSpin(HIGH);
129 switchCSpin(LOW);
130
131 // Shift data from target link into the last one...
132 while(i < chain_length) {
134 i++;
135 }
136
137 // ...and once more to MCU
138 status_response = transfer(addressByte); // Send the address byte again
139 out = transfer(0x00);
140 out <<= 8; out |= transfer(0x00);
141 out <<= 8; out |= transfer(0x00);
142 out <<= 8; out |= transfer(0x00);
143
145 switchCSpin(HIGH);
146 return out;
147}
148
149__attribute__((weak))
150void TMC2240Stepper::write(uint8_t addressByte, uint32_t config) {
151 addressByte |= TMC_WRITE;
152 int8_t i = 1;
153
155 switchCSpin(LOW);
156 status_response = transfer(addressByte);
157 transfer(config>>24);
158 transfer(config>>16);
159 transfer(config>>8);
160 transfer(config);
161
162 // Shift the written data to the correct driver in chain
163 // Default link_index = -1 and no shifting happens
164 while (i < link_index) {
166 i++;
167 }
168
170 switchCSpin(HIGH);
171}
172
174 // set pins
176 switchCSpin(HIGH);
177
178 if (TMC_SW_SPI != nullptr) TMC_SW_SPI->init();
179
180 GCONF(GCONF_register.sr);
181 CHOPCONF(CHOPCONF_register.sr);
182 PWMCONF(PWMCONF_register.sr);
183 IHOLD_IRUN(IHOLD_IRUN_register.sr);
184
185 //toff(8); //off_time(8);
186 //tbl(1); //blank_time(24);
187}
188
190 TPOWERDOWN(TPOWERDOWN_register.sr);
191 TPWMTHRS(TPWMTHRS_register.sr);
192 GCONF(GCONF_register.sr);
193 SLAVECONF(NODECONF_register.sr);
194 DRV_CONF(DRV_CONF_register.sr);
195 IHOLD_IRUN(IHOLD_IRUN_register.sr);
196 CHOPCONF(CHOPCONF_register.sr);
197 PWMCONF(PWMCONF_register.sr);
198
199 //GSTAT(GSTAT_register.sr);
200 //TPOWERDOWN(TPOWERDOWN_register.sr);
201
202 //IOIN(IOIN_register.sr);
203
204 //DRV_STATUS(DRV_STATUS_register.sr);
205 //GLOBAL_SCALER(GLOBAL_SCALER_register.sr);
206
207 //TSTEP(TSTEP_register.sr);
208
209 //TCOOLTHRS(TCOOLTHRS_register.sr);
210 //THIGH(THIGH_register.sr);
211
212 //COOLCONF(COOLCONF_register.sr);
213
214 //PWM_SCALE(PWM_SCALE_register.sr);
215 //PWM_AUTO(PWM_AUTO_register.sr);
216 SG4_THRS(SG4_THRS_register.sr);
217 //SG4_RESULT(SG4_RESULT_register.sr);
218}
219
220bool TMC2240Stepper::isEnabled() { return !drv_enn() && toff(); }
221
223 return read(IFCNT_t::address);
224}
225
231 r.sr = PWM_SCALE();
232 return r.pwm_scale_sum;
233}
234
237 r.sr = PWM_SCALE();
238 return r.pwm_scale_auto;
239 // Not two's complement? 9nth bit determines sign
240 /*
241 uint32_t d = PWM_SCALE();
242 int16_t response = (d>>PWM_SCALE_AUTO_bp)&0xFF;
243 if (((d&PWM_SCALE_AUTO_bm) >> 24) & 0x1) return -response;
244 else return response;
245 */
246}
247
248// R: PWM_AUTO
251}
254
258//#define TMC2240_CURRENT_RANGE 2
259
263//#define TMC2240_Rref 12000 // Standard
264//#define TMC2240_Rref 12300 // FLY TMC2240
265
266/*
267 Requested current = mA = I_rms/1000
268 Equation for current:
269 I_rms = (CS+1)/32 * V_fs/R_sense * 1/sqrt(2)
270 Solve for CS ->
271 CS = 32*sqrt(2)*I_rms*R_sense/V_fs - 1
272
273 Example:
274 vsense = 0b0 -> V_fs = 0.310V //Typical
275 mA = 1650mA = I_rms/1000 = 1.65A
276 R_sense = 0.100 Ohm
277 ->
278 CS = 32*sqrt(2)*1.65*0.100/0.310 - 1 = 24,09
279 CS = 24
280*/
281
282uint16_t TMC2240Stepper::cs2rms(uint8_t CS) {
283 float IFS_current_RMS = calc_IFS_current_RMS();
284 const uint32_t globalscaler = GLOBAL_SCALER();
285 return float(CS + 0.5f) * (globalscaler * IFS_current_RMS) / 256 / 32 * 1000;
286}
287
289 uint32_t Kifs_values[] = { 11750, 24000, 36000, 36000 };
290 uint32_t Kifs = Kifs_values[DRV_CONF_register.current_range];
291 return (float(Kifs) / Rref) / 1.414f;
292}
293
294uint32_t TMC2240Stepper::set_globalscaler(float current, float IFS_current_RMS) {
295 uint32_t globalscaler = ((current * 256) / IFS_current_RMS) + 0.5f;
296
297 if (globalscaler < 32) globalscaler = 32;
298 if (globalscaler >= 256) globalscaler = 0;
299 GLOBAL_SCALER(globalscaler);
300 return globalscaler;
301}
302
304 float IFS_current_RMS = calc_IFS_current_RMS();
305 float mA_float = (float)mA / 1000;
306 uint32_t globalscaler = set_globalscaler(mA_float, IFS_current_RMS);
307 int32_t CS = mA_float * globalscaler / 256.0f * IFS_current_RMS * 32 - 1 + 0.5f;
308 if (CS > 31) CS = 31;
309 if (CS < 0) CS = 0;
310 irun(CS);
311 ihold(CS * holdMultiplier);
312}
313
314void TMC2240Stepper::rms_current(uint16_t mA, float mult) {
315 holdMultiplier = mult;
316 rms_current(mA);
317}
318
320 return cs2rms(irun());
321}
322
323void TMC2240Stepper::microsteps(uint16_t ms) {
324 switch(ms) {
325 case 256: mres(0); break;
326 case 128: mres(1); break;
327 case 64: mres(2); break;
328 case 32: mres(3); break;
329 case 16: mres(4); break;
330 case 8: mres(5); break;
331 case 4: mres(6); break;
332 case 2: mres(7); break;
333 case 0: mres(8); break;
334 default: break;
335 }
336}
337
339 switch(mres()) {
340 case 0: return 256;
341 case 1: return 128;
342 case 2: return 64;
343 case 3: return 32;
344 case 4: return 16;
345 case 5: return 8;
346 case 6: return 4;
347 case 7: return 2;
348 case 8: return 0;
349 }
350 return 0;
351}
352
353// R+C: GSTAT
361
363 uint32_t drv_status = DRV_STATUS();
364 switch (drv_status) {
365 case 0xFFFFFFFF: return 1;
366 case 0: return 2;
367 default: return 0;
368 }
369}
370
371// W: TPOWERDOWN
372uint8_t TMC2240Stepper::TPOWERDOWN() { return TPOWERDOWN_register.sr; }
373void TMC2240Stepper::TPOWERDOWN(uint8_t input) {
374 TPOWERDOWN_register.sr = input;
375 write(TPOWERDOWN_register.address, TPOWERDOWN_register.sr);
376}
377
378// W: TPWMTHRS
379uint32_t TMC2240Stepper::TPWMTHRS() { return TPWMTHRS_register.sr; }
380void TMC2240Stepper::TPWMTHRS(uint32_t input) {
381 TPWMTHRS_register.sr = input;
382 write(TPWMTHRS_register.address, TPWMTHRS_register.sr);
383}
384
386
387void TMC2240Stepper::hysteresis_end(int8_t value) { hend(value+3); }
388int8_t TMC2240Stepper::hysteresis_end() { return hend() - 3; };
389
390void TMC2240Stepper::hysteresis_start(uint8_t value) { hstrt(value-1); }
391uint8_t TMC2240Stepper::hysteresis_start() { return hstrt() + 1; }
392
393// W: TCOOLTHRS
394uint32_t TMC2240Stepper::TCOOLTHRS() { return TCOOLTHRS_register.sr; }
395void TMC2240Stepper::TCOOLTHRS(uint32_t input) {
396 TCOOLTHRS_register.sr = input;
397 write(TCOOLTHRS_register.address, TCOOLTHRS_register.sr);
398}
399
400// W: THIGH
401uint32_t TMC2240Stepper::THIGH() { return THIGH_register.sr; }
402void TMC2240Stepper::THIGH(uint32_t input) {
403 THIGH_register.sr = input;
404 write(THIGH_register.address, THIGH_register.sr);
405}
406
407// RW: SG4_THRS
408uint32_t TMC2240Stepper::SG4_THRS() { return SG4_THRS_register.sr; }
409void TMC2240Stepper::SG4_THRS(uint32_t input) {
410 SG4_THRS_register.sr = input;
411 write(SG4_THRS_register.address, SG4_THRS_register.sr);
412}
413uint8_t TMC2240Stepper::sg4_thrs() { return SG4_THRS_register.sg4_thrs; }
415 SG4_THRS_register.sg4_thrs = B;
416 write(SG4_THRS_register.address, SG4_THRS_register.sr);
417}
418bool TMC2240Stepper::sg4_filt_en() { return SG4_THRS_register.sg4_filt_en; }
420 SG4_THRS_register.sg4_filt_en = B;
421 write(SG4_THRS_register.address, SG4_THRS_register.sr);
422}
423uint8_t TMC2240Stepper::sg4_angle_offset() { return SG4_THRS_register.sg4_angle_offset; }
425 SG4_THRS_register.sg4_angle_offset = B;
426 write(SG4_THRS_register.address, SG4_THRS_register.sr);
427}
428
429// R:SG4_RESULT
432
433// RW: ADC_VSUPPLY_AIN
437
438// RW: ADC_TEMP
442
443// RW: OTW_OV_VTH
447
448void TMC2240Stepper::OTW_OV_VTH(uint32_t input) {
449 OTW_OV_VTH_register.sr = input;
450 write(OTW_OV_VTH_register.address, OTW_OV_VTH_register.sr);
451}
452
453// R: AIN Voltage (ADC_AIN × 305.2 µV)
456 r.sr = ADC_VSUPPLY_AIN();
457 return r.adc_ain * 0.0003052f;
458}
459
460// R: Supply Voltage (ADC_VSUPPLY × 9.732 mV)
463 r.sr = ADC_VSUPPLY_AIN();
464 return r.adc_vsupply * 0.009732f;
465}
466
467// R: Internal temperature in °C
470 r.sr = ADC_TEMP();
471 return (r.adc_temp - 2038.0f) * (1.0f / 7.7f);
472}
473
474// RW: OVERTEMPPREWARNING_VTH (°C)
477 r.sr = OTW_OV_VTH();
478 return (r.overtemp_prewarn_vth - 2038.0f) * (1.0f / 7.7f);
479}
480
482 uint16_t adc_temp_th = (uint16_t)(tempC * 7.7f + 2038.0f + 0.5f);
484 r.sr = OTW_OV_VTH();
485 r.overtemp_prewarn_vth = adc_temp_th;
486 write(r.address, r.sr);
487}
488
489// RW: OVERVOLTAGE_VTH (V)
495
497 uint16_t adc_vth = (uint16_t)(volts / 0.009732f + 0.5f);
499 r.sr = OTW_OV_VTH();
500 r.overvoltage_vth = adc_vth;
501 write(r.address, r.sr);
502}
503
504// RO: MSCNT
506
507// RO: MSCURACT
511 r.sr = MSCURACT();
512 int16_t value = r.cur_a;
513 if (value > 255) value -= 512;
514 return value;
515}
518 r.sr = MSCURACT();
519 int16_t value = r.cur_b;
520 if (value > 255) value -= 512;
521 return value;
522}
523
524// StallGuard4 convenience methods
526 return SG4_RESULT() & 0x3FF; // Return true if StallGuard4 has detected a stall
527}
528
530 COOLCONF_register.sg4_en = B;
531 COOLCONF(COOLCONF_register.sr);
532}
533
535 return COOLCONF_register.sg4_en;
536}
537
539 COOLCONF_register.sg4_smin = B;
540 COOLCONF(COOLCONF_register.sr);
541}
542
544 return COOLCONF_register.sg4_smin;
545}
546
548 COOLCONF_register.sg4_smax = B;
549 COOLCONF(COOLCONF_register.sr);
550}
551
553 return COOLCONF_register.sg4_smax;
554}
555
556void TMC2240Stepper::sg4_filt_en(bool B) {
557 COOLCONF_register.sg4_filt_en = B;
558 COOLCONF(COOLCONF_register.sr);
559}
560
562 return COOLCONF_register.sg4_filt_en;
563}
564
565void TMC2240Stepper::sg4_angle_offset(uint8_t B) {
566 COOLCONF_register.sg4_angle_offset = B;
567 COOLCONF(COOLCONF_register.sr);
568}
569
571 return COOLCONF_register.sg4_angle_offset;
572}
573
574void TMC2240Stepper::sg4_thrs(uint8_t B) {
575 SG4_THRS_register.sg4_thrs = B;
576 SG4_THRS(SG4_THRS_register.sr);
577}
578
579uint8_t TMC2240Stepper::sg4_thrs() {
580 return SG4_THRS_register.sg4_thrs;
581}
582
583// Legacy compatibility methods
584void TMC2240Stepper::enableStallGuard4() {
585 sg4_en(true);
586}
587
588void TMC2240Stepper::disableStallGuard4() {
589 sg4_en(false);
590}
591
592bool TMC2240Stepper::isStallGuard4Active() {
593 return sg4();
594}
595
596uint16_t TMC2240Stepper::getStallGuard4Result() {
597 return sg4_result();
598}
__attribute__((weak)) void TMC2240Stepper
#define MSBFIRST
Definition bcm2835_spi.h:10
SPIClass SPI
#define SPI_MODE3
Definition bcm2835_spi.h:14
void endTransaction()
void beginTransaction(SPISettings settings)
uint8_t transfer(uint8_t)
uint32_t CHOPCONF()
Definition CHOPCONF.cpp:102
uint8_t hstrt()
Definition CHOPCONF.cpp:124
uint8_t GLOBAL_SCALER()
void beginTransaction()
uint32_t GCONF()
Definition GCONF.cpp:118
uint32_t OTW_OV_VTH()
uint8_t ihold()
uint16_t SLAVECONF()
const uint16_t _pinCS
uint32_t SG4_RESULT()
float get_chip_temperature()
TMC2240Stepper(uint16_t pinCS, int8_t link_index=-1)
void setSPISpeed(uint32_t speed)
SW_SPIClass * TMC_SW_SPI
uint16_t rms_current()
uint8_t pwm_scale_sum()
void write(uint8_t addressByte, uint32_t config)
uint32_t ADC_VSUPPLY_AIN()
uint8_t transfer(const uint8_t data)
uint8_t hysteresis_start()
void set_overvoltage_threshold_voltage(float volts)
void set_overtemp_prewarn_celsius(float tempC)
uint32_t set_globalscaler(float current, float IFS_current_RMS)
static constexpr uint8_t TMC_WRITE
void switchCSpin(bool state)
bool drv_enn()
Definition IOIN.cpp:97
uint8_t mres()
Definition CHOPCONF.cpp:133
uint32_t IHOLD_IRUN()
float calc_IFS_current_RMS()
void endTransaction()
void transferEmptyBytes(const uint8_t n)
uint32_t DRV_CONF()
Definition DRV_CONF.cpp:37
uint32_t PWMCONF()
Definition PWMCONF.cpp:102
uint16_t cs2rms(uint8_t CS)
uint32_t read(uint8_t addressByte)
uint8_t hend()
Definition CHOPCONF.cpp:125
float get_vsupply_voltage()
uint16_t microsteps()
uint8_t status_response
float get_overtemp_prewarn_celsius()
uint32_t COOLCONF()
uint8_t irun()
uint8_t pwm_grad_auto()
static int8_t chain_length
float get_overvoltage_threshold_voltage()
int16_t pwm_scale_auto()
uint8_t toff()
Definition CHOPCONF.cpp:123
uint8_t test_connection()
uint8_t sg4_angle_offset()
uint32_t DRV_STATUS()
static uint32_t spi_speed
uint16_t sg4_result()
#define pinMode(PIN, MODE)
Definition rpi_bcm2835.h:13
#define digitalWrite(PIN, MODE)
Definition rpi_bcm2835.h:14
#define OUTPUT
Definition rpi_bcm2835.h:11
uint8_t pwm_grad_auto
static constexpr uint8_t address
uint8_t pwm_ofs_auto
static constexpr uint8_t address
static constexpr uint8_t address
static constexpr uint8_t address
static constexpr uint8_t address
static constexpr uint8_t address
static constexpr uint8_t address
static constexpr uint8_t address
static constexpr uint8_t address
static constexpr uint8_t address
static constexpr uint8_t address