66#include " configuration.h"
77#include " main.h"
88#include < Throttle.h>
9+ #ifdef ARCH_NRF52
10+ #include " sleep.h"
11+ #endif
12+
913DetectionSensorModule *detectionSensorModule;
1014
1115#define GPIO_POLLING_INTERVAL 100
@@ -73,17 +77,65 @@ int32_t DetectionSensorModule::runOnce()
7377
7478 // This is the first time the OSThread library has called this function, so do some setup
7579 firstTime = false ;
80+
7681 if (moduleConfig.detection_sensor .monitor_pin > 0 ) {
77- pinMode (moduleConfig.detection_sensor .monitor_pin , moduleConfig.detection_sensor .use_pullup ? INPUT_PULLUP : INPUT);
82+
83+ #ifdef ARCH_NRF52
84+ if (config.device .role == meshtastic_Config_DeviceConfig_Role_SENSOR && config.power .is_power_saving ) {
85+ nrf_gpio_pin_sense_t toSense =
86+ (moduleConfig.detection_sensor .detection_trigger_type & 1 ) ? NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
87+ nrf_gpio_cfg_input (moduleConfig.detection_sensor .monitor_pin ,
88+ moduleConfig.detection_sensor .use_pullup ? NRF_GPIO_PIN_PULLUP : NRF_GPIO_PIN_NOPULL);
89+ nrf_gpio_cfg_sense_set (moduleConfig.detection_sensor .monitor_pin , toSense);
90+
91+ if (NRF_P0->LATCH || NRF_P1->LATCH ) {
92+ LOG_INFO (" Woke up from eternal sleep by GPIO. Sending message." ,
93+ __builtin_ctz (NRF_P0->LATCH ? NRF_P0->LATCH : NRF_P1->LATCH ), NRF_P0->LATCH ? 0 : 1 );
94+ NRF_P1->LATCH = 0xFFFFFFFF ;
95+ NRF_P0->LATCH = 0xFFFFFFFF ;
96+ sendDetectionMessage ();
97+ } else if (NRF_POWER->GPREGRET2 == 255 ) {
98+ LOG_INFO (" Woke up from timeout. Sending state message." );
99+ sendCurrentStateMessage (hasDetectionEvent ());
100+ } else if (NRF_POWER->GPREGRET2 ) {
101+ LOG_INFO (" Woke up from sleep by GPIO. Sending detection message." );
102+ sendDetectionMessage ();
103+ } else {
104+ // We booted fresh. Enforce sending on first detection event.
105+ lastSentToMesh = -Default::getConfiguredOrDefaultMs (moduleConfig.detection_sensor .minimum_broadcast_secs );
106+ }
107+ NRF_POWER->GPREGRET2 = 0 ;
108+
109+ LOG_INFO (" Detection Sensor Module: init in power saving mode" );
110+ // Choose the minimum wakeup time (config.power.min_wake_sec) depending to your needs.
111+ // The least time should be 5s to send just the detection message.
112+ // Choose 45s+ for comfortable connectivity via BLE or USB.
113+ // Device Telemetry is sent after ~62s.
114+ return Default::getConfiguredOrDefaultMs (config.power .min_wake_secs , 90 );
115+ } else
116+ #endif
117+ pinMode (moduleConfig.detection_sensor .monitor_pin ,
118+ moduleConfig.detection_sensor .use_pullup ? INPUT_PULLUP : INPUT);
78119 } else {
79120 LOG_WARN (" Detection Sensor Module: Set to enabled but no monitor pin is set. Disable module" );
80121 return disable ();
81122 }
82- LOG_INFO (" Detection Sensor Module: init" );
123+ LOG_INFO (" Detection Sensor Module: init in default mode " );
83124
84125 return setStartDelay ();
85126 }
86127
128+ #ifdef ARCH_NRF52
129+ if ((config.device .role == meshtastic_Config_DeviceConfig_Role_SENSOR && config.power .is_power_saving )) {
130+ // if a 'State Broadcast Interval' (moduleConfig.detection_sensor.state_broadcast_secs) is specified it will be used, if
131+ // unset the sleep will be forever in the first case the module enters a low power mode, in the 2nd case it will shutdown
132+ // with least power consumption possible
133+ uint32_t nightyNightMs =
134+ Default::getConfiguredOrDefault (moduleConfig.detection_sensor .state_broadcast_secs * 1000 , DELAY_FOREVER);
135+ doDeepSleep (nightyNightMs, false , true );
136+ }
137+ #endif
138+
87139 // LOG_DEBUG("Detection Sensor Module: Current pin state: %i", digitalRead(moduleConfig.detection_sensor.monitor_pin));
88140
89141 if (!Throttle::isWithinTimespanMs (lastSentToMesh,
@@ -124,6 +176,9 @@ void DetectionSensorModule::sendDetectionMessage()
124176 meshtastic_MeshPacket *p = allocDataPacket ();
125177 p->want_ack = false ;
126178 p->decoded .payload .size = strlen (message);
179+ if (config.device .role == meshtastic_Config_DeviceConfig_Role_SENSOR)
180+ p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
181+
127182 memcpy (p->decoded .payload .bytes , message, p->decoded .payload .size );
128183 if (moduleConfig.detection_sensor .send_bell && p->decoded .payload .size < meshtastic_Constants_DATA_PAYLOAD_LEN) {
129184 p->decoded .payload .bytes [p->decoded .payload .size ] = 7 ; // Bell character
@@ -146,6 +201,9 @@ void DetectionSensorModule::sendCurrentStateMessage(bool state)
146201 meshtastic_MeshPacket *p = allocDataPacket ();
147202 p->want_ack = false ;
148203 p->decoded .payload .size = strlen (message);
204+ if (config.device .role == meshtastic_Config_DeviceConfig_Role_SENSOR)
205+ p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
206+
149207 memcpy (p->decoded .payload .bytes , message, p->decoded .payload .size );
150208 lastSentToMesh = millis ();
151209 if (!channels.isDefaultChannel (0 )) {
@@ -156,9 +214,36 @@ void DetectionSensorModule::sendCurrentStateMessage(bool state)
156214 delete[] message;
157215}
158216
217+ boolean DetectionSensorModule::getState ()
218+ {
219+ return digitalRead (moduleConfig.detection_sensor .monitor_pin );
220+ }
221+
159222bool DetectionSensorModule::hasDetectionEvent ()
160223{
161- bool currentState = digitalRead (moduleConfig. detection_sensor . monitor_pin );
224+ bool currentState = getState ( );
162225 // LOG_DEBUG("Detection Sensor Module: Current state: %i", currentState);
163226 return (moduleConfig.detection_sensor .detection_trigger_type & 1 ) ? currentState : !currentState;
164- }
227+ }
228+
229+ boolean DetectionSensorModule::shouldSleep ()
230+ {
231+ return moduleConfig.detection_sensor .enabled && config.power .is_power_saving && moduleConfig.detection_sensor .monitor_pin > 0 ;
232+ }
233+
234+ #ifdef ARCH_NRF52
235+ void DetectionSensorModule::lpLoop (uint32_t msecToWake)
236+ {
237+ for (uint32_t i = msecToWake / 100 ; i >= 0 ; i--) {
238+ delay (100 );
239+ if (hasDetectionEvent () &&
240+ !Throttle::isWithinTimespanMs (
241+ lastSentToMesh, Default::getConfiguredOrDefaultMs (moduleConfig.detection_sensor .minimum_broadcast_secs ))) {
242+ NRF_POWER->GPREGRET2 = 1 ; // use 1 for detection
243+ break ;
244+ }
245+ if (i == 0 )
246+ NRF_POWER->GPREGRET2 = 255 ; // use 255 for timeout without detection
247+ }
248+ }
249+ #endif
0 commit comments