2020-04-24 12:34 PM
Hello,
I want to send the float type voltage value that I read with stm32f429I discovery card using adc reference voltage via usb cdc. My problem is this; I read the adc reference voltage and voltage value, and I can assign it to a float type variable. But when I want to send this variable via usb, the voltage value is read infinitely and I cannot send it. Can you help with this problem? The codes I use are below;
#include "main.h"
#include "usb_device.h"
#include "usbd_cdc_if.h"
#include <string.h>
#include <stdio.h>
#define VREFIN_CAL ((uint16_t*)((uint32_t)0x1FFF7A2A))
uint16_t adc_value[2];
float Vadc = 0, Vdda = 0;
int count = 0;
char volt_array[16];
void Read_ADC()
{
if(HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
{
adc_value[count] = HAL_ADC_GetValue(&hadc1);
count++;
if(count == 2)
count = 0;
Vdda = (float) 3.3 * (*VREFIN_CAL) / adc_value[1];
Vadc = Vdda * adc_value[0] / 4095;
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_I2C1_Init();
MX_SPI1_Init();
MX_TIM2_Init();
MX_USB_DEVICE_Init();
HAL_ADC_Start(&hadc1);
while (1)
{
Read_ADC();
sprintf(volt_array, "%.4f\n\r", Vadc);
CDC_Transmit_HS((uint8_t*)volt_array, strlen(volt_array));
}
}
Thank you for your help.
2020-04-24 01:03 PM
You're sending it as a string, not a float.
> But when I want to send this variable via usb, the voltage value is read infinitely and I cannot send it.
What does this mean?
The first time you call Read_ADC(), you'll have adc_value[1] = 0, so your value is infinite. Is that what you mean?
You're calling CDC_Transmit_HS repeatedly, which isn't going to work if it's already busy. Should still send data occasionally though.
2020-04-24 01:22 PM
Hello there,
Thank you for your answer. When I watch the Vadc value as below, the value is read infinitely. (You can see in the first picture in the Annex-1.)
while (1)
{
Read_ADC();
sprintf(volt_array, "%.4f\n\r", Vadc);
CDC_Transmit_HS((uint8_t*)volt_array, strlen(volt_array));
}
Vadc value can be read if I don't use the sprintf function. So if I call in the following way, Vadc value can be read. (You can see the second picture in the Annex-2.)
while (1)
{
Read_ADC();
//sprintf(volt_array, "%.4f\n\r", Vadc);
CDC_Transmit_HS((uint8_t*)volt_array, strlen(volt_array));
}
2020-04-24 01:32 PM
On the first call, adc_value[1] = 0, thus
Vdda = (float) 3.3 * (*VREFIN_CAL) / adc_value[1];
is infinity. Thus,
Vadc = Vdda * adc_value[0] / 4095;
is infinity as well.
It looks like you're trying to convert two channels with the same ADC in the same conversion group. This requires DMA to handle effectively. Otherwise, the values will overwrite one another since they share the same output register ADC->DR. What you're trying can work, but only if your CPU is fast enough to handle every single interrupt and if your conversion rate is slow enough.
From the reference manual:
13.8.1 Using the DMA
Since converted regular channel values are stored into a unique data register, it is useful to
use DMA for conversion of more than one regular channel. This avoids the loss of the data
already stored in the ADC_DR register.
2020-04-24 01:52 PM
Hello,
Thank you for your answer. Should the use of DMA be for this application as follows?
#include "main.h"
#include "usb_device.h"
#include "usbd_cdc_if.h"
#include <string.h>
#include <stdio.h>
#define VREFIN_CAL ((uint16_t*)((uint32_t)0x1FFF7A2A))
uint32_t adc_value[2];
float Vadc = 0, Vdda = 0;
int count = 0;
char volt_array[16];
void Read_ADC()
{
if(HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
{
adc_value[count] = HAL_ADC_GetValue(&hadc1);
count++;
if(count == 2)
count = 0;
Vdda = (float) 3.3 * (*VREFIN_CAL) / adc_value[1];
Vadc = Vdda * adc_value[0] / 4095;
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_I2C1_Init();
MX_SPI1_Init();
MX_TIM2_Init();
MX_USB_DEVICE_Init();
HAL_ADC_Start_DMA(&hadc1, adc_value, 2); <------- UPDATED
while (1)
{
Read_ADC();
sprintf(volt_array, "%.4f\n\r", Vadc);
CDC_Transmit_HS((uint8_t*)volt_array, strlen(volt_array));
}
}