tf
Created August 27, 2023 © GPL3+

Fall Detection & Alert

For people with mobility issues experiencing a fall unnoticed by others can have severe health consequences ...

Beginner3.14159265359 hours71

Things used in this project

Hardware components

Spresense boards (main & extension)
Sony Spresense boards (main & extension)
×1
Spresense LTE extension board
Sony Spresense LTE extension board
×1
6 DOF Sensor - MPU6050
DFRobot 6 DOF Sensor - MPU6050
×1

Software apps and online services

Arduino IDE
Arduino IDE
CallMeBot
Signal

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Schematics

Wiring

Code

fall_detection.ino

Arduino
/*
  fall_detection.ino

    Simple example/proof-of-concept for a fall detection device featuring the
    Sony Spresense with Spresense LTE extension board and a a MPU6050 3-axis accelerometer
    and gyroscope ...
    Read more: https://github.com/dxcfl/fall-detection-with-sony-spresense#readme
    Git: https://github.com/dxcfl/fall-detection-with-sony-spresense
    (c) 2022 by dxcfl
*/

#define DEBUG
#include "debug2serial.h"

// include application settings
#include "app_settings.h"

// miscellaneous
#define STRING_BUFFER_SIZE 128

/* Setup
 */
void setup(void)
{
#ifdef DEBUG
  Serial.begin(115200);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens
#endif

  accelerometer_and_gyroscope_setup();
  lte_web_client_setup();
#ifdef APP_USE_GNSS
  gnss_setup();
#endif
}

/* Loop
 */
void loop()
{
  float accX, accY, accZ;
  float gyrX, gyrY, gyrZ;
  bool fall_detected;

  read_acceleration_and_rotation(&accX, &accY, &accZ, &gyrX, &gyrY, &gyrZ);
  fall_detected = fall_detection(accX, accY, accZ, gyrX, gyrY, gyrZ);

#ifdef APP_USE_GNSS
  double latitude;
  double longitude;
  double altitude;

  gnss_update(&latitude, &longitude, &altitude);
#endif

  if (fall_detected)
  {
    DEBUG_SERIAL_PRINTLN("INFO: FALL DETECTED!!!");

#ifdef APP_USE_GNSS
    char message[STRING_BUFFER_SIZE];
    sprintf(message, "Fall detected at Lat %0.6lf, Lon %0.6lf", latitude, longitude);
#else
    const char message[] = "Fall detected!";
#endif
    send_request(message);

#ifdef DEBUG
    DEBUG_SERIAL_PRINTLN("WARNING: Pausing execution for 10 seconds ...");
    delay(10000);
#endif
  }
}

/* Fall detection: Determine fall detection based on 3-axis acceleration and rotation
 */
