This is how micro controllers were supposed to be used, not as sodding PC's!!! You get everything done with one counter and have a system timer for free and you don't even have to worry about reading the counter value but you could if you wanted 50ns accuracy. You also have a system clock variable that you can use, that is in a decent round number and unlike the arduino is what it says it is. at 400rpm you will have 75ms pulses which will be 1875 counts. that is 750 counts even at the highest speed. This means that you know every time the counter got to 100, that means you can increment a variable every 40µs, even at a fan speed of 2000rpm that is 30ms/rev or 15ms per pulse? at 2 pulses per rev. Now if you are not super hot on your accuracy of speed measuring what you can do is not only have a capture compare output running for PWM but the top count/rollover interrupt enabled. with the 16MHz that most people use that is 640 steps, or to run at 25kHz on a 100 step PWM that is a divider of 6.4, or if you were at 20MHz that is 8, wonder where I see that number a lot, it is likely that the counters can have a prescaler of 8. Now you need 25kHz PWM ? if the thing were running at 20MHz that would give you 800 steps (20MHz / 25kHz). It just needed a cast to float in the function return.Įven the ATmega328 has 3 timers: 2x 8 bit and one 16 bit. EDIT2: Localized the rate calculating logic to the getTachRateInRPM() function. EDIT: We don't stop the millis() clock just hold-off updating it by preventing the ISR to run briefly. Also, the rate is in RPM to avoid a divide by zero (in the last version). That way any slower math and floating point operations can be taken out of the critical section. I've updated the code below to do the bare minimum amount of work just take a snapshot of the vars (5 assignments + 1.5us interrupt overhead, I think). It'll just need to finish before you can change to a new PWM value. And TIMER1 should still be outputting the same PWM even if the CPU is in an ISR. So by keeping the interrupts-disabled state to a minimum (kept way below min(1ms,16ms)+overhead), you shouldn't lose any interrupts. I'm not sure of the need to call any ISR for TIMER1 ( ICR1?). TIMER1, the one you are using, should also be set and forget until the need to change the PWM value. TIMER0 is set and forget by Arduino runtime initialization. But we shouldn't stay in this interrupts-disabled state too long otherwise subsequent interrupts will be missed (flag still set, ISR yet to run when a newer interrupt arrives). And will run their ISR (and clear the flag) as soon as the call to interrupts() re-enables global interrupts. All timer interrupts and the external interrupt raise a flag when their interrupt occurs (see: TIFR0:TOV, TIFR1, EIFR). The noInterrupts() call stops all ISRs from executing. Assuming 1000 RPM fan, that's 16.6 times per second or an interrupt every 60 milliseconds. Pin 2 external interrupt is handled by the INT0_vect ISR which Arduino hides behind the attachInterrupt() call. Millis() returns the value of an internal variable that is updated every 1.024 milliseconds via TIMER0_OVF_vect ISR.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |