RPM measurement without attachInterrupt?

Hello!
The project I'm working on involves a current sensor and an IR sensor which monitors the status of a fan.

I'm using dfrobot's line tracking sensor and grove's rotary detection code to measure rpm.

The problem is, the current updates frequently than the rpm. Is there a way where I can update them at the same time? Maybe, display them both on the void loop() or get even the past value of rpm so the current and rpm change simultaneously?

Here's the code:

#include <TimerOne.h>

int curPin = 19;

unsigned int counter = 0;

void blink(){
  counter++;
}

void timerIsr(){
  Timer1.detachInterrupt();  //disable the timer1 
  Serial.print(counter,DEC); Serial.println(" rpm"); 
  counter=0;  
  Timer1.attachInterrupt( timerIsr );  //enable the timer1
}
//----------

void setup(){
  Serial.begin(9600);
  Timer1.initialize(60000000); // set a timer of length 1sec
  attachInterrupt(0, blink, RISING);  //INT0
  Timer1.attachInterrupt( timerIsr ); // attach the service routine here
}

void loop(){
  Serial.print(readCurrent(curPin)); Serial.println(" A");
}

float readCurrent(int pin){
  float average = 0;
  for(int i = 0; i < 1000; i++) {
  average = average + (.0264 * analogRead(pin) -13.51);
  delay(1);
  }
  average = average / 1000;
  
  if(average < 0){
    average = average * (-1);
  }
  return average;
}

Using Serial inside an ISR is not good, and I'm surprised it works at all

Added
int finalCounter

I'm cheating a bit, you really need a flag and a variable, but I'm using -1 to indicate data not available yet, as I assume that 0 may be a valid number

if you only want to display the current when you display the rpm, move the
Serial.print(readCurrent(curPin)); Serial.println(" A");
inside the if {}

int finalCounter=-1;

void timerIsr(){
 // Timer1.detachInterrupt();  //disable the timer1 
 // Serial.print(counter,DEC); Serial.println(" rpm"); 
finalCounter=counter;
  counter=0;  
  //Timer1.attachInterrupt( timerIsr );  //enable the timer1
}
//----------

void setup(){
  Serial.begin(9600);
  Timer1.initialize(60000000); // set a timer of length 1sec
  attachInterrupt(0, blink, RISING);  //INT0
  Timer1.attachInterrupt( timerIsr ); // attach the service routine here
}

void loop(){
  Serial.print(readCurrent(curPin)); Serial.println(" A");
if (finalCounter!=-1)
{
 Serial.print(counter,DEC); Serial.println(" rpm"); 
finalCounter=-1;
}
}

arduinoTime:
The problem is, the current updates frequently than the rpm. Is there a way where I can update them at the same time? Maybe, display them both on the void loop() or get even the past value of rpm so the current and rpm change simultaneously?

when timerISR runs, just store the value to a global variable instead of printing.

then print it in the loop() function:

#include <TimerOne.h>

int curPin = 19;

unsigned int counter = 0;
unsigned int lastCount;

void blink(){
  counter++;
}

void timerIsr(){
  Timer1.detachInterrupt();  //disable the timer1 
  lastCount = counter; 
  counter=0;  
  Timer1.attachInterrupt( timerIsr );  //enable the timer1
}
//----------

void setup(){
  Serial.begin(9600);
  Timer1.initialize(60000000); // set a timer of length 1sec
  attachInterrupt(0, blink, RISING);  //INT0
  Timer1.attachInterrupt( timerIsr ); // attach the service routine here
}

void loop(){
  Serial.print(readCurrent(curPin)); Serial.println(" A");
  Serial.print(counter,DEC); Serial.println(" rpm"); 
}

float readCurrent(int pin){
  float average = 0;
  for(int i = 0; i < 1000; i++) {
  average = average + (.0264 * analogRead(pin) -13.51);
  delay(1);
  }
  average = average / 1000;
  
  if(average < 0){
    average = average * (-1);
  }
  return average;
}

Thank you for the fast response, Sir BulldogLowell and Sir rogerClark!

I think I'll go with Sir BulldogLowell's code as the rpm value is more constant :slight_smile:
Just need to change counter to lastCount in void loop()

arduinoTime:
Thank you for the fast response, Sir BulldogLowell and Sir rogerClark!

