metal
Global Moderator
Hero Member
Offline
Posts: 2420
Thank You
-Given: 862
-Receive: 678
Top Topic Starter
|
|
« on: June 25, 2016, 10:13:15 22:13 » |
|
Hi,
I managed to 24KHz PWM the fan using TIM2 CH1 on PA5, the fan's PWM pin is connected directly to PA5, next step is to figure the correct way of measuring the speed of 4-wire fan using stm32f072. the architecture thinks is a different way compared to 8-bit archs.
|
|
« Last Edit: June 25, 2016, 10:15:52 22:15 by metal »
|
Logged
|
|
|
|
Mega32
Active Member
Offline
Posts: 179
Thank You
-Given: 207
-Receive: 37
|
|
« Reply #1 on: June 26, 2016, 05:28:39 17:28 » |
|
I did it on a 3-wire fan with an AVR , PWM & measure speed using an interrupt. The trick was to disable the irq for a short period when fired , to avoid "bouncing" from the rpm sensor.
Mega32
|
|
|
Logged
|
|
|
|
mars01
V.I.P
Hero Member
Offline
Posts: 537
Thank You
-Given: 697
-Receive: 1774
|
|
« Reply #2 on: June 26, 2016, 06:11:56 18:11 » |
|
Hi Metal,
Could you please post the code here? I am trying to work with STM32 Cortex M0 myself and it will be of help to see how you configured the chip. Thanks!
|
|
|
Logged
|
|
|
|
metal
Global Moderator
Hero Member
Offline
Posts: 2420
Thank You
-Given: 862
-Receive: 678
Top Topic Starter
|
|
« Reply #3 on: June 26, 2016, 08:10:15 20:10 » |
|
of course. Look at the comments inside MX_TIM2_Init function's body. You will understand how it is being done. I also included cubeMX file. Here is the link for the project P.S. Interesting, I seek help, I end up helping someone else
|
|
|
Logged
|
|
|
|
metal
Global Moderator
Hero Member
Offline
Posts: 2420
Thank You
-Given: 862
-Receive: 678
Top Topic Starter
|
|
« Reply #4 on: June 29, 2016, 04:04:27 16:04 » |
|
Mega32,
can you share the atmega code?
|
|
|
Logged
|
|
|
|
sam_des
Senior Member
Offline
Posts: 256
Thank You
-Given: 128
-Receive: 151
|
|
« Reply #5 on: June 30, 2016, 03:32:58 15:32 » |
|
@metal, RPM Sensor ISR->Disable RPM Sensor Interrupt->Start a Timer with predefined delay period->Do Counter math for RPM measurement->Return
Timer Expired ISR->Reenable RPM Sensor Interrupt->Stop/Disable Timer & Interrupt->Return
You can probably use your 24kHz PWM Timer Interrupt instead of using a separate timer by counting no. of times PWM interrupt is invoked for measuring disable period. You just need flag PWM ISR when to start counting delay from RPM ISR. Obviously Disable Period should be less than RPM interrupt period. _sam_des
|
|
« Last Edit: June 30, 2016, 03:35:29 15:35 by sam_des »
|
Logged
|
Never be afraid to do something new. Remember Amateurs built the Ark, Professionals built the Titanic !
|
|
|
metal
Global Moderator
Hero Member
Offline
Posts: 2420
Thank You
-Given: 862
-Receive: 678
Top Topic Starter
|
|
« Reply #6 on: July 01, 2016, 12:52:24 00:52 » |
|
you make me appear thickhead, explain more please
|
|
|
Logged
|
|
|
|
sam_des
Senior Member
Offline
Posts: 256
Thank You
-Given: 128
-Receive: 151
|
|
« Reply #7 on: July 01, 2016, 11:17:23 11:17 » |
|
@metal, 1) So you're getting a Pulse Train on Tach line of 4-Wire fan which is indicative of fan rpm. Ideally it should be 1 pulse/revolution, but it may be different, just refer to your Fan datasheet. You need to measure no. of pulses/second to get the actual RPS, multiplying it by 60 will give you RPM. 2) Use this pulse train as "external interrupt" (most probably Tach line is OD, so with external pullup resistor, you need interrupt on Hi->Lo transition) on one of uC line. This will be your RPM Sensor interrupt. This Interrupt Service Routine(ISR) should keep track of pulse-count for RPS measurement. 3) There is possibility of spurious pulses on this line(due to multiple reasons), so we should debounce it. So once you enter ISR of External Interrupt, you need to disable External Interrupt generation for brief period of time which will allow you to ignore spurious pulses. Once This brief period is over, you need to reenable External Interrupt again get to next pulse. 4) For precise generation of this "brief" period, you should use a spare hardware timer, instead of software delays. As longer period will lead to missing "valid" pulses & shorter may cause recognizing "invalid" pulses. 5) On entering RPM ISR, it will start this timer & disable itself. On Timer overflow, its Timer ISR will stop timer & reenable External RPM interrupt. 6) Since you have 24kHz PWM timer already running, you can enable its Overflow interrupt which will occur precisely every 41.66uS and use it to generate "disable period" by counting no. of times Timer OVF ISR is invoked after External interrupt is disabled. And after desired period is over, it can reenable External Interrupt. You may not use Compare Interrupt instead of Overflow, since Compare interrupt period will depend on duty cycle of your PWM. 7) You can also use this 24kHz Timer to for counting 'n' seconds needed for RPM pulse count & averaging for RPS result. Note that you may not need this "debounce" logic at all, but it never hurts to be of safer side. 9) One more additional complexity, when using PWM to drive FAN, is Tach line will most probably gets activated only when Power is applied during "ON" period of PWM. So during "OFF" period of PWM, Tach line won't generate the pulse, even when it should. This may result in wrong pulse count & ultimately wrong RPM measurement.This will probably help. http://www.analog.com/library/analogDialogue/archives/38-02/fan_speed.pdf
Hope this time, I am able to be clear... _sam_des
|
|
« Last Edit: July 01, 2016, 11:21:17 11:21 by sam_des »
|
Logged
|
Never be afraid to do something new. Remember Amateurs built the Ark, Professionals built the Titanic !
|
|
|
metal
Global Moderator
Hero Member
Offline
Posts: 2420
Thank You
-Given: 862
-Receive: 678
Top Topic Starter
|
|
« Reply #8 on: July 04, 2016, 02:41:05 02:41 » |
|
Thank you for your answer, very much!
It is logical to generate the 'disable period' using TIM2 which is already used for PWM generation, you are right, I like your approach tbh. If I got your idea correctly, I must use (N x 41.66uS) where N is the number that will finally determine for how long the RPM ISR should be disabled in order to debounce the tachometer line, once I reach N=x, I must re-enable the RPM ISR again. So, what is the best way to measure this period? Suppose we don't go the safe way and I decided to use TIM2 to count 1 second, still I am not sure if a time base of 41.66uS is accurate enough, provided that I need to pass 24003.84 interrupts in order to get 1 second and get the counts of RPM interrupts on the tachometer line.
Also, the FAN I am using is the 4-wire type, the power is always there, so I don't have to worry about the power being absent. The FAN is actually controlled by the PWM signal while power is applied all the time, contrary to 3-wire FANs. What I do respect about 4-wire FANs is that even at duty cycle = 0, the FAN is spinning at the lowest speed.
The FAN on which I want to run tests = AFB0712HHB, it seems that every 4T means one rotation, I can get away by just looking at high-low transitions, hence measuring only 2T, multiplied by 2 will yield the rotation time. 60 divided by this period will give me RPM.
|
|
« Last Edit: July 04, 2016, 02:50:31 02:50 by metal »
|
Logged
|
|
|
|
Mega32
Active Member
Offline
Posts: 179
Thank You
-Given: 207
-Receive: 37
|
|
« Reply #9 on: July 04, 2016, 04:40:57 16:40 » |
|
@Metal
Did you solve it your self , w. the explanations above ? Else i have to dig through my old code , to see if i can find it.
Mega32
|
|
|
Logged
|
|
|
|
sam_des
Senior Member
Offline
Posts: 256
Thank You
-Given: 128
-Receive: 151
|
|
« Reply #10 on: July 04, 2016, 06:36:05 18:36 » |
|
@metal,
Any particular reason to choose 24kHz?? Why not go for 25kHz? Nice round 40.00uS period giving 25k PWM ISRs for every 1 sec... AFAIK, if you are using STM32, you can have any prescalar from 1-65535, so you can get 25k PWM frequency as easily as 24k..
_sam_des
|
|
|
Logged
|
Never be afraid to do something new. Remember Amateurs built the Ark, Professionals built the Titanic !
|
|
|
metal
Global Moderator
Hero Member
Offline
Posts: 2420
Thank You
-Given: 862
-Receive: 678
Top Topic Starter
|
|
« Reply #11 on: July 05, 2016, 12:20:26 12:20 » |
|
oh, thank you both, really. first time I try to measure speed on my own! Yesterday, I tried to use IC of TIM16 and PWM of TIM17, results were good and tracking was excellent and funny I used 15 for the filter of the IC input. No debouncing required. HAL_TIM_IC_CaptureCallback did a fine job actually. sam_des, I know you will kill me byt I really want to try the ext. int. thing as well, Im curious to see the differences myself. One drawback of my approach is that if the fan stops, I can never find out more later. thanks again
|
|
« Last Edit: July 05, 2016, 02:13:33 14:13 by metal »
|
Logged
|
|
|
|
Mega32
Active Member
Offline
Posts: 179
Thank You
-Given: 207
-Receive: 37
|
|
« Reply #12 on: July 05, 2016, 06:04:26 18:04 » |
|
One drawback of my approach is that if the fan stops, I can never find out thanks again Just use another (or same) timer that increments a variable , and reset the variable in the capture INT If the variable goes above some threshold , the capture haven't fired , and fan must be stopped. Mega32
|
|
|
Logged
|
|
|
|
metal
Global Moderator
Hero Member
Offline
Posts: 2420
Thank You
-Given: 862
-Receive: 678
Top Topic Starter
|
|
« Reply #13 on: July 06, 2016, 02:25:47 14:25 » |
|
I believe I can use TIM17 interrupt to increment a variable, while TIM16 interrupt resets this variable, anyway, I need to see when TIM16 and TIM17 fire the interrupts correctly, I will dig more into it.
|
|
|
Logged
|
|
|
|
metal
Global Moderator
Hero Member
Offline
Posts: 2420
Thank You
-Given: 862
-Receive: 678
Top Topic Starter
|
|
« Reply #14 on: July 06, 2016, 08:48:55 20:48 » |
|
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { static uint8_t counter_ic = 0; // static uint8_t counter_rpm = 0; if(htim->Instance == TIM16) { if (counter_ic++ < 2) { input_capture_tim16_ch_1 += __HAL_TIM_GET_COMPARE(htim, TIM_CHANNEL_1); } else { rpm = 45 / (input_capture_tim16_ch_1 * 0.00001); input_capture_tim16_ch_1 = 0; counter_ic = 0; } __HAL_TIM_SET_COUNTER(htim, 0); timeout = 0; } }
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM17) { if (timeout++ > 250000) { rpm = 0; timeout = 0; } } }
|
|
|
Logged
|
|
|
|
metal
Global Moderator
Hero Member
Offline
Posts: 2420
Thank You
-Given: 862
-Receive: 678
Top Topic Starter
|
|
« Reply #15 on: July 07, 2016, 01:27:50 13:27 » |
|
here is the complete code download link for PWM and input capture, datasheet of the FAN, including a simple schematic and snapshot for keil while in debug mode.
|
|
« Last Edit: July 07, 2016, 02:53:28 14:53 by metal »
|
Logged
|
|
|
|
metal
Global Moderator
Hero Member
Offline
Posts: 2420
Thank You
-Given: 862
-Receive: 678
Top Topic Starter
|
|
« Reply #16 on: July 11, 2016, 08:31:27 08:31 » |
|
the new question, how can I do it the DMA way!!?? Seriously, I tried, but apparently I failed! Also, here is a link for the video testing the previous code.
|
|
« Last Edit: July 11, 2016, 08:33:39 08:33 by metal »
|
Logged
|
|
|
|
metal
Global Moderator
Hero Member
Offline
Posts: 2420
Thank You
-Given: 862
-Receive: 678
Top Topic Starter
|
|
« Reply #17 on: July 16, 2016, 04:35:07 16:35 » |
|
Is there any known issue with STM32F072 TIM2 and DMA? I can't see HAL_TIM_IC_CaptureCallback being called in DMA mode, it only works for interrupt mode only in TIM2 IC.. really strange...
|
|
|
Logged
|
|
|
|
|