Skip to content

Instantly share code, notes, and snippets.

@technobly
Created March 26, 2016 23:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save technobly/f040eb7fa751600c4e93 to your computer and use it in GitHub Desktop.
Save technobly/f040eb7fa751600c4e93 to your computer and use it in GitHub Desktop.
Particle Asset Tracker Wake on Accelerometer bump, sleep after 10 seconds of no motion
// Uncomment for BUILD IDE
// #pragma SPARK_NO_PREPROCESSOR
#include <math.h>
#include "math.h"
#include <ctype.h>
// Particle application functions
#include "application.h"
// If compiling locally, need Adafruit_LIS3DH.cpp/.h and Adafruit_Sensor.h
#include "Adafruit_LIS3DH.h"
Adafruit_LIS3DH accel = Adafruit_LIS3DH(A2, A5, A4, A3);
// Configure where DEBUG_D() calls go to
Serial1DebugOutput debugOutput; // Serial1
// SerialDebugOutput debugOutput; // Serial USB
SYSTEM_MODE(MANUAL);
// lets wakeup every 6 hours and check in (seconds)
#define HOW_LONG_SHOULD_WE_SLEEP (6 * 60 * 60)
unsigned long lastUpdate = 0;
#define UPDATE_INTERVAL_MS (10)
unsigned long noMotionCounter = 0;
#define SLEEP_AFTER_10S_NO_MOTION (10 * 1000)
#define now millis()
bool timeToSleep = false;
void initAccel() {
// for blinking.
pinMode(D7, OUTPUT);
digitalWrite(D7, LOW);
accel.begin(LIS3DH_DEFAULT_ADDRESS);
// Default to 5kHz low-power sampling
accel.setDataRate(LIS3DH_DATARATE_LOWPOWER_5KHZ);
accel.writeRegister8(LIS3DH_REG_CTRL2, 0xC9); // Enable HP Filter with AUTORESET on interrupt
accel.writeRegister8(LIS3DH_REG_CTRL3, 0x40); // Enable AOI interrupt
// Set 2g range
accel.setRange(LIS3DH_RANGE_2_G);
accel.writeRegister8(LIS3DH_REG_CTRL5, 0x08); // latch interrupt so we can read when ready if blocked
accel.writeRegister8(LIS3DH_REG_INT1THS, 0x08); // Set threshold to 8 (relatively low?)
accel.writeRegister8(LIS3DH_REG_INT1DUR, 0x01); // Set duration to 1 cycle
accel.writeRegister8(LIS3DH_REG_INT1CFG, 0x2A); // Enable X,Y,Z interrupt generation
// Reset HP Filter
accel.readRegister8(LIS3DH_REG_INT1SRC);
accel.readRegister8(LIS3DH_REG_CTRL2);
}
void button_clicked(system_event_t event, int param)
{
int times = system_button_clicks(param);
DEBUG_D("Button %d pressed %d times...\r\n", times, param);
if(times == 3) {
timeToSleep = true;
} else {
DEBUG_D("Mode button %d clicks is unknown! Maybe this is a system handled number?\r\n", event);
}
}
void setup() {
initAccel();
// Setup manual sleep button clicks
System.on(button_final_click, button_clicked);
}
bool hasMotion() {
bool motion = digitalRead(WKP);
digitalWrite(D7, (motion) ? HIGH : LOW);
// Reset accelerometer interrupt (latched)
accel.readRegister8(LIS3DH_REG_INT1SRC);
return motion;
}
void checkMotion() {
if(hasMotion()) {
noMotionCounter = 0;
DEBUG_D("BUMP! ");
}
else {
noMotionCounter += UPDATE_INTERVAL_MS;
}
}
void sleepNow() {
System.sleep(SLEEP_MODE_DEEP, HOW_LONG_SHOULD_WE_SLEEP);
}
void checkSleep() {
if (timeToSleep) {
DEBUG_D("\r\nManually deep sleeping for %ds but will wake up for motion...\r\n", HOW_LONG_SHOULD_WE_SLEEP);
delay(100);
sleepNow();
}
}
void loop() {
if (now - lastUpdate > UPDATE_INTERVAL_MS) {
lastUpdate = now;
checkMotion();
checkSleep();
}
if (noMotionCounter > SLEEP_AFTER_10S_NO_MOTION) {
DEBUG_D("\r\nNo motion for %ds, sleeping for %ds but will wake up for motion...\r\n", SLEEP_AFTER_10S_NO_MOTION/1000, HOW_LONG_SHOULD_WE_SLEEP);
delay(100);
sleepNow();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment