Skip to main content
Associate
June 20, 2025
Solved

Extern Potentiometer MCSDK

  • June 20, 2025
  • 1 reply
  • 1056 views

Hello,

I bought the STM32 Nucleo Pack with the Nucleo-F302R8, the X-Nucleo-IHM07M1 and a three-phase motor.

I use MCSDK to control my motor and it's no problem.

But when I want to add an external potentiometer to the ADC, I can't get the values from it.

I've tried lots of things, but nothing works.

To be sure of my potentiometer and my program, I tried with a simple program that doesn't use MCSDK, and everything worked perfectly.

 

Here is the configuration of my MX_ADC1_Init with mcsdk activated:

 
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */

ADC_AnalogWDGConfTypeDef AnalogWDGConfig = {0};
ADC_InjectionConfTypeDef sConfigInjected = {0};
ADC_ChannelConfTypeDef sConfig = {0};

/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */

/** Common config */
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_LEFT;
hadc1.Init.NbrOfConversion = 3;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}

/** Configure Analog WatchDog 1 */
AnalogWDGConfig.WatchdogNumber = ADC_ANALOGWATCHDOG_1;
AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_INJEC;
AnalogWDGConfig.HighThreshold = 0;
AnalogWDGConfig.LowThreshold = 0;
AnalogWDGConfig.Channel = ADC_CHANNEL_9;
AnalogWDGConfig.ITMode = DISABLE;
if (HAL_ADC_AnalogWDGConfig(&hadc1, &AnalogWDGConfig) != HAL_OK)
{
Error_Handler();
}

/** Configure Injected Channel */
sConfigInjected.InjectedChannel = ADC_CHANNEL_9;
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
sConfigInjected.InjectedNbrOfConversion = 1;
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_19CYCLES_5;
sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_FALLING;
sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T1_TRGO;
sConfigInjected.AutoInjectedConv = DISABLE;
sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
sConfigInjected.QueueInjectedContext = DISABLE;
sConfigInjected.InjectedOffset = 0;
sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)
{
Error_Handler();
}

/** Configure Regular Channel */
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}

/** Configure Regular Channel */
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}

/** Configure Regular Channel */
sConfig.Channel = ADC_CHANNEL_5; //Potentiometer
sConfig.Rank = ADC_REGULAR_RANK_3;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}

/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */

}
Best answer by Undertaker

Hello @MotorHobbyist ,

Before you sent me this information, I tried something myself. And I think it's similar to your method.

I added my external potentiometer in ADC by STM32CubeMX with the parameters:

PA4 - IN5 - Analog mode - No pull-up and No pull-down

Then I added in ADC_Regular_Conversion_Mode a new row with the parameters: 181.5 Cycles - No offset - 0

Then in STM32CubeIDE, I modified mc_config_common.c, mc_config_common.h and mc_app_hooks.c.

In the first, I added this code at the end in the user section:

uint16_t ExtPotentiometer_ValuesBuffer_M1[ 1 << POTENTIOMETER_LPF_BANDWIDTH_POW2_M1 ];

/*
 * Potentiometer instance for motor 1
 */
RegConv_t ExtPotRegConv_M1 =
{
 .regADC = ADC1,
 .channel = MC_ADC_CHANNEL_5,
 .samplingTime = POTENTIOMETER_ADC_SAMPLING_TIME_M1,
 .data = 0
};

Potentiometer_Handle_t ExtPotentiometer_M1 = {
 .LPFilterBandwidthPOW2 = POTENTIOMETER_LPF_BANDWIDTH_POW2_M1,
 .PotMeasArray = ExtPotentiometer_ValuesBuffer_M1
};

 

In the second, I added this:

extern Potentiometer_Handle_t ExtPotentiometer_M1;
extern RegConv_t ExtPotRegConv_M1;

 

Finally, in the last one, I modified it like this :

__weak void MC_APP_BootHook(void)
{
 /* RCM component initialization */
 (void)RCM_RegisterRegConv(&PotRegConv_M1);
 SPDPOT_Init(&SpeedPotentiometer_M1);
 /* USER CODE BEGIN BootHook */
 RCM_RegisterRegConv(&ExtPotRegConv_M1);
 POT_Init(&ExtPotentiometer_M1);
 /* USER CODE END BootHook */
}

/**
 * @brief Hook function called right after the Medium Frequency Task for Motor 1.
 *
 *
 *
 */
__weak void MC_APP_PostMediumFrequencyHook_M1(void)
{
 uint16_t rawValue = RCM_GetRegularConv(&PotRegConv_M1);
 if (SDC_GetOpenLoopFlag(pOLS[M1]))
 {
 SDC_Potentiometer_Run(pOLS[0], rawValue);
 }
 else
 {
 (void)SPDPOT_Run(&SpeedPotentiometer_M1, rawValue);
 }

 /* USER SECTION BEGIN PostMediumFrequencyHookM1 */
 uint16_t rawExtPotValue = RCM_GetRegularConv(&ExtPotRegConv_M1);
 POT_TakeMeasurement(&ExtPotentiometer_M1, rawExtPotValue);
 /* USER SECTION END PostMediumFrequencyHookM1 */
}

 

Then to retrieve my value in main.c I do like this:

#include "potentiometer.h"
extern SpeedPotentiometer_Handle_t SpeedPotentiometer_M1;
extern Potentiometer_Handle_t ExtPotentiometer_M1;
 if (POT_ValidValueAvailable(&ExtPotentiometer_M1))
 {
	 uint16_t extVal = POT_GetValue(&ExtPotentiometer_M1)>>4;
 }

 

Now I just have to check that it doesn't interfere with the motor

Regards
.

1 reply

Karl Yamashita
Principal
June 21, 2025

Use the </> when posting code. It properly formats it and so it's easier to view the code instead of all the text left hand adjusted

Code Snippet.jpg

 

You need to do is post code on where and how you're using your code along side with the MCSDK.

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Associate
June 21, 2025

Hello,
I can't post my code today but I can explain how it works.
For now, I just want to read the potentiometer value at the beginning of while(1) and just after start the motor for a while.
Once I'm sure that the potentiometer reading program is correct, I'll use this value as the setpoint for the motor.

cedric H
Technical Moderator
July 7, 2025

Hello @Undertaker,

 

With MCSDK 6.4.0 or 6.3.2, the potentiometer feature is already proposed. You can just enable it from the "Stage configuration" window as shown below:

cedricH_0-1751870115629.png

Once enabled, generate your project, and you will have all the leisure to read and understand the code.

The only condition to have the possibility to enable the potentiometer is that it is described in the power board (or inverter) and the signal is connected to an ADC input pin (which is the case in your pack).