VESC Support - 1kW of Power!

Nice!

Thanks for sharing, this really will help me. I’ve got my head full of ‘can bus’ at the moment but will return to looking at current in a few weeks.

Any reason you are talking directly to registers and not using HAL libs? The HALs give a bit more cross board compatibility. Might not matter for vesc as all the boards I’ve seen are for stm32f405

@Owen_Williams,
You are right about the Hals for a best compatibility, but sometimes that permits to know better the mcu target, as I don’t know well yet the STM32 peripheral.

Here is the synchronize between TIM1 & TIM8 for the TRGO :

void Init_TIMER(void){
  /* Configure TIM1 in Master mode*/
  TIM_HandleTypeDef htim1;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim1.Instance = TIM1;
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
  if(HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    // Configuration Error 
    Error_Handler();
  }

  /* Configure TIM8 */
  TIM_HandleTypeDef htim8;

  RCC->APB2ENR |= RCC_APB2ENR_TIM8EN;

  htim8.Instance = TIM8;
  htim8.Init.Prescaler = 0;
  htim8.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED2;
  htim8.Init.Period = 168000000/500;  
  htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim8.Init.RepetitionCounter = 1;
  htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  /* Configure TIM8 in Gated slave mode &
  use the Internal Trigger 0 (ITR0) as trigger source */
  TIM_SlaveConfigTypeDef sSlaveConfig;

  sSlaveConfig.SlaveMode     = TIM_SLAVEMODE_RESET;
  sSlaveConfig.InputTrigger  = TIM_TS_ITR0;
  if(HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig) != HAL_OK)
  {
    /* Configuration Error */
    Error_Handler();
  }
} 

You will tell me, if it works from your side, when you get more time after the CAN :wink:

1 Like

Hi @Owen_Williams,
I think I found an issue, in fact the core is running only 48MHz (?), because my loop takes 138us (it is a lot!) to execute the FOC.
I found this with a scope with a pin toggle for the scope, and this bit of program:

while (1)
  {
    if ((HAL_GetTick () - time)> 5000) // Xsec interval
      {
        
        serial6.print("Core (Hz) = ");
        serial6.println(SystemCoreClock);
        serial6.print("Core (MHz) = ");
        serial6.println(SystemCoreClock / 1000000);
        serial6.print("HCLK (Hz) =");
        serial6.println(HAL_RCC_GetHCLKFreq ());
        serial6.print("APB1 (Hz) = ");
        serial6.println(HAL_RCC_GetPCLK1Freq ());
        serial6.print("APB2 (Hz) = ");
        serial6.println(HAL_RCC_GetPCLK2Freq ());
        serial6.println();
        time = HAL_GetTick ();
      }
  }

I don’t know how to fix this issue, could you help me ?

thanks.

Hi @Owen_Williams, @Antun_Skuric,
I got it ! I get 9000rpm @24V now !

It was therefore the loop time too long and the core frequency that was wrong.

For your information @Owen_Williams, the SystemClock_Config(void) from vesc_4_12.h doesn’t work with me, I have had to use the configuration as shown below:

void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;

  __PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
        
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;   // 8MHz
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLM = 8;           //  VCO input=1MHz, (default 0) frequency= 16M*(192/16)=192M
  RCC_OscInitStruct.PLL.PLLN = 336;         //VCO=336MHz    
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;  //main frequency=168MHz (default 0)
  RCC_OscInitStruct.PLL.PLLQ = 7;           //usb=48MHz  (default 4)
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_HCLK  
                              |RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;       
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;      //42MHz
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;      //84MHz
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);  // set FLASH waiting cycle=FLASH_LATENCY_5,set clock source



  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);

  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
}

From my side, my code here above with the code previous works well too.

1 Like

Very cool @Marc_O!

So you had to implement the current sending or you’re running the voltage mode?

Hi @Antun_Skuric,
Yes, I implemented the current mode low side shunts (2 here) with the Clarke/Park transforms using 3 currents.

c = ADC1->DR; 
a = ADC2->DR;

c -= offset_1;
a -= offset_2;
b = -(a+c);

ia *= I_SCALE;
ib *= I_SCALE;
ic *= I_SCALE;

Then I use the transform with these 3 currents, and so on.

So that I keep the “mode regular” for the ADCs, I synchronized these ones with TIM8 TRGO (TIM1 TRGO synchronized with TIM8 TRGO too, as shown here above).

Glad you’ve made progress. I’m pretty sure I’ve checked speeds recently (during can bus tests) and things look ok for me.

I’m setting -D HSE_VALUE=8000000
as a build flag and trying not to use HSI otherwise SerialUSB won’t work.