I think I'll go with Sir BulldogLowell's code as the rpm value is more constant :slight_smile:
Just need to change counter to lastCount in void loop()

errrr... uhhh.,. right... that was a, a, a test, yeah a test!

and... uhhh... you passed

:blush:

I suspect you don't need to use either timers or timer interrupts for what you are doing - just the ISR for counting the RPM.

You could use millis() for the timing as in the Blink Without Delay example sketch and the extended demo in the first post in this Thread.

...R

I have not analized your code in detail. AFAIK serial.print and interrupts do not mix properly (I had problems using interrupts from an encoder and motorizing results -simultaneously through the serial monitor).

Regards

Is there a way to avoid using attachInterrupt() without making my code longer?

No.

@Robin2 gave you a great recommendation and some demonstration code with which you could easily add another sensor and detect the RPM of two spinning wheels:

two interrupts, two sensors.

http://forum.arduino.cc/index.php?topic=254053.msg1797991#msg1797991

Why are you confusing everyone and wasting everyone's time with 3 Threads on the same subject.

I am asking the moderator to merge them.

...R

Moderator edit: emphasis added

I thought they were 3 different topics :blush:

'displaying rpm and amps simultaneously'

  • I want to print current reading and rpm measurement at the same time
  • this was fixed by Sir BulldogLowell

'unstable current reading when mixed with other code'

  • I was pertaining to the LCD Keypad Shield because when I use the rpm and amps code, readings are stable

'rpm measurement without attachInterrupt()'

  • If I want to add more IR sensor

Sorry, I may have confused you because I used the same header saying it's for the fan monitoring project.

..but all is well, I think it's ok if everything is here

All your questions relate to the same background information.

And please delete the 4th Thread

...R

And please delete the 4th Thread

I want to, but I can't.

PaulS:

Is there a way to avoid using attachInterrupt() without making my code longer?

No.

Sir, how long will it be if I will not use attachInterrupt()?

arduinoTime:

PaulS:

Is there a way to avoid using attachInterrupt() without making my code longer?

No.

Sir, how long will it be if I will not use attachInterrupt()?

Did you check out @Robin2's post above?

not too much longer, but you have to learn that part: "blink without delay" extended for multiple events

BulldogLowell:
@Robin2 gave you a great recommendation and some demonstration code with which you could easily add another sensor and detect the RPM of two spinning wheels:

two interrupts, two sensors.

Sir BuldogLowell, how can I measure the rpm in the 'SeveralThingsAtTheSameTimeRev1.ino'?
The code i found on grove.com has a command attachInterrupt(0, blink, RISING)--the RISING means trigger when the pin goes from low to high--should I count the updateLed_A_State() change from LOW to HIGH? How?

You are using an Uno, right?

Yes. Sorry, I'm not good at programming.

Sir BuldogLowell, how can I measure the rpm in the 'SeveralThingsAtTheSameTimeRev1.ino'?

What I meant was, what should I count to determine the rpm of the fan?

something like this, which is not tested...

you can reduce the sampling time and calculate the RPM accordingly.

int pinOne = 2; //interrupt Zero on pin2
int pinTwo = 3; //interrupt One on pin3
int wheelOneCount = 0;
int wheelTwoCount = 0;
unsigned long startTime;
unsigned long oneMinute = 60000UL;  //sample over a period of one minute
//
void setup()
{
  Serial.begin(9600);
  attachInterrupt(0, countWheelOne, RISING); // when sensor voltage rises
  attachInterrupt(1, countWheelTwo, RISING);
  startTime = millis();
}

void loop()
{
  if (millis() - startTime >= oneMinute)
  {
    int rpmOne = wheelOneCount;
    int rpmTwo = wheelTwoCount;
    Serial.print(F("Wheel One RPM: "));
    Serial.println(rpmOne);
    Serial.print(F("Wheel Two RPM: "));
    Serial.println(rpmTwo);
    wheelOneCount = 0;
    wheelTwoCount = 0;
    startTime = millis();
  }
}
//
void countWheelOne()
{
  wheelOneCount++;
}
//
void countWheelTwo()
{
  wheelTwoCount++;
}

Thank you Sir Buldoglowell but can I do it without attachInterrupt()? I want to read the blade rpm of 5 fans.
You said I can use 'SeveralThingsAtTheSameTimeRev1.ino' but I don't know what to count :frowning: