Go Down

Topic: Revolutions Per Minute Calculating Error (Read 4840 times)previous topic - next topic

GoForSmoke

#15
Jun 19, 2012, 08:34 pm
You got a bicycle wheel that will hold together at 5 ms per rev? Reality check time!

27" rim with 1"-1.25" tire, that's about 7' per rev x 200 revs/sec (@ 5ms) = 1400 ft/sec where 60 mph is 88'/sec.

Maybe change the reed switch for a Hall Effect sensor?
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

mykiscool

#16
Jun 20, 2012, 02:54 am
Oh ok thanks I'll try that.
Technician at Yuneec Electric Aviation

mykiscool

#17
Jun 20, 2012, 03:11 amLast Edit: Jun 20, 2012, 03:14 am by mykiscool Reason: 1
I wasn't using my bike right away for the test I was just testing the concept by doing a simulation of moving the magnet in front with my hand. As for the hall effect, I'll look into that. My reed switch does however seem to be working because the light goes on when I move it in front of it. Also here's my new code, strangely it keeps getting 257 then a decimal like 257.45 and 257.56 rps even when I wait a long time.
Code: [Select]
`//these are just some references for it to work properly#include <StopWatch.h>#include <LiquidCrystal.h>//these are the microcontroller ports that an lcd screen is connected to, a status led, and the switch.LiquidCrystal lcd(12, 11, 7, 6, 5, 4);#define LED 13 //pin for the LED indicator (green)#define Reed 3 //pin for the switch//create a timerStopWatch MySW (StopWatch::MICROS);//state of sensor 1 or 0byte reedState=0;//time between pass of magnetfloat timeSincePass=0;//revolutions per secondfloat RPS=0;//revolutions per minutefloat RPM=0;//last state of reed switch on or offbyte lastReedState=LOW;long lastDebounceTime = 0;long debounceDelay = 50;//just some setup stuffvoid setup(){  pinMode(LED,OUTPUT);  pinMode(Reed,INPUT);  Serial.begin(9600);  lcd.begin(16, 4);  lcd.print("Your Revs/Sec");}void loop(){    byte reading = digitalRead(Reed);    //get the state of the sensor;  //time since pass of magnet  timeSincePass= MySW.elapsed();  //set the lcd cursor to write on the second line  lcd.setCursor(0, 1);  if (reading != lastReedState)  {    // reset the debouncing timer    lastDebounceTime = millis();  }      if ((millis() - lastDebounceTime) > debounceDelay)  {    // whatever the reading is at, it's been there for longer    // than the debounce delay, so take it as the actual current state:    reedState = reading;  }//if the magnet engages the switch  if (reedState==HIGH)  {    //turn on status led for visual purposes    digitalWrite(LED, HIGH);    //convert milliseconds to seconds    RPS=(float)1000000.0/timeSincePass;    //reset the timer storage int        timeSincePass=0;    //reset the timer and start it again    MySW.reset();    MySW.start();  }  else  {    //turn off led otherwise    digitalWrite(LED, LOW);  }  //convert seconds to minutes  RPM=(float)RPS*60;    //print the results to a screen  lcd.print(RPS);  lcd.print("  ");  lcd.print(timeSincePass);  lastReedState = reading;} `
Technician at Yuneec Electric Aviation

GoForSmoke

#18
Jun 20, 2012, 04:27 am
I see you have read the sensor (reed switch) then if it changes from last read to start the debounce delay and if the delay is over to actually set the switch state to what is read which is not bad though 50 ms may be a bit long if you race down long hills.

But then if the state is HIGH you compute and show data... and the state may stay HIGH many times through loop() before debouncing back to low, at least 50 ms worth. You only want it to detect and calculate once per pass, otherwise your timing and resultant calculations will be wrong.

I used to have a generator light. The brightness varied with my speed until the bulb burned out, usually on the way downhill. It also dragged, that was when bike lights were incandescents. But a lightweight DC motor of the right type should generate low voltage (depending on how big a wheel is on the shaft) when driven and might give an analog reading of speed though probably not linear analog (twice the volts not being twice the speed kind of thing, probably response being a curve). However you'd have an idea of speed well before the bicycle wheel turned once.
Because face it, if the wheel has to turn 1 or 1/2 revolution to generate a reading then you will have noticeable lag in calculation and display until you really get moving. 1 rev/sec is about 5 mph with a 27" rim wheel.

2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

The Clever Monkey

#19
Jun 20, 2012, 05:00 am

Can someone please help me with this code. It is supposed to detect the revolutions per second on a bicycle wheel and then convert it to revolutions per minute. The magnetic sensor code works fine, the timer resets itself when it passes by, but no matter what speed or increment of time i wait to pass the magnet by again, it only comes up with 2 readings 5,000 and 6,000, which are not goods revolution per second readings. I expect to get some number like 230.14 or something random like that. My code is below. Any help is appreciated.

