Using INT0 with USB libraries is tricky and something you need to be quite careful with. In previous versions of the digispark IDE, it wasn't possible. As of the 1.0.4 release a couple of days ago, INT0 interrupts don't crash the USB library so long as the interrupt happens infrequently. 200hz should be infrequent enough. Effectively the problem is this:
To allow the USB libraries to work with timers (millis, micros, delay) and INT0, I changed the interrupt behaviour on all of these to allow stacking. That is, the millis() interrupt can fire to increment the time, and while it's doing that the PCINT0 interrupt used by DigiUSB can fire and will immediately pause the millis interrupt and jump in to the USB library. In previous versions of the digispark software the USB library would have to wait till millis was done, and computers aren't that patient so they would disconnect the digispark and send an error to the program accessing it. Now there is just one issue. When an interrupt first fires it takes a couple of instructions before interrupts are re-enabled so pin change interrupt used by USB can fire again. This tiny delay is okay if it only happens once, but if it happens several times the delay builds up to be so long that again, the computer disconnects the digispark. That's fine for timers and other interrupts, but INT0 is higher priority than PCINT0, so if the INT0 interrupt is enabled and the pin is changing very quickly (in the megahertz range) it still stalls the chip and looses the USB connection. Worse yet, with the new behaviour the interrupt keeps adding function calls to the stack, so the chip quickly runs out of memory and crashes the program on the digispark!
So for all these reasons INT0 must be used with great caution, especially when using the USB libraries. Don't use INT0 with buttons which need software debouncing - use hardware debouncing in this case (capacitor and resistor low pass filter). If the frequency you're measuring is cleanly digital it should be okay because those frequencies are not anywhere near high enough to cause issue. If they maybe unclean, you should use a small low pass filter just like with hardware button debouncing - pass your signal through a resistor to pin 2, and connect pin2 to ground with a capacitor. Tweaking the resistor value relative to the capacitor will adjust how high of a frequency you can read.
As for how to measure it, just add a global variable of the type unsigned long, and in your interrupt handler write down the time and how long it's been since the last time the interrupt fired. Then it's easy to calculate in a function later on:
#include <DigiUSB.h>
unsigned long time_of_last_interrupt;
unsigned long duration_of_cycle;
void interrupt() {
unsigned long time_now = micros();
duration_of_cycle = time_now - time_of_last_interrupt;
time_of_last_interrupt = time_now;
}
unsigned int d2_frequency() {
// should be 1000000UL, working around bug, micros thinking
// clock speed is 16.0mhz when it is 16.5mhz
return 1031250UL / duration_of_cycle;
}
void setup() {
DigiUSB.begin();
attachInterrupt(0, interrupt, FALLING);
}
void loop() {
DigiUSB.println(d2_frequency());
DigiUSB.delay(200); // update five times per second
}
This version works really nicely up to frequencies of about 330hz, after that it starts getting off by 1hz or so in some of the measurements, just due to the granularity of micros I think. Or maybe my signal generator isn't working right. Either way it seems good for your specs. Notably the number in d2_frequency, 1031250UL, should really be 1000000UL, but there seems to be a bug in micros() when compiling for speeds other than 16.0mhz and 8mhz with current versions of the digispark software. millis doesn't seem to have the issue, but effectively micros thinks the clock speed is 16.0mhz when it is 16.5mhz, so I have corrected for this by multiplying 1000000 with 1.03125, because 16.5/16 = 1.03125. Seems to work alright but when this bug gets fixed in a future version of the digispark software you'll need to change that number in your code back to 1000000UL.
You can change the 200ms delay in loop() to be much lower if you want more frequent updates. I think 10ms would be fine for an update frequency of 100hz. I don't know how much lower/faster it would work. Depends partially on how feircely your host software is polling the device. You could squeeze out a little extra performance by changing the println type to send out raw bytes as well, instead of decimal ascii.