bool fall_detection(float accX, float accY, float accZ, float gyrX, float gyrY, float gyrZ)
{
  bool freeFallTrigger, impactTrigger, orientationChangeTrigger;

  // Thresholds and interval
  const unsigned long detectionInterval = APP_FD_DETECTION_TIME_INTERVAL;
  const float freeFallThreshold = APP_FD_FREE_FALL_ACCELERATION_THRESHOLD;
  const float impactThreshold = APP_FD_IMPACT_ACCELERATION_THRESHOLD;
  const float orientationChangeThreshold = APP_FD_ORIENTATION_CHANGE_THRESHOLD;

  // Last detection time for each trigger
  static unsigned long timeFreeFall = 0;
  static unsigned long timeImpact = 0;
  static unsigned long timeOrientationChange = 0;

  unsigned long currentTime = millis();

  // Total acceleration and rotation for all three axes
  float totalAcc = total(accX, accY, accZ);
  float totalRot = total(gyrX, gyrY, gyrZ);

  DEBUG_SERIAL_PRINT("INFO: Total acceleration = ");
  DEBUG_SERIAL_PRINTLN(totalAcc);
  DEBUG_SERIAL_PRINT("INFO: Rotation magnitude = ");
  DEBUG_SERIAL_PRINTLN(totalRot);

  // Free fall detected: Total acceleration below defined threshold
  if (totalAcc <= freeFallThreshold)
  {
    timeFreeFall = currentTime;
  }

  // Impact detected: Total acceleration above defined threshold
  if (totalAcc >= impactThreshold)
  {
    timeImpact = currentTime;
  }

  // Orientation change detected: Total rotation above defined threshold
  if (totalRot >= orientationChangeThreshold)
  {
    timeOrientationChange = currentTime;
  }

  DEBUG_SERIAL_PRINT("INFO: Detection time (millis current, free fall, impact, orientation): ");
  DEBUG_SERIAL_PRINT(currentTime);
  DEBUG_SERIAL_PRINT(",");
  DEBUG_SERIAL_PRINT(timeFreeFall);
  DEBUG_SERIAL_PRINT(",");
  DEBUG_SERIAL_PRINT(timeImpact);
  DEBUG_SERIAL_PRINT(",");
  DEBUG_SERIAL_PRINT(timeOrientationChange);
  DEBUG_SERIAL_PRINTLN("");

  // Events triggered within defined time interval?
  freeFallTrigger = (currentTime - timeFreeFall < detectionInterval);
  impactTrigger = (currentTime - timeImpact < detectionInterval);
  orientationChangeTrigger = (currentTime - timeOrientationChange < detectionInterval);
  DEBUG_SERIAL_PRINT("INFO: Trigger (free fall, impact, orientation change): ");
  DEBUG_SERIAL_PRINT(freeFallTrigger);
  DEBUG_SERIAL_PRINT(",");
  DEBUG_SERIAL_PRINT(impactTrigger);
  DEBUG_SERIAL_PRINT(",");
  DEBUG_SERIAL_PRINT(orientationChangeTrigger);
  DEBUG_SERIAL_PRINTLN("");

  // Fall detected: All three triggers occured within defined time interval.
  return freeFallTrigger && impactTrigger && orientationChangeTrigger;
}

accelerometer_and_gyroscope.ino

Arduino
/*
  accelerometer_and_gyroscope.ino

    Functions to initialize and read sensor date from a MPU6050 3-axis accelerometer and gyroscope
    using the Adafruit library ...
    Read more: https://github.com/dxcfl/fall-detection-with-sony-spresense#readme
    Git: https://github.com/dxcfl/fall-detection-with-sony-spresense
    (c) 2022 by dxcfl
*/

// Accelerometer and gyroscope readings from a MPU6050 sensor using the Adafruit library ...

// To test/use this sketch standalone: #define ACC_GYR_STANDALONE

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_MPU6050.h>
#include <math.h>
#include "debug2serial.h"

Adafruit_MPU6050 mpu;

void accelerometer_and_gyroscope_setup(void)
{
  DEBUG_SERIAL_PRINTLN("INFO: Initialising accelerometer ...");
  // Try to initialize MPU6050!
  DEBUG_SERIAL_PRINTLN("INFO: Initialising MPU6050 ...");
  if (!mpu.begin(MPU6050_I2CADDR_DEFAULT, &Wire1, 0))
  {
    DEBUG_SERIAL_PRINTLN("ERROR: Failed to detect MPU6050 sensor.");
    while (1)
    {
      delay(10);
    }
  }
  DEBUG_SERIAL_PRINTLN("INFO: MPU6050 initialized.");
}

