How i dislike to have to download things.
But there are some problems.
int lastTick = 0;
int lastBlink = 0;
int refreshInterval = 500;
int totalTime = 0;
int lastInt = 0;
int counter = 0;
void setup() {
Serial.begin(9600);
lastTick = lastBlink = lastInt = millis();
pinMode(13, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), countUp, FALLING);
}
void loop() {
int timeIs = millis();
if (timeIs - lastTick > refreshInterval) {
// int rpm = ( (float) counter / ( (float)refreshInterval / 1000) ) * 60 * 2; // * 2 = moteur 4 temps
// Tr/min = Fréquence (1 / moyenne entre deux explosions) * 60 secondes * 2 pour un moteur 4 cylindres 4 temps (1 explosion tous les deux tours)
// Donne la vitesse de rotation moyenne sur la période de rafraichissement
float rpm = 0;
if (counter > 0) {
rpm = 1 / ( (float) totalTime / (float) counter) * 60 * 1000 * 2;
}
Serial.print("Counter: ");
Serial.print(counter);
Serial.print(" refresh: ");
Serial.print(totalTime);
Serial.print(" RPM: ");
Serial.println(rpm, 3);
counter = totalTime = 0;
lastTick = millis();
}
}
void countUp() {
int now = millis();
totalTime += now - lastInt;
counter++;
lastInt = now;
}
first of all any variable that is being modified inside the ISR and used outside of it (and vice-versa) needs to be declared 'volatile' That is probably the crutch, but i would not bother about measuring time during the interrupt. Just count and multiply. every half a second we count the ticks.
If we want to take averages, we can.
#define REFRESH_INTERVAL 500
uint32_t lastTick = 0;
volatile uint8_t counter = 0;
void setup() {
Serial.begin(9600);
lastTick = lmillis();
pinMode(13, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), countUp, FALLING);
}
void loop() {
const uint16_t multiplier = 60 * 1000UL / REFRESH_INTERVAL / 2; // counting every ignition 4 Cyl.
// const uint16_t multiplier = 2 * 60 * 1000UL / REFRESH_INTERVAL; // counting single spark
uint32_t timeIs = millis();
if (timeIs - lastTick > REFRESH_INTERVAL) {
uint8_t counted = counter; // read the counter
counter = 0; // reset the counter. Ayn count in between gets lost.
/*noInterruots();
uint16_t counted = counter; // off course counter then also needs to be 16-bit
interruots();
*/
lastTick = lastTick + REFRESH_INTERVAL; // add the refresh time
//ideally all these things happen straightaway and at the same time
uint32_t rpm = counted * multiplier; // that is all we measure the ticks in half a second
// if we measure every discharge from the coil, that is 120 frames, and 2 discharges = 60
// per revolution. (at 4 cylinders) at 10000 RPM that would be 167 ticks which fits into an 8-bit variable
// if you measure the ignition of a single sparkpluglead, then it would be
// uint32_t rpm = counted * 240;
// so to do it from the refresh interval.
// 60 * 1000 / REFRESH_INTERVAL / 2
// ideally you would actually want the maximum resolution, the smallest multiplier, though
// if your counter may exceed your 8-bit variable, then you need to turn interruots off during the
// the reading of it.
Serial.print("Counter: ");
Serial.print(counted, DEC);
Serial.print(" RPM: ");
Serial.println(rpm, DEC);
}
}
void countUp() { // all we do is count !
counter++;
}
the last bit of loop() can be something like this + the average function.
Serial.print("Counter: ");
Serial.print(counted, DEC);
Serial.print(" RPM: ");
Serial.print(rpm, DEC);
rpm = Average(rpm);
Serial.print(" Average: ");
Serial.println(rpm, DEC);
}
}
#define AVERAGE_OFF 20 // the number of values we take average over
uint16_t Average(uint16_t revs) {
static uint16_t aValues[AVERAGE_OFF];
static uint8_t ndx = 0;
uint32_t average = 0;
aValues[ndx] = revs;
ndx++;
ndx = ndx % AVERAGE_OFF;
for (uint8_t i = 0; i < AVERAGE_OFF; i++) {
average += aValues[i];
}
average = average / AVERAGE_OFF;
return average;
}
Hope this helps, i should probably do something like this my self, but all my cars already have one, (and one is a variomatic, the revcounter is rather boring) i may be able to improve on what i have though.