Need to accurately find the generated frequency of a small generator motor to know its state and if all is running well.
I have Hall effect sensor that read the magnet of the flywheel every turn it does. This is on pin 2 of my arduino nano atmega328p 16 mhz. so it is configured to do an interrupt on rising of pin 2.
While this works ok, I am searching for way to count precisely time.
I was told that I could use timer0,1,or 2 for interrupts and that with prescaler, I know those are a bit picky.
S0 the goal is every time the timer1 running at 10khz do a cycle, it add 1 to a variable. while this go on, the input 2 create some interrupt,the isr routine copy the value of the timer1 variable and reset the timer1 to 0 ,the collected value is let say 823 in the variable.
So the hall effect sensor detect the magnet of the flywheel every 823 one 10 thousand of a second. SO to calculate the frequency we need to do that calculation. 1/(823/10000) so 823/10000= 0,0823 1 /0.0823 = 12.15 hz on a generator. DO you think that will be too much for an arduino nano?
It will also deal with a few relay to start the generator, open/close the choke, stop the generator, open and close the main breaker with a linear actuator. but those are not time critical as the rpm counter.
Do you think this will be to much demand on the arduino nano?
I dont need any display, but I do have a 16x2 lcd I could use.
You sound like you are recreating the setup on Timer0 that drives millis. If that's what you want, then you can just use millis or micros to figure the time between two interrupts.
If you want something more accurate, then use the input capture function on Timer1. It will require moving the input to pin 9 or 10, but it's a great way to measure frequency if nanoseconds count.
Another approach is:
Operate Timer/Counter-1 to generate 5-sec time slot (repetitive) during which the interrupts events (say: n) will be accumulated is a variable. The RPM of the wheel would be:
RPM = (n/5)*60 rev/min
Or
If you want to avoid the interrupt strategy, then let the TC-1 be generating 5-sec time slot in the background. You keep counting the wheel turning pulses until 5-sec time has elapsed and then compute the RPM.
Watch out when using millis(). Sometimes millis() advances with 2 milliseconds at a time, so when measuring short times, deviation can be large.
You might want to use micros(), this advances with 4 microseconds each time, giving a far better accuracy. In the ISR that is triggered by your Hall-sensor, read micros(), subtract the previous reading and you can calculate the frequency (1,000,000UL / (presentMicros – previousMicros)) or RPM (60,000,000UL / (presentMicros – previousMicros))
volatile unsigned int presentRPM = 0;
void calculateSpeed() {
static unsigned long previousMicros = micros(); // remember variable, initialize first time
unsigned long presentMicros = micros(); // read microseconds
unsigned long revolutionTime = presentMicros - previousMicros; // works fine with wrap-around of micros()
if (revolutionTime < 1000UL) return; // avoid divide by 0, also debounce, speed can't be over 60,000
presentRPM = (60000000UL / revolutionTime); // calculate
previousMicros = presentMicros; // store microseconds for next time
}
void setup() {
attachInterrupt(digitalPinToInterrupt(2), calculateSpeed, RISING); // define interrupt
}
void loop() {
// use presentRPM here
// also possible: presentFreq = (float) presentRPM / 60
}
Compiled, not tested.
No need to access registers.
Exactly. Unsingned long when reading millis() or microSeconds(). For low RPM this method gives a higher resolution than counting events in a time slot.
The static local variable previousMicros will be remembered next time, and will be initialized at the first time the function is executed.
The local variable presentMicros will be set every time the function is executed, and thrown away at the end of the function.