void read_acceleration_and_rotation(float *accX, float *accY, float *accZ, float *gyroX, float *gyroY, float *gyroZ)
{
  /* Get new sensor event with the reading */
  sensors_event_t eventA, eventG, eventT;
  DEBUG_SERIAL_PRINTLN("INFO: Reading acceleration / rotation values from MPU6050 ...");
  mpu.getEvent(&eventA, &eventG, &eventT);

  DEBUG_SERIAL_PRINT("INFO: Acceleration X: ");
  DEBUG_SERIAL_PRINT(eventA.acceleration.x);
  DEBUG_SERIAL_PRINT(", Y: ");
  DEBUG_SERIAL_PRINT(eventA.acceleration.y);
  DEBUG_SERIAL_PRINT(", Z: ");
  DEBUG_SERIAL_PRINT(eventA.acceleration.z);
  DEBUG_SERIAL_PRINTLN(" m/s^2");
  DEBUG_SERIAL_PRINT("INFO: Rotation X: ");
  DEBUG_SERIAL_PRINT(eventG.gyro.x);
  DEBUG_SERIAL_PRINT(", Y: ");
  DEBUG_SERIAL_PRINT(eventG.gyro.y);
  DEBUG_SERIAL_PRINT(", Z: ");
  DEBUG_SERIAL_PRINT(eventG.gyro.z);
  DEBUG_SERIAL_PRINTLN(" rad/s");

  *accX = eventA.acceleration.x;
  *accY = eventA.acceleration.y;
  *accZ = eventA.acceleration.z;
  *gyroX = eventG.gyro.x;
  *gyroY = eventG.gyro.y;
  *gyroZ = eventG.gyro.z;
}

inline float total(float x, float y, float z)
{
  return sqrt(x * x + y * y + z * z);
}

#ifdef ACC_GYR_STANDALONE
void setup(void)
{
  Serial.begin(115200);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens
  accelerometer_and_gyroscope_setup();
}

void loop(void)
{
  float accX, accY, accZ;
  float gyrX, gyrY, gyrZ;
  read_acceleration_and_rotation(&accX, &accY, &accZ, &gyrX, &gyrY, &gyrZ);
  Serial.print(accX);
  Serial.print(",");
  Serial.print(accY);
  Serial.print(",");
  Serial.print(accZ);
  Serial.print(",");
  Serial.print(gyrX);
  Serial.print(",");
  Serial.print(gyrY);
  Serial.print(",");
  Serial.print(gyrZ);
  Serial.print(",");
  Serial.print(total(accX, accY, accZ));
  Serial.print(",");
  Serial.println(total(gyrX, gyrY, gyrZ));
#ifdef DEBUG
  delay(500);
#endif
}
#endif

lte_web_client.ino

Arduino
/*
  lte_web_client.ino

  derived from

    LteHttpSecureClient.ino - Example for secure HTTP client using LTE
    Copyright 2019, 2021, 2022 Sony Semiconductor Solutions Corporation

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    This sketch connects to a website via LTE.
    In this example, an HTTP GET request is sent to https://httpin.org/get,
    and an HTTP POST request is sent to https://httpin.org/post.
*/

#include "debug2serial.h"

// include application settings
#include "app_settings.h"

// libraries
#include <ArduinoHttpClient.h>
#include <RTC.h>
#include <SDHCI.h>
#include <LTE.h>

// URL, path & port (for example: arduino.cc)
char server[] = APP_SEND_MESSAGE_HOST;
char getPath[] = APP_SEND_MESSAGE_PATH;
int port = APP_SEND_MESSAGE_PORT; 

// initialize the library instance
LTE lteAccess;
LTETLSClient tlsClient;
HttpClient client = HttpClient(tlsClient, server, port);
SDClass theSD;

/* LTE web client setup
 */
