Go Down

Topic: RPM calclater (Read 3305 times) previous topic - next topic

gshubham96

How to make a RPM calculater with arduino>..??
I wanna calculate rpms of some of my motors . I am planning to do it using a IR sensor(easiest to make)
I have attached a wheel to the motor and pasted a black circle over the wheel with only one stripe of white(see the pic, u'll understand)
so whenever the ir rays are reflected by the white strip, arduino reads it ad calculate how many times the rays are received i.e. RPM of the motor.
I do not noe how to make a stopwatch such that the arduino stop reading the rays after a minute. :smiley-zipper: =(
Reagrds,
Shubham Garg
Regards
Shubham Garg

CrossRoads

Use the millis() function.
Something like this:
Code: [Select]

void loop(){

//read the current time

current_time = millis();
//then count until 1 minute (= 60*1000 ms, 60000mS) has elapsed
while (millis()<=(current_time+60000)){
count=count+1; // every time a black/white transition is detected, will leave that to you
}
Serial.print(count);
}
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

liudr

How fast will the motor run? Will it run outdoor with the IR from sun mixed with your sensor? Maybe a Hall Effect Switch with a magnet is better.

Magician

Look in:
http://arduino.cc/en/Reference/PulseIn
Return value would be in reverse proportion to RPM.

gshubham96

thx every1 fr the reply...:)
@crossroads, your sol works great except that whenever the wheel rotates single time, instead of showing 1 count it shows multiple of them.
how to fix this?
Regards
Shubham Garg

robtillaart

Please post your current code so we can have a look
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

gshubham96

here is the code:
Code: [Select]
int count ;
int ir = 5 ;
int current_time ;

void setup(){
Serial.begin(9600) ;
Serial.print("start")  ;
}

void loop(){   //read the current time

current_time = millis();
//then count until 1 minute (= 60*1000 ms, 60000mS) has elapsed
if (millis()<=(current_time+60000)){
  if(digitalRead(ir) == LOW)
  {
count=count+1; // every time a black/white transition is detected, will leave that to you
Serial.println(count);
  }
}
else
{
 
}
}


here is the result:(on a single transition)
Code: [Select]
start1
2
3
4
5
6
7
8
9
10
11
12
Regards
Shubham Garg

robtillaart

#7
Jul 17, 2011, 11:19 am Last Edit: Jul 18, 2011, 12:56 pm by robtillaart Reason: 1
Quote

 if(digitalRead(ir) == LOW)
 {
count=count+1; // every time a black/white transition is detected, will leave that to you
Serial.println(count);
 }


This is incorrect logic, what you do is check the state of the sensor, not if there is a transition. A transition is a change. To measure a change you need a current value and a previous value. See code below.

(code not tested or compiled ...
Code: [Select]

#define IRPIN 5

unsigned int count;  // can only be positive
unsigned long current_time;
int prevState;  //  LOW = BLACK, HIGH = WHITE
int newState;

void setup()
{
 Serial.begin(115200) ;
 Serial.println("Start RPM 0.1") ;
 pinMode (IRPIN, INPUT);
}

void loop()
{
 count = 0;  
 prevState = digitalRead(IRPIN );   // read the reference state
 current_time = millis();

 //count until 1 minute (= 60*1000 ms, 60000mS) has elapsed
 while (millis() - 60000L <= current_time )  // use L for LONG math !!!
 {
   newState = digitalRead(IRPIN);
   if (prevState == LOW && newState == HIGH)  // this is a transition from LOW to HIGH
   {
     count++
   }
   prevState = newState;
 }
 Serial.println();
 Serial.print("RPM: ")
 Serial.println(count);
}


Succes,
Rob
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

gshubham96

@robtillaart
here is the code(compiles)
Code: [Select]
#define IRPIN 5

unsigned int count;  // can only be positive
unsigned long current_time;
int prevState;  //  LOW = BLACK, HIGH = WHITE
int newState;

void setup()
{
  Serial.begin(115200) ;
  Serial.println("Start RPM 0.1") ;
}

void loop()
{
  count = 0; 
  prevState = digitalRead(IRPIN );   // read the reference state
  current_time = millis();

  //count until 1 minute (= 60*1000 ms, 60000mS) has elapsed
  while (millis() - 60000L <= current_time )  // use L for LONG math !!!
  {
    newState = digitalRead(IRPIN);
    if (prevState == LOW && newState == HIGH)  // this is a transition from LOW to HIGH
    {
      count++ ;
    }
    prevState = newState;
  }
  Serial.println();
  Serial.print("RPM: ") ;
  Serial.println(count);
}


here is he result
Code: [Select]
2 Æ?J$!6
???
?


what's wrong with this?
Regards
Shubham Garg

cyclegadget


  Serial.begin is set 115200. You probably have your serial monitor set to 9600.


Mark
Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

CrossRoads

#10
Jul 17, 2011, 05:03 pm Last Edit: Jul 17, 2011, 05:41 pm by CrossRoads Reason: 1
Check your baud rates - your original code was at 9600, the latest is at 115200 - what is your serial monitor set at?

@robtillart,

while (millis() - 60000L <= current_time )  // use L for LONG math !!!

Should this be UL for unsigned long, to agree with millis() and current_time?
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

robtillaart

Quote
Should this be UL for unsigned long, to agree with millis() and current_time?

point is that 60000 is not in the int range so should be declared as a datatype larger than int.
Long is OK, Unsigned long is probably better as it keeps the whole math in unsigned long. 

Thanx for this addition.

BaudRate (why 115200)
I changed the baudrate as it takes 12x less time at 115200  than 9600 to transmit a character. It gives the inner loop While (millis() - 60000L <= current_time) ... the change to stop after 60000 millis (almost) exactly. Recall there was a print of count in this while loop earlier. This print would take a few millis @9600 but @115200 it prints in less (or about) than 1 millis. Reading the code over before posting made me decide to remove the print statement altogether to optimize the timing to the max.

Rob
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Techone

Hi guys. I just read at the discussion here, and the RPM counter program do sample every minute. Just like : Turn / minute. OK But What if it can be reprogram to take sample every second. Like  : Sample -->Numbers of Turn / second re-calculate into Turns / min and display the result via serial ?  I assume the motor is a high speed type ( electric motor )    So  the data sample will be for example :  15 count in 1 second---> Take 15 * 60 = 900 rpm.  Heh, I just don't like to wait every minute.  Just an idea.   

robtillaart

#13
Jul 18, 2011, 12:48 am Last Edit: Jul 18, 2011, 12:56 pm by robtillaart Reason: 1
Good idea but (there is allways a but)  you get the granularity. 900 RPM jumps to 960 RPM or 840 RPM

You should count per second, but keep a sum of the last 60 seconds or so.

something like this: not ideal but
Code: [Select]



#define IRPIN 5

unsigned int count;  // can only be positive
unsigned long current_time;
int prevState;  //  LOW = BLACK, HIGH = WHITE
int newState;

void setup()
{
 Serial.begin(115200) ;
 Serial.println("Start RPM 0.1") ;
  pinMode (IRPIN, INPUT);
 prevState = digitalRead(IRPIN );   // read the reference state
}

int idx;
int count[60];
int sum;

void loop()
{
 current_time = millis();

 idx = (current_time/1000) % 60;
 sum = sum - count[idx];           // remove current second of prev minute

 // COLLECT
 count[idx] = 0;
 while (millis() - 1000L <= current_time )  // use L for LONG math !!!
 {
   newState = digitalRead(IRPIN);
   if (prevState == LOW && newState == HIGH)  // this is a transition from LOW to HIGH
   {
     count[idx]++ ;
   }
   prevState = newState;
 }
 sum = sum + count[idx];       // add current second of this minute

 // DISPLAY
 Serial.println();
 Serial.print("RPM: ") ;
 Serial.println(sum);
}

drawback is that it has a delay, the running average of the last 5 seconds iso 60 will follow the RPM faster.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

gshubham96

#14
Jul 18, 2011, 11:56 am Last Edit: Jul 18, 2011, 11:59 am by gshubham96 Reason: 1
I like the discussion going on, :D :D..

@CrossRoads,
I did changed the baudrate to 9600 and
Quote
Serial.println("Start RPM 0.1") ;
to "start RPM 1"
the result was like this

RPM = 0
RPM = 0
RPM = 0

"0" val was not changing..:(...
Regards
Shubham Garg

Go Up