- 01Check range
- 02Keep near-state band
- 03Select next zone
- 04Return value
Make one header the policy boundary
beacon.hpp has no Arduino dependency. Inline definitions allow this small header to be included in both a test translation unit and the sketch without violating the One Definition Rule. Larger projects can use declarations in a header and one implementation file instead.
#pragma once
#include <cstdint>
enum class Zone { unknown, close, caution, clear };
inline Zone zone_for(std::uint32_t mm, Zone previous) {
if (mm == 0 || mm > 4000) return Zone::unknown;
if (mm < 80 || (previous == Zone::close && mm < 100)) return Zone::close;
if (mm < 250 || (previous == Zone::caution && mm < 270)) return Zone::caution;
return Zone::clear;
}
inline bool due(std::uint32_t now, std::uint32_t last, std::uint32_t interval) {
return static_cast<std::uint32_t>(now - last) >= interval;
}
inline std::uint32_t distance_mm(std::uint32_t echo_us) {
// Only accept durations from our 25 ms measurement window.
return echo_us <= 25000 ? echo_us * 343u / 2000u : 0u;
}A previous close state remains close below 100 mm, although a new close state begins below 80 mm. A previous caution state persists below 270 mm, while a new caution state begins below 250 mm. Those gaps prevent immediate switching at one noisy boundary.
Zero means a missing echo in this adapter and is rejected before band selection. The 4000 mm ceiling is a lab acceptance limit, not a promise that the physical module measures accurately across that whole range.
Inspect the clock arithmetic
The scheduler computes an unsigned difference. With a fixed 100 ms interval and frequent polling, it continues across the 32-bit millis() wrap. It does not use now >= last + interval, whose addition can wrap near the boundary. This pattern assumes polling often enough that an entire clock wrap is not missed.
Try it
Run the supplied tests. Add the 80 mm and 250 mm exact-boundary cases with two different previous states. Explain why the same distance can produce a different state when hysteresis is active.