void lte_web_client_setup()
{
  char apn[LTE_NET_APN_MAXLEN] = APP_LTE_APN;
  LTENetworkAuthType authtype = APP_LTE_AUTH_TYPE;
  char user_name[LTE_NET_USER_MAXLEN] = APP_LTE_USER_NAME;
  char password[LTE_NET_PASSWORD_MAXLEN] = APP_LTE_PASSWORD;

  DEBUG_SERIAL_PRINTLN("INFO: Starting LTE web client.");

  /* "Stop" if APN is empty */
  if (strlen(APP_LTE_APN) == 0)
  {
    DEBUG_SERIAL_PRINTLN("ERROR: This sketch doesn't have a APN information.");
    while (1)
    {
      delay(10);
    }
  }
  else
  {
    DEBUG_SERIAL_PRINTLN("INFO: =========== APN information ===========");
    DEBUG_SERIAL_PRINT("INFO: Access Point Name  : ");
    DEBUG_SERIAL_PRINTLN(apn);
    DEBUG_SERIAL_PRINT("INFO: Authentication Type: ");
    DEBUG_SERIAL_PRINTLN(authtype == LTE_NET_AUTHTYPE_CHAP ? "CHAP" : authtype == LTE_NET_AUTHTYPE_NONE ? "NONE"
                                                                                                        : "PAP");
    if (authtype != LTE_NET_AUTHTYPE_NONE)
    {
      DEBUG_SERIAL_PRINT("INFO: User Name          : ");
      DEBUG_SERIAL_PRINTLN(user_name);
      DEBUG_SERIAL_PRINT("INFO: Password           : ");
      DEBUG_SERIAL_PRINTLN(password);
    }
  }

  while (true)
  {
    /* Power on the modem and Enable the radio function. */
    if (lteAccess.begin() != LTE_SEARCHING)
    {
      DEBUG_SERIAL_PRINTLN("ERROR: Could not transition to LTE_SEARCHING.");
      DEBUG_SERIAL_PRINTLN("ERROR: Please check the status of the LTE board.");
      for (;;)
      {
        sleep(1);
      }
    }

    /* The connection process to the APN will start.
       If the synchronous parameter is false,
       the return value will be returned when the connection process is started.
    */
    if (lteAccess.attach(APP_LTE_RAT,
                         apn,
                         user_name,
                         password,
                         authtype,
                         APP_LTE_IP_TYPE) == LTE_READY)
    {
      DEBUG_SERIAL_PRINTLN("INFO: attach succeeded.");
      break;
    }

    /* If the following logs occur frequently, one of the following might be a cause:
       - APN settings are incorrect
       - SIM is not inserted correctly
       - If you have specified LTE_NET_RAT_NBIOT for APP_LTE_RAT,
         your LTE board may not support it.
       - Rejected from LTE network
    */
    DEBUG_SERIAL_PRINTLN("ERROR: An error has occurred. Shutdown and retry the network attach process after 1 second.");
    lteAccess.shutdown();
    sleep(1);
  }

  // Set local time (not UTC) obtained from the network to RTC.
  DEBUG_SERIAL_PRINTLN("INFO: Obtaining time from network to RTC ...");
  RTC.begin();
  unsigned long currentTime;
  while (0 == (currentTime = lteAccess.getTime()))
  {
    sleep(1);
  }
  RtcTime rtc(currentTime);
  DEBUG_SERIAL_PRINTF("%04d/%02d/%02d %02d:%02d:%02d\n",
                      rtc.year(), rtc.month(), rtc.day(),
                      rtc.hour(), rtc.minute(), rtc.second());
  RTC.setTime(rtc);

  /* Initialize SD */
  DEBUG_SERIAL_PRINTLN("INFO: Mounting SD card ...");
  while (!theSD.begin())
  {
    ; /* wait until SD card is mounted. */
  }
}

/* Send HTTP(S) GET request
 */
