Skip to content

Commit 311dfe7

Browse files
committed
bugfix for low-side sync
1 parent 0bb487a commit 311dfe7

File tree

8 files changed

+255
-94
lines changed

8 files changed

+255
-94
lines changed

src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_mcu.cpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
// array of values of 4 injected channels per adc instance (3)
1717
uint32_t adc_val[3][4]={0};
1818
// does adc interrupt need a downsample - per adc (3)
19-
bool needs_downsample[3] = {1};
19+
bool needs_downsample[3] = {0};
2020
// downsampling variable - per adc (3)
2121
uint8_t tim_downsample[3] = {0};
2222

@@ -48,26 +48,49 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){
4848
// stop all the timers for the driver
4949
stm32_pause(driver_params);
5050

51+
// If DIR is 0 (upcounting), the next event is high-side active (PWM rising edge)
52+
// If DIR is 1 (downcounting), the next event is low-side active (PWM falling edge)
53+
bool next_event_high_side = (cs_params->timer_handle->Instance->CR1 & TIM_CR1_DIR) == 0;
54+
5155
// if timer has repetition counter - it will downsample using it
5256
// and it does not need the software downsample
5357
if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){
5458
// adjust the initial timer state such that the trigger
55-
// - for DMA transfer aligns with the pwm peaks instead of throughs.
56-
// - for interrupt based ADC transfer
5759
// - only necessary for the timers that have repetition counters
58-
cs_params->timer_handle->Instance->CR1 |= TIM_CR1_DIR;
59-
cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR;
60-
// remember that this timer has repetition counter - no need to downasmple
61-
needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0;
60+
// - basically make sure that the next trigger event is the one that is expected (high-side first then low-side)
61+
62+
// set the direction and the
63+
for(int i=0; i< 6; i++){
64+
if(driver_params->timers_handle[i] == NP) continue; // skip if not set
65+
if(next_event_high_side){
66+
// Set DIR bit to 0 (downcounting)
67+
driver_params->timers_handle[i]->Instance->CR1 |= TIM_CR1_DIR;
68+
// Set CNT to ARR so it starts upcounting from the top
69+
driver_params->timers_handle[i]->Instance->CNT = driver_params->timers_handle[i]->Instance->ARR;
70+
}else{
71+
// Set DIR bit to 0 (upcounting)
72+
driver_params->timers_handle[i]->Instance->CR1 &= ~TIM_CR1_DIR;
73+
// Set CNT to ARR so it starts upcounting from zero
74+
driver_params->timers_handle[i]->Instance->CNT = 0;// driver_params->timers_handle[i]->Instance->ARR;
75+
}
76+
}
6277
}else{
6378
if(!use_adc_interrupt){
6479
// If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing
6580
use_adc_interrupt = 1;
66-
#ifdef SIMPLEFOC_STM32_DEBUG
81+
uint8_t adc_index = _adcToIndex(cs_params->adc_handle);
82+
// remember that this timer does not have the repetition counter - need to downasmple
83+
needs_downsample[adc_index] = 1;
84+
85+
if(next_event_high_side) // Next event is high-side active
86+
tim_downsample[adc_index] = 0; // skip the next interrupt (and every second one)
87+
else // Next event is low-side active
88+
tim_downsample[adc_index] = 1; // read the next one (and every second one after)
89+
6790
SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used");
68-
#endif
6991
}
7092
}
93+
7194
// set the trigger output event
7295
LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE);
7396

@@ -127,6 +150,7 @@ extern "C" {
127150
adc_val[adc_index][0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1);
128151
adc_val[adc_index][1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2);
129152
adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3);
153+
adc_val[adc_index][3]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_4);
130154
}
131155
}
132156

src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
// array of values of 4 injected channels per adc instance (3)
1919
uint32_t adc_val[3][4]={0};
2020
// does adc interrupt need a downsample - per adc (3)
21-
bool needs_downsample[3] = {1};
21+
bool needs_downsample[3] = {0};
2222
// downsampling variable - per adc (3)
2323
uint8_t tim_downsample[3] = {0};
2424

