ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
rcwl0516.h File Reference

RCWL-0516 microwave Doppler presence sensor, and the shared one-GPIO presence facade (PROTOCORE_ENABLE_RCWL0516). More...

#include "protocore_config.h"

Go to the source code of this file.

Classes

struct  PresenceCore
 Debounced, hold-extended state of one active-high presence pin. Pure: it decides. More...
 
struct  Rcwl0516Ns
 Dispatch table. Addressed by offset, so the layout is asserted below. More...
 

Macros

#define PROTOCORE_RCWL0516_HOLD_MS   2000
 Default hold time (ms) for the RCWL-0516.
 
#define PROTOCORE_RCWL0516_DEBOUNCE_MS   50
 Default debounce (ms) for the RCWL-0516 - long enough to swallow comparator chatter.
 

Functions

 PROTOCORE_NS_LAYOUT (Rcwl0516Ns, presence_init, presence_update, presence_get, presence_take_event, core_init, begin, poll, present)
 
void protocore_rcwl0516_presence_init (uint8_t *work, PresenceCore *c, uint32_t debounce_ms, uint32_t hold_ms, uint32_t now)
 Initialize to absent at now, with the pin treated as idle (LOW). .
 
proto_bool protocore_rcwl0516_presence_update (uint8_t *work, PresenceCore *c, proto_bool pin_high, uint32_t now)
 Feed one sample of the presence pin. Call it as often as .
 
proto_bool protocore_rcwl0516_presence_get (uint8_t *work, const PresenceCore *c)
 Current presence, without sampling.
 
proto_bool protocore_rcwl0516_presence_take_event (uint8_t *work, PresenceCore *c)
 Consume the presence-changed event.
 
void protocore_rcwl0516_core_init (uint8_t *work, PresenceCore *c, uint32_t now)
 Initialize c with the RCWL-0516 defaults .
 
proto_bool protocore_rcwl0516_begin (uint8_t *work, int out_pin)
 Configure out_pin as an input and start the core. true where the .
 
proto_bool protocore_rcwl0516_poll (uint8_t *work)
 Sample the pin at the current time. true if presence changed on .
 
void protocore_rcwl0516_present (uint8_t *work)
 Latest debounced, hold-extended presence.
 
uint8_t * protocore_rcwl0516_span (void)
 The PROTOCORE_RCWL0516_BORROW bytes this module's state lives in.
 

Variables

PROTOCORE_NS Rcwl0516Ns Rcwl0516 PROTOCORE_UNUSED
 Module namespace.
 

Detailed Description

RCWL-0516 microwave Doppler presence sensor, and the shared one-GPIO presence facade (PROTOCORE_ENABLE_RCWL0516).

The RCWL-0516 (RCWL-9196 controller + MMBR941M RF amp, ~3.18 GHz Doppler) has no data protocol at all: a single 3.3 V OUT pin that latches HIGH when a moving reflector is detected and returns LOW once its own retrigger window expires. Everything interesting is therefore in time, not in bytes - which is what this module provides.

Two problems a bare digitalRead() does not solve, and this does:

  1. Chatter. The OUT pin is driven by an analog comparator, so around the detection threshold it can flicker. A raw read turns one person walking past into a burst of presence events. A level must therefore hold for PresenceCore::debounce_ms before it is believed.
  2. Gaps. The module drops OUT between retriggers, so a person who is present but briefly still reads as absent for a moment. Presence is therefore held for PresenceCore::hold_ms past the last believed-HIGH sample, which turns a stream of retriggers into one continuous "occupied" span instead of a flapping boolean.

The core is pure and takes an explicit now, exactly like services/hotswap: it decides, the binding acts. That makes the whole machine host-testable by injecting pin levels against a synthetic clock, with no GPIO and no real time involved. All timing comparisons are unsigned differences, so they are wrap-safe across a millis() rollover.

PresenceCore is deliberately sensor-agnostic: it is a debounced, hold-extended view of one active-high presence pin. The RCWL-0516 is simply its first user, via the protocore_rcwl0516_core_init defaults - the HMMD's OUT pin, a PIR, or an HB100 can reuse the same core by supplying their own two constants.

Fail-safe start: a freshly initialized core reports absent and treats the pin as idle, so presence is only ever reported after it has actually been observed and believed. Claiming presence you have not yet measured is the failure mode worth avoiding.

work is PROTOCORE_RCWL0516_BORROW bytes the CALLER took, at an address it knows. It is not held past the call, so nothing here aliases it. How those bytes are carved is this module's and is never named here.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file rcwl0516.h.

Macro Definition Documentation

◆ PROTOCORE_RCWL0516_HOLD_MS

#define PROTOCORE_RCWL0516_HOLD_MS   2000

Default hold time (ms) for the RCWL-0516.

The module's own retrigger window is ~2 s, so holding for at least that long bridges the gap between retriggers while a target is still present.

Definition at line 61 of file rcwl0516.h.

◆ PROTOCORE_RCWL0516_DEBOUNCE_MS

#define PROTOCORE_RCWL0516_DEBOUNCE_MS   50

Default debounce (ms) for the RCWL-0516 - long enough to swallow comparator chatter.