void send_request(const char *message)
{
  char buffer[STRING_BUFFER_SIZE]="\0";
  strcat(buffer,getPath);
  strcat(buffer,URLEncoder.encode(message).c_str());
  
  // Set certifications via a file on the SD card before connecting to the server
  DEBUG_SERIAL_PRINTLN("INFO: Reading root CA ...");
  File rootCertsFile = theSD.open(APP_ROOTCA_FILE, FILE_READ);
  tlsClient.setCACert(rootCertsFile, rootCertsFile.available());
  rootCertsFile.close();

  DEBUG_SERIAL_PRINT("INFO: Sending request to ");
  DEBUG_SERIAL_PRINT(server);
  DEBUG_SERIAL_PRINT(":");
  DEBUG_SERIAL_PRINT(port);
  DEBUG_SERIAL_PRINTLN(" ...");

  // HTTP GET method
  DEBUG_SERIAL_PRINT("INFO: Sending HTTP GET request for ");
  DEBUG_SERIAL_PRINTLN(buffer);
  client.get(buffer);

  // read the status code and body of the response
  int statusCode = client.responseStatusCode();
  String response = client.responseBody();
  DEBUG_SERIAL_PRINT("INFO: Status code: ");
  DEBUG_SERIAL_PRINTLN(statusCode);
  DEBUG_SERIAL_PRINT("INFO: Response: ");
  DEBUG_SERIAL_PRINTLN(response);
}

gnss_positioning.ino

Arduino
/* gnss:positioning.ino

    derived from

    gnss.ino - GNSS example application
    Copyright 2018 Sony Semiconductor Solutions Corporation

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/**
   @file gnss.ino
   @author Sony Semiconductor Solutions Corporation
   @brief GNSS example application
   @details Spresense has an built in GNSS receiver which supports GPS and other
            GNSS satellites. This skecth provides an example the GNSS operation.
            Simply upload the sketch, reset the board and check the USB serial
            output. After 3 seconds status information should start to appear.\n\n

            This example code is in the public domain.
*/

#include "debug2serial.h"

// include application settings
#include "app_settings.h"

/* include the GNSS library */
#include <GNSS.h>

#define STRING_BUFFER_SIZE 128 /**< %Buffer size */

#define RESTART_CYCLE (60 * 5 * 100000) /**< positioning test term */

static SpGnss Gnss; /**< SpGnss object */

/**
   @enum ParamSat
   @brief Satellite system
*/
enum ParamSat
{
  eSatGps,            /**< GPS                     World wide coverage  */
  eSatGlonass,        /**< GLONASS                 World wide coverage  */
  eSatGpsSbas,        /**< GPS+SBAS                North America        */
  eSatGpsGlonass,     /**< GPS+Glonass             World wide coverage  */
  eSatGpsBeidou,      /**< GPS+BeiDou              World wide coverage  */
  eSatGpsGalileo,     /**< GPS+Galileo             World wide coverage  */
  eSatGpsQz1c,        /**< GPS+QZSS_L1CA           East Asia & Oceania  */
  eSatGpsGlonassQz1c, /**< GPS+Glonass+QZSS_L1CA   East Asia & Oceania  */
  eSatGpsBeidouQz1c,  /**< GPS+BeiDou+QZSS_L1CA    East Asia & Oceania  */
  eSatGpsGalileoQz1c, /**< GPS+Galileo+QZSS_L1CA   East Asia & Oceania  */
  eSatGpsQz1cQz1S,    /**< GPS+QZSS_L1CA+QZSS_L1S  Japan                */
};

/* Set this parameter depending on your current region. */
static enum ParamSat satType = eSatGps;

const long gnss_update_cycle = APP_GNSS_POSITION_UPDATE_CYCLE;
int gnss_error_flag = 0;

