2024-06-05 02:36 PM
Hello everyone,
I have designed my own card and used F103 uC on it. I want to measure battery voltage with DMA method. I hope to drive BLDC motor with this card one day
So, forget about the phase voltages first. I just want to sense battey voltage. I have defined some variables. I have voltage driver on the same line so i need to multiply every array value with multiplier. I eant to write buffer values to data array for true measurement of the voltage. Then i want to send this scaled values to my computer.
#define Buffer_Size 5
uint16_t V_BATT_ADC_Buffer[Buffer_Size]={0};
uint16_t V_BATT_ADC_Data[Buffer_Size]={0};
float V_BATT_ADC = 0.0;
float V_BATT = 0.0;
uint8_t V_BATT_Sense_Conv_End = 0;
float multiplier_V_BATT = (3.3/4095)*(100+5.6)/5.6;
void multiplyArray(uint16_t *array, size_t size, float multiplier) // Array multiplication function
{
for (size_t i = 0; i < size; i++)
{
array[i] = (uint16_t)(array[i] * multiplier);
}
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) // Get value with DMA and write it when Conv. Cmp. to other array function
{
if (hadc == &hadc3)
{
for(int i = 0 ; i<Buffer_Size; i++)
{
V_BATT_ADC_Data[i] = V_BATT_ADC_Buffer[i];
}
V_BATT_Sense_Conv_End=1;
}
}
int main(void)
....
....
HAL_ADC_Start_DMA(&hadc3, (uint32_t *)V_BATT_ADC_Buffer, Buffer_Size);
while(1)
........
........
if(V_BATT_Sense_Conv_End == 1)
{
size_t size = sizeof(V_BATT_ADC_Buffer)/sizeof(V_BATT_ADC_Buffer[0]);
multiplyArray(V_BATT_ADC_Buffer, size, multiplier_V_BATT);
char str[80];
int V_BATT_txlength = sprintf(str, "ADC Value: %d, Battery Voltage Level: %dV\r\n", V_BATT_ADC_Data[0], V_BATT_ADC_Data[1]);
HAL_UART_Transmit(&huart1, (uint8_t*)str, V_BATT_txlength, 100);
HAL_Delay(500);
V_BATT_Sense_Conv_End=0;
}
}
As summary, i want to sense battery voltage with dma then write it to an array then multiply this array according to my voltage divider and send it to my computer. I know it is little long but any help would be appreciated.
2024-06-05 05:16 PM
Use the code sample button so your code is properly formatted for easy reading.
2024-06-06 06:08 AM
Thanks a lot
#define Buffer_Size 5
void V_Sense_BATT(void);
void multiplyArray(uint16_t *V_BATT_ADC_Buffer, size_t size, float multiplier);
ADC_HandleTypeDef hadc3;
uint16_t V_BATT_ADC_Buffer[Buffer_Size]={0};
uint16_t V_BATT_ADC_Data[Buffer_Size]={0};
float V_BATT_ADC = 0.0;
float V_BATT = 0.0;
uint8_t V_BATT_Sense_Conv_End = 0;
float multiplier_V_BATT = (3.3/4095)*(100+5.6)/5.6;
static void MX_DMA_Init(void);
static void MX_ADC3_Init(void);
void multiplyArray(uint16_t *array, size_t size, float multiplier)
{
for (size_t i = 0; i < size; i++)
{
array[i] = (uint16_t)(array[i] * multiplier);
}
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if (hadc == &hadc3)
{
for(int i = 0 ; i<Buffer_Size; i++)
{
V_BATT_ADC_Data[i] = V_BATT_ADC_Buffer[i];
}
V_BATT_Sense_Conv_End=1;
}
}
int main(void)
{
HAL_ADC_Start_DMA(&hadc3, (uint32_t *)V_BATT_ADC_Buffer, Buffer_Size);
while (1)
{
if(V_BATT_Sense_Conv_End == 1)
{
size_t size = sizeof(V_BATT_ADC_Buffer)/sizeof(V_BATT_ADC_Buffer[0]);
multiplyArray(V_BATT_ADC_Buffer, size, multiplier_V_BATT);
char str[80];
int V_BATT_txlength = sprintf(str, "ADC Data 1: %d, ADC Data 2: %dV\r\n", V_BATT_ADC_Data[0], V_BATT_ADC_Data[1]);
HAL_UART_Transmit(&huart1, (uint8_t*)str, V_BATT_txlength, 100);
HAL_Delay(500);
V_BATT_Sense_Conv_End=0;
}
}
}
2024-06-06 09:36 PM
You seem to be transmitting the battery voltage correctly. So I guess i'm not understanding the issue?
2024-06-06 10:07 PM
Problem is i can not see battery voltage readings on CubeIDE Console. For testing the serial connection between my card and computer, i have used some dummy code. Looks like everything is okey. Then i narrow my code down and commented everything until;
HAL_ADC_Start_DMA(&hadc3, (uint32_t *)V_BATT_ADC_Buffer, Buffer_Size);
It looks like when i start dma, conversion never completes and there is an infinite loop. Could this be the problem?
2024-06-06 10:20 PM
When using DMA, you should not use the ADC conversion complete, but rather the DMA complete flag / interrupt.
And yes - at least on F7 / H7 - once started with HAL_ADC_Start_DMA() it runs forever unless stopped actively.
I actually like that for power monitoring: ADC / DMA is running constantly in the background, but I only check every few 100 ms by simply checking the ADC DMA buffer.
You showed only snippets of your main code, correct? Because there's no inits called...
2024-06-06 10:48 PM
Thanks for your reply.
@LCE wrote:When using DMA, you should not use the ADC conversion complete, but rather the DMA complete flag / interrupt.
So you say i dont have to use;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
What should i use instead of that? Can you please elaborate
@LCE wrote:
And yes - at least on F7 / H7 - once started with HAL_ADC_Start_DMA() it runs forever unless stopped actively.
I actually like that for power monitoring: ADC / DMA is running constantly in the background, but I only check every few 100 ms by simply checking the ADC DMA buffer.
Actually i was planning to check battery voltage every 1 seconds but measure phase voltages like every commutation. So i have to use conversion end flag for them.
@LCE wrote:You showed only snippets of your main code, correct? Because there's no inits called...
Yes
2024-06-06 11:19 PM
> What should i use instead of that? Can you please elaborate
Good question...
I think you can also activate DMA complete interrupts and callbacks.
As I said, I don't use these, just check the buffer when needed.
2024-06-07 01:32 PM
You're not showing enough code. Have no idea where you're calling HAL_ADC_Start_DMA from? What do you mean by infinite loop?
Attach your IOC file so we can see your settings.
2024-06-08 10:24 AM - edited 2024-06-15 12:24 PM
Hi, sorry for late response. When i start debugger mode, it constantly loops inside HAL library of DMA function. It takes readings but never skips to incomong line.
Again, thanks for your big interest.