Electronics > Projects, Designs, and Technical Stuff
Measuring time span very precise
HendriXML:
About the bench lighting: my first project was a fume extractor led ring combo.
I't basically a flower bucket with not bottom anymore mounted on a monitor stand and thus adjustable. There's a silent fan in it, that only goes to high speed once you pick up the soldering iron from it's stand.
The bucked faces downwards and near the outer diameter at the level where the fan is mounted, there is a ring of 6 adjustable 3 watt LED's. They're a behind diffuser cloth, otherwise the individual leds make unpleasant bright spots on shiny surfaces of the work item. I really like the setup, but would go for more leds the next time.
Quality light is important! And because of the ring of leds, there almost no shadows while working.
HendriXML:
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)
--- Code: ---#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;
}
}
--- End code ---
HendriXML:
The output of 2 rapid nerf darts:
--- Code: ---16:55:22.796 -> Timer started
16:55:22.796 -> Timer stopped: 10.87300014495849 ms
16:55:22.796 -> 13.79563999176025 m/s
16:55:22.796 -> 49.66430282592773 km/h
16:55:22.796 -> 173968 ticks
16:55:22.796 -> 0.00006250000476 msec/tick
16:55:23.245 -> Timer started
16:55:23.278 -> Timer stopped: 9.80293750762939 ms
16:55:23.278 -> 15.30153560638427 m/s
16:55:23.278 -> 55.08552551269531 km/h
16:55:23.278 -> 156847 ticks
16:55:23.278 -> 0.00006250000476 msec/tick
--- End code ---
HendriXML:
Found a good reference on changing fuse bits and stuff:
https://youtu.be/93dSfEczqgk
HendriXML:
Just to give an update. I found a smaller ATMega2560 board with a crystal resonator which I use for the measurements.
https://www.eevblog.com/forum/projects/nerfo-meter-measuring-the-speed-of-nerf-darts/msg2711130/#msg2711130
The higher precision timing will be used for something else or at least for experimenting.
Navigation
[0] Message Index
[*] Previous page
Go to full version