/**
   @brief Activate GNSS device and start positioning.
*/
void gnss_setup()
{

#ifdef DEBUG
  /* Set Debug mode to Info */
  Gnss.setDebugMode(PrintInfo);
#endif

  /* Activate GNSS device */
  int result = Gnss.begin();

  if (result != 0)
  {
    DEBUG_SERIAL_PRINTLN("Gnss begin error!!");
    gnss_error_flag = 1;
  }
  else
  {
    /* Setup GNSS
        It is possible to setup up to two GNSS satellites systems.
        Depending on your location you can improve your accuracy by selecting different GNSS system than the GPS system.
        See: https://developer.sony.com/develop/spresense/developer-tools/get-started-using-nuttx/nuttx-developer-guide#_gnss
        for detailed information.
    */
    switch (satType)
    {
    case eSatGps:
      Gnss.select(GPS);
      break;

    case eSatGpsSbas:
      Gnss.select(GPS);
      Gnss.select(SBAS);
      break;

    case eSatGlonass:
      Gnss.select(GLONASS);
      break;

    case eSatGpsGlonass:
      Gnss.select(GPS);
      Gnss.select(GLONASS);
      break;

    case eSatGpsBeidou:
      Gnss.select(GPS);
      Gnss.select(BEIDOU);
      break;

    case eSatGpsGalileo:
      Gnss.select(GPS);
      Gnss.select(GALILEO);
      break;

    case eSatGpsQz1c:
      Gnss.select(GPS);
      Gnss.select(QZ_L1CA);
      break;

    case eSatGpsQz1cQz1S:
      Gnss.select(GPS);
      Gnss.select(QZ_L1CA);
      Gnss.select(QZ_L1S);
      break;

    case eSatGpsBeidouQz1c:
      Gnss.select(GPS);
      Gnss.select(BEIDOU);
      Gnss.select(QZ_L1CA);
      break;

    case eSatGpsGalileoQz1c:
      Gnss.select(GPS);
      Gnss.select(GALILEO);
      Gnss.select(QZ_L1CA);
      break;

    case eSatGpsGlonassQz1c:
    default:
      Gnss.select(GPS);
      Gnss.select(GLONASS);
      Gnss.select(QZ_L1CA);
      break;
    }

    /* Start positioning */
    result = Gnss.start(COLD_START);
    if (result != 0)
    {
      DEBUG_SERIAL_PRINTLN("ERROR: Gnss start error!!");
      gnss_error_flag = 1;
    }
    else
    {
      DEBUG_SERIAL_PRINTLN("INFO: Gnss setup OK");
    }
  }
}

