Skip to content

Commit

Permalink
Partially handle case when there is no injected ADC
Browse files Browse the repository at this point in the history
  • Loading branch information
Candas1 committed Mar 22, 2024
1 parent cf09939 commit 9c3b732
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 77 deletions.
109 changes: 60 additions & 49 deletions src/current_sense/hardware_specific/stm32/stm32_adc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ int adc_inj_trigger[ADC_COUNT] = {0};
int adc_reg_trigger[ADC_COUNT] = {0};
ADC_HandleTypeDef *interrupt_adc = NP;
int max_inj_adc = 0;
int max_reg_adc = 0;

ADC_HandleTypeDef *_get_ADC_handle(ADC_TypeDef* Instance){
if (Instance == ADC1) return &hadc1;
Expand Down Expand Up @@ -188,6 +189,7 @@ int _add_ADC_sample(uint32_t pin,int32_t trigger,int type){
sample.adc_index = adc_index;

if (type == 0){
#ifdef ADC_INJECTED_SOFTWARE_START
if (adc_inj_channel_count[adc_index] == MAX_INJ_ADC_CHANNELS){
#ifdef SIMPLEFOC_STM32_DEBUG
SIMPLEFOC_DEBUG("STM32-CS: ERR: max inj channel reached: ", (int) sample.adc_index+1);
Expand All @@ -198,6 +200,7 @@ int _add_ADC_sample(uint32_t pin,int32_t trigger,int type){
sample.index = adc_inj_channel_count[adc_index];
adc_inj_channel_count[adc_index]++; // Increment total injected channel count for this ADC
max_inj_adc = max(max_inj_adc,adc_inj_channel_count[adc_index]); // Longest number of injected adc channels
#endif
}else{
if (adc_reg_channel_count[adc_index] == MAX_REG_ADC_CHANNELS){
#ifdef SIMPLEFOC_STM32_DEBUG
Expand All @@ -208,6 +211,7 @@ int _add_ADC_sample(uint32_t pin,int32_t trigger,int type){
sample.rank = _getRegADCRank(adc_reg_channel_count[adc_index] + 1);
sample.index = adc_reg_channel_count[adc_index];
adc_reg_channel_count[adc_index]++; // Increment total regular channel count for this ADC
max_reg_adc = max(max_reg_adc,adc_reg_channel_count[adc_index]); // Longest number of injected adc channels
}

samples[sample_count] = sample;
Expand All @@ -220,7 +224,9 @@ int _init_ADCs(){
for (int i=0;i<sample_count;i++){
if (_init_ADC(samples[i]) == -1) return -1;
if (samples[i].type == 0 ){
#ifdef ADC_INJECTED_SOFTWARE_START
if (_add_inj_ADC_channel_config(samples[i]) == -1) return -1;
#endif
}else{
if (_add_reg_ADC_channel_config(samples[i]) == -1) return -1;
}
Expand Down Expand Up @@ -359,48 +365,6 @@ int _init_DMA(ADC_HandleTypeDef *hadc){
return 0;
}

int _add_inj_ADC_channel_config(Stm32ADCSample sample)
{
ADC_InjectionConfTypeDef sConfigInjected = {};

#if !defined(STM32F1xx)
#if defined(ADC_EXTERNALTRIGINJECCONVEDGE_RISING)
sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONVEDGE_RISING;
#endif
#if defined(ADC_EXTERNALTRIGINJECCONV_EDGE_RISING)
sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING;
#endif
#endif

sConfigInjected.AutoInjectedConv = DISABLE;
#if defined(ADC_DIFFERENTIAL_ENDED) && !defined(ADC1_V2_5)
sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
#endif
sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
sConfigInjected.InjectedOffset = 0;
//sConfigInjected.InjecOversamplingMode = DISABLE;
//sConfigInjected.QueueInjectedContext = DISABLE;


int adc_index = _adcToIndex(sample.handle);

sConfigInjected.ExternalTrigInjecConv = adc_inj_trigger[sample.adc_index];
sConfigInjected.InjectedSamplingTime = sample.SamplingTime;
sConfigInjected.InjectedNbrOfConversion = adc_inj_channel_count[adc_index];
sConfigInjected.InjectedRank = sample.rank;
sConfigInjected.InjectedChannel = sample.channel;
if (HAL_ADCEx_InjectedConfigChannel(sample.handle, &sConfigInjected) != HAL_OK){
#ifdef SIMPLEFOC_STM32_DEBUG
SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init inj channel: ", (int) sConfigInjected.InjectedChannel);
#endif
return -1;
}

return 0;

}

int _add_reg_ADC_channel_config(Stm32ADCSample sample)
{
ADC_ChannelConfTypeDef AdcChannelConf = {};
Expand Down Expand Up @@ -461,8 +425,50 @@ int _calibrate_ADC(ADC_HandleTypeDef* hadc){
}


// Only if Injected ADC is available
#ifdef ADC_INJECTED_SOFTWARE_START
int _add_inj_ADC_channel_config(Stm32ADCSample sample)
{
ADC_InjectionConfTypeDef sConfigInjected = {};

#if defined(ADC_EXTERNALTRIGINJECCONVEDGE_RISINGFALLING)
sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONVEDGE_RISING;
#endif
#if defined(ADC_EXTERNALTRIGINJECCONV_EDGE_RISINGFALLING)
sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING;
#endif

sConfigInjected.AutoInjectedConv = DISABLE;
#if defined(ADC_DIFFERENTIAL_ENDED) && !defined(ADC1_V2_5)
sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
#endif
sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
sConfigInjected.InjectedOffset = 0;
//sConfigInjected.InjecOversamplingMode = DISABLE;
//sConfigInjected.QueueInjectedContext = DISABLE;


int adc_index = _adcToIndex(sample.handle);

sConfigInjected.ExternalTrigInjecConv = adc_inj_trigger[sample.adc_index];
sConfigInjected.InjectedSamplingTime = sample.SamplingTime;
sConfigInjected.InjectedNbrOfConversion = adc_inj_channel_count[adc_index];
sConfigInjected.InjectedRank = sample.rank;
sConfigInjected.InjectedChannel = sample.channel;
if (HAL_ADCEx_InjectedConfigChannel(sample.handle, &sConfigInjected) != HAL_OK){
#ifdef SIMPLEFOC_STM32_DEBUG
SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init inj channel: ", (int) sConfigInjected.InjectedChannel);
#endif
return -1;
}

return 0;

}

// Starts the injected ADC
int _start_ADC(ADC_HandleTypeDef* hadc){
int _start_inj_ADC(ADC_HandleTypeDef* hadc){
#ifdef SIMPLEFOC_STM32_DEBUG
SIMPLEFOC_DEBUG("STM32-CS: start inj ADC :",_adcToIndex(hadc)+1);
#endif
Expand All @@ -477,7 +483,7 @@ int _start_ADC(ADC_HandleTypeDef* hadc){
}

// Starts the regular ADC with interrupt
int _start_ADC_IT(ADC_HandleTypeDef* hadc){
int _start_inj_ADC_IT(ADC_HandleTypeDef* hadc){
#ifdef SIMPLEFOC_STM32_DEBUG
SIMPLEFOC_DEBUG("STM32-CS: start inj ADC with IT:",_adcToIndex(hadc)+1);
#endif
Expand Down Expand Up @@ -528,6 +534,7 @@ int _start_ADC_IT(ADC_HandleTypeDef* hadc){
}
return 0;
}
#endif

// Calibrated and starts all the ADCs that have been initialized
int _start_ADCs(int use_adc_interrupt){
Expand All @@ -545,10 +552,10 @@ int _start_ADCs(int use_adc_interrupt){
interrupt_adc == NP // if adc triggering the interrupt is not yet identified
){
// Only one ADC is started with interrupt
if(_start_ADC_IT(adc_handles[i]) == -1) return -1;
if(_start_inj_ADC_IT(adc_handles[i]) == -1) return -1;
interrupt_adc = adc_handles[i]; // Save adc handle triggering the interrupt
}else{
if(_start_ADC(adc_handles[i]) == -1) return -1;
if(_start_inj_ADC(adc_handles[i]) == -1) return -1;
}
}

Expand Down Expand Up @@ -583,8 +590,9 @@ int _start_DMA(ADC_HandleTypeDef* hadc){
return 0;
}


// Writes Injected ADC values to the adc buffer
void _read_ADC(ADC_HandleTypeDef* hadc){
void _read_inj_ADC(ADC_HandleTypeDef* hadc){

int adc_index = _adcToIndex(hadc);
int channel_count = adc_inj_channel_count[_adcToIndex(hadc)];
Expand All @@ -594,10 +602,10 @@ void _read_ADC(ADC_HandleTypeDef* hadc){
}

// Writes Injected ADC values to the adc buffer for all ADCs that have been initialized
void _read_ADCs(){
void _read_inj_ADCs(){
for (int i = 0; i < ADC_COUNT; i++){
if (adc_handles[i] != NP){
_read_ADC(adc_handles[i]);
_read_inj_ADC(adc_handles[i]);
}
}
}
Expand Down Expand Up @@ -632,6 +640,8 @@ uint32_t _read_ADC_pin(int pin){
}

extern "C" {
// Only if injected ADC available
#ifdef ADC_INJECTED_SOFTWARE_START
#if defined(STM32F4xx) || defined(STM32F7xx)
void ADC_IRQHandler(void)
{
Expand Down Expand Up @@ -668,6 +678,7 @@ extern "C" {
}
#endif
#endif
#endif
}

#endif
16 changes: 10 additions & 6 deletions src/current_sense/hardware_specific/stm32/stm32_adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ typedef struct Stm32ADCSample {
uint32_t SamplingTime = NP;
} Stm32ADCSample;


int _add_inj_ADC_sample(uint32_t pin,int32_t trigger);
int _add_reg_ADC_sample(uint32_t pin);
int _add_ADC_sample(uint32_t pin,int32_t trigger,int type);
Expand All @@ -123,20 +124,23 @@ int _init_DMA(ADC_HandleTypeDef *hadc);
int _init_OPAMP(OPAMP_HandleTypeDef *hopamp, OPAMP_TypeDef *OPAMPx_Def);
int _init_OPAMPs(void);
#endif
int _add_inj_ADC_channel_config(Stm32ADCSample sample);
int _add_reg_ADC_channel_config(Stm32ADCSample sample);

int _calibrate_ADC(ADC_HandleTypeDef* hadc);
int _start_ADC(ADC_HandleTypeDef* hadc);
int _start_ADC_IT(ADC_HandleTypeDef* hadc);
int _start_ADCs(int use_adc_interrupt = 0);
int _start_DMA(ADC_HandleTypeDef* hadc);
void _read_ADC(ADC_HandleTypeDef* hadc);
void _read_ADCs(void);
uint32_t _read_ADC_buf(int adc_index,int index);
uint32_t _read_DMA_buf(int adc_index,int index);
uint32_t _read_ADC_sample(int index);
uint32_t _read_ADC_pin(int pin);

#ifdef ADC_INJECTED_SOFTWARE_START
int _add_inj_ADC_channel_config(Stm32ADCSample sample);
int _start_inj_ADC(ADC_HandleTypeDef* hadc);
int _start_inj_ADC_IT(ADC_HandleTypeDef* hadc);
void _read_inj_ADC(ADC_HandleTypeDef* hadc);
void _read_inj_ADCs(void);
#endif


#endif
#endif
47 changes: 42 additions & 5 deletions src/current_sense/hardware_specific/stm32/stm32_mcu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ void* _configureADCInline(const void* driver_params, const int pinA,const int pi
.adc_voltage_conv = (_ADC_VOLTAGE)/(_ADC_RESOLUTION),
.samples = {NP,NP,NP},
.inj_trigger = NP,
.reg_trigger = NP,
};

#if defined(STM32F1xx) || defined(STM32F4xx) || defined(STM32F7xx) || defined(STM32G4xx) || defined(STM32L4xx)
Expand Down Expand Up @@ -69,6 +70,7 @@ void* _configureADCLowSide(const void* driver_params, const int pinA, const int
.adc_voltage_conv = (_ADC_VOLTAGE) / (_ADC_RESOLUTION),
.samples = {NP,NP,NP},
.inj_trigger = NP,
.reg_trigger = NP,
};
_adc_gpio_init(cs_params, pinA,pinB,pinC);

Expand Down Expand Up @@ -97,8 +99,9 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive
{
ADC_TypeDef *Instance = {};
int status;

// automating TRGO flag finding - hardware specific

#ifdef ADC_INJECTED_SOFTWARE_START
// automating Injected TRGO flag finding - hardware specific
uint8_t tim_num = 0;
while(driver_params->timers[tim_num] != NP && tim_num < 6){
cs_params->inj_trigger = _timerToInjectedTRGO(driver_params->timers[tim_num++]);
Expand All @@ -119,10 +122,37 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive

for(int i=0;i<3;i++){
if _isset(cs_params->pins[i]){
cs_params->samples[i] = _add_inj_ADC_sample(cs_params->pins[i],cs_params->inj_trigger);
cs_params->samples[i] = _add_ADC_sample(cs_params->pins[i],cs_params->inj_trigger,0);
if (cs_params->samples[i] == -1) return -1;
}
}
#else
// automating Injected TRGO flag finding - hardware specific
uint8_t tim_num = 0;
while(driver_params->timers[tim_num] != NP && tim_num < 6){
cs_params->reg_trigger = _timerToRegularTRGO(driver_params->timers[tim_num++]);
if(cs_params->reg_trigger == _TRGO_NOT_AVAILABLE) continue; // timer does not have valid trgo for injected channels

// this will be the timer with which the ADC will sync
cs_params->timer_handle = driver_params->timers[tim_num-1];
// done
break;
}
if( cs_params->timer_handle == NP ){
// not possible to use these timers for low-side current sense
#ifdef SIMPLEFOC_STM32_DEBUG
SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot sync any timer to regular channels!");
#endif
return -1;
}

for(int i=0;i<3;i++){
if _isset(cs_params->pins[i]){
cs_params->samples[i] = _add_ADC_sample(cs_params->pins[i],cs_params->reg_trigger,1);
if (cs_params->samples[i] == -1) return -1;
}
}
#endif

#ifdef ARDUINO_B_G431B_ESC1
// Add other channels to sample on this specific board
Expand Down Expand Up @@ -184,7 +214,11 @@ void _driverSyncLowSide(void* _driver_params, void* _cs_params){

// function reading an ADC value and returning the read voltage
float _readADCVoltageLowSide(const int pin, const void* cs_params){
if (!use_adc_interrupt) _read_ADCs(); // Fill the adc buffer now in case no interrup is used
// Only if injected ADC available
#ifdef ADC_INJECTED_SOFTWARE_START
if (!use_adc_interrupt) _read_inj_ADCs(); // Fill the adc buffer now in case no interrup is used
#endif

for(int i=0; i < 3; i++){
if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer
return _read_ADC_sample(((Stm32CurrentSenseParams*)cs_params)->samples[i]) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv;
Expand All @@ -194,6 +228,8 @@ float _readADCVoltageLowSide(const int pin, const void* cs_params){
}

extern "C" {
// Only if injected ADC available
#ifdef ADC_INJECTED_SOFTWARE_START
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){
// calculate the instance
int adc_index = _adcToIndex(AdcHandle);
Expand All @@ -204,8 +240,9 @@ extern "C" {
return;
}

_read_ADCs(); // fill the ADC buffer
_read_inj_ADCs(); // fill the ADC buffer
}
#endif
}


Expand Down
1 change: 1 addition & 0 deletions src/current_sense/hardware_specific/stm32/stm32_mcu.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ typedef struct Stm32CurrentSenseParams {
float adc_voltage_conv;
int samples[3] = {NP,NP,NP};
uint32_t inj_trigger = NP;
uint32_t reg_trigger = NP;
HardwareTimer* timer_handle = NP;
} Stm32CurrentSenseParams;

Expand Down
Loading

0 comments on commit 9c3b732

Please sign in to comment.