5.4 KiB
Frequency / Pulse measurement
- Frequency measurement
- Direct method (counting pulses in a time period)
- Indirect method (measuring a single pulse)
- PWM measurement - Indirect method also reports duty cycle
- Single pulse measurement
- Free-running pulse counter
Direct vs Indirect method
The direct method works well for a wide range of frequencies, from Hz to tens of MHz. For very high frequencies, a prescaller can be enabled. This method has a best-case resolution of 1 Hz, which could be increased by extending the measurement time, which already needs to be long, usually 1 second or more for low frequencies.
The indirect method has a sub-Hz resolution and is much faster than the direct method for low frequencies. It can be used for signals up to tens of kHz, while the direct method can handle 20 MHz or more without issues.
NOTE: The accuracy of all measurements is dependent on the system clock speed.
To measure the system clock using an external counter, you can output it on a pin using
the MCO function configured in SYSTEM.INI
.
Burst vs Continuous
Both the direct and indirect methods can operate in a free-running or burst mode.
- Burst mode performs one or several measurements (with averaging if using the indirect method).
- Free-running (continuous) mode performs periodic measurements without averaging. The advantage is that the last measurement is always immediately available for read-out, without having to wait for the emasurement.
Commands
STOP (0)
Stops all ongoing measurements.
INDIRECT_CONT_START (1)
Start a free-running frequency / duty cycle measuring using the indirect method.
INDIRECT_BURST_START (2)
Start a burst of indirect measurements. Waits for the next rising edge before starting the measurements.
Request:
- u16 - number of pulses to average
Response:
- u16 - core speed in MHz
- u16 - number of pulses
- u64 - sum of all periods (in core ticks)
- u16 - sum of all on-times (positive interval of the pulse)
GEX avoids using float here to reduce code size and avoid floating
point errors. To get the period, use period_sec = periods / (mhz * 10e6 * count)
Frequency is freq = 1 / period
.
The average duty cycle is duty = ontimes / periods
DIRECT_CONT_START (3)
Start repeated measurement using the direct method.
Request:
- u16 - measurement time (ms)
- 0 = no change
- default 1000, configurable in the unit settings
- u8 - prescaller (1,2,4,8)
- 0 = no change
- default 1, configurable in the unit settings
DIRECT_BURST_START (4)
Start a single direct measurement (pulse counting) over a given time period. Longer periods can be used for higher precision using averaging.
Request:
- u16 - measurement time (ms), often 1000 (=1s)
- u8 - prescaller (1,2,4,8)
- 0 = no change
- default 1, configurable in the unit settings
Response:
- u8 - prescaller (1,2,4,8)
- u16 - measurement time (ms)
- u32 - pulse count
Calculate the frequency by freq = (1000 * count * presc) / time_ms
.
FREECOUNT_START (5)
Clear and start the free-running pulse counter.
Request:
- u8 - prescaller (1,2,4,8)
- 0 = no change
- default 1, configurable in the unit settings
MEASURE_SINGLE_PULSE (6)
Measure a single pulse on the input. Waits for a rising edge.
NOTE: The result may be inaccurate if the input is High when starting the measurement.
Response:
- u16 - core speed in MHz
- u32 - pulse length (core ticks)
FREECOUNT_CLEAR (7)
Clear the free-running counter while retrieving the current value. Normally no pulses should be missed, but please be aware that this operation is not atomic and glitches can occur at high frequencies.
Response:
- u32 - last counter value
INDIRECT_CONT_READ (10)
Read the latest result from the continuous indirect method measurement (measurement of individual pulses).
Response:
- u16 - core speed in MHz
- u32 - period (core ticks)
- u32 - on-time (positive interval of the pulse)
Duty cycle is duty = ontime / period
.
Period period_sec = period / (mhz * 10e6)
.
Frequency freq = 1 / period_sec
.
DIRECT_CONT_READ (11)
Read the latest result from the continuous direct method measurement (pulse counting).
Response:
- u8 - prescaller (1,2,4,8)
- u16 - measurement time (ms)
- u32 - pulse count
Frequency is freq = (1000 * presc * count) / time_ms
.
FREECOUNT_READ (12)
Read the current value of the free-running pulse counter.
Response:
- u32 - counter value
SET_POLARITY (20)
Set the measured pulse polarity.
NOTE: This is normally configured in the unit settings. Changes done through this method are temporary, not persisted to flash. The same applies to the other SET_* commands.
Request:
- u8 - active level (0,1)
SET_DIR_PRESC (21)
Set prescaller for the direct mode measurement.
NOTE: This does not take effect until the direct measurement is restarted. (TODO: fix?)
Request:
- u8 - prescaller (1,2,4,8)
SET_INPUT_FILTER (22)
Set input filtering (a hardware feature designed to ignore short glitches)
Request:
- u8 - digital filtering factor (0-15, 0=off)
SET_DIR_MSEC (23)
Set direct measurement period.
NOTE: This does not take effect until the direct measurement is restarted. (TODO: fix?)
Request:
- u16 - period in milliseconds
RESTORE_DEFAULTS (30)
Stop any measurement and restore all the run-time configurable settings to their default values (as configured in the unit settings).