TCCR1B ^= _BV(ICES1);
The edge detection toggle must be elimintated from your code. We went through this a few post ago. That line should be commented out., or else you will be reading the high and low periods of the signal. You want to be determining the time between the same edge of a repeating pulse. It's also important because the logic within the ISR relays on ICES1 being set when the toggle is gone.
The reason why the version without the delay is not working is that you set index=0 at the start of every loop, and then your calculation follows a conditional test of if (index > 0)
I think you can modify the code as by just commenting the line which begins the loop. Index is then reset to 0 after the calculation.
#include <Arduino.h>
#include <avr/interrupt.h>
#include <LiquidCrystal.h>
void setup();
void loop();
unsigned long timer;
byte counter;
LiquidCrystal lcd (5, 6, 9, 10, 11, 12);
const int led = 7;
const int Backlight = 4;
const int inputCapturePin = 8;
const int prescale = 64;
const byte prescaleBits = B011;
const long precision = (1000000 / (F_CPU / 1000.0)) * prescale;
const int numberOfEntries = 6;
const int gateSamplePeriod = 1000;
int timerTest = millis();
volatile byte index = 0;
volatile byte gate = 0;
volatile unsigned int results[numberOfEntries];
unsigned long rpm;
/* ICR INTERRUPT VECTOR */
ISR(TIMER1_CAPT_vect)
{
TCNT1 = 0;
if (gate) {
if (index != 0 || bitRead(TCCR1B, ICES1) == true) {
if (index < numberOfEntries) {
results[index] = ICR1;
index++;
}
}
}
//TCCR1B ^= _BV(ICES1);
}
void setup() {
lcd.begin(16, 2);
pinMode(led, OUTPUT);
pinMode(Backlight, OUTPUT);
pinMode(inputCapturePin, INPUT_PULLUP);
digitalWrite(Backlight, HIGH);
digitalWrite(inputCapturePin, HIGH);
lcd.home();
lcd.print("Tachometer13:");
TCCR1A = 0;
TCCR1B = prescaleBits;
TCCR1C = 0;
bitSet(TCCR1B, ICES1);
bitSet(TCCR1B, ICNC1);//activate the input capture noise cancellation
bitSet(TIFR1, ICF1);
bitSet(TIMSK1, ICIE1);
}
void loop() {
//index = 0;
gate = 1;
//delay(gateSamplePeriod);//Don't want to use delay
if (millis() - timer >= 1000) {
timer = millis();
gate = 0;
if (index > 0)
{
for (byte i = 0; i < index; i++)
{
long duration;
duration = results[i] * precision;
if (duration > 0) {
float actualDuration = duration / 1000000.0;
float rpm = (1000 / actualDuration * 60);
lcd.setCursor(0, 1);
lcd.print(rpm * 2, 0);
lcd.print(" RPM ");
results[i] = 0;
}
}
index = 0;
}
}
}
There is a structural problem with the code which can be fixed when you have worked out the delay issue. The code is currently creating an array of results[numberOfEntries] which will hold 6 values. I think you are displaying each value, instead of averaging them.
Essentially, the code reads six values from the timer, either during the gated delay period or while the millis() timer interval is running. At 1200 rpm you have 20 pulses/sec and the six pulses are read in 300 ms.
Given how the code has been modified from what you picked up when you went to the input capture scheme there are several things which can be cleaned up relating to the gate, the index, and some conditional tests.