@@ -50,25 +50,47 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){
5050
// stop all the timers for the driver
5151
stm32_pause(driver_params);
5252

53+
// If DIR is 0 (upcounting), the next event is high-side active (PWM rising edge)
54+
// If DIR is 1 (downcounting), the next event is low-side active (PWM falling edge)
55+
bool next_event_high_side = (cs_params->timer_handle->Instance->CR1 & TIM_CR1_DIR) == 0;
56+
5357
// if timer has repetition counter - it will downsample using it
5458
// and it does not need the software downsample
5559
if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){
5660
// adjust the initial timer state such that the trigger
57-
// - for DMA transfer aligns with the pwm peaks instead of throughs.
58-
// - for interrupt based ADC transfer
5961
// - only necessary for the timers that have repetition counters
60-
cs_params->timer_handle->Instance->CR1 |= TIM_CR1_DIR;
61-
cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR;
62-
// remember that this timer has repetition counter - no need to downasmple
63-
needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0;
62+
// - basically make sure that the next trigger event is the one that is expected (high-side first then low-side)
63+
64+
// set the direction and the
65+
for(int i=0; i< 6; i++){
66+
if(driver_params->timers_handle[i] == NP) continue; // skip if not set
67+
if(next_event_high_side){
68+
// Set DIR bit to 0 (downcounting)
69+
driver_params->timers_handle[i]->Instance->CR1 |= TIM_CR1_DIR;
70+
// Set CNT to ARR so it starts upcounting from the top
71+
driver_params->timers_handle[i]->Instance->CNT = driver_params->timers_handle[i]->Instance->ARR;
72+
}else{
73+
// Set DIR bit to 0 (upcounting)
74+
driver_params->timers_handle[i]->Instance->CR1 &= ~TIM_CR1_DIR;
75+
// Set CNT to ARR so it starts upcounting from zero
76+
driver_params->timers_handle[i]->Instance->CNT = 0;// driver_params->timers_handle[i]->Instance->ARR;
77+
}
78+
}
6479
}else{
6580
if(!use_adc_interrupt){
66-
// If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing
67-
use_adc_interrupt = 1;
68-
#ifdef SIMPLEFOC_STM32_DEBUG
69-
SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used");
70-
#endif
71-
}
81+
// If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing
82+
use_adc_interrupt = 1;
83+
uint8_t adc_index = _adcToIndex(cs_params->adc_handle);
84+
// remember that this timer does not have the repetition counter - need to downasmple
85+
needs_downsample[adc_index] = 1;
86+
87+
if(next_event_high_side) // Next event is high-side active
88+
tim_downsample[adc_index] = 0; // skip the next interrupt (and every second one)
89+
else // Next event is low-side active
90+
tim_downsample[adc_index] = 1; // read the next one (and every second one after)
91+
92+
SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used");
93+
}
7294
}
7395
// set the trigger output event
7496
LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE);
@@ -125,7 +147,8 @@ extern "C" {
125147

126148
adc_val[adc_index][0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1);
127149
adc_val[adc_index][1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2);
128-
adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3);
150+
adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3);
151+
adc_val[adc_index][3]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_4);
129152
}
130153
}
131154

src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,6 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive
132132
}
133133
}
134134

135-
#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT
136-
// enable interrupt
137-
HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
138-
HAL_NVIC_EnableIRQ(ADC_IRQn);
139-
#endif
140-
141135
cs_params->adc_handle = &hadc;
142136
return 0;
143137
}
@@ -174,13 +168,11 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int
174168
return 0;
175169
}
176170

177-
#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT
178171
extern "C" {
179172
void ADC_IRQHandler(void)
180173
{
181174
HAL_ADC_IRQHandler(&hadc);
182175
}
183176
}
184-
#endif
185177

186178
#endif

