Hi, I’m relatively new to programming and have decided to take on a project where I’d have my Arduino Duemilanova output the Rate of Fire of a paintball marker using two optical sensors. I have the sensors working properly and I am able to check when they are triggered however I am having trouble figuring out how to have the program check the shotcount every second. Right now, I have my program increment the shotcount(“ShotCount++;”) every time a ball triggers both sensors. I simply need to check the value of ShotCount every second. Ive read some tutorials on Timer Interrupts but am not 100% sure how to go about coding one.
I need to be able to determine(With an accuracy of 1 decimal place) the ROF in Balls/Second. Could anyone with knowledge on interrupts show me how to program one to check my shotcount every second without disrupting the time sensitive code that’s already within my loop()? Thanks
Right now my code looks something like this:
#include <LiquidCrystal.h>
#define pin6 (1 << PORTD6)
#define pin7 (1 << PORTD7)
int BPS;
int FPS;
int Flag;
long Inches;
unsigned long StartTime;
unsigned long StopTime;
unsigned long Duration;
volatile unsigned long ShotCount;
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
void setup()
{
DDRD &= ~ ((1 << PORTD6) | (1 << PORTD7)); //Sets Pins 6 and 7 as INPUTS
lcd.begin(16, 2);
Duration=0;
FPS=0;
BPS=0;
Flag=0;
}
void loop()
{
if (PIND & (1 <<PORTD6) && Flag==0) //Checks if Sensor 1 has been triggered(HIGH)
{
StartTime=micros();
Flag=1;
}
if (PIND & (1 <<PORTD7) && Flag==1)
{
StopTime=micros();
ShotCount++; //Increments the ShotCount by 1
Flag=0; //Triggers the ChronoFlag to equal 1
Duration=StopTime-StartTime; //Calculates the time interval for the projectile to trigger both sensors
}
}
I fixed the code by adding the closing brace. As for the volatile, I know I don't need it unless Im using an ISR. I put it there because I had read it was the proper way to declare a variable that is going to be shared with your main code and your ISR. If this is incorrect, ill change it..
thanks for the sample code WizenedEE, that looks like it will work...I just have one more question. I want my program to print the shotspersecond value only if that value is greater than 3. Is there a way to have the interrupt output that value or should i add some "if" functions within the interrupt?
I added the sample code given to me by WizenedEE and it seems to work, however, I'm not getting any decimal precision which is standard on your average paintball Chrono...looking at my code, I'm not sure it's been written to do so and it might require a re-write of certain sections. Anyone know how I could go about having the Shots/Second displayed with an accuracy of 1 decimal place?
DDRD &= ~ ((1 << PORTD6) | (1 << PORTD7)); //Sets Pins 6 and 7 as INPUTS
Aw, is there a problem with using the more readable:
pinMode (6, INPUT);
pinMode (7, INPUT);
?
Maybe play with the ports in time-critical code. The setup function is not such a place.
Anyway, all pins default as inputs after a reset.
Moving on from that, if you are timing two pins, why not put the pins onto the interrupts? Rather than using timers. Timers are just a way of polling. Interrupt react pretty quickly.
I didn't put the pins in the interrupts because I want them to continuously take measurements, not stop and take measurements every second...perhaps I'm not understanding what you mean exactly. Im still having problems with my shot counter,
DTM22:
I added the sample code given to me by WizenedEE and it seems to work, however, I'm not getting any decimal precision which is standard on your average paintball Chrono...looking at my code, I'm not sure it's been written to do so and it might require a re-write of certain sections. Anyone know how I could go about having the Shots/Second displayed with an accuracy of 1 decimal place?
I didn't put the pins in the interrupts because I want them to continuously take measurements, not stop and take measurements every second...
In an interrupt, you're "measuring" the stae of the pin every instruction cycle.
At 16MHz, this means every 62.5 nanoseconds. Is that continuous enough?
If you're not using interrupts, then the title of the thread is misleading.
I am using an ISR in my code, just not for the input pins...my questions now still remains, how to get an accuracy of 1 decimal place with my BPS value?
how to get an accuracy of 1 decimal place with my BPS value?
You need to count the number of shots in one tenth of a second and then multiply that figure by ten.
You should use interrupts to increment the shot counter. Then you should use the 1/10 th of a second ISR to get the shot counter and stores it in another variable and set a flag that indicates that the new value is ready for output or logging or averaging or what ever. Finally it resets the shots counter.
Your main loop should look at the flag and when it sees it set it should grab the shot counter store, and reset the flag. Then it can do the multiply by 10 or whatever, and display the result.
So if I understand correctly, I need to change the interrupt to check the shot count ever 1/10th of a second instead of every second. Do I need to add other interrupts or keeping the one will be sufficient? What other changes do I need to make?
Duration is the time measured for 1 single ball to trigger both sensors and shotcount is the number of shots counted in 1 second. Are you sure that relating shotcount to the duration of only one ball to travel past both sensors is the proper way of measuring a rate of fire in BPS?
Not in my code it isn’t. It is the cumulative duration. So if 20 balls drop that is the time it took 20 to fall. Normalized for seconds and you get balls per second.
what if I wait ten seconds before firing, that would affect the results
Yes of course, because it is also part of the time.
Do you only want to measure the firing rate from the time of the first shot? If so that is not what you said originally, you have changed the specification.
Are you a boss? They are always doing that. :~