I am measuring the pulses of an encoder bearing and using the pulseIn function to get a total number of "lows". I currently have the counter function working just fine but what I am wanting to happen is when the bearing stops rotating, I want to print the current counter value.
I know how to use the Serial.println(counter); to print the counter value, what I don't know how to do is only print it once "counter" has stopped. This will be a controlled enviroment and I am using this to measure total number of rotations of an axle once power is removed.
How best to do this depends on how your sketch is structured. The basic idea is to periodically check the count and if it doesn't change within a time period then you can assume its stopped and print the count.
If you are using pulseIn, an easy way to do this is to check to see if the return value is the same as the timeout value, if so you can assume that no pulse has been detected within the timout period (default is one second).
See the pulseIn reference if you need to set a different timeout.
I haven't tried it so would be interested to hear how it works.
int pulsePin = 2;
int switchPin = 3;
unsigned long counter = 0;
unsigned long duration = 0;
unsigned long timeout = 1000000;
int ledPin = 13;
void setup(){
pinMode(pulsePin, INPUT);
pinMode(switchPin, INPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(switchPin, HIGH);
digitalWrite(pulsePin, HIGH);
Serial.begin(9600);
// wait 5 seconds before starting loop
delay(5000);
}
void loop(){
// send signal that counter is starting
digitalWrite(ledPin, HIGH);
duration = pulseIn(pulsePin, LOW);
counter++;
// display counter value only if bearing is moving
if(counter == counter){
Serial.println(counter);}
}
Basically I am new at this Arduino thing. Actually, I am a mechanical engineer, so I am not so good at any electrical things, but I am working on it. I have figured out how to display the counter if the bearing is moving, but what I want to happen is when "counter" stops increasing, it prints its final value. How would I do this?
int pulsePin = 2;
int switchPin = 3;
unsigned long counter = 0;
unsigned long duration = 0;
unsigned long timeout = 2000; // two seconds ?
int ledPin = 13;
void setup(){
pinMode(pulsePin, INPUT);
pinMode(switchPin, INPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(switchPin, HIGH);
digitalWrite(pulsePin, HIGH);
Serial.begin(9600);
// wait 5 seconds before starting loop
delay(5000);
}
void loop(){
// send signal that counter is starting
digitalWrite(ledPin, HIGH);
duration = pulseIn(pulsePin, timeout);
counter++;
// display counter value only if bearing is moving
if(duration >= timeout){
// no pulse received within the timeout period!
Serial.println(counter);
//you may want to reset the counter here
}
}
I don't think the duration will tell me what I need. I am using this to measure the number of rotations that a shaft takes to stop once the power is removed. The duration would give me time but not number of rotations.
The bearing I am using sends 48 pulses/revolution. I only want to output one number for simple data collection. I will take that number directly into a spreadsheet.
Thanks for your help, and let me know if you have any other suggestions. I already tried treating each pulse like a button press and counting them, but I still don't know what to do when the counts stop, and how to output that number.
I am suggesting printing the duration as a debugging aid. I would expect pulseIn to return a duration equal to the timeout value when there is no pulse – the code posted above checks to see if this is the case to determine if it should print the count, But if its not working then we need to see what pulseIn returns (if anything). Once we find that out, the print statement can be removed and the code fixed.
Alright, I set it to print the duration and it only prints a value if the bearing is turning. The Serial.println(duration) function only seems to work if the bearing is turning. I would prefer it to print constantly and I am sure this is something to do with the pulseIn command..... I am going to try a few other things.
Are you saying that you have added a statement to print duration immediately after the pulseIn function? If so and you aren't seeing the output, then perhaps pulseIn is not timing out.
If that is the case then you will need to use something other than pulseIn to count pulses. For example, you could use attachInterrupt to increment a counter on either the rising or falling edge of your pulse. Your code in loop would check periodically to see if the count was no longer changing.
Alright, I am using the attachInterrupt function now to count on the falling edge. I have this working just fine. I have it giving the appropriate 48 counts per revolution in a serial output.
Now, what I need to figure out is how to look at my "counter" value and tell when it stops changing for say 1 second. When that happens, I want to print the current value once.
How often to check depends on the shortest time between pulses when the shaft is moving. But lets say one second is good enough.
So, your code needs to compare the count variable with the value in the previous second. You can do this by copying the value of count into another variable, delaying a second, then checking to see if count is the same as the previously copied value. If it is the same, the shaft has stopped. If its not the same then copy the new value of count to your variable and repeat until the are the same.
The problem with that is I think it ignores the pulses during the 1 second delay. I need to report the total number of pulses at the end of this so that I can calculate the total number of rotations.
I tried this:
int pulsePin = 2;
int previousCount = 0;
int currentCount = 0;
And, once the shaft stops rotating, I get a value every second, but it does not correlate to the total number of rotations. I am turning the bearing by hand right now about 4 turns then stopping and it is returning the number 6, where it should return 192 or so.....
I went back to the pulseIn function and if I include a value for timeout, I get the following error:
This is highlighted:
duration = pulseIn(pulsePin, LOW, 10000);
This is the error:
C:/Documents and Settings/rsnodgra/Desktop/Arduino/arduino-0009-win/arduino-0009/lib/targets/arduino/wiring.h:98: error: too many arguments to function 'long unsigned int pulseIn(uint8_t, uint8_t)'
It looks like you are running Arduino Version 0009, timeout was added to pulseIn in a later version. Why aren't you running 0011 or 0012? I expect the code suggested in my first post would have worked and we would both have saved some time
Ok, I updated and got the timeout function working. Now I am printing the "duration" out to see what is happening to it. As the bearing rotates, it is constantly changing. When I stop, the pulseIn command will go to zero after the 2 second timeout. Other times it will set there and do nothing until I move the bearing slightly. I thought this was because I was stopping on a pulse point, so I changed the pulse to CHANGE, instead of low. So now it looks for a change from LOW TO HIGH. This gives the same results.
Just realized that I am getting some duration values larger than my timeout! I thought that was the point of timeout - to return 0 for the duration if the duration of the pulse lasts longer than the timeout is specified for....
I just had a look at the source code for pulseIn and it does not timeout once the pulse has started. If your pulses can be either high or low when the shaft is stopped then this may make pulseIn unsuitable for your purpose.
As you have the attachInterrupt code counting pulses, shall we see if you can get that working the way you want.