STM32F103C8 RPM counter using Hall sensor

Thread Starter

NV64

Joined Feb 15, 2019
38
I want to do a rpm counter. I also have a problem with the hall sensor. STM32F103C8 microcontroller, sensor such https://www.aliexpress.com/item/329...ail.1000016.1.333239a3rFRUR9&isOrigTitle=true , IDE Keil 5.
Setting the clock:



Setting the timer:



If I understand correctly, 1 "tick" of the timer is 1 microsecond.
The D0 pin of the hall sensor is connected to timer 3 input 1. The function hallSensor is called in a FreeRTOS thread.When I bring the magnet to the sensor, I get into the interrupt. In debug mode, if put a breakpoint on rpmTmp = 60/halfCalc; I get a value. But I am not sure of its correctness. If do not set a breakpoint, the RPM is not calculated at all and is always zero.
Source code:
JavaScript:
static void rpmCalc(void);



//-----------------------------------------------------------------------------
void hallSensor(void)
{
    HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
 
    while(1)
    {
        if(flagUpdateData == 1)
        {
            flagUpdateData = 0;
            rpmCalc();         
        }
     
        //--- Reset RPM if 1 second no new value
        /*while(flagUpdateData != 1)
        {
            osDelay(10);
            cntWait++;
            if(cntWait == 100)
            {
                rpm = 0;
                cntWait = 0;
            }
         
            if(flagUpdateData == 1)
            {
                break;
            }
        }*/
        osDelay(50);
    }
}

//-----------------------------------------------------------------------------
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM3)
    {
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
        {
            cntCapture++;
            if(cntCapture == 1)
            {
                capValue1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
                //__HAL_TIM_SET_COUNTER(&htim3, 0x0000); // Reset counter
                //--- Reset counter
                TIM3->CNT = 0;

            }
            else if(cntCapture == 2)
            {
                capValue2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
                //__HAL_TIM_SET_COUNTER(&htim3, 0x0000); // Reset counter             
                //--- Reset counter
                TIM3->CNT = 0;
                cntCapture = 0;
                flagUpdateData = 1;                                     
             
            }         
            __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_UPDATE);         
            //currTime = osKernelSysTick();             
         
        }
    }
}

//-----------------------------------------------------------------------------
static void rpmCalc(void)
{ 
    uint32_t halfCalc = 0;
 
 
    //--- If the values are incorrect
    if((capValue2 - capValue1) <= 5)
    {
        cntCapture = 0;
        flagUpdateData = 0;
        TIM3->CNT = 0;
        return;
    }
 
    //--- Computation of the period, translation in seconds
    halfCalc = (capValue2 - capValue1)/1000;
    //--- Setting a ban on reading before writing the value of RPM
    setSemaphor(SemHallBusyHandle);
    //--- Calculation RPM
    rpmTmp = 60/halfCalc; 
    //--- Cancel reading ban 
    clrSemaphor(SemHallBusyHandle); 
}

//-----------------------------------------------------------------------------
uint32_t hallGetRpm(void)
{
    while(getSemaphor(SemHallBusyHandle))
    {
        osDelay(5);
    }
 
    return rpmTmp;
}
 
Last edited:

Thread Starter

NV64

Joined Feb 15, 2019
38
I tried to change the calculation method. Took the microcontroller STM32F746. Calculation: in the timer interrupt(when the magnet passes near the hall sensor) increasing the counter. In another thread, I call the RPM counting function once a second. In counter function interrupt (turn per second) multiplied by 60. The resulting value must be RPM. Resetting the interrupt counter. But I have an interrupt counter that shows about 218 interrupts per second. a simple electric motor can not develop such speed.
Source code:
JavaScript:
/* Function prototypes -------------------------------------------------------*/
void StartDefaultTask(void const * argument);
void TskLcd(void const * argument);

extern void MX_USB_DEVICE_Init(void);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/* USER CODE BEGIN FunctionPrototypes */

static void rpmCalc(void);
static int factor_digits(int num, int *digits, int limit);
/* USER CODE END FunctionPrototypes */

/* Hook prototypes */

/* Init FreeRTOS */

void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */
      
  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* definition and creation of TskLcd_ */
  osThreadDef(TskLcd_, TskLcd, osPriorityNormal, 0, 128);
  TskLcd_Handle = osThreadCreate(osThread(TskLcd_), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */
}

/* StartDefaultTask function */
void StartDefaultTask(void const * argument)
{
  /* init code for USB_DEVICE */
  MX_USB_DEVICE_Init();

  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */               
    HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);   
   
    for(;;)
    {       
        rpmCalc();
        osDelay(1000);
    }
  /* USER CODE END StartDefaultTask */
}

/* TskLcd function */
void TskLcd(void const * argument)
{
  /* USER CODE BEGIN TskLcd */
    /* Infinite loop */
   
    lcd2004Init(&hi2c1);
    lcdSendStringInPos(0, 0, "RPM: ");
   
    for(;;)
    {
        lcdSendNumInPos(0, 5, rpmTmp);
        osDelay(500);
        lcdClearChar(0, 5);
        lcdClearChar(0, 6);
        lcdClearChar(0, 7);
        lcdClearChar(0, 8);
        lcdClearChar(0, 9);
        osDelay(500);
    }
  /* USER CODE END TskLcd */
}

/* USER CODE BEGIN Application */
     //-----------------------------------------------------------------------------
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM3)
    {
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
        {
            cntCapture++;                   
            capValue1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);  
            //__HAL_TIM_SET_COUNTER(&htim3, 0x0000); // Reset counter
            //--- Reset counter
            //TIM3->CNT = 0;           
            __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_UPDATE);           
            //currTime = osKernelSysTick();               
           
        }  
    }
} 

//-----------------------------------------------------------------------------
static void rpmCalc(void)
{       
    int txMass[6];
    char massChar[5];
       
           
    //--- Calculation RPM
    rpmTmp = 60 * cntCapture;                   
    cntCapture = 0;
}
 
Top