src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,16 @@
1818
// array of values of 4 injected channels per adc instance (3)
1919
uint32_t adc_val[3][4]={0};
2020
// does adc interrupt need a downsample - per adc (3)
21-
bool needs_downsample[3] = {1};
21+
bool needs_downsample[3] = {0};
2222
// downsampling variable - per adc (3)
23-
uint8_t tim_downsample[3] = {1};
23+
uint8_t tim_downsample[3] = {0};
24+
25+
26+
#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT
27+
uint8_t use_adc_interrupt = 1;
28+
#else
29+
uint8_t use_adc_interrupt = 0;
30+
#endif
2431

2532
void* _configureADCLowSide(const void* driver_params, const int pinA, const int pinB, const int pinC){
2633

@@ -44,28 +51,61 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){
4451
// stop all the timers for the driver
4552
stm32_pause(driver_params);
4653

54+
// If DIR is 0 (upcounting), the next event is high-side active (PWM rising edge)
55+
// If DIR is 1 (downcounting), the next event is low-side active (PWM falling edge)
56+
bool next_event_high_side = (cs_params->timer_handle->Instance->CR1 & TIM_CR1_DIR) == 0;
57+
4758
// if timer has repetition counter - it will downsample using it
4859
// and it does not need the software downsample
4960
if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){
5061
// adjust the initial timer state such that the trigger
51-
// - for DMA transfer aligns with the pwm peaks instead of throughs.
52-
// - for interrupt based ADC transfer
5362
// - only necessary for the timers that have repetition counters
54-
55-
cs_params->timer_handle->Instance->CR1 |= TIM_CR1_DIR;
56-
cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR;
57-
// remember that this timer has repetition counter - no need to downasmple
58-
needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0;
63+
// - basically make sure that the next trigger event is the one that is expected (high-side first then low-side)
64+
65+
// set the direction and the
66+
for(int i=0; i< 6; i++){
67+
if(driver_params->timers_handle[i] == NP) continue; // skip if not set
68+
if(next_event_high_side){
69+
// Set DIR bit to 0 (downcounting)
70+
driver_params->timers_handle[i]->Instance->CR1 |= TIM_CR1_DIR;
71+
// Set CNT to ARR so it starts upcounting from the top
72+
driver_params->timers_handle[i]->Instance->CNT = driver_params->timers_handle[i]->Instance->ARR;
73+
}else{
74+
// Set DIR bit to 0 (upcounting)
75+
driver_params->timers_handle[i]->Instance->CR1 &= ~TIM_CR1_DIR;
76+
// Set CNT to ARR so it starts upcounting from zero
77+
driver_params->timers_handle[i]->Instance->CNT = 0;// driver_params->timers_handle[i]->Instance->ARR;
78+
}
79+
}
80+
}else{
81+
if(!use_adc_interrupt){
82+
// If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing
83+
use_adc_interrupt = 1;
84+
uint8_t adc_index = _adcToIndex(cs_params->adc_handle);
85+
// remember that this timer does not have the repetition counter - need to downasmple
86+
needs_downsample[adc_index] = 1;
87+
88+
if(next_event_high_side) // Next event is high-side active
89+
tim_downsample[adc_index] = 0; // skip the next interrupt (and every second one)
90+
else // Next event is low-side active
91+
tim_downsample[adc_index] = 1; // read the next one (and every second one after)
92+
93+
SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used");
94+
}
5995
}
96+
6097
// set the trigger output event
6198
LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE);
6299

63100
// start the adc
64-
#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT
65-
HAL_ADCEx_InjectedStart_IT(cs_params->adc_handle);
66-
#else
67-
HAL_ADCEx_InjectedStart(cs_params->adc_handle);
68-
#endif
101+
if (use_adc_interrupt){
102+
// enable interrupt
103+
HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
104+
HAL_NVIC_EnableIRQ(ADC_IRQn);
105+
HAL_ADCEx_InjectedStart_IT(cs_params->adc_handle);
106+
}else{
107+
HAL_ADCEx_InjectedStart(cs_params->adc_handle);
108+
}
69109

