I want to calculate the RPM of a car wheel using the hall sensor A3144, with Arduino Uno. When its mailed to me, I will connected the output (pin 3) to the digital pin 2 (interrupt 0) of the Uno, connected pull up resistor to Vcc, and connected Vcc and ground.
I am going to fit a powerful magnet I have to the wheel so that in every revolution it comes close to the hall sensor and its presence is detected. I was going through this topic on measuring the RPM using a reed switch, would my code be any different?
volatile int counter = 0; //For counting number of times the magnet passes the reed switch
volatile long lastRiseTime = 0; //Time at which pin2 (interrupt 0) goes from LOW to HIGH
void setup()
{
Serial.begin(9600);
attachInterrupt(0, rising, RISING);
attachInterrupt(0, falling, FALLING);
pinMode(2, INPUT);
digitalWrite(2, HIGH); //Enable pullup
}
void loop()
{
Serial.println(counter, DEC);
}
void falling()
{
//If more than 50 ms has elapsed since the last time pin 2 went high
if ((millis() - lastRiseTime) > 50)
{
counter++;
}
}
void rising()
{
lastRiseTime = millis();
}
I think the point of him putting the two is for the debounce mechanism. In my case, if I use FALLING would a code like this work?
byte revolutions;
unsigned int rpmilli;
float speed;
unsigned long timeold;
float wheel_circ = 1.634;
void setup()
{
Serial.begin(9600);
attachInterrupt(0, rpm_fun, FALLING);
revolutions = 0;
rpmilli = 0;
timeold = 0;
}
void loop()
{
if (revolutions >= 10) {
//Update RPM every 10 counts
// calculate the revolutions per milli(second)
rpmilli = revolutions/(millis() - timeold);
timeold = millis();
revolutions = 0;
speed = rpmilli * wheel_circ/ 1000; // speed in meters per second
speed = 2.237*speed; // speed in miles per hour
Serial.print(" Speed:");
Serial.print(speed,DEC);
Serial.println(" mph");
}
}
void rpm_fun()
{
revolutions++;
}
For now I don't have a wheel or rotating object which I can attach my magnet to, but I tried periodically bringing the magnet close to the hall sensor and it keeps showing me 0.0000000000 mph in my COM port :~
The fact that you haven't declared the necessary variables volatile?
The fact that you haven't removed one of the attachInterrupt calls?
You haven't told us what changes you've made. All you've done is defend stupid code.
if (revolutions >= 10) {
//Update RPM every 10 counts
// calculate the revolutions per milli(second)
rpmilli = revolutions/(millis() - timeold);
timeold = millis();
revolutions = 0;
Between these three different uses of revolutions, the interrupt could have fired a dozen times. You need to copy revolutions and record time, reset revolutions, then diddle around using the values you saved.
Between these three different uses of revolutions, the interrupt could have fired a dozen times. You need to copy revolutions and record time, reset revolutions, then diddle around using the values you saved.
You should not be calling millis() twice, either.
Hi Paul,
So in the code below I have made the following changes : put revolutions into revs and millis() into milliseconds a variable first and then do the calculations.
volatile byte revolutions;
byte revs; //** revolutions goes into this**
unsigned int rpmilli;
float speed;
volatile unsigned long timeold;
unsigned long milliseconds; // **millis() goes into this**
float wheel_circ = 1.634;
void setup()
{
Serial.begin(9600);
attachInterrupt(0, rpm_fun, FALLING);
revolutions = 0;
rpmilli = 0;
timeold = 0;
}
void loop()
{
if (revolutions >= 10) //** Update RPM every 10 counts**
{
revs = revolutions;
milliseconds = millis();
rpmilli = revs/(milliseconds - timeold); // **calculate the revolutions per milli(second)**
timeold = milliseconds;
revolutions = 0;
speed = rpmilli * wheel_circ/ 1000; // speed in meters per second
speed = 2.237*speed; // speed in miles per hour
Serial.print(" Speed:");
Serial.print(speed,DEC);
Serial.println(" mph");
}
}
void rpm_fun()
{
revolutions++;
}
I am sorry for the late reply. I changed the variable speed into velocity because speed was showing in orange, so I guessed it must be a keyword of some sort for Arduino and best not used as a variable.
This is the code I have :
volatile byte revolutions;
byte revs; //** revolutions goes into this**
unsigned int rpmilli;
float velocity;
volatile unsigned long timeold;
unsigned long milliseconds; // **millis() goes into this**
float wheel_circ = 1.634;
void setup()
{
Serial.begin(9600);
attachInterrupt(0, rpm_fun, FALLING);
revolutions = 0;
rpmilli = 0;
timeold = 0;
}
void loop()
{
if (revolutions >= 10) //** Update RPM every 10 counts**
{
revs = revolutions;
milliseconds = millis();
rpmilli = revs/(milliseconds - timeold); // **calculate the revolutions per milli(second)**
timeold = milliseconds;
revolutions = 0;
velocity = rpmilli * wheel_circ/ 1000; // speed in meters per second
velocity = 2.237*velocity; // speed in miles per hour
Serial.print(" Speed:");
Serial.print(velocity,DEC);
Serial.println(" mph");
}
}
void rpm_fun()
{
revolutions++;
}
The display I get however when I bring the magnet close and far from the sensor is still 0.000000000 mph.
I got the code working. But there is another thing that's come up (there always is lol).
A while ago, I discussed capturing temperature data using the MLX90614 and transmitting that data to my computer's COM port wireless using XBees. At this point the professor I am working with wants me to send this (RPM) data wireless to the receiver along with the temperature data and display both of them.
My question is when Arduino is at a delay of 1 second, would it enter the void rpm_fun() function and increment the number of revolutions if they are happening?
I have heard XBee requires some delay after transmission, I can make it smaller. But the issue I would still have is : millis() is going to be counted accurately, but at the point where there is a delay() following the the XBee transmission commands the revolutions variable will not be counted (because Arduino won't enter rpm_fun() when it is at the delay() ).
Is it a good idea to do away with the delay() after the XBee transmission since the very condition in the if loop makes sure there is some delay?
the delay() function does not disable interrupts, if that was your question.
it seems to me that there is no good reason for the delay there unless you are concerned that the rotation of the wheel if VERY fast and 10 rotations occur faster than your serial transmission (and then you have another problem here). you would be adding to the serial buffer faster than it could be processed. Serial is slow, but maybe not that slow.
If that is the case, you can change your loop() to calculate on a larger number of rotations, therefore updating your XBee less frequently.