Project admin

This project is private.

Aymerick
Created May 2, 2020

Connected Safety Jacket

A connected safety jacket which locate and send health information to enable the rescue services to save the victim.

16
Connected Safety Jacket

Things used in this project

Hardware components

KIM1 shield
×1
400 MHz antenna
×1
Seeed Studio Seeed - Grove - GPS
×1
Grove - 3-Axis Digital Accelerometer(±1.5g)
Seeed Studio Grove - 3-Axis Digital Accelerometer(±1.5g)
×1
Seeed Studio Grove - Finger-clip Heart Rate Sensor with shell
×1
Arduino UNO
Arduino UNO
×1
Base Shield V2
Seeed Studio Base Shield V2
×1

Software apps and online services

Arduino IDE
Arduino IDE
Argos platform access

Story

Read more

Schematics

Developer circuit diagram

The circuit diagram used by the dev team during the project.

Electronic schematic

The electronic schematic of the industrial version.

PCB

PCB of the industrial version.

Code

Connected safety jacket firmware

Arduino
The firmware implemented ine safety jacket MCU. It is used to control the MCU working (sensors measurements, GPS location, data transmission...).
#include <SoftwareSerial.h>
#include "Arduino.h"
#include "KIM.h"
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <SoftwareSerial.h> 
#include <Wire.h>
#include "MMA7660.h"

#define RX_PIN 7
#define TX_PIN 8

SoftwareSerial kserial(RX_PIN, TX_PIN);
SoftwareSerial SoftSerial(2, 3); 

KIM kim;

//GPS variables
String heure_tot, lat, NS, longi, EW, fix, nb_sat, precision, heure, minute; 
int deg_lat, min_lat, deg_longi, min_longi;
unsigned int min_dec1,min_dec2,min_dec3;

void setup() {
  Serial.begin(4800);                       // Start PC serial port @ 4800 baud
  delay(100);
  Wire.begin();                             //Start the BPM sensor connection
  kim.set_SoftwareSerial(&kserial, 4800);   //Start UART connection with KIM @ 4800 baud
}

void loop() {
  //Variable initilization
  int aX_MAX=0, aY_MAX=0, aZ_MAX=0;
  int aX, aY, aZ;
  int BPM[60];
  int somme=0,den=0;
  int BPM_moy;
  int cpt=0;
  String GPS_GGA;
  int BAT, alert, wakup;
  Serial.println("Accelerometer measurements");
  for(cpt=0;cpt<810;cpt++)    //Cycle of 810*1s with only acceleration measurements 
  {
    aX = measure_accX();      //X axis acceleration measurement
    aY = measure_accY();      //Y axis acceleration measurement
    aZ = measure_accZ();      //Z axis acceleration measurement
    //aX = simu_accX(0.95);   //X axis acceleration simulation fonction to emule the accelerometer
    //aY = simu_accY(0.63);   //Y axis acceleration simulation fonction to emule the accelerometer
    //aZ = simu_accZ(1.2);    //Z axis acceleration simulation fonction to emule the accelerometer
    aX_MAX=MAX(aX_MAX,aX);    //Store the max X axis acceleration value
    aY_MAX=MAX(aY_MAX,aY);    //Store the max Y axis acceleration value
    aZ_MAX=MAX(aZ_MAX,aZ);    //Store the max Z axis acceleration value
    delay(990);    
  }
  Serial.println("Accelerometer + BPM measurements");
  for(cpt=810;cpt<870;cpt++)  //Cycle of 60*1s with only acceleration+BPM measurements
  {
    aX = measure_accX();
    aY = measure_accY();
    aZ = measure_accZ();
    //aX = simu_accX(0.95);
    //aY = simu_accY(0.63);
    //aZ = simu_accZ(1.2);
    aX_MAX=MAX(aX_MAX,aX);
    aY_MAX=MAX(aY_MAX,aY);
    aZ_MAX=MAX(aZ_MAX,aZ);
    BPM[cpt-810]=measure_BPM();   //BPM measurements
    //BPM[cpt-810]=simu_BPM(128); //BPM simulation fonction to emule the heart rate sensor
    delay(990); 
  }
    //Start of the BPM average calculation
    for(int i=0;i<60;i++)
    {
      if(BPM[i]>0)
      {
      somme+=BPM[i];
      den++;
      }
    }
    BPM_moy=somme/den;
    //End of the BPM average calculation
    GPS_GGA = GPS_acquisition();      //GPS localisation
    //GPS_GGA = simu_GPS_GGA("154415.000,4839.4308,N,00214.6685,E,1,5,1.66,102.9,M,47.3,M,,*51");   //GPS trame simulation fonction to emule the GPS chip
    recept_val_GPS(GPS_GGA);          //GPS data treatment
    BAT = simu_BAT(87);               //Battery level simulation
    alert = simu_alert(1);            //Alert state simulation
    wakup = simu_Wakup(3);            //Wakupe victim indication simulation
    String TRANSMIT=conception_trame_sat(BAT,alert,wakup,BPM_moy,aX_MAX,aY_MAX,aZ_MAX);             //Initialization of the transmission string
    KIM_switch_on();                  //KIM1 switch on
    KIM_config("B1",300,1500);        //KIM1 config
    KIM_transmit(TRANSMIT);           //Satelite transmission (1st try)
    delay(1000);
    KIM_transmit(TRANSMIT);           //Satelite transmission (2nd try)
    delay(1000);
    KIM_transmit(TRANSMIT);           //Satelite transmission (3rd try)
    delay(1000);
    KIM_transmit(TRANSMIT);           //Satelite transmission (4th try)
    delay(1000);
    KIM_switch_off();                 //KIM1 switch off

}