70110
// restart all the timers of the driver
71111
stm32_resume(driver_params);
@@ -82,20 +122,19 @@ float _readADCVoltageLowSide(const int pin, const void* cs_params){
82122
uint8_t channel_no = 0;
83123
for(int i=0; i < 3; i++){
84124
if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer
85-
#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT
125+
if (use_adc_interrupt){
86126
return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv;
87-
#else
127+
}else{
88128
// an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3
89129
uint32_t channel = _getADCInjectedRank(channel_no);
90130
return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv;
91-
#endif
131+
}
92132
}
93133
if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++;
94134
}
95135
return 0;
96136
}
97137

98-
#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT
99138
extern "C" {
100139
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){
101140

@@ -111,8 +150,8 @@ extern "C" {
111150
adc_val[adc_index][0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1);
112151
adc_val[adc_index][1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2);
113152
adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3);
153+
adc_val[adc_index][3]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_4);
114154
}
115155
}
116-
#endif
117156

118157
#endif

src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
// array of values of 4 injected channels per adc instance (5)
2121
uint32_t adc_val[5][4]={0};
2222
// does adc interrupt need a downsample - per adc (5)
23-
bool needs_downsample[5] = {1};
23+
bool needs_downsample[5] = {0};
2424
// downsampling variable - per adc (5)
2525
uint8_t tim_downsample[5] = {0};
2626

@@ -52,24 +52,47 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){
5252
// stop all the timers for the driver
5353
stm32_pause(driver_params);
5454

55+
56+
// If DIR is 0 (upcounting), the next event is high-side active (PWM rising edge)
57+
// If DIR is 1 (downcounting), the next event is low-side active (PWM falling edge)
58+
bool next_event_high_side = (cs_params->timer_handle->Instance->CR1 & TIM_CR1_DIR) == 0;
59+
5560
// if timer has repetition counter - it will downsample using it
5661
// and it does not need the software downsample
5762
if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){
5863
// adjust the initial timer state such that the trigger
59-
// - for DMA transfer aligns with the pwm peaks instead of throughs.
60-
// - for interrupt based ADC transfer
6164
// - only necessary for the timers that have repetition counters
62-
cs_params->timer_handle->Instance->CR1 |= TIM_CR1_DIR;
63-
cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR;
64-
// remember that this timer has repetition counter - no need to downasmple
65-
needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0;
65+
// - basically make sure that the next trigger event is the one that is expected (high-side first then low-side)
66+
67+
// set the direction and the
68+
for(int i=0; i< 6; i++){
69+
if(driver_params->timers_handle[i] == NP) continue; // skip if not set
70+
if(next_event_high_side){
71+
// Set DIR bit to 0 (downcounting)
72+
driver_params->timers_handle[i]->Instance->CR1 |= TIM_CR1_DIR;
73+
// Set CNT to ARR so it starts upcounting from the top
74+
driver_params->timers_handle[i]->Instance->CNT = driver_params->timers_handle[i]->Instance->ARR;
75+
}else{
76+
// Set DIR bit to 0 (upcounting)
77+
driver_params->timers_handle[i]->Instance->CR1 &= ~TIM_CR1_DIR;
78+
// Set CNT to ARR so it starts upcounting from zero
79+
driver_params->timers_handle[i]->Instance->CNT = 0;// driver_params->timers_handle[i]->Instance->ARR;
80+
}
81+
}
6682
}else{
6783
if(!use_adc_interrupt){
6884
// If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing
6985
use_adc_interrupt = 1;
70-
#ifdef SIMPLEFOC_STM32_DEBUG
86+
uint8_t adc_index = _adcToIndex(cs_params->adc_handle);
87+
// remember that this timer does not have the repetition counter - need to downasmple
88+
needs_downsample[adc_index] = 1;
89+
90+
if(next_event_high_side) // Next event is high-side active
91+
tim_downsample[adc_index] = 0; // skip the next interrupt (and every second one)
92+
else // Next event is low-side active
93+
tim_downsample[adc_index] = 1; // read the next one (and every second one after)
94+
7195
SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used");
72-
#endif
7396
}
7497
}
7598

0 commit comments

Comments
 (0)