@@ -10,6 +10,19 @@ int getTimerNumber(int timerIndex);
10
10
#endif
11
11
12
12
13
+
14
+
15
+ #ifndef SIMPLEFOC_STM32_MAX_PINTIMERSUSED
16
+ #define SIMPLEFOC_STM32_MAX_PINTIMERSUSED 12
17
+ #endif
18
+ int numTimerPinsUsed;
19
+ PinMap* timerPinsUsed[SIMPLEFOC_STM32_MAX_PINTIMERSUSED];
20
+
21
+
22
+
23
+
24
+
25
+
13
26
// setting pwm to hardware pin - instead analogWrite()
14
27
void _setPwm (HardwareTimer *HT, uint32_t channel, uint32_t value, int resolution)
15
28
{
@@ -33,17 +46,19 @@ HardwareTimer* _initPinPWM(uint32_t PWM_freq, PinMap* timer) {
33
46
if (timer==NP)
34
47
return NP;
35
48
uint32_t index = get_timer_index ((TIM_TypeDef*)timer->peripheral );
49
+ bool init = false ;
36
50
if (HardwareTimer_Handle[index] == NULL ) {
37
51
HardwareTimer_Handle[index]->__this = new HardwareTimer ((TIM_TypeDef*)timer->peripheral );
38
52
HardwareTimer_Handle[index]->handle .Init .CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
39
53
HAL_TIM_Base_Init (&(HardwareTimer_Handle[index]->handle ));
54
+ init = true ;
40
55
}
41
56
HardwareTimer *HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this );
42
57
uint32_t channel = STM_PIN_CHANNEL (timer->function );
43
- HT->setMode (channel, TIMER_OUTPUT_COMPARE_PWM1, timer->pin );
44
- HT->setOverflow (PWM_freq, HERTZ_FORMAT);
45
58
HT->pause ();
46
- HT->refresh ();
59
+ if (init)
60
+ HT->setOverflow (PWM_freq, HERTZ_FORMAT);
61
+ HT->setMode (channel, TIMER_OUTPUT_COMPARE_PWM1, timer->pin );
47
62
return HT;
48
63
}
49
64
@@ -54,8 +69,7 @@ HardwareTimer* _initPinPWM(uint32_t PWM_freq, PinMap* timer) {
54
69
55
70
56
71
// init high side pin
57
- HardwareTimer* _initPinPWMHigh (uint32_t PWM_freq, PinMap* timer)
58
- {
72
+ HardwareTimer* _initPinPWMHigh (uint32_t PWM_freq, PinMap* timer) {
59
73
return _initPinPWM (PWM_freq, timer);
60
74
}
61
75
@@ -64,31 +78,39 @@ HardwareTimer* _initPinPWMLow(uint32_t PWM_freq, PinMap* timer)
64
78
{
65
79
uint32_t index = get_timer_index ((TIM_TypeDef*)timer->peripheral );
66
80
81
+ bool init = false ;
67
82
if (HardwareTimer_Handle[index] == NULL ) {
68
83
HardwareTimer_Handle[index]->__this = new HardwareTimer ((TIM_TypeDef*)timer->peripheral );
69
84
HardwareTimer_Handle[index]->handle .Init .CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
70
85
HAL_TIM_Base_Init (&(HardwareTimer_Handle[index]->handle ));
71
- TIM_OC_InitTypeDef sConfigOC = TIM_OC_InitTypeDef ();
72
- sConfigOC .OCMode = TIM_OCMODE_PWM2;
73
- sConfigOC .Pulse = 100 ;
74
- sConfigOC .OCPolarity = TIM_OCPOLARITY_LOW;
75
- sConfigOC .OCFastMode = TIM_OCFAST_DISABLE;
76
- #if defined(TIM_OCIDLESTATE_SET)
77
- sConfigOC .OCIdleState = TIM_OCIDLESTATE_SET;
78
- #endif
79
- #if defined(TIM_OCNIDLESTATE_RESET)
80
- sConfigOC .OCNPolarity = TIM_OCNPOLARITY_HIGH;
81
- sConfigOC .OCNIdleState = TIM_OCNIDLESTATE_RESET;
82
- #endif
83
- uint32_t channel = STM_PIN_CHANNEL (timer->function );
84
- HAL_TIM_PWM_ConfigChannel (&(HardwareTimer_Handle[index]->handle ), &sConfigOC , channel);
86
+ init = true ;
85
87
}
86
88
HardwareTimer *HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this );
87
89
uint32_t channel = STM_PIN_CHANNEL (timer->function );
88
- HT->setMode (channel, TIMER_OUTPUT_COMPARE_PWM2, timer->pin );
89
- HT->setOverflow (PWM_freq, HERTZ_FORMAT);
90
+ // SIMPLEFOC_DEBUG("Configuring low timer ", (int)getTimerNumber(get_timer_index(HardwareTimer_Handle[index]->handle.Instance)));
91
+ // SIMPLEFOC_DEBUG("Configuring low channel ", (int)channel);
92
+
93
+
90
94
HT->pause ();
91
- HT->refresh ();
95
+
96
+ if (init)
97
+ HT->setOverflow (PWM_freq, HERTZ_FORMAT);
98
+ // sets internal fields of HT, but we can't set polarity here
99
+ HT->setMode (channel, TIMER_OUTPUT_COMPARE_PWM2, timer->pin );
100
+ // set polarity, unfortunately we have to set these other fields too
101
+ // TIM_OC_InitTypeDef sConfigOC = TIM_OC_InitTypeDef();
102
+ // sConfigOC.OCMode = TIM_OCMODE_PWM2;
103
+ // sConfigOC.Pulse = __HAL_TIM_GET_COMPARE(&(HardwareTimer_Handle[index]->handle), HT->getChannel(channel));
104
+ // sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
105
+ // sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
106
+ // #if defined(TIM_OCIDLESTATE_SET) // TODO check this flag, looks like G4 uses something else...
107
+ // sConfigOC.OCIdleState = TIM_OCIDLESTATE_SET;
108
+ // #endif
109
+ // #if defined(TIM_OCNIDLESTATE_RESET) // TODO check this flag, looks like G4 uses something else...
110
+ // sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
111
+ // sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
112
+ // #endif
113
+ // HAL_TIM_PWM_ConfigChannel(&(HardwareTimer_Handle[index]->handle), &sConfigOC, channel);
92
114
return HT;
93
115
}
94
116
@@ -130,6 +152,40 @@ void _alignPWMTimers(HardwareTimer *HT1, HardwareTimer *HT2, HardwareTimer *HT3,
130
152
131
153
132
154
155
+ void _alignTimersNew () {
156
+ int numTimers = 0 ;
157
+ HardwareTimer *timers[numTimerPinsUsed];
158
+
159
+ // reset timer counters
160
+ for (int i=0 ; i<numTimerPinsUsed; i++) {
161
+ uint32_t index = get_timer_index ((TIM_TypeDef*)timerPinsUsed[i]->peripheral );
162
+ HardwareTimer *timer = (HardwareTimer *)(HardwareTimer_Handle[index]->__this );
163
+ bool found = false ;
164
+ for (int j=0 ; j<numTimers; j++) {
165
+ if (timers[j] == timer) {
166
+ found = true ;
167
+ break ;
168
+ }
169
+ }
170
+ if (!found)
171
+ timers[numTimers++] = timer;
172
+ }
173
+
174
+ // enable timer clock
175
+ for (int i=0 ; i<numTimers; i++) {
176
+ timers[i]->pause ();
177
+ timers[i]->refresh ();
178
+ }
179
+
180
+ for (int i=0 ; i<numTimers; i++) {
181
+ // SIMPLEFOC_DEBUG("Resuming timer ", getTimerNumber(get_timer_index(timers[i]->getHandle()->Instance)));
182
+ timers[i]->resume ();
183
+ }
184
+
185
+ }
186
+
187
+
188
+
133
189
134
190
int getLLChannel (PinMap* timer) {
135
191
#if defined(TIM_CCER_CC1NE)
@@ -243,13 +299,6 @@ STM32DriverParams* _initHardware6PWMInterface(long PWM_freq, float dead_zone, Pi
243
299
244
300
245
301
246
- #ifndef SIMPLEFOC_STM32_MAX_PINTIMERSUSED
247
- #define SIMPLEFOC_STM32_MAX_PINTIMERSUSED 12
248
- #endif
249
- int numTimerPinsUsed;
250
- PinMap* timerPinsUsed[SIMPLEFOC_STM32_MAX_PINTIMERSUSED];
251
-
252
-
253
302
/*
254
303
timer combination scoring function
255
304
assigns a score, and also checks the combination is valid
@@ -265,7 +314,10 @@ int scoreCombination(int numPins, PinMap* pinTimers[]) {
265
314
&& STM_PIN_CHANNEL (pinTimers[i]->function ) == STM_PIN_CHANNEL (timerPinsUsed[i]->function ))
266
315
return -2 ; // bad combination - timer channel already used
267
316
}
268
- // check for inverted channels - TODO move this to outer loop also...
317
+
318
+ // TODO LPTIM and HRTIM should be ignored for now
319
+
320
+ // check for inverted channels
269
321
if (numPins < 6 ) {
270
322
for (int i=0 ; i<numPins; i++) {
271
323
if (STM_PIN_INVERTED (pinTimers[i]->function ))
@@ -307,12 +359,30 @@ int scoreCombination(int numPins, PinMap* pinTimers[]) {
307
359
&& STM_PIN_CHANNEL (pinTimers[4 ]->function ) == STM_PIN_CHANNEL (pinTimers[5 ]->function )
308
360
&& STM_PIN_INVERTED (pinTimers[1 ]->function ) && STM_PIN_INVERTED (pinTimers[3 ]->function ) && STM_PIN_INVERTED (pinTimers[5 ]->function )) {
309
361
// hardware 6pwm, score <10
362
+
363
+ // TODO F37xxx doesn't support dead-time insertion, it has no TIM1/TIM8
364
+ // F301, F302 --> 6 channels, but only 1-3 have dead-time insertion
365
+ // TIM2/TIM3/TIM4/TIM5 don't do dead-time insertion
366
+ // TIM15/TIM16/TIM17 do dead-time insertion only on channel 1
367
+
368
+ // TODO check these defines
369
+ #if defined(STM32F4xx_HAL_TIM_H) || defined(STM32F3xx_HAL_TIM_H) || defined(STM32F2xx_HAL_TIM_H) || defined(STM32F1xx_HAL_TIM_H) || defined(STM32F100_HAL_TIM_H) || defined(STM32FG0x1_HAL_TIM_H) || defined(STM32G0x0_HAL_TIM_H)
370
+ if (STM_PIN_CHANNEL (pinTimers[0 ]->function )>3 || STM_PIN_CHANNEL (pinTimers[2 ]->function )>3 || STM_PIN_CHANNEL (pinTimers[4 ]->function )>3 )
371
+ return -8 ; // channel 4 does not have dead-time insertion
372
+ #endif
373
+ #ifdef STM32G4xx_HAL_TIM_H
374
+ if (STM_PIN_CHANNEL (pinTimers[0 ]->function )>4 || STM_PIN_CHANNEL (pinTimers[2 ]->function )>4 || STM_PIN_CHANNEL (pinTimers[4 ]->function )>4 )
375
+ return -8 ; // channels 5 & 6 do not have dead-time insertion
376
+ #endif
310
377
}
311
378
else {
312
-
313
379
// check for inverted low-side channels
314
380
if (STM_PIN_INVERTED (pinTimers[1 ]->function ) || STM_PIN_INVERTED (pinTimers[3 ]->function ) || STM_PIN_INVERTED (pinTimers[5 ]->function ))
315
381
return -6 ; // bad combination - inverted channel used on low-side channel in software 6-pwm
382
+ if (pinTimers[0 ]->peripheral != pinTimers[1 ]->peripheral
383
+ || pinTimers[2 ]->peripheral != pinTimers[3 ]->peripheral
384
+ || pinTimers[4 ]->peripheral != pinTimers[5 ]->peripheral )
385
+ return -7 ; // bad combination - non-matching timers for H/L side in software 6-pwm
316
386
score += 10 ; // software 6pwm, score >10
317
387
}
318
388
}
@@ -387,19 +457,23 @@ int findBestTimerCombination(int numPins, int index, int pins[], PinMap* pinTime
387
457
}
388
458
389
459
460
+
461
+
462
+
390
463
int findBestTimerCombination (int numPins, int pins[], PinMap* pinTimers[]) {
391
464
int bestScore = findBestTimerCombination (numPins, 0 , pins, pinTimers);
392
465
if (bestScore == NOT_FOUND) {
393
466
#ifdef SIMPLEFOC_STM32_DEBUG
394
- SimpleFOCDebug::print (" STM32: no workable combination found on these pins " );
395
- printTimerCombination (numPins, pinTimers, bestScore);
467
+ SimpleFOCDebug::println (" STM32: no workable combination found on these pins" );
396
468
#endif
397
469
return -10 ; // no workable combination found
398
470
}
399
- #ifdef SIMPLEFOC_STM32_DEBUG
400
- SimpleFOCDebug::print (" STM32: best: " );
401
- printTimerCombination (numPins, pinTimers, bestScore);
402
- #endif
471
+ else if (bestScore >= 0 ) {
472
+ #ifdef SIMPLEFOC_STM32_DEBUG
473
+ SimpleFOCDebug::print (" STM32: best: " );
474
+ printTimerCombination (numPins, pinTimers, bestScore);
475
+ #endif
476
+ }
403
477
return bestScore;
404
478
};
405
479
@@ -474,7 +548,7 @@ void* _configure3PWM(long pwm_frequency,const int pinA, const int pinB, const in
474
548
HardwareTimer* HT2 = _initPinPWM (pwm_frequency, pinTimers[1 ]);
475
549
HardwareTimer* HT3 = _initPinPWM (pwm_frequency, pinTimers[2 ]);
476
550
// allign the timers
477
- _alignPWMTimers (HT1, HT2, HT3);
551
+ // _alignPWMTimers(HT1, HT2, HT3);
478
552
479
553
uint32_t channel1 = STM_PIN_CHANNEL (pinTimers[0 ]->function );
480
554
uint32_t channel2 = STM_PIN_CHANNEL (pinTimers[1 ]->function );
@@ -488,6 +562,9 @@ void* _configure3PWM(long pwm_frequency,const int pinA, const int pinB, const in
488
562
timerPinsUsed[numTimerPinsUsed++] = pinTimers[0 ];
489
563
timerPinsUsed[numTimerPinsUsed++] = pinTimers[1 ];
490
564
timerPinsUsed[numTimerPinsUsed++] = pinTimers[2 ];
565
+
566
+ _alignTimersNew ();
567
+
491
568
return params;
492
569
}
493
570
@@ -574,7 +651,7 @@ void _writeDutyCycle4PWM(float dc_1a, float dc_1b, float dc_2a, float dc_2b, vo
574
651
// Configuring PWM frequency, resolution and alignment
575
652
// - BLDC driver - 6PWM setting
576
653
// - hardware specific
577
- void * _configure6PWM (long pwm_frequency, float dead_zone, const int pinA_h, const int pinA_l, const int pinB_h, const int pinB_l, const int pinC_h, const int pinC_l){
654
+ void * _configure6PWM (long pwm_frequency, float dead_zone, const int pinA_h, const int pinA_l, const int pinB_h, const int pinB_l, const int pinC_h, const int pinC_l){
578
655
if (numTimerPinsUsed+6 > SIMPLEFOC_STM32_MAX_PINTIMERSUSED) {
579
656
SIMPLEFOC_DEBUG (" STM32: ERR: too many pins used" );
580
657
return (STM32DriverParams*)SIMPLEFOC_DRIVER_INIT_FAILED;
@@ -602,7 +679,7 @@ void* _configure6PWM(long pwm_frequency, float dead_zone, const int pinA_h, cons
602
679
HardwareTimer* HT4 = _initPinPWMLow (pwm_frequency, pinTimers[3 ]);
603
680
HardwareTimer* HT5 = _initPinPWMHigh (pwm_frequency, pinTimers[4 ]);
604
681
HardwareTimer* HT6 = _initPinPWMLow (pwm_frequency, pinTimers[5 ]);
605
- _alignPWMTimers (HT1, HT2, HT3);
682
+ // _alignPWMTimers(HT1, HT2, HT3);
606
683
uint32_t channel1 = STM_PIN_CHANNEL (pinTimers[0 ]->function );
607
684
uint32_t channel2 = STM_PIN_CHANNEL (pinTimers[1 ]->function );
608
685
uint32_t channel3 = STM_PIN_CHANNEL (pinTimers[2 ]->function );
@@ -617,8 +694,11 @@ void* _configure6PWM(long pwm_frequency, float dead_zone, const int pinA_h, cons
617
694
.interface_type = _SOFTWARE_6PWM
618
695
};
619
696
}
620
- for (int i=0 ; i<6 ; i++)
621
- timerPinsUsed[numTimerPinsUsed++] = pinTimers[i];
697
+ if (score>=0 ) {
698
+ for (int i=0 ; i<6 ; i++)
699
+ timerPinsUsed[numTimerPinsUsed++] = pinTimers[i];
700
+ _alignTimersNew ();
701
+ }
622
702
return params; // success
623
703
}
624
704
@@ -629,21 +709,21 @@ void* _configure6PWM(long pwm_frequency, float dead_zone, const int pinA_h, cons
629
709
// Function setting the duty cycle to the pwm pin (ex. analogWrite())
630
710
// - BLDC driver - 6PWM setting
631
711
// - hardware specific
632
- void _writeDutyCycle6PWM (float dc_a, float dc_b, float dc_c, void * params){
712
+ void _writeDutyCycle6PWM (float dc_a, float dc_b, float dc_c, void * params){
633
713
switch (((STM32DriverParams*)params)->interface_type ){
634
714
case _HARDWARE_6PWM:
635
715
_setPwm (((STM32DriverParams*)params)->timers [0 ], ((STM32DriverParams*)params)->channels [0 ], _PWM_RANGE*dc_a, _PWM_RESOLUTION);
636
716
_setPwm (((STM32DriverParams*)params)->timers [2 ], ((STM32DriverParams*)params)->channels [2 ], _PWM_RANGE*dc_b, _PWM_RESOLUTION);
637
717
_setPwm (((STM32DriverParams*)params)->timers [4 ], ((STM32DriverParams*)params)->channels [4 ], _PWM_RANGE*dc_c, _PWM_RESOLUTION);
638
718
break ;
639
719
case _SOFTWARE_6PWM:
640
- float dead_zone = ((STM32DriverParams*)params)->dead_zone ;
641
- _setPwm (((STM32DriverParams*)params)->timers [0 ], ((STM32DriverParams*)params)->channels [0 ], _constrain (dc_a + dead_zone/ 2 , 0 , 1 )*_PWM_RANGE, _PWM_RESOLUTION);
642
- _setPwm (((STM32DriverParams*)params)->timers [0 ], ((STM32DriverParams*)params)->channels [1 ], _constrain (dc_a - dead_zone/ 2 , 0 , 1 )*_PWM_RANGE, _PWM_RESOLUTION);
643
- _setPwm (((STM32DriverParams*)params)->timers [1 ], ((STM32DriverParams*)params)->channels [2 ], _constrain (dc_b + dead_zone/ 2 , 0 , 1 )*_PWM_RANGE, _PWM_RESOLUTION);
644
- _setPwm (((STM32DriverParams*)params)->timers [1 ], ((STM32DriverParams*)params)->channels [3 ], _constrain (dc_b - dead_zone/ 2 , 0 , 1 )*_PWM_RANGE, _PWM_RESOLUTION);
645
- _setPwm (((STM32DriverParams*)params)->timers [2 ], ((STM32DriverParams*)params)->channels [4 ], _constrain (dc_c + dead_zone/ 2 , 0 , 1 )*_PWM_RANGE, _PWM_RESOLUTION);
646
- _setPwm (((STM32DriverParams*)params)->timers [2 ], ((STM32DriverParams*)params)->channels [5 ], _constrain (dc_c - dead_zone/ 2 , 0 , 1 )*_PWM_RANGE, _PWM_RESOLUTION);
720
+ float dead_zone = ((STM32DriverParams*)params)->dead_zone / 2 . 0f ;
721
+ _setPwm (((STM32DriverParams*)params)->timers [0 ], ((STM32DriverParams*)params)->channels [0 ], _constrain (dc_a - dead_zone, 0 . 0f , 1 . 0f )*_PWM_RANGE, _PWM_RESOLUTION);
722
+ _setPwm (((STM32DriverParams*)params)->timers [1 ], ((STM32DriverParams*)params)->channels [1 ], _constrain (dc_a + dead_zone, 0 . 0f , 1 . 0f )*_PWM_RANGE, _PWM_RESOLUTION);
723
+ _setPwm (((STM32DriverParams*)params)->timers [2 ], ((STM32DriverParams*)params)->channels [2 ], _constrain (dc_b - dead_zone, 0 . 0f , 1 . 0f )*_PWM_RANGE, _PWM_RESOLUTION);
724
+ _setPwm (((STM32DriverParams*)params)->timers [3 ], ((STM32DriverParams*)params)->channels [3 ], _constrain (dc_b + dead_zone, 0 . 0f , 1 . 0f )*_PWM_RANGE, _PWM_RESOLUTION);
725
+ _setPwm (((STM32DriverParams*)params)->timers [4 ], ((STM32DriverParams*)params)->channels [4 ], _constrain (dc_c - dead_zone, 0 . 0f , 1 . 0f )*_PWM_RANGE, _PWM_RESOLUTION);
726
+ _setPwm (((STM32DriverParams*)params)->timers [5 ], ((STM32DriverParams*)params)->channels [5 ], _constrain (dc_c + dead_zone, 0 . 0f , 1 . 0f )*_PWM_RANGE, _PWM_RESOLUTION);
647
727
break ;
648
728
}
649
729
}
0 commit comments