I’ll try to print out some hz values when i get time.

@Owen_Williams, @Antun_Skuric,
I think to have found another issue about Hall sensors this time. The original “sensor.getVelocity()” sometimes returns 0, even at high velocity. I modified like this to fix it:

/*
  Shaft velocity calculation
  function using mixed time and frequency measurement technique
*/
float HallSensor::getVelocity(){
  if (pulse_diff <= 0 || pulse_diff > 130000){
    return 0;
  } else {
    float Ts = pulse_diff * 1e-6;
    return direction * (_2PI / cpr) / Ts;
  }
}

130000 corresponds to around 10 rpm, which is more than enough for hall effect sensors.

I can see the problem, but I’m not happy with that fix as the replaced code does fix the slow speed case.

At slow speed the last velocity might be say 0.1 rad/s, it then stops. There are no more interrupts, therefore pulse_timestamp and pulse_diff do not change. The velocity would continue to report 0.1 rad/s for ever.

Do you think pulse_diff > 130000 is needed? Are you seeing the occasional freakish high readings?

Would you be happy with

if (pulse_diff <= 0 || ((_micros() - pulse_timestamp) > timeout_factor * pulse_diff)){

Where timeout factor defaults to 1.1 but can be configured higher?

If you are not interested in spotting a stop situation quickly you could set it to 10.0 or something?

@Owen_Williams,
I would write this rather :

if (pulse_diff <= 0 || ((_micros() - pulse_timestamp) > timeout_velocity)){
    return 0;
  } else {
    float Ts = pulse_diff * 1e-6;
    return direction * (_2PI / cpr) / Ts;
  }

From my point of view (but it is my point of view :wink: ), yes, it is needed, like for “pulse_diff <= 0” is needed instead of “pulse_diff == 0” from original code. I would avoid to use pulse_diff with timeout_factor.

The compromise is to create a variable :

int32_t timeout_velocity = 1000000 / ((RPM / 60) * 2 * POLE_PAIRS * 6); // minimum velocity of Hall sensors, 

I tried something similar initially. I set timeout velocity to 1s.

…but when velocity is 0 in reality but sensor is reporting old velocity because timeout hasn’t happened yet, the velocity loop becomes unstable/unhappy as it overcompensates.

The current approach, whilst a bit wrong is reasonably stable at slow speeds.

The intuition is that if your last pulse diff is 500ms then you can expect no info (new pulse) for about 500ms. If it is late then perhaps it has stopped. In reality, particularly at high speed, it is probably slowing down. I think the algorithm needs some sort of velocity half-life when a pulse is ‘late’ but at slow speed this is latency (which could cause instability).

Hi @Owen_Williams,
You are quite right for the reasoning whether for high speed or low speed, because it is the case here, and the behavior we are facing. The calculation time also is important at high velocity.
Anyway, below 50 rpm with hall sensors and 8 pôles or 14 pôles motor, it becomes difficult to get a stable velocity due to the resolution per turn (24 or 42 counts per turn i.e.).

Once that we told this, I think it would be interesting to improve this important function…to think about.

1 Like

So what is the verdict on SimpleFOC with the VESC4.12? works well? What are the changes needed in the code?

Hi,
I am new to SimpleFOC. And I have a Flysky 4.20

I have managed to move the motor in open loop.

But the driver(drv8302) doesn’t work with the latest version of the SimpleFoc(2.2). It only works with 2.0.2 version. Any Idea how to update to the latest version?

I see the open loop draws much current. But I couldn’t move the motor in closed-loop. The motor vibrate a lot. Any idea?

Regards.

Hi, and welcome @PathumSuda ,

May I ask which sensor you are using? Can you print the angle values from the sensor when turning the motor just by hand? Does it look plausible?

The drv8302 should be supported in SimpleFOC 2.2, and if it is working in open loop, but not in closed loop, then probably the issue is not with the driver, but with the sensor…

Hi, Thank you for the reply @runger,

Yes, the problem was with the sensor and I fixed it. Now it’s working in a closed-loop too.

I compiled the same code from Arduino IDE and uploaded it, then it worked with the SimpleFOC 2.2, But it didn’t work with platform io.

The only problem I am facing is the motor tuning. When I increase the velocity of the motor above 200 rad/s, it starts to draw much current.

Any advice for tuning?

Regards.

Hey @PathumSuda ,

Sorry for the late reply…

You could try the option lib_archive = false in your platformio.ini, if you did not already do this.

You can see how quickly your loop is running and do things to make it faster (remove printf, etc).

Which motor are you using? What RPM can you expect to get from it?