I finished an example sketch that outputs stuff to the serial.
I know it could do with less interrupts, because of them being in sync. (Sorry for that the codingstyle is a bit Pascal like)
#include <HardwareSerial.h>
enum TCaptureState { csNone, csCapture4, csDiff, csErrorCapture5 };
volatile uint64_t TimerCycles4A = 0;
volatile uint64_t TimerCycles4B = 0;
volatile uint64_t TimerCycles4O = 0;
volatile uint64_t TimerCycles5A = 0;
volatile uint64_t TimerCycles5B = 0;
volatile uint64_t TimerCycles5O = 0;
volatile uint64_t CaptureCount4;
volatile uint64_t CaptureCountDiff;
volatile uint16_t CaptureSequence = 0;
volatile TCaptureState CaptureState = csNone;
uint16_t PrevCaptureSequence = 0;
TCaptureState PrevCaptureState = csNone;
double MilliSecondsTickPeriod = 1000.0 / 16000000.0;
const uint16_t HighCountA = 0xFFFF / 3;
const uint16_t HighCountB = 0xFFFF / 3 * 2;
ISR(TIMER4_COMPA_vect)
{
TimerCycles4A++;
}
ISR(TIMER4_COMPB_vect)
{
TimerCycles4B++;
}
ISR(TIMER4_OVF_vect)
{
TimerCycles4O++;
}
ISR(TIMER4_CAPT_vect)
{
CaptureSequence++;
uint16_t CaptureCount = ICR4;
CaptureState = csCapture4;
// Using the cycle count that is linked to the captured counter
if (CaptureCount < HighCountA)
CaptureCount4 = (TimerCycles4B << 16) + CaptureCount;
else if (CaptureCount < HighCountB)
CaptureCount4 = (TimerCycles4O << 16) + CaptureCount;
else
CaptureCount4 = ((TimerCycles4A - 1) << 16) + CaptureCount;
}
ISR(TIMER5_COMPA_vect)
{
TimerCycles5A++;
}
ISR(TIMER5_COMPB_vect)
{
TimerCycles5B++;
}
ISR(TIMER5_OVF_vect)
{
TimerCycles5O++;
}
ISR(TIMER5_CAPT_vect)
{
uint16_t CaptureCount = ICR5;
uint64_t CaptureCount5;
if (CaptureState != csCapture4)
{
CaptureState = csErrorCapture5;
return;
}
// Using the cycle count that is linked to the captured counter
if (CaptureCount < HighCountA)
CaptureCount5 = (TimerCycles5B << 16) + CaptureCount;
else if (CaptureCount < HighCountB)
CaptureCount5 = (TimerCycles5O << 16) + CaptureCount;
else
CaptureCount5 = ((TimerCycles5A - 1) << 16) + CaptureCount;
CaptureCountDiff = CaptureCount5 - CaptureCount4;
CaptureState = csDiff;
}
// The setup() function runs once each time the micro-controller starts
void setup()
{
Serial.begin(115200);
Serial.println("Setup started");
noInterrupts();
// pinMode(48, INPUT);
// pinMode(49, INPUT);
// Halt timers
GTCCR = (1 << TSM) | (1 << PSRASY) | (1 << PSRSYNC);
// enable capture, compare a, compare b, and overflow interrupts
TIMSK4 = (1 << ICIE4) | (1 << OCIE4A) | (1 << OCIE4B) | (1 << TOIE4);
TIMSK5 = (1 << ICIE5) | (1 << OCIE5A) | (1 << OCIE5B) | (1 << TOIE5);
TCCR4A = 0;
TCCR5A = 0;
// no noise cancelling, falling edge, no prescaling
TCCR4B = (0 << ICNC4) | (0 << ICES4) | ((0 << CS42) | (0 << CS41) | (1 << CS40));
TCCR5B = (0 << ICNC5) | (0 << ICES5) | ((0 << CS52) | (0 << CS51) | (1 << CS50));
OCR4A = HighCountA;
OCR5A = HighCountA;
OCR4B = HighCountB;
OCR5B = HighCountB;
TCNT4 = 0;
TCNT5 = 0;
// just to be sure..
TimerCycles4A = 0;
TimerCycles4B = 0;
TimerCycles4O = 0;
TimerCycles5A = 0;
TimerCycles5B = 0;
TimerCycles5O = 0;
// Continue timers
GTCCR = 0;
interrupts();
Serial.println("Setup is ready");
}
// Add the main program code into the continuous loop() function
void loop()
{
// these must be constistent
noInterrupts();
uint64_t LocCaptureCountDiff = CaptureCountDiff;
uint16_t LocCaptureSequence = CaptureSequence;
TCaptureState LocCaptureState = CaptureState;
interrupts();
if ((LocCaptureState != PrevCaptureState) || (LocCaptureSequence != PrevCaptureSequence))
{
switch (LocCaptureState)
{
case csNone:
{
break;
}
case csCapture4:
{
Serial.println("Timer started");
break;
}
case csDiff:
{
Serial.print("Timer stopped: ");
double MilliSecs = LocCaptureCountDiff * MilliSecondsTickPeriod;
double Speed = 150 / MilliSecs;
Serial.print(MilliSecs, 14);
Serial.println(" ms");
Serial.print(Speed, 14);
Serial.println(" m/s");
Serial.print(Speed * 3.6, 14);
Serial.println(" km/h");
Serial.print((uint32_t)LocCaptureCountDiff);
Serial.println(" ticks");
Serial.print(MilliSecondsTickPeriod, 14);
Serial.println(" msec/tick");
break;
}
case csErrorCapture5:
{
Serial.println("Timer hasn't started!!");
break;
}
default:
Serial.println("??");
break;
}
PrevCaptureState = LocCaptureState;
PrevCaptureSequence = LocCaptureSequence;
}
}