Go Down

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

#### gshubham96

##### Jul 15, 2011, 08:16 pm
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. =(
Reagrds,
Shubham Garg
Regards
Shubham Garg

#1
##### Jul 15, 2011, 08:25 pm
Use the millis() function.
Something like this:
Code: [Select]
`void loop(){//read the current timecurrent_time = millis();//then count until 1 minute (= 60*1000 ms, 60000mS) has elapsedwhile (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

#2
##### Jul 15, 2011, 10:16 pm
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

#3
##### Jul 16, 2011, 12:23 am
Look in:
http://arduino.cc/en/Reference/PulseIn
Return value would be in reverse proportion to RPM.

#### gshubham96

#4
##### Jul 17, 2011, 10:31 am
@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

#5
##### Jul 17, 2011, 10:56 am
Rob Tillaart

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

#### gshubham96

#6
##### Jul 17, 2011, 11:02 am
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 timecurrent_time = millis();//then count until 1 minute (= 60*1000 ms, 60000mS) has elapsedif (millis()<=(current_time+60000)){  if(digitalRead(ir) == LOW)  {count=count+1; // every time a black/white transition is detected, will leave that to youSerial.println(count);  }}else{  }}`

here is the result:(on a single transition)
Code: [Select]
`start123456789101112`
Regards
Shubham Garg

#### robtillaart

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

{
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 5unsigned int count;  // can only be positiveunsigned long current_time;int prevState;  //  LOW = BLACK, HIGH = WHITEint 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

#8
##### Jul 17, 2011, 04:13 pm
@robtillaart
here is the code(compiles)
Code: [Select]
`#define IRPIN 5unsigned int count;  // can only be positiveunsigned long current_time;int prevState;  //  LOW = BLACK, HIGH = WHITEint 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

#9
##### Jul 17, 2011, 05:03 pm

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

Mark
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

#10
##### Jul 17, 2011, 05:03 pmLast 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

#11
##### Jul 17, 2011, 07:02 pm
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.

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

#12
##### Jul 17, 2011, 11:42 pm
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 amLast 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 5unsigned int count;  // can only be positiveunsigned long current_time;int prevState;  //  LOW = BLACK, HIGH = WHITEint 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 amLast Edit: Jul 18, 2011, 11:59 am by gshubham96 Reason: 1
I like the discussion going on, ..

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

Please enter a valid email to subscribe