Pages: 1 [2]   Go Down
Author Topic: Revolutions Per Minute Calculating Error  (Read 2096 times)
0 Members and 1 Guest are viewing this topic.
Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 99
Posts: 4837
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

California
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh ok thanks I'll try that.
Logged

Proud Member of the Nighthawk Robotics Club Team 569 B

California
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

//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 timer
StopWatch MySW (StopWatch::MICROS);
//state of sensor 1 or 0
byte reedState=0;
//time between pass of magnet
float timeSincePass=0;
//revolutions per second
float RPS=0;
//revolutions per minute
float RPM=0;
//last state of reed switch on or off
byte lastReedState=LOW;
long lastDebounceTime = 0;
long debounceDelay = 50;

//just some setup stuff
void 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;
}
« Last Edit: June 19, 2012, 08:14:25 pm by mykiscool » Logged

Proud Member of the Nighthawk Robotics Club Team 569 B

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 99
Posts: 4837
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.



 
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Canada
Offline Offline
Full Member
***
Karma: 0
Posts: 246
Code Monkey
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
//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 timer
StopWatch MySW;
//state of sensor 1 or 0
byte reedState=0;
//time between pass of magnet
float timeSincePass=0;
//revolutions per second
float RPS=0;
//revolutions per minute
float RPM=0;

//just some setup stuff
void 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.
Logged

I yield() for co-routines.

California
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for all your help, I fixed it.

Code:
//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 timer
StopWatch MySW (StopWatch::MICROS);
//state of sensor 1 or 0
byte reedState=0;
//time between pass of magnet
unsigned long timeSincePass=0.0;
//revolutions per second
float RPS=0.0;
//revolutions per minute
float RPM=0.0;
//last state
byte lastreedState=0;

//just some setup stuff
void 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)
« Last Edit: July 16, 2012, 03:37:10 pm by Nick Gammon » Logged

Proud Member of the Nighthawk Robotics Club Team 569 B

Pages: 1 [2]   Go Up
Jump to: