Hi All,
I am attempting to adapt the http://www.arduino.cc/playground/Main/ReadingRPM code from the playground for my specific purposes.
Instead of reading a fan's RPM, I want to read the RPM from a bicycle. I've got a cyclocomputer sensor attached to my stationary bike and a magnet on the spoke, so we're dealing with a basic reed switch.
The code actually works well. I have it set to calculate the RPM every rotation and print the value to the serial monitor.
I'm using the RPM values to determine whether or not to send play or stop messages to a Robertsonics MP3 Trigger.
Here's the issue: The RPM can only be calculated when the magnet passes the sensor each time. So if the magnet passes the sensor and then the wheel does not complete another full rotation, the RPM value will not be updated. I've installed a brake on the bicycle and it's possible to stop the wheel very quickly. In other words, the bike will be stopped (or close to stopping), but the computer doesn't know that, so the track continues to play even though I'd like it to stop.
So right now, the sound will stop if the RPM falls below a set value, but if that low value is never recieved (because of the brake), the sound will keep going. I'd like the program to be able to detect if the wheel has stopped without making another full rotation.
The ReadingRPM code uses interrupts, and I wonder if it might make more sense to use digitalRead(), allowing me to measure the time in between rotation. This might be possible within the interrupt function, but I'd be pretty clueless on how to do that.
Here's the code as it stands. I'd appreciate any help or suggestions for how to make my program more robust. I realize I could just remove the brake or maybe add more magnets, but having a software solution would be preferable.
Thanks!
/*Reed switch from cyclocmputer attached to Digital Pin 2. Magnet attached to spoke.
Take constant readings and send serial messages to Robertsonics MP3 trigger if certain conditions are met */
volatile byte rpmcount;
unsigned int rpm;
unsigned long timeold;
int bikePlaying = 0;
byte volume = 255;
void setup()
{
Serial.begin(38400);
attachInterrupt(0, rpm_fun, RISING);
Serial.write('v'); //Serial message for volume
Serial.write(volume); //Set volume at lowest value
rpmcount = 0;
rpm = 0;
timeold = 0;
}
void loop()
{
if (rpmcount >= 1) {
//Update RPM every 1 count, increase this for better RPM resolution,
//decrease for faster update
rpm = 30*1000/(millis() - timeold)*rpmcount;
timeold = millis();
rpmcount = 0;
Serial.println(rpm,DEC);
if((rpm >= 80) && (bikePlaying == 0)){ //if a certain RPM is reached
Serial.write('t'); //Play Track 2 stored on MP3 Trigger
Serial.write(2);
bikePlaying = 1;
while (volume != 1) {
fadeIn(); //Fade volume in from min to max.
}
delay(3000);
}
if ((rpm <= 40) && (bikePlaying == 1)) { //If RPM falls below 40 and MP3 was playing
while (volume < 255) {
fadeOut(); //Fade out,
}
if (volume = 255) { //Then Stop.
Serial.write('O'); //Serial message for "stop"
bikePlaying = 0; //playing is off....
delay(3000);
}
}
}
}
void rpm_fun()
{
rpmcount++;
//Each rotation, this interrupt function is run twice
}
void fadeOut() {
volume += (240/100);
delay(40);
Serial.write('v');
Serial.write(volume);
}
void fadeIn() {
volume -= (240/100);
delay(40);
Serial.write('v');
Serial.write(volume);
}