SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
b_g431_mcu.cpp
Go to the documentation of this file.
1#include "../../../hardware_api.h"
2
3#if defined(ARDUINO_B_G431B_ESC1)
4
5#include "b_g431_hal.h"
6#include "Arduino.h"
7#include "../stm32_mcu.h"
8#include "../../../../drivers/hardware_specific/stm32/stm32_mcu.h"
10#include "../stm32_adc_utils.h"
11
12#define _ADC_VOLTAGE 3.3f
13#define _ADC_RESOLUTION 4096.0f
14#ifdef OPAMP_USE_INTERNAL_CHANNEL
15#define ADC_BUF_LEN_1 4
16#define ADC_BUF_LEN_2 2
17#else
18#define ADC_BUF_LEN_1 5
19#define ADC_BUF_LEN_2 1
20#endif
21
22static ADC_HandleTypeDef hadc1;
23static ADC_HandleTypeDef hadc2;
24static OPAMP_HandleTypeDef hopamp1;
25static OPAMP_HandleTypeDef hopamp2;
26static OPAMP_HandleTypeDef hopamp3;
27
28static DMA_HandleTypeDef hdma_adc1;
29static DMA_HandleTypeDef hdma_adc2;
30
31volatile uint16_t adcBuffer1[ADC_BUF_LEN_1] = {0}; // Buffer for store the results of the ADC conversion
32volatile uint16_t adcBuffer2[ADC_BUF_LEN_2] = {0}; // Buffer for store the results of the ADC conversion
33
34
35// structure containing the configuration of the adc interrupt
36Stm32AdcInterruptConfig adc_interrupt_config[5] = {
37 {0, 0, 0}, // ADC1
38 {0, 0, 0}, // ADC2
39 {0, 0, 0}, // ADC3
40 {0, 0, 0}, // ADC4
41 {0, 0, 0} // ADC5
42};
43
44// function reading an ADC value and returning the read voltage
45// As DMA is being used just return the DMA result
46float _readADCVoltageLowSide(const int pin, const void* cs_params){
47 uint32_t raw_adc;
48 #ifdef OPAMP_USE_INTERNAL_CHANNEL
49 #define ADC1_OFFSET 0
50 #else
51 #define ADC1_OFFSET 1
52 #endif
53
54 switch (pin)
55 {
56 case A_OP1_OUT:
57 case -1:
58 raw_adc = adcBuffer1[0+ADC1_OFFSET];
59 break;
60 case A_OP2_OUT:
61 case -2:
62 raw_adc = adcBuffer2[0];
63 break;
64 #ifdef A_OP3_OUT
65 case A_OP3_OUT:
66 #endif
67 case -3:
68 #ifdef OPAMP_USE_INTERNAL_CHANNEL
69 raw_adc = adcBuffer2[1];
70 #else
71 raw_adc = adcBuffer1[0];
72 #endif
73 break;
74 case A_POTENTIOMETER:
75 raw_adc = adcBuffer1[1+ADC1_OFFSET];
76 break;
77 case A_TEMPERATURE:
78 raw_adc = adcBuffer1[2+ADC1_OFFSET];
79 break;
80 case A_VBUS:
81 raw_adc = adcBuffer1[3+ADC1_OFFSET];
82 break;
83 default:
84 raw_adc = 0;
85 break;
86 }
87 return raw_adc * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv;
88}
89
90void _configureOPAMP(OPAMP_HandleTypeDef *hopamp, OPAMP_TypeDef *OPAMPx_Def){
91 // could this be replaced with LL_OPAMP calls??
92 hopamp->Instance = OPAMPx_Def;
93 hopamp->Init.PowerMode = OPAMP_POWERMODE_HIGHSPEED;
94 hopamp->Init.Mode = OPAMP_PGA_MODE;
95 hopamp->Init.NonInvertingInput = OPAMP_NONINVERTINGINPUT_IO0;
96 hopamp->Init.InternalOutput = OPAMP_USE_INTERNAL_CHANNEL ? ENABLE : DISABLE;
97 hopamp->Init.TimerControlledMuxmode = OPAMP_TIMERCONTROLLEDMUXMODE_DISABLE;
98 hopamp->Init.PgaConnect = OPAMP_PGA_CONNECT_INVERTINGINPUT_IO0_BIAS;
99 hopamp->Init.PgaGain = OPAMP_PGA_GAIN_16_OR_MINUS_15;
100 hopamp->Init.UserTrimming = OPAMP_TRIMMING_FACTORY;
101 if (HAL_OPAMP_Init(hopamp) != HAL_OK)
102 {
103 SIMPLEFOC_DEBUG("HAL_OPAMP_Init failed!");
104 }
105}
106void _configureOPAMPs(OPAMP_HandleTypeDef *OPAMPA, OPAMP_HandleTypeDef *OPAMPB, OPAMP_HandleTypeDef *OPAMPC){
107 // Configure the opamps
108 _configureOPAMP(OPAMPA, OPAMP1);
109 _configureOPAMP(OPAMPB, OPAMP2);
110 _configureOPAMP(OPAMPC, OPAMP3);
111}
112
113void MX_DMA1_Init(ADC_HandleTypeDef *hadc, DMA_HandleTypeDef *hdma_adc, DMA_Channel_TypeDef* channel, uint32_t request) {
114 hdma_adc->Instance = channel;
115 hdma_adc->Init.Request = request;
116 hdma_adc->Init.Direction = DMA_PERIPH_TO_MEMORY;
117 hdma_adc->Init.PeriphInc = DMA_PINC_DISABLE;
118 hdma_adc->Init.MemInc = DMA_MINC_ENABLE;
119 hdma_adc->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
120 hdma_adc->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
121 hdma_adc->Init.Mode = DMA_CIRCULAR;
122 hdma_adc->Init.Priority = DMA_PRIORITY_LOW;
123 HAL_DMA_DeInit(hdma_adc);
124 if (HAL_DMA_Init(hdma_adc) != HAL_OK)
125 {
126 SIMPLEFOC_DEBUG("HAL_DMA_Init failed!");
127 }
128 __HAL_LINKDMA(hadc, DMA_Handle, *hdma_adc);
129}
130
131void* _configureADCInline(const void* driver_params, const int pinA,const int pinB,const int pinC){
132 _UNUSED(driver_params);
133 _UNUSED(pinA);
134 _UNUSED(pinB);
135 _UNUSED(pinC);
136
137 SIMPLEFOC_DEBUG("B-G431B does not implement inline current sense. Use low-side current sense instead.");
139}
140
141
142void* _configureADCLowSide(const void* driver_params, const int pinA,const int pinB,const int pinC){
143 _UNUSED(driver_params);
144
145 HAL_Init();
146 MX_GPIO_Init();
147 MX_DMA_Init();
148 _configureOPAMPs(&hopamp1, &hopamp3, &hopamp2);
149 MX_ADC1_Init(&hadc1);
150 MX_ADC2_Init(&hadc2);
151
152 HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);
153 HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);
154
155 MX_DMA1_Init(&hadc1, &hdma_adc1, DMA1_Channel1, DMA_REQUEST_ADC1);
156 MX_DMA1_Init(&hadc2, &hdma_adc2, DMA1_Channel2, DMA_REQUEST_ADC2);
157
158 if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcBuffer1, ADC_BUF_LEN_1) != HAL_OK)
159 {
160 SIMPLEFOC_DEBUG("DMA read init failed");
161 }
162 if (HAL_ADC_Start_DMA(&hadc2, (uint32_t*)adcBuffer2, ADC_BUF_LEN_2) != HAL_OK)
163 {
164 SIMPLEFOC_DEBUG("DMA read init failed");
165 }
166
167 HAL_OPAMP_Start(&hopamp1);
168 HAL_OPAMP_Start(&hopamp2);
169 HAL_OPAMP_Start(&hopamp3);
170
171 Stm32CurrentSenseParams* params = new Stm32CurrentSenseParams {
172 .pins = { pinA, pinB, pinC },
173 .adc_voltage_conv = (_ADC_VOLTAGE) / (_ADC_RESOLUTION),
174 .timer_handle = ((STM32DriverParams*)driver_params)->timers_handle[0],
175 };
176
177 return params;
178}
179
180extern "C" {
181void DMA1_Channel1_IRQHandler(void) {
182 HAL_DMA_IRQHandler(&hdma_adc1);
183}
184
185void DMA1_Channel2_IRQHandler(void) {
186 HAL_DMA_IRQHandler(&hdma_adc2);
187}
188}
189
190void* _driverSyncLowSide(void* _driver_params, void* _cs_params){
191 STM32DriverParams* driver_params = (STM32DriverParams*)_driver_params;
192 Stm32CurrentSenseParams* cs_params = (Stm32CurrentSenseParams*)_cs_params;
193
194 // stop all the timers for the driver
195 stm32_pause(driver_params);
196
197 // get the index of the adc
198 int adc_index = _adcToIndex(cs_params->adc_handle);
199
200 bool tim_interrupt = _initTimerInterruptDownsampling(cs_params, driver_params, adc_interrupt_config[adc_index]);
201 if(tim_interrupt) {
202 // error in the timer interrupt initialization
203 SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt not supported for B-G431");
205 }
206
207 // set the trigger output event
208 LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE);
209
210 // restart all the timers of the driver
211 stm32_resume(driver_params);
212
213 // return the cs parameters
214 // successfully initialized
215 // TODO verify if success in future
216 return _cs_params;
217}
218
219#endif
#define SIMPLEFOC_DEBUG(msg,...)
void * _configureADCInline(const void *driver_params, const int pinA, const int pinB, const int pinC=NOT_SET)
void * _driverSyncLowSide(void *driver_params, void *cs_params)
#define SIMPLEFOC_CURRENT_SENSE_INIT_FAILED
void * _configureADCLowSide(const void *driver_params, const int pinA, const int pinB, const int pinC=NOT_SET)
float _readADCVoltageLowSide(const int pinA, const void *cs_params)
const int const int const int pinC
GenericCurrentSenseParams * params
#define _UNUSED(v)
Definition foc_utils.h:14