cancel
Showing results for 
Search instead for 
Did you mean: 

Read flow rate sensor with STM32F411RE Nucleo - Timer Interrupts

As.2
Associate II

I have a water flow rate sensor which I want to read with my STM32F411RE Nucleo-64 board. The output signal is a frequency. How can I read the signal?

The sensor has following properties:

Flow Range = 1 - 15 L/min

Pulses per Liter = 2200

Frequency Output = 37 - 550 Hz 

The conversion will be:

flow rate [L/min] = frequency output [Hz] * 60 / (Pulses per Liter) [1/L]

I am unsure on how to read the frequency output with my Nucleo board. I searched a bit already and found out that I need to use Timer Interrupts, however I am confused how to. Based on the reference guide for STM32F411CC I would use the general purpose timer - TIM2, TIM5, TIM3, TIM4.

I constantly read the input from the pin which the sensor is connected to. --> GPIO_PIN_ReadPin

Whilst I count upwards with my timer and compare each new time with the old time + 1s (I want to display the flow rate each second onto a serial terminal). When the condition (1s passed) is fulfilled, the frequency output value from the interrupt function is converted to a flow rate which can then be displayed via USART to my serial monitor.

How do I setup this timer? How do I incorporate the interrupt here?

Thanks for any help guys!

5 REPLIES 5

Choose a timer and one channel on that timer, and a corresponding pin. After having enabled given GPIO's clock in RCC, in GPIO_MODER, set that pin to AF, and in GPIO_AFR, set that pin to the proper AF number according to the pins AF table in Datasheet. Then enable clock to chosen TIM, set the chosen channel to Input Capture in TIMx_CCMRx and enable it in TIMx_CCER. Enable related interrupt in TIMx_DIER, and enable the given timer's interrupt in NVIC. Enable timer by setting TIMx_CR1.CEN.

Write an Interrupt Service Routine (ISR) with the appropriate name (see vector table in startup file), which checks if the flag respective to the given channel is set in TIMx_SR, and if yes, clear it and read out respective TIMx_CCRx, to determine the time when chosen edge on the input signal occured. From two successive readings and the timer clock frequency you determine the input signal's frequency.

JW

Thanks for your reply!

I think I got the jist of your idea for using TIM. I read the frequency from the sensor input signal with GPIO_ReadPin. Simultaneously I read the timer frequency as the GPIO signal goes high and then again when the signal goes low. I find the difference between the first and second timer frequency. This is the length of the sensor frequency signal being high. I can then use that to convert to a time in s, then with my formula get the flow rate in L/min.

However, as a STM nube the short description of yours I am not quite able to follow soz :grinning_face_with_sweat:

To see how much I understood I will write the steps to take, based on what I understood from your reply:

In CUBEIDE Pinout & Configuration:

  1. Timer --> choose TIM3, Channel 1 Input Capture direct mode. Enable NVIC TIM3 global interrupt
  2. GPIO --> set a pin as GPIO Input. You talk about enabling GPIO's clock however the RCC settings under GPIO don't show my pin...
  3. RCC --> HSE and LSE set to crystal. Enable RCC global interrupt

In stm32f4xx_it.c :

  1. The ISR would be void TIM3_IRQHandler(void) in which I can do HAL_GPIO_ReadPin to get the sensor frequency. With __HAL_TIM_GET_COUNTER I read the timer frequency at rise and fall of GPIO pin. Is this where I check for the flag respective? If yes, what do you exactly mean by it? I am not getting wiser with the UM1725 user manual. Why do I read a flag in TIMx_SR but then clear it?

I don't use Cube/CubeMX so can't help with clicking.

Read the timer chapter in Reference Manual (RM).

Input capture is a feature of timer, where each selected (e.g. each rising) edge of signal on TIMx_CHx pin will copy current content of TIMx_CNT register (i.e. the running counter) to given channel's TIMx_CCRx register, and also invoke an interrupt. So, you don't need to read a GPIO's state, you simply read that TIMx_CCRx register, store it, and calculate frequency from two consecutive values.

Try to find an example for Input Capture in Cube, maybe that will help.

JW

Thanks for your reply!

So, the input capture will capture both the frequency of the timer and cause the interrupt which captures the frequency of the pin to which the sensor is connected to? If so, how do I tell the µcontroller that e.g. pin PB_8 is the pin it should cause the interrupt to?

You basically read time from timer, and calculate frequency from that.

You cannot arbitrarily assign pins to time channels. See pin alternate functions in the datasheet, it contains assignment of various functions, including timer channels, to individual pins.

Clicking to timers in CubeMX should indicate which pins are related to given timer, too; I'm not familiar with that as I don't use CubeMX.

JW