Delhi, India
Offline
Jr. Member
Karma: 0
Posts: 80
~
|
 |
« on: July 15, 2011, 01:16:07 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
|
|
|
|
|
Logged
|
Regards Shubham Garg
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 248
Posts: 16535
Available for Design & Build services
|
 |
« Reply #1 on: July 15, 2011, 01:25:27 pm » |
Use the millis() function. Something like this: 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); }
|
|
|
|
|
Logged
|
|
|
|
|
Central MN, USA
Offline
Faraday Member
Karma: 35
Posts: 5929
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
|
 |
« Reply #2 on: July 15, 2011, 03:16:05 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.
|
|
|
|
|
Logged
|
|
|
|
|
Montreal
Offline
Edison Member
Karma: 16
Posts: 2209
Per aspera ad astra.
|
 |
« Reply #3 on: July 15, 2011, 05:23:44 pm » |
Look in: http://arduino.cc/en/Reference/PulseInReturn value would be in reverse proportion to RPM.
|
|
|
|
|
Logged
|
|
|
|
|
Delhi, India
Offline
Jr. Member
Karma: 0
Posts: 80
~
|
 |
« Reply #4 on: July 17, 2011, 03:31:03 am » |
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?
|
|
|
|
|
Logged
|
Regards Shubham Garg
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 90
Posts: 9401
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #5 on: July 17, 2011, 03:56:01 am » |
Please post your current code so we can have a look
|
|
|
|
|
Logged
|
|
|
|
|
Delhi, India
Offline
Jr. Member
Karma: 0
Posts: 80
~
|
 |
« Reply #6 on: July 17, 2011, 04:02:02 am » |
here is the code: 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) start1 2 3 4 5 6 7 8 9 10 11 12
|
|
|
|
|
Logged
|
Regards Shubham Garg
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 90
Posts: 9401
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #7 on: July 17, 2011, 04:19:51 am » |
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 ... #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
|
|
|
|
« Last Edit: July 18, 2011, 05:56:14 am by robtillaart »
|
Logged
|
|
|
|
|
Delhi, India
Offline
Jr. Member
Karma: 0
Posts: 80
~
|
 |
« Reply #8 on: July 17, 2011, 09:13:52 am » |
@robtillaart here is the code(compiles) #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 2ÆJ$!6 what's wrong with this?
|
|
|
|
|
Logged
|
Regards Shubham Garg
|
|
|
|
Greenville, IL
Offline
Edison Member
Karma: 11
Posts: 1289
Warning Novice on board! 0 to 1 chance of errors!
|
 |
« Reply #9 on: July 17, 2011, 10:03:08 am » |
Serial.begin is set 115200. You probably have your serial monitor set to 9600.
Mark
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 248
Posts: 16535
Available for Design & Build services
|
 |
« Reply #10 on: July 17, 2011, 10:03:55 am » |
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?
|
|
|
|
« Last Edit: July 17, 2011, 10:41:50 am by CrossRoads »
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 90
Posts: 9401
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #11 on: July 17, 2011, 12:02:12 pm » |
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
|
|
|
|
|
Logged
|
|
|
|
|
Toronto, Canada
Offline
Edison Member
Karma: 2
Posts: 1233
"Keep it R.E.I.L. - "Research, Experiment, Investigate and Learn"
|
 |
« Reply #12 on: July 17, 2011, 04:42:47 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.
|
|
|
|
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 90
Posts: 9401
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #13 on: July 17, 2011, 05:48:34 pm » |
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
#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.
|
|
|
|
« Last Edit: July 18, 2011, 05:56:41 am by robtillaart »
|
Logged
|
|
|
|
|
Delhi, India
Offline
Jr. Member
Karma: 0
Posts: 80
~
|
 |
« Reply #14 on: July 18, 2011, 04:56:43 am » |
I like the discussion going on,  .. @CrossRoads, I did changed the baudrate to 9600 and 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..  ...
|
|
|
|
« Last Edit: July 18, 2011, 04:59:19 am by gshubham96 »
|
Logged
|
Regards Shubham Garg
|
|
|
|
|