void KIM_switch_on(){
    Serial.println(F("main-->Turning ON the Kim1"));
    kim.set_ModuleStateON();                  // Set the Kim1 On/Off pin HIGH and thus turn the Kim1 module ON
    kim.get_KIMPlatform_Info();
    delay(2000);
}

void KIM_config(String BAND, int FREQUENCY, int POWER){
    Serial.println(F("main-->Configuring the transmission parameters"));
    kim.set_TX_Band(BAND);                    // Assign the band for transmission using AT command
    kim.set_TX_OffsetFreq(FREQUENCY);         // Assign the transmission offset frequency for transmission using AT command
    kim.set_TX_Power(POWER);                  // Assign the power for transmission using AT command
    Serial.println(F("main-->Function called to check the values configured for the transmission parameters: "));
    kim.get_TransmissionParameters_Values();
}

void KIM_transmit(String HEXA_STRING){
    Serial.println(F("main-->-------- transmit hexadecimal user message -------"));
    Serial.print(F("main-->User message length:"));
    Serial.println(HEXA_STRING.length());
    Serial.print(F("main-->User Data:"));
    Serial.println(HEXA_STRING);
    String HEXA_MESSAGE = HEXA_STRING;
    String command = "AT+TX=" + HEXA_MESSAGE + "\r";
    Serial.print(F("Command :"));
    Serial.println(command);   
    kim.send_ATCommand(command);
}

void KIM_switch_off() {
    Serial.println(F("main-->Stop the Kim1 and the Arduino board"));
    kim.set_ModuleStateOFF();
    kim.stop();
}

int measure_BPM()
{
    unsigned char c;
    Wire.requestFrom(0xA0 >> 1, 1);     // request 1 bytes from slave device
    while(Wire.available()) 
    {
        c = Wire.read();                // receive heart rate value (a byte)
    }
    return (int)(c);
}

int measure_accX()
{
  MMA7660 acc;
  acc.init();
  float ax, ay, az;
  acc.getAcceleration(&ax,&ay,&az);
  return (int)(ax*100);
}

int measure_accY()
{
  MMA7660 acc;
  acc.init();
  float ax, ay, az;
  acc.getAcceleration(&ax,&ay,&az);
  return (int)(ay*100);
}

int measure_accZ()
{
  MMA7660 acc;
  acc.init();
  float ax, ay, az;
  acc.getAcceleration(&ax,&ay,&az);
  return (int)(az*100);
}

int MAX(int a, int b)
{
  if(a<b)
  return b;
  else
  return a;
}

