Hi, I'm absolutely new to Arduino programming and all but i've been messing around with it for awhile now so most of the basic arduino functions, im able to understand and use. Currently, I wan to able to count the number of pulses in a given time interval(Let say 1sec), at the same time I also want to ensure that this time interval I can change it as i wish.
I tried using attachinterrupt(pin,ISR,RISING) to increase the count every time it detects a RISING pulse, however i realise that this doesn't allow me to select the gating/time interval as I wish.
Is there any way i can work with without it being too complicated? I would like to keep it as simple as possible. Thanks!
It will be easier to help if you post your program.
How many pulses are you expecting in a second?
Have a look at how millis() is used to manage timing without blocking in Several things at a time. If you need more precision the same technique works with micros().
Robin2:
It will be easier to help if you post your program.
unsigned long period,periodHI,periodLO,gatinginterval;
volatile long int pulsecount = 0;
int specialpin = 9;
int strobepin = 6;
int count = 0;
float frequency,frequency1,radar_speed;
float ave_radar_speed;
unsigned period_array[200];
void setup()
{
// put your setup code here, to run once:
Serial.begin (9600);
pinMode(strobepin,INPUT);
pinMode(specialpin,INPUT);
}
void loop()
{
// put your main code here, to run repeatedly:
interrupts();
while(digitalRead(specialpin) != 0); //loop and do nothing, wait for pulse back to 0 to start reading
attachInterrupt(digitalPinToInterrupt(strobepin),pulseISR,RISING); //My attempt to use attachinterrupt to count the number of pulse in the time interval
delay(gatinginterval);
detachInterrupt(digitalPinToInterrupt(strobepin);
do
{
periodLO = pulseIn(strobepin, LOW);
periodHI = pulseIn(strobepin, HIGH);
if( (periodLO == 0) || (periodHI ==0) )
Serial.println("Error");
period = periodHI + periodLO;
period_array[count++] = period;
}while(digitalRead(specialpin) == 0);
for (i=0,ave_radar_speed=0;i<count;i++)
{
period = period_array[i];
frequency = (1.0/period);
frequency1 = 1000000.0 * frequency;
radar_speed = (frequency1)/4.82;
ave_radar_speed += radar_speed;
}
Serial.print("Total count is ");
Serial.print(count);
Serial.print(" ");
Serial.print("Total speed is ");
Serial.print(constrain(ave_radar_speed/count,0.0,99.0));
Serial.print(" ");
Serial.print("km/hr");
Serial.println("");
count = 0;
gatinginterval = pulseIn(specialpin,LOW); //This pin is connected to a variable resistor on a separate PCB which adjust my gating/time interval
}
void pulseISR()
{
pulsecount++;
}
So what i'm actually trying to do is, to count the number of pulses that occur in that time interval. This gating interval can be adjusted with a variable resistor that is connected on a separate PCB board where it is wired to the digital pin on the Arduino UNO for the measurement of the timing interval.
I suppose this actually makes sense and i can try doing this
6v6gt:
void loop() {
static unsigned long lastPeriodMs = 0 ;
if (millis() - lastPeriodMs > gatinginterval ) { // gatinginterval in mS
Serial.print( "pulses received in gatinginterval = " ;
Serial.print( pulsecount ) ;
pulsecount = 0 ; // should be volatile
lastPeriodMs = millis() ;
}
There are 3 hardware timers/counters in Arduino Uno.
TC0 is used for millis(), TC2 cannot be clocked externaly while using external main clock but TC1 is free to use and very suitable for this job.
Look into Datasheet or some internet guides how to use it, it should be quite easy.
I would attachInterrupt() in setup() and leave it attached. I would create pulseCount as unsigned long and I would never reset it in my code - eventually it will rollover, but that won't cause a problem
Then I would use code pretty much like @6v6gt has suggested
if (millis() - lastPeriodMs > gatinginterval ) { // gatinginterval in mS
previousPulseCount = latestPulseCount; // save the previous value
noInterrupts();
latestPulseCount = pulseCount; // take a copy of the current value while interrupts are off
interrupts();
Serial.print( "pulses received in gatinginterval = " ;
Serial.print( latestPulseCount - previousPulseCount );
lastPeriodMs += gatinginterval;
}
Note that it is essential to pause the interrupts while reading any value that is bigger than a single byte to prevent the possibility that the value is updated by the ISR while you are reading it.
Elegant? I consider counting events via ISR quite crude. It is slow, may miss pulses easily etc. It has some uses but in general using (internal) hardware counter is beter. If you don't need PWM on pins 9 and 10 (you can still use those pins, you just cannot analogWrite them) this code:
will setup Timer/Counter 1 to be externaly clocked by rising edge on pin 5 (another PWM pin!). In 16 bit register TCNT1 there is current value of the counter. It can be written and read without need of disabling interrupts, it counts even in Idle sleep mode without need to wake up.
Id partially fully unload this from software and use the Timers/Counters.
You could use the 16bit counter for accurate timing I guess...with an iterrupt on MAX that triggers an ISR to take the counter's value and assign it to a global variable...then resetting the counter to 0 ready for the next interrupt.
Then in main() you can just poll the global variable at your leisure.
Hey all, thanks for helping me out on this. But for some reason, when i tested out the program, it keeps giving me an output "ovf". I didnt connect anything to pin6 for it to receive any pulses thus theoretically it should be giving me output of 0 instead of ovf or 99.
unsigned long gatinginterval;
unsigned long int pulseCount = 0,previousPulseCount = 0, latestPulseCount = 0, savedPulseCount = 0;
static unsigned long lastPeriodMs = 0 ;
float frequency,frequency1,radar_speed;
int specialpin = 9;
int strobepin = 6;
void setup()
{
// put your setup code here, to run once:
Serial.begin (9600);
attachInterrupt(digitalPinToInterrupt(strobepin),pulseISR,RISING);
pinMode(strobepin,INPUT);
pinMode(specialpin,INPUT);
}
void loop()
{
// put your main code here, to run repeatedly:
interrupts();
while(digitalRead(specialpin) != 0); //loop and do nothing, wait for pulse back to 0 to start reading
if (millis() - lastPeriodMs > gatinginterval ) { // gatinginterval in mS
previousPulseCount = latestPulseCount; // save the previous value
noInterrupts();
latestPulseCount = pulseCount; // take a copy of the current value while interrupts are off
interrupts();
savedPulseCount = latestPulseCount - previousPulseCount;
lastPeriodMs += gatinginterval;
} else {
return;
}
frequency = (savedPulseCount / gatinginterval);
frequency1 = 1000000.0 * frequency;
radar_speed = (frequency1) / 4.82;
Serial.print("The speed is ");
Serial.print(constrain(radar_speed,0.0,99.0));
Serial.print(" ");
Serial.print("km/hr");
Serial.println("");
gatinginterval = pulseIn(specialpin,LOW); //This pin is connected to a variable resistor on a separate PCB which adjust my gating/time interval
}
void pulseISR()
{
pulseCount++;
}
Print also the value of gatinginterval to see if it is as you expect. It should be a value in units of one millisecond. A division by zero can cause an overflow.
What is the purpose of the line while(digitalRead(specialpin) != 0);? If it is intended to halt everything and only start the count when specialpin is triggered then I don't think the rest of your code will work because you are not initiating anything when the trigger occurs. It's a bit like timing the end of a race without timing the start.
As I'm not sure what you really want to do I won't say any more.