Code: [Select]
`//these are just some references for it to work properly#include <StopWatch.h>#include <LiquidCrystal.h>//these are the microcontroller ports that an lcd screen is connected to, a status led, and the switch.LiquidCrystal lcd(12, 11, 7, 6, 5, 4);#define LED 13 //pin for the LED indicator (green)#define Reed 3 //pin for the switch//create a timerStopWatch MySW;//state of sensor 1 or 0byte reedState=0;//time between pass of magnetfloat timeSincePass=0;//revolutions per secondfloat RPS=0;//revolutions per minutefloat RPM=0;//just some setup stuffvoid setup(){  pinMode(LED,OUTPUT);  pinMode(Reed,INPUT);  Serial.begin(9600);  lcd.begin(16, 4);  lcd.print("Your Revs/Sec");}void loop(){  //get the state of the sensor  reedState=digitalRead(Reed);  //time since pass of magnet  timeSincePass= MySW.elapsed();  //set the lcd cursor to write on the second line  lcd.setCursor(0, 1); //if the magnet engages the switch  if (reedState==HIGH)  {    //turn on status led for visual purposes    digitalWrite(LED, HIGH);    //convert milliseconds to seconds    RPS=(float)timeSincePass*1000;    //reset the timer storage int        timeSincePass=0;    //reset the timer and start it again    MySW.reset();    MySW.start();  }  else  {    //turn off led otherwise    digitalWrite(LED, LOW);  }  //convert seconds to minutes  RPM=(float)RPS*60;    //print the results to a screen  lcd.print(RPS);  lcd.print("  ");  lcd.print(timeSincePass);} `

There was a lively conversation about this on another thread recently. If you _really_ need error correction, you might want to look into rotary encoding and Gray codes.
I yield() for co-routines.

mykiscool

#20
Jul 15, 2012, 02:15 amLast Edit: Jul 16, 2012, 10:37 pm by Nick Gammon Reason: 1
Thanks for all your help, I fixed it.

Code: [Select]
` //these are just some references for it to work properly#include <StopWatch.h>#include <LiquidCrystal.h>//these are the microcontroller ports that an lcd screen is connected to, a status led, and the switch.LiquidCrystal lcd(12, 11, 7, 6, 5, 4);#define LED 13#define Reed 3 //pin for the switch//create a timerStopWatch MySW (StopWatch::MICROS);//state of sensor 1 or 0byte reedState=0;//time between pass of magnetunsigned long timeSincePass=0.0;//revolutions per secondfloat RPS=0.0;//revolutions per minutefloat RPM=0.0;//last statebyte lastreedState=0;//just some setup stuffvoid setup(){  pinMode(LED,OUTPUT);  pinMode(Reed,INPUT);  Serial.begin(9600);  lcd.begin(16, 4);  lcd.print("RPM");}void loop(){    reedState=digitalRead(3);  //get the state of the sensor;  //time since pass of magnet  timeSincePass= MySW.elapsed();  //set the lcd cursor to write on the second line    //if the magnet engages the switch  if (reedState != lastreedState && reedState==HIGH)  {    //turn on status led for visual purposes    //convert milliseconds to seconds    RPS=(float)1000000.0/timeSincePass;    //reset the timer storage int        timeSincePass=0;    //reset the timer and start it again    MySW.reset();    MySW.start();  }  if (reedState==HIGH)  {    digitalWrite(LED, HIGH); // gives a visual aid to tell when it is being magnetized  }  else  {    digitalWrite(LED, LOW); //Turns off when no magnet is detected  }  //convert seconds to minutes  RPM=(float)RPS*60.0;    //print the results to a screen  lcd.print(RPM);  lcd.setCursor(0, 1);  lcd.print("Time  ");  lcd.print(timeSincePass);    lcd.print(" MPH ");  lcd.print();  lastreedState = reedState;  Serial.begin(9600);  Serial.println(RPM);}`

Moderator edit: [code] ... [/code] tags added. (Nick Gammon)
Technician at Yuneec Electric Aviation

honeychm

#21
Jun 23, 2016, 03:04 pm
Counting the objects that pass with IR sensor when reach the expected quantity will generate a alarm signal.

Have any sample code?

Paul_KD7HB

#22
Jun 23, 2016, 10:14 pm
I am curious about the magnet you are using with the reed switch. If it is a bar magnet, is it oriented so only one pole passes the reed switch, or do both poles pass the reed switch when the wheel rotates? If the latter is the case, that may be the source if what you think is "bounce".

Paul

Go Up

Please enter a valid email to subscribe