I am working on a project where i have a continuous string of pulses on one input and need to determine how many pulses occur over a 20ms period. The pulses are from an incremental encoder so I thought the z pulse could trigger the micros() function and count the number of pulses for 20ms, but i can't seem to get this to work. Any clues or suggestions would be much appreciated.
How many pulses are you expecting in 20 ms?
What is the shortest pulse width?
What are you trying to accomplish? What else is going on in your loop?
If you count a fixed number of pulses and determine the time period you may have a more accurate result than counting the number of pulses in a 20 ms period. In that scenario, you would not have to trigger off the Z pulse.
Depending upon the frequency of your pulses, its not clear that if you trigger the 20 ms time interval off the rising edge of the Z pulse you will count a different number of pulses than if you merely count A or B pulses over a 20 ms unsyncronized interval.
Can you use an averaging or running averaging function?
crissp:
The pulses are from an incremental encoder so I thought the z pulse could trigger the micros() function and count the number of pulses for 20ms, but i can't seem to get this to work.
Post your current code please. Saying "I tried something and it didn't work" doesn't tell us much.
LarryD:
How many pulses are you expecting in 20 ms?
What is the shortest pulse width?
I am expecting 3 rising edges in a 20ms period. The pulses are 4ms (high) and 2,5ms(low). This is the same signal from a conditioned AC supply. I need to get a rotary encoder on the shaft of a generator to match the conditioned AC signal. I figured that if the encoder returns 3 rising edges in 20ms then it will be in sync with the AC signal.
Post your current code please.
We aren't mind-readers. How can we guess what your code is, and then guess what the problem is?
Hi this is code i have so far.
int pin=3;
volatile int ISRcounter=0;// interrupt counter set to 0
volatile int ISRreset=0;// interrupt for Z pulse set to 0
volatile unsigned long current=0; //current time stamp
volatile unsigned long previous=0; //previous time stamp
unsigned long _start;
unsigned long _stop;
unsigned long time;
int pulse_counts=0;
int mains =7;
int count1;
int count2;
int countTotal;
int result;
int countCycle=LOW;
void setup()
{
Serial.begin (9600); //initialise comms and set baud rate
pinMode (pin,INPUT_PULLUP); //set pin as output
pinMode(2,INPUT_PULLUP); //set pin 2 as input
pinMode(4,INPUT);
attachInterrupt(0,encPulseISR,RISING); //interrupt acts on rising edge of pulse coming into pin 2
attachInterrupt(1,z_PulseISR,RISING); //interrupt acts on rising edge of Zpulse coming into pin 3
}
void loop()
{
unsigned long period; //local variable period
unsigned long total;
if (digitalRead(countCycle)==HIGH){
_start= _stop;
_stop=micros();
_start=micros();
count1=ISRcounter;
delay (20);
_stop=micros();
count2=ISRcounter;
countTotal=count2-count1;
time=(_stop - _start);
result=countTotal/time;
digitalWrite(4,LOW);}
Serial.print("Encoder counts = ");
Serial.println(ISRcounter);
Serial.print(" count1 = ");
Serial.println(count1);
Serial.print(" count2 = ");
Serial.println(count2);
Serial.print(" time = ");
Serial.println(time);
delay(50);
}
void encPulseISR()
{
ISRcounter++;
}
void z_PulseISR()
{
if (digitalRead (pin)==HIGH)
ISRcounter=0;
digitalWrite(4,HIGH);
}
All I need is to have the Arduino (Uno) count the rising edges for 20ms and display the count. I only need this to happen once on every Z pulse.
int countCycle=LOW;
...
if (digitalRead(countCycle)==HIGH){
Why are you doing a digital read of LOW?
_start= _stop;
_stop=micros();
_start=micros();
What's with the underscores? Don't use them at the start of a variable name. Why make _start = _stop and then make it = micros()?
What is it currently printing?
For timing an interval, see: Timing an interval
I'm not following the logic of what you're trying to acheive.
if (digitalRead (pin)==HIGH)
ISRcounter=0;
So every time the z_Pulse goes high you zero the counter, even if your loop is in the process of waiting 20ms to see what it gets to?
I put the digital Write pin to low so that it would run the loop and then stop. At the beginning is an if statement...if pin ==high. That was my thinking anyway.
I used the underscores to prevent the assembler from treating start & stop as functions, not variables.
The start=stop then micros bit was an experiment and i thought i had commented that out. Sorry for the red herring in there.
Currently I am printing the encoder counts and time to see what the values are, to get an idea of what the program is doing.
KenTF:
I'm not following the logic of what you're trying to acheive.if (digitalRead (pin)==HIGH)
ISRcounter=0;
So every time the z_Pulse goes high you zero the counter, even if your loop is in the process of waiting 20ms to see what it gets to?
Yes.Otherwise the encoder will continue to count up until it overflows. This way will get 1 reading where count 1 will be higher than count2 and I disregard that using an if statement.
if (digitalRead(countCycle)==HIGH){
I put the digital Write pin to low so that it would run the loop and then stop. At the beginning is an if statement...if pin ==high. That was my thinking anyway.
That does not set anything to low. LOW is equal to zero, so you are doing a digitalRead of pin 0, which is the serial Rx pin, which is usually high.
My latest update, This is working quite well.
int pin=3;
volatile int ISRcounter=0;// interrupt counter set to 0
volatile int ISRreset=0;// interrupt for Z pulse set to 0
volatile unsigned long current=0; //current time stamp
volatile unsigned long previous=0; //previous time stamp
unsigned long _start;
unsigned long _stop;
unsigned long time;
int pulse_counts=0;
int mains =7;
int count1;
int count2;
int countTotal;
int result;
int rpm;
void setup()
{
Serial.begin (9600); //initialise comms and set baud rate
pinMode (pin,INPUT_PULLUP); //set pin as output
pinMode(2,INPUT_PULLUP); //set pin 2 as input
pinMode(4,INPUT);
attachInterrupt(0,encPulseISR,RISING); //interrupt acts on rising edge of pulse coming into pin 2
attachInterrupt(1,z_PulseISR,RISING); //interrupt acts on rising edge of Zpulse coming into pin 3
}
void loop()
{
unsigned long period; //local variable period
unsigned long total;
{
_start=micros();
count1=ISRcounter;
delay (20);
_stop=micros();
count2=ISRcounter;
countTotal=(count2-count1);
time=(_stop - _start);
result=countTotal/time;
digitalWrite(4,LOW);
}
Serial.print("Encoder counts = ");
Serial.println(ISRcounter);
period=current-previous;
rpm=(1.0/period)*60000;
Serial.print( "Speed =");
Serial.print(rpm);
Serial.println(" RPM");
if (count1 < count2)
Serial.print(" Total edges = ");
Serial.println(countTotal);
Serial.print(" Result = ");
Serial.println(result);
delay(300);
}
void encPulseISR()
{
ISRcounter++;
previous=current;
current=micros();
}
void z_PulseISR()
{
if (digitalRead (pin)==HIGH)
ISRcounter=0;
digitalWrite(4,HIGH);
}
Thank you for all your help.
attachInterrupt(1,z_PulseISR,RISING); //interrupt acts on rising edge of Zpulse coming into pin 3
...
void z_PulseISR()
{
if (digitalRead (pin)==HIGH)
What else would it be on a RISING interrupt?
You are right.A redundant line of code. Thanks for picking that up.