bool gnss_update(double *latitude, double *longitude, double *altitude)
{
  static long lastUpdateMillis = 0;
  static int LoopCount = 0;
  boolean update = false;

  if (lastUpdateMillis > 0 && lastUpdateMillis + gnss_update_cycle > millis())
  {
    return false;
  }

  /* Check update. */
  if (Gnss.isUpdate())
  {
    /* Get NaviData. */
    SpNavData NavData;
    Gnss.getNavData(&NavData);

#ifdef DEBUG
    char StringBuffer[STRING_BUFFER_SIZE];
    /* print time */
    snprintf(StringBuffer, STRING_BUFFER_SIZE, "%04d/%02d/%02d ", NavData.time.year, NavData.time.month, NavData.time.day);
    DEBUG_SERIAL_PRINT("INFO: ");
    DEBUG_SERIAL_PRINT(StringBuffer);
    snprintf(StringBuffer, STRING_BUFFER_SIZE, "%02d:%02d:%02d.%06ld, ", NavData.time.hour, NavData.time.minute, NavData.time.sec, NavData.time.usec);
    DEBUG_SERIAL_PRINT(StringBuffer);
    /* print satellites count */
    snprintf(StringBuffer, STRING_BUFFER_SIZE, "numSat:%2d, ", NavData.numSatellites);
    DEBUG_SERIAL_PRINT(StringBuffer);
    /* print position data */
    if (NavData.posFixMode == FixInvalid)
    {
      DEBUG_SERIAL_PRINT("No-Fix, ");
    }
    else
    {
      DEBUG_SERIAL_PRINT("Fix, ");
    }
    if (NavData.posDataExist == 0)
    {
      DEBUG_SERIAL_PRINT("No Position");
    }
    else
    {
      DEBUG_SERIAL_PRINT("Lat=");
      DEBUG_SERIAL_PRINT(NavData.latitude, 6);
      DEBUG_SERIAL_PRINT(", Lon=");
      DEBUG_SERIAL_PRINT(NavData.longitude, 6);
    }
    DEBUG_SERIAL_PRINTLN("");
#endif

    /* Check if position data is available  */
    if (NavData.posFixMode != FixInvalid && NavData.posDataExist != 0)
    {
      *latitude = NavData.latitude;
      *longitude = NavData.longitude;
      *altitude = NavData.altitude;

      DEBUG_SERIAL_PRINT("INFO: GNSS position data retrieved - Lat=");
      DEBUG_SERIAL_PRINT(*latitude, 6);
      DEBUG_SERIAL_PRINT(", Lon=");
      DEBUG_SERIAL_PRINT(*longitude, 6);
      DEBUG_SERIAL_PRINTLN("");

      lastUpdateMillis = millis();
      gnss_error_flag = 0;
      update = true;
    }
    else
    {
      /* No position */
      DEBUG_SERIAL_PRINTLN("WARNING: No position");
    }
  }
  else
  {
    /* No update. */
    DEBUG_SERIAL_PRINTLN("WARNING: Gnss data not updated");
  }

  /* Check loop count. */
  LoopCount++;
  if (LoopCount >= RESTART_CYCLE)
  {
    DEBUG_SERIAL_PRINTLN("WARNING: Restarting Gnss ...");
    /* Restart GNSS. */
    if (Gnss.stop() != 0)
    {
      DEBUG_SERIAL_PRINTLN("ERROR: Gnss stop error!!");
      gnss_error_flag = 1;
    }
    else if (Gnss.end() != 0)
    {
      DEBUG_SERIAL_PRINTLN("ERROR: Gnss end error!!");
      gnss_error_flag = 1;
    }
    else
    {
      DEBUG_SERIAL_PRINTLN("INFO: Gnss stop OK.");
    }

    if (Gnss.begin() != 0)
    {
      DEBUG_SERIAL_PRINTLN("ERROR: Gnss begin error!!");
      gnss_error_flag = 1;
    }
    else if (Gnss.start(HOT_START) != 0)
    {
      DEBUG_SERIAL_PRINTLN("ERROR: Gnss start error!!");
      gnss_error_flag = 1;
    }
    else
    {
      DEBUG_SERIAL_PRINTLN("INFO: Gnss restart OK.");
    }
    LoopCount = 0;
  }

  return update;
}

app_settings.h

C Header File
/*
  app_setting.h

    Simple example/proof-of-concept for a fall detection device featuring the
    Sony Spresense with Spresense LTE extension board and a a MPU6050 3-axis accelerometer
    and gyroscope ...

    Application configuration

    Read more: https://github.com/dxcfl/fall-detection-with-sony-spresense#readme
    Git: https://github.com/dxcfl/fall-detection-with-sony-spresense
    (c) 2022 by dxcfl
*/

#ifndef APP_SETTINGS_H
#define APP_SETTINGS_H

/* Fall detection parameters **************************************************
*/

#define APP_FD_DETECTION_TIME_INTERVAL 1000 // Fall detection interval in ms
#define APP_FD_FREE_FALL_ACCELERATION_THRESHOLD 2 // m/s^2
#define APP_FD_IMPACT_ACCELERATION_THRESHOLD 20 // m/s^2
#define APP_FD_ORIENTATION_CHANGE_THRESHOLD 5 // rad/s

/* Messaging parameters *******************************************************
*/
 #define APP_SEND_MESSAGE_HOST "api.callmebot.com" 
 #define APP_SEND_MESSAGE_PORT 443
 #define APP_SEND_MESSAGE_PATH "/signal/send.php?phone=+491631737743&apikey=123456&text="
 #define APP_ROOTCA_FILE "isrg_root_x1_dst_root_ca_x3_.cer"
 
/* LTE web client settings ****************************************************
*/

/* Settings for GNSS positioning **********************************************
*/

#define APP_USE_GNSS 1

#define APP_GNSS_POSITION_UPDATE_CYCLE 3000 // ms 

// APN name
#define APP_LTE_APN "iot.truphone.com" // replace your APN