String GPS_acquisition()
{
  String trame_GPS_GGA, trame_GPS;
  SoftSerial.begin(9600);
  char buffer[64];                   // buffer array for data receive over serial port 
  int count=0;
  int count_trame = 0;
  int etape = 0; 
  if (SoftSerial.available())                     // if date is coming from software serial port ==> data is coming from SoftSerial shield     
  {      
    while(SoftSerial.available())               // reading data into char array         
    {           
      buffer[count++]=SoftSerial.read();      // writing data into array         
      if(count == 64)break;        
    } 
     for (int i=0; i<count;i++)
     {     
      Serial.print(buffer[i]);
      trame_GPS.concat(buffer[i]);
     }
     Serial.println();
     for(count_trame=0;((count_trame<count) or (etape == 6));count_trame++)
    {
      int buf_ascii = trame_GPS[count_trame]; 
      if(buf_ascii == 36)
      {
        etape = 1;
        count_trame++;
      }
      else 
      { etape = 0; }
      buf_ascii = trame_GPS[count_trame];
        
      if((buf_ascii == 71)and(etape == 1)) 
      {
        etape = 2;
        count_trame++;
      }
      else 
        {etape = 0; }
      buf_ascii = trame_GPS[count_trame];     
      if((buf_ascii == 80)and(etape == 2)) 
      {
        etape = 3;
        count_trame++;
      }
      else 
        {etape = 0; }
      buf_ascii = trame_GPS[count_trame];  
      if((buf_ascii == 71)and(etape == 3)) 
      {
        etape = 4;
        count_trame++;
      }
      else 
        {etape = 0;}
      buf_ascii = trame_GPS[count_trame]; 
      if((buf_ascii == 71)and(etape == 4)) 
      {
        etape = 5;
        count_trame++;
      }
      else 
        {etape = 0;}
      buf_ascii = trame_GPS[count_trame]; 
      if((buf_ascii == 65)and(etape == 5)) 
      {
        etape = 6;
        count_trame++;
         int buf_ascii2 = buffer[count_trame];
         trame_GPS_GGA = "";
         for(int i = count_trame;(i<count);i++)
          {
            buf_ascii2 = trame_GPS[i];
            if(buf_ascii2== 36)
            {
              etape=0;
              trame_GPS_GGA = "";
    }
    else
      trame_GPS_GGA.concat(trame_GPS[i]);
  }
      }
      else 
        {etape = 0;}
      buf_ascii = trame_GPS[count_trame]; 
     }
    
     for (int i=0; i<count;i++)     
     { 
        buffer[i]=NULL;
     }                   
     trame_GPS = ""; 
     count = 0;                                  // set counter of while loop to zero 
  }      
  delay(10);
  return trame_GPS_GGA;
}

 void recept_val_GPS(String trame_GPS_GGA)
/******************************************************
Splitting GPS data function

Global variables used:
String heure_tot, lat, NS, longi, EW, fix, nb_sat, precision, heure, minute; 
int deg_lat, min_lat, deg_longi, min_longi;
******************************************************/
{
  //String s = "12345, 6789, 101112"; // exemple
  int n_av=0, n_ap =0;
  //double nb;
  //String subs, newStr="";
  int temp =0;
  String Stemp;

  
  n_av=0;
  n_ap = trame_GPS_GGA.indexOf(",",n_av+1);
  heure_tot = trame_GPS_GGA.substring(n_av+1, n_ap);
  heure = heure_tot.substring(0,1);
  minute = heure_tot.substring(2,3);
  n_av=n_ap;
  n_ap = trame_GPS_GGA.indexOf(",",n_av+1);
  lat = trame_GPS_GGA.substring(n_av+1, n_ap);
  n_av=n_ap;
  n_ap = trame_GPS_GGA.indexOf(",",n_av+1);
  NS = trame_GPS_GGA.substring(n_av+1, n_ap);
  n_av=n_ap;
  n_ap = trame_GPS_GGA.indexOf(",",n_av+1);
  longi = trame_GPS_GGA.substring(n_av+1, n_ap);
  n_av=n_ap;
  n_ap = trame_GPS_GGA.indexOf(",",n_av+1);
  EW = trame_GPS_GGA.substring(n_av+1, n_ap);
  n_av=n_ap;
  n_ap = trame_GPS_GGA.indexOf(",",n_av+1);
  fix = trame_GPS_GGA.substring(n_av+1, n_ap);
  n_av=n_ap;
  n_ap = trame_GPS_GGA.indexOf(",",n_av+1);
  nb_sat = trame_GPS_GGA.substring(n_av+1, n_ap);
  n_av=n_ap;
  n_ap = trame_GPS_GGA.indexOf(",",n_av+1);
  precision = trame_GPS_GGA.substring(n_av+1, n_ap);
  n_ap=0;
  n_ap = lat.indexOf(".",0);
  Stemp=lat.substring(0, n_ap);
  temp = Stemp.toInt();
  deg_lat = (int)(temp/100);
  temp = temp%100;
  Stemp="";
  Stemp=lat.substring(n_ap+1);
  min_lat = Stemp.toInt();
  min_lat = min_lat + temp*10000;
  n_ap=0;
  temp=0;
  Stemp="";
  n_ap = longi.indexOf(".",0);
  Stemp=longi.substring(0, n_ap);
  temp = Stemp.toInt();
  deg_longi = (int)(temp/100);
  temp = temp%100;
  Stemp="";
  Stemp=longi.substring(n_ap+1);
  min_longi = Stemp.toInt();
  min_longi = min_longi + temp*10000;
}

