I’m trying to figure out how to do this, by combining the two examples from the LIS3DH library on wake ups from movement, and position change. I however have had no luck with this, and I feel like I’m just cluelessly searching around for a solution. Here’s my code: https://go.particle.io/shared_apps/59655abc64245d03ac0012d9
As of now, the sensor simply wakes up on movement, and disregards position change.What I want it to do, is to remain in sleep mode as sleep as it remains flat, but once it for example is held upside down, it will wake up from it.
But how will you know it’s upside down if it’s asleep? The accelerometer can generate an interrupt based on movement, but I don’t think you can pre-program a certain orientation it needs to be in.
You can try waking up only the microcontroller and not fh e radio to check the orientation before determining what to do next.
This probably should be possible, but it didn’t seem to work quite right for me either.
Using the AssetTrackerRK library:
#include "Particle.h"
#include "LIS3DH.h"
// System threading is required for this project
SYSTEM_THREAD(ENABLED);
// This example doesn't use cellular so it's turned off to save data. Position wake-up
// works fine with cellular on as well.
SYSTEM_MODE(MANUAL);
// Global objects
LIS3DHSPI accel(SPI, A2, WKP);
const unsigned SLEEP_TIME_SEC = 3600;
const uint8_t movementThreshold = 32;
bool hasAccel = false;
bool positionChanged = false;
void setup() {
Serial.begin(9600);
Serial.println("resetting accelerometer");
LIS3DHConfig config;
config.setLowPowerWakeMode(movementThreshold);
// For position detection instead of motion detection, enable these:
// AOI-6D = '01' is movement recognition. An interrupt is generate when orientation move from unknown zone to known zone.
// The interrupt signal stay for a duration ODR.
// Not set: LIS3DH::INT1_CFG_AOI
config.int1_cfg |= LIS3DH::INT1_CFG_6D;
hasAccel = accel.setup(config);
if (!hasAccel) {
Serial.println("accelerometer not found");
}
}
void loop() {
if (!hasAccel) {
return;
}
// Wait for Electron to stop moving for 2 seconds so we can recalibrate the accelerometer
accel.calibrateFilter(2000);
Serial.println("going to sleep");
// Sleep
System.sleep(WKP, RISING, SLEEP_TIME_SEC);
// This delay should not be necessary, but sometimes things don't seem to work right
// immediately coming out of sleep.
delay(500);
positionChanged = ((accel.clearInterrupt() & LIS3DH::INT1_SRC_IA) != 0);
Serial.printlnf("positionChanged=%d", positionChanged);
}
Setting the 6D bit in INT1_CFG should enable position detection, according the LIS3DH app node AN3308. I’m not positive it’s actually working, however. It seems to trigger with sufficient movement without an orientation change for me. I’m not sure why.
Instead of relying on a changing position, I’m trying to have the sensor wake up based purely on movement. However, I can’t find a way to actually make the sensor less sensitive than the default setting.For instance, I have this:
Sorry for asking so many questions - though I can’t quite figure this one out. I have some issues where my sensor is wrongfully activated - so instead of getting false alerts, I tried to build in an additional check. After the sensor wakes up, it goes into a new state, where it enters standby sleep mode for 5 seconds; if the sensor isn’t woken up during this time, it enters sleep mode, if it is, it will continue to GPS_Wait_State. Issue here however is that it it will always go back to sleep mode regardless. Here’s the code:
case SLEEP_TRIGGER_STATE: {
Serial.println("resetting accelerometer");
LIS3DHConfig config;
config.setLowPowerWakeMode(10);
delay(5000);
System.sleep(WKP, RISING, 5000, SLEEP_NETWORK_STANDBY);
awake = ((accel.clearInterrupt() & LIS3DH::INT1_SRC_IA) != 0);
Serial.printlnf("awake=%d", awake);
if (awake != 0) {
state = GPS_WAIT_STATE;
break;
}
state = SLEEP_STATE;
}
break;
Probably this is not the correct way to do it. Is there any way for a sensor to pick one or the other state depending on whether an acceleration was measured by the LIS3DH?
This is Stop Mode sleep for th µC (with the radio in standby). Standby sleep would reset the device on wake and hence not execute the follow-up checks.
Do you have any recommendations how I could do what I want to do? Essentially, I just want to have the device be idle for a few seconds; if movement is detected in that time it enters state A, if not it enters State B. I’ve been thinking for ways to do it with the limited knowledge I have regarding code structure but nothing seems to work well for me, and I can’t find any examples of it in the libraries I digged through.
I suppose sleep-mode in general would be unfavourable for the power consumption of the electron?
From sleep state it’ll enter Sleep_Trigger state, and from there move into Verification_State. But once it wakes up from sleep, after connecting it will just breathe cyan continously. Something seems amiss here.
With this adjustment, the bug is (obviously) fixed...but regardless of movement the sensor will still always enter publish mode. Not sure what it is. Here's the two modes: I expect the sensor, while in Sleep Trigger state, to count the time it takes for uint32_t to be triggered, and if that time is less than 5 seconds, it will enter GPS wait state.
case SLEEP_TRIGGER_STATE: {
Serial.println("measuring time");
_msWait = millis();
state = VERIFICATION_STATE;
break;
case VERIFICATION_STATE:
if (millis() - _msWait < VERIFICATION_TIME) {
state = GPS_WAIT_STATE;
break;
}
state = SLEEP_STATE;