The saved frequency rule counts one direction of crossing. A previous centred voltage sample must be below zero and the next at or above it. After the collection, the program uses the crossing count minus one divided by the duration of the whole acquisition. Those are definite choices I can follow. They make the interesting question more particular than whether counting crossings somehow gives frequency.
A waveform can pass through zero in two directions. A sine wave crosses from negative to positive, then later from positive to negative. Those are two events in one complete cycle. If I count both and forget that detail, I can end up reporting twice the frequency. If I count only one direction, I need to make sure that is really what the code does rather than what I imagine it does.
I'm using an ideal 50 Hz wave as a calculation. One full cycle takes 20 ms. A crossing in the same direction comes around once per cycle. Crossings in alternate directions are separated by half a cycle in that ideal case. Drawing the wave makes this much easier to follow than trying to decide from an isolated counter variable whether its final value means cycles or half-cycles.
There are different ways to use the crossings. One is to count events inside a time window. Another is to measure the time between matching crossings. Both can tell me something, but the details of the calculation have to match the method. I can't count one kind of event and put it into an equation meant for another just because both versions contain a division by time.
Here's another small example, still entirely on paper. If I record ten consecutive crossings in the same direction, there are nine complete intervals between the first and the last. That’s an easy place to make an off-by-one mistake. Ten event markers don't create ten gaps between themselves. Once I draw the marks and count the spaces, the difference is obvious. In a list of timestamps, it is easier to overlook.
The time-window version raises a different question at the edges. Where does the window begin relative to the waveform? Is a crossing exactly at the boundary included? A short window can make one event more or less a noticeable part of the answer. I don't need to invent an accuracy figure to see why the length of the window and the counting rule belong beside the result.
The full-window denominator is different from a timer between the first and last accepted crossings. The acquisition can begin before the first event and end after the last. Counting the gaps between events does not automatically describe those extra pieces of time. The display then adds another decision: it prints the frequency only between 30 and 70 Hz and shows -- Hz otherwise. I can keep the estimate and the display rule separate, just as I separate the waveform from the sampled values used to describe it.
Then there is the signal near zero. My drawing crosses it cleanly. A real reading may move slightly above and below a threshold more than once because of noise. If the program treats each small change as another genuine crossing, the event count can increase without another physical cycle occurring. The condition for accepting a crossing matters as much as the line that adds one to the counter.
The transition condition in this file compares consecutive raw voltage values after centring them around the channel mean. It does not add a separate hysteresis band in that condition. That makes possible repeated crossings near the boundary a useful reasoning question, while the actual amount of noise and resulting error remain measurement questions. I can distinguish the rule that is present from filtering ideas I might discuss in general.
Sampling belongs in the question too. The program only sees the values it takes. It doesn't watch a continuous drawing between them. If the readings are too far apart or their timing is unclear, the apparent crossing information can be misleading. That’s why a familiar-looking frequency number doesn't settle the sampling question by itself. I need to follow how the number was obtained.
I'm finding it useful to keep three things separate: the physical waveform, the sampled values and the events the software decides to count. The waveform has a frequency. The samples give incomplete observations of it. The event rule tries to extract useful timing information from those observations. Skipping the middle step makes the last calculation look much simpler than the measurement actually is.
The exact rule gives me a clear description of what the estimator does. Its numerator counts intervals by subtracting one from the rising-crossing count, while its denominator covers the entire collection timed with micros. That description is already a result of reading the program. An accuracy comparison would be a different result, with an actual reference and observed timing beside it.
I also want the count and elapsed time kept together in the notes. A final frequency value on its own would make it harder to see which part of the calculation needs checking later.
I now have a specific estimator to explain: rising crossings, a count-minus-one numerator and a whole-collection duration. The division is simple; understanding which events and which interval it combines is the useful work.