Definition at line 66 of file rcwl0516.h.

Function Documentation

◆ PROTOCORE_NS_LAYOUT()

PROTOCORE_NS_LAYOUT ( Rcwl0516Ns  ,
presence_init  ,
presence_update  ,
presence_get  ,
presence_take_event  ,
core_init  ,
begin  ,
poll  ,
present   
)

◆ protocore_rcwl0516_presence_init()

void protocore_rcwl0516_presence_init ( uint8_t *  work,
PresenceCore *  c,
uint32_t  debounce_ms,
uint32_t  hold_ms,
uint32_t  now 
)

Initialize to absent at now, with the pin treated as idle (LOW). .

Parameters
workPROTOCORE_RCWL0516_BORROW bytes the caller took. Not held past the call.
cC
debounce_ms0 disables debouncing (every sample is believed immediately)
hold_ms0 disables the hold (presence follows the debounced level exactly)
nowNow

◆ protocore_rcwl0516_presence_update()

proto_bool protocore_rcwl0516_presence_update ( uint8_t *  work,
PresenceCore *  c,
proto_bool  pin_high,
uint32_t  now 
)

Feed one sample of the presence pin. Call it as often as .

Parameters
workPROTOCORE_RCWL0516_BORROW bytes the caller took. Not held past the call.
cC
pin_highPin high
nowNow
Returns
PROTO_TRUE on success.

◆ protocore_rcwl0516_presence_get()

proto_bool protocore_rcwl0516_presence_get ( uint8_t *  work,
const PresenceCore *  c 
)

Current presence, without sampling.

Parameters
workPROTOCORE_RCWL0516_BORROW bytes the caller took. Not held past the call.
cC
Returns
PROTO_TRUE on success.

◆ protocore_rcwl0516_presence_take_event()

proto_bool protocore_rcwl0516_presence_take_event ( uint8_t *  work,
PresenceCore *  c 
)

Consume the presence-changed event.

Parameters
workPROTOCORE_RCWL0516_BORROW bytes the caller took. Not held past the call.
cC
Returns
PROTO_TRUE on success.

◆ protocore_rcwl0516_core_init()

void protocore_rcwl0516_core_init ( uint8_t *  work,
PresenceCore *  c,
uint32_t  now 
)

Initialize c with the RCWL-0516 defaults .

Parameters
workPROTOCORE_RCWL0516_BORROW bytes the caller took. Not held past the call.
cC
nowNow

◆ protocore_rcwl0516_begin()

proto_bool protocore_rcwl0516_begin ( uint8_t *  work,
int  out_pin 
)

Configure out_pin as an input and start the core. true where the .

Parameters
workPROTOCORE_RCWL0516_BORROW bytes the caller took. Not held past the call.
out_pinOut pin
Returns
PROTO_TRUE on success.

◆ protocore_rcwl0516_poll()

proto_bool protocore_rcwl0516_poll ( uint8_t *  work)

Sample the pin at the current time. true if presence changed on .

Parameters
workPROTOCORE_RCWL0516_BORROW bytes the caller took. Not held past the call.
Returns
PROTO_TRUE on success.

◆ protocore_rcwl0516_present()

void protocore_rcwl0516_present ( uint8_t *  work)

Latest debounced, hold-extended presence.

Parameters
workPROTOCORE_RCWL0516_BORROW bytes the caller took. Not held past the call.

◆ protocore_rcwl0516_span()

uint8_t * protocore_rcwl0516_span ( void  )

The PROTOCORE_RCWL0516_BORROW bytes this module's state lives in.

Stated beside the namespace rather than on it: an entry takes a borrow, and this is where that borrow comes from. Taken once from the end of the pool, which no mark and no release walks, so the state lasts the life of the program.

Returns
the span.

Variable Documentation

◆ PROTOCORE_UNUSED

PROTOCORE_NS Rcwl0516Ns Rcwl0516 PROTOCORE_UNUSED
Initial value:
void protocore_rcwl0516_presence_init(uint8_t *work, PresenceCore *c, uint32_t debounce_ms, uint32_t hold_ms, uint32_t now)
Initialize to absent at now, with the pin treated as idle (LOW). .
proto_bool protocore_rcwl0516_presence_get(uint8_t *work, const PresenceCore *c)
Current presence, without sampling.
proto_bool protocore_rcwl0516_presence_take_event(uint8_t *work, PresenceCore *c)
Consume the presence-changed event.
proto_bool protocore_rcwl0516_poll(uint8_t *work)
Sample the pin at the current time. true if presence changed on .
void protocore_rcwl0516_core_init(uint8_t *work, PresenceCore *c, uint32_t now)
Initialize c with the RCWL-0516 defaults .
proto_bool protocore_rcwl0516_begin(uint8_t *work, int out_pin)
Configure out_pin as an input and start the core. true where the .
void protocore_rcwl0516_present(uint8_t *work)
Latest debounced, hold-extended presence.
proto_bool protocore_rcwl0516_presence_update(uint8_t *work, PresenceCore *c, proto_bool pin_high, uint32_t now)
Feed one sample of the presence pin. Call it as often as .

Module namespace.

Definition at line 168 of file rcwl0516.h.