/* APN authentication settings
 * Ignore these parameters when setting LTE_NET_AUTHTYPE_NONE.
 */
#define APP_LTE_USER_NAME "" // replace with your username
#define APP_LTE_PASSWORD  "" // replace with your password

// APN IP type
#define APP_LTE_IP_TYPE (LTE_NET_IPTYPE_V4V6) // IP : IPv4v6
// #define APP_LTE_IP_TYPE (LTE_NET_IPTYPE_V4) // IP : IPv4
// #define APP_LTE_IP_TYPE (LTE_NET_IPTYPE_V6) // IP : IPv6

// APN authentication type
// #define APP_LTE_AUTH_TYPE (LTE_NET_AUTHTYPE_CHAP) // Authentication : CHAP
// #define APP_LTE_AUTH_TYPE (LTE_NET_AUTHTYPE_PAP) // Authentication : PAP
#define APP_LTE_AUTH_TYPE (LTE_NET_AUTHTYPE_NONE) // Authentication : NONE

/* RAT to use
 * Refer to the cellular carriers information
 * to find out which RAT your SIM supports.
 * The RAT set on the modem can be checked with LTEModemVerification::getRAT().
 */

#define APP_LTE_RAT (LTE_NET_RAT_CATM) // RAT : LTE-M (LTE Cat-M1)
// #define APP_LTE_RAT (LTE_NET_RAT_NBIOT) // RAT : NB-IoT




#endif

debug2serial.h

C Header File
/*
  debug2serial.h

    Macros to switch off/on debug output to serial interface.

    Read more: https://github.com/dxcfl/fall-detection-with-sony-spresense#readme
    Git: https://github.com/dxcfl/fall-detection-with-sony-spresense
    (c) 2022 by dxcfl
*/

#ifndef DEBUG2SERIAL_H
#define DEBUG2SERIAL_H

#ifdef DEBUG
    #ifdef DEBUG_VERBOSE
        #define DEBUG_SERIAL_INIT(baud) \
            Serial.begin(baud); \
            Serial.println("DEBUG ENABLED")
        #define DEBUG_SERIAL_FLUSH() Serial.flush() 
        #define DEBUG_SERIAL_PRINT(...)  \
            Serial.print(millis());     \
            Serial.print(": ");    \
            Serial.print(__PRETTY_FUNCTION__); \
            Serial.print(' ');      \
            Serial.print(__LINE__);     \
            Serial.print(' ');      \
            Serial.print(__VA_ARGS__)
        #define DEBUG_SERIAL_PRINTLN(...)  \
            Serial.print(millis());     \
            Serial.print(": ");    \
            Serial.print(__PRETTY_FUNCTION__); \
            Serial.print(' ');      \
            Serial.print(__LINE__);     \
            Serial.print(' ');      \
            Serial.println(__VA_ARGS__)
        #define DEBUG_SERIAL_PRINTF(...)  \
            Serial.print(millis());     \
            Serial.print(": ");    \
            Serial.print(__PRETTY_FUNCTION__); \
            Serial.print(' ');      \
            Serial.print(__LINE__);     \
            Serial.print(' ');      \
            Serial.printf(__VA_ARGS__)
    #else
        #define DEBUG_SERIAL_INIT(baud) Serial.begin(baud)
        #define DEBUG_SERIAL_PRINT(...) Serial.print(__VA_ARGS__)
        #define DEBUG_SERIAL_PRINTLN(...) Serial.println(__VA_ARGS__)
        #define DEBUG_SERIAL_PRINTF(...) Serial.printf(__VA_ARGS__)
    #endif
#else
    #define DEBUG_SERIAL_INIT(baud)
    #define DEBUG_SERIAL_FLUSH()
    #define DEBUG_SERIAL_PRINT(...)
    #define DEBUG_SERIAL_PRINTLN(...)
    #define DEBUG_SERIAL_PRINTF(...)
#endif

#endif

Credits

tf

tf

14 projects • 3 followers

Comments