I'll be receiving pulses and want to know the relative times of pulse start/end with microsecond precision (or better).
- pulse frequency: probably 1Hz to 10Hz
- pulse length: 1μs to 200ms
- pulse spacing: >10μs between consecutive pulses
I want to measure (ideally) the durations of HIGH/LOW levels, or otherwise absolute times of edges (relative to internal clock) from which I can then calculate the durations. I want durations/timestamps to have microsecond precision or better. 100ns would be great!
My ideal output data would be a series of sequential HIGH/LOW durations for example:
- HIGH for 205μs
- LOW for 134μs
- HIGH for 18μs
This is just a hobby project, so if I mess up measurement of 1% of events then I can just drop those values. No mission-critical requirements or angry customers :)
I figure that I can use some STM32 MCU, with timer in "input" configuration. Then have it store timestamps every time an input pin raises or lowers.
The "filtering" that the STM32 timers can perform will be great for debouncing and noise rejection too.
The times of pulse rises/falls need to be precise to the microsecond or better, but there are no other tight realtime constraints. If it takes an extra 500ms after an edge, before these timestamps get transmitted, that's fine.
Initial solution idea
Ok, not my first solution (that was an oscillator plus a huge pile of 7474+7476 for clock counting and edge-triggered buffering of the clock value)...
Is the solution really just as simple as:
- connect my signal to a timer-input pin on the STM32
- configure a 32-bit timer as input (so timer's value is stored on an input edge transition) and with appropriate filtering
- configure an interrupt to take the stored timer value after an edge and put the value into a queue
- process that queue during idle-time, since there's no realtime requirements on getting the data
The input signal will be the output of a transimpedance amplifier, driven by a filtered photodiode. Signal-to-noise is expected to be pretty good, at least 30dBV.
I'm planning to use STM32G431KBT6 just because it's easily available and I can hand-solder it. I'm not strongly tied to using this MCU part though.
Time wrap-around could also be an issue if counting at e.g. 16MHz with 16-bit timer. I guess I can just slave another 16-bit timer to it and use the other one to count wraparounds, effectively giving me a 32-bit timestamp when reading both timers? Although provided that, at most, only one wraparound event occurs between two timestamps (in the case of a 32-bit timer), unsigned integer subtraction should give me the interval correctly anyway.
Since the timer input is filtered, I'm thinking to eliminate the Schmitt buffer/inverter.
Also I'm wondering whether to use the STM32's internal comparators so I have a bit of extra fine tuning for edge thresholds and hysteresis, and connect the comparator output to the timer input, so that edge transitions on the comparator output drive clock inputs, allowing me to record precise timestamps of when edge-transitions occurred. I'd "tune" the thresholds by connecting DAC output to other comparator input.
Some STM32 parts have opamps built-in too, which I could maybe use for the transimpedance amplifier. The slew rate is only 0.7V/μs as far as I've seen, but that might be fast enough, I don't have a hard figure yet for what bandwidth I need.
Oh wait, the GaN STM32G-series parts have much faster opamps that are totally suitable for what I want to do!
I also considered using the analog watchdog, but STM32L0: Fast processing of an analog sinusoidal signal suggests that it will be too slow for microsecond-resolution timing and it's a bit of a hack to use it for this.