void conv_dec_bin_20b(long unsigned int dec)
/***********************************************************
Converts a <524,288 decimal value to a binary value of 20 bits 
split into 3 bytes with min_dec1 per byte of byte weight 
high and min_dec3 the low byte

Global variables used :
unsigned int min_dec1,min_dec2,min_dec3;
***********************************************************/
{
  long int dec_temp;
  double temp=0;

  min_dec1=0;
  min_dec2=0;
  min_dec3=0;
  for(int i=19;i>=16;i--)
  {
    dec_temp = dec-pow(2,i);
    if(dec_temp>=0)
    {
      dec=dec-pow(2,i);
      temp= temp + pow(2,i-16);
    }
  }
  min_dec1 = (unsigned int)(temp+1);
  temp = 0;
  for(int i=15;i>=8;i--)
  {
    dec_temp = dec-pow(2,i);
    if(dec_temp>=0)
    {
      dec=dec-pow(2,i);
      temp= temp+pow(2,i-8);
    }
  }
  min_dec2 = (unsigned int) (temp+1);
  temp = 0;
  for(int i=7;i>=0;i--)
  {
    dec_temp = dec-pow(2,i);
    if(dec_temp>=0)
    {
      dec=dec-pow(2,i);
      temp= temp+pow(2,i);
    }
  }
  min_dec3 = (unsigned int) (temp+1);
  temp = 0;
}

String conception_trame_sat(int niv_bat,int et_alerte,int Wakup,int BPM,int acc_x,int acc_y,int acc_z)

{
  String userdataS;
  String HEXA_STRING;
   unsigned int temp;
   userdataS=String(heure.toInt(),HEX);
   HEXA_STRING=generate_hexa_string(1,userdataS,HEXA_STRING);
   userdataS=String((minute.toInt() + Wakup*64),HEX);
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);  
   if(NS=="N")
    userdataS=String(deg_lat,HEX);
   else 
    userdataS=String((deg_lat+128),HEX);
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   userdataS=String(deg_longi,HEX);
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);   
   if(NS=="N")
    userdataS=String(((int)(precision.toFloat()*10)),HEX);
   else 
    userdataS=String((((int)(precision.toFloat()*10))+128),HEX);
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   conv_dec_bin_20b(((long unsigned int) min_lat));
   userdataS=String( min_dec3,HEX);
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   userdataS= String(min_dec2,HEX);
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   temp=min_dec1;
   conv_dec_bin_20b(((long unsigned int) min_lat));
   userdataS=String((temp+ (min_dec1*16)),HEX);
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   userdataS=String( min_dec2,HEX);
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   userdataS= String(min_dec3,HEX);
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   userdataS=String((niv_bat + 128*et_alerte),HEX);
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   userdataS=String(BPM,HEX);
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   if(acc_x<0)
   {
    if(acc_x>127)
      acc_x=127;   
    userdataS=String((acc_x),HEX);
   }
   else
   {
    if(acc_x<-127)
     acc_x=-127;     
    userdataS=String(((acc_x)+128),HEX);  //ajout du bit de signe
   }
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   if(acc_y<0)
   {
    if(acc_y>127)
      acc_y=127;  
    userdataS=String((acc_y),HEX);
   }
   else
   {
    if(acc_y<-127)
     acc_y=-127;
    userdataS=String(((acc_y)+128),HEX);
   }
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   if(acc_z<0)
   {
    if(acc_z>127)
      acc_z=127;
    userdataS=String((acc_z),HEX);
   }
   else
   {
    if(acc_z<-127)
     acc_z=-127;
    userdataS=String(((acc_z)+128),HEX);
   }
   HEXA_STRING=generate_hexa_string(0,userdataS,HEXA_STRING);
   return HEXA_STRING;  
} 

String generate_hexa_string(int init,String USDT,String HS)
{
  String HEXA_STRING=HS;
  if (init==1)
    HEXA_STRING="";
    if(USDT.length()==1)
      HEXA_STRING+="0"+USDT;
    else
      HEXA_STRING+=USDT;
    Serial.println(HEXA_STRING);
  HEXA_STRING.toUpperCase();
  return HEXA_STRING;
}

 String simu_GPS_GGA(String GGA)
 {
  return GGA;
 }

int simu_BAT(int lv)
{
  return lv;
}

int simu_alert(int alt)
{
  return alt;
}

int simu_Wakup (int wkp)
{
  return wkp;
}

 int simu_BPM(int BPM)
 {
  return BPM;
 }

 int simu_accX(float X)
 {
  return int(X*100);
 }

 int simu_accY(float Y)
 {
  return int(Y*100);
 }

  int simu_accZ(float Z)
 {
  return int(Z*100);
 }

Credits

Aymerick
0 projects • 0 followers

Comments