Dependencies:   mbed LSM9DS1 FastPWM

main.cpp

Committer:
NTesla
Date:
2019-03-05
Revision:
0:33061e64e773
Child:
1:72bcbf11c621

File content as of revision 0:33061e64e773:

#include "mbed.h"
#include "LSM9DS1.h"
#include "FastPWM.h"
#include <math.h>
// setting of MIX DEVICE 
#define DA_PS_BT false //Digital Accelerometer + Pulse Sensor + Bluetooth
#define AA_PS_BT false// Analog Accelerometer + Pulse Sensor + Bluetooth
#define DA_PS_Op true//Digital Accelerometer + Pulse Sensor + Optical
#define AA_PS_Op false// Analog Accelerometer + Pulse Sensor + Optical

#define PS_MODE false // On/Off Pulse Sensor
#define PS_PIN A3 //Pulse Sensor pin

#define ACC_X_PIN A6
#define ACC_Y_PIN A5 //Analog Accelerometer pins
#define ACC_Z_PIN A4

#define X0 1.69  //calibrated counts of analog Accelerometer
#define Y0 1.67
#define Z0 1.68
#define Sx 0.65
#define Sy 0.65
#define Sz 0.65

#define BT_TX_PIN PA_9 // Bluetooth pins
#define BT_RX_PIN PA_10

#define OPT_TX_PIN A7 // optical pins, pwm, baudrate
#define OPT_RX_PIN A2 
#define BAUD_RATE 19200
#define PWM_PIN D10
#define PWM_MODE 455

#if (DA_PS_Op || DA_PS_BT) 
    LSM9DS1 acc(D4, D5);
    //acc.setAcceleroRange(LSM9DS1_ACCELERO_RANGE_2G);  
#endif

#if (AA_PS_BT || DA_PS_BT) // uart's init
    Serial pc(SERIAL_TX, SERIAL_RX); // tx, rx
    Serial BT(BT_TX_PIN, BT_RX_PIN); // tx, rx  
    float acc_x,acc_y,acc_z;
#endif

#if (AA_PS_Op || DA_PS_Op)
    Serial Serial2(OPT_TX_PIN,OPT_RX_PIN,BAUD_RATE);
    int16_t acc_x,acc_y,acc_z;
#endif

#if (AA_PS_BT || AA_PS_Op)
    AnalogIn X(ACC_X_PIN);
    AnalogIn Y(ACC_Y_PIN);
    AnalogIn Z(ACC_Z_PIN);
#endif

#if (PS_MODE)
    AnalogIn P(ACC_X_PIN);
#endif

DigitalOut myled(LED1, 1);

PwmOut buzz(A1);

float ARes = 2.0 / 32768.0; // Digital ACC have datatype int16_t 

int Signal = 0;
int total = 0;

int average = 0;
int IsoLine = 0;
int Tpulse = 0;
int Tpulse2 = 0;
uint16_t count2=0;
uint16_t count3=0;
int AccData[3];
unsigned int  trame1,trame2,trame3,trame4,trame5,trame6,trame7,trame8, trame9,tramePULSE;
int cptmesure;
Timer t;
Timer T1;
Timer T2;

//variables globals

float delta;

double Last, Now;
bool START = false;
int coun;

float tableau_x[10], tableau_y[10], tableau_z[10], t_delta[10];

int numReadings = 70;
int Index = 0;
int readings[70];
int IndexBPM = 5;
int IndexB = 0;
int readingsBPM[5];
int k;
int totalBPM;
int averageBPM;
int verif;
int patient;

void setup()
{
    #if (AA_PS_Op || DA_PS_Op)
        FastPWM mypwm(PWM_PIN,1); //Initializing of clock Output
        //Clock settings for 38kHz
        if (PWM_MODE == 38)
        {
            mypwm.period_us(26.3158);
            mypwm.pulsewidth_us(13.1579);//Duty-Cycle 50% here
        } 
        //Clock settings for 455kHz
        if (PWM_MODE == 455)
        {
            mypwm.period_us(2.1978);
            mypwm.pulsewidth_us(1.0989);//Duty-Cycle 50% here
        }
    #endif
    
    #if (AA_PS_BT || DA_PS_BT)
        BT.baud(115200);
        pc.baud(115200); // Start serial at 115200 bps
    #endif
      
    #if (DA_PS_BT || DA_PS_Op)
         acc.setAcceleroRange(LSM9DS1_ACCELERO_RANGE_2G);
    #endif
    buzz.period_us(2272.7f);
    buzz.write(0.0f);
}
#if (PS_MODE)
    int readMean(int samples)
    {
        int sum = 0;
        for (int i = 0; i < samples; i++)
        {
            sum = sum + (4096 * P);
        }
        return sum/samples;
    }


void pulse()
{
    Signal =  readMean(10);
    total = total - readings[Index];
    readings[Index] = Signal;  // ...которое было считано от сенсора:
    total = total + readings[Index]; // добавляем его к общей сумме:
    Index = Index + 1;        // продвигаемся к следующему значению в массиве:             
    if (Index >= numReadings)
        Index = 0;    // ...возвращаемся к началу:
    int Maxn = 0;  //обнуляем максимальное значение предидущих выборок массив
    for (int i = 0; i < numReadings; i++) // поиск макимальеого значения в масиве из "numReadings" выборок 
    {
        if (readings[i]>Maxn)
            Maxn =  readings[i];
    }                      
    average = total/numReadings;
    IsoLine =  average +  ((Maxn - average)*0.7);
        
    //Serial2.printf("%u %u %u\n", Signal, IsoLine ,average); 
    if ((Signal > IsoLine) && (k > 0))
    {
        T1.stop();
        Tpulse = Tpulse2 + T1.read_us();
        int Tpulse22 = (long)(60L*1000L*1000L)/Tpulse;
        totalBPM = totalBPM - readingsBPM[IndexB];
        readingsBPM[IndexB] = Tpulse;  // ...которое было считано от сенсора:
        totalBPM = totalBPM + readingsBPM[IndexB]; // добавляем его к общей сумме:
        IndexB = IndexB + 1;       // продвигаемся к следующему значению в массиве:             
        averageBPM = 60000000L/((long)totalBPM/IndexBPM);
        if(IndexB >= 5)IndexB = 0;  // если мы в конце массива возвращаемся к началу:
        //Serial2.printf("BPM: %d averageBPM: %d\n", Tpulse22, averageBPM);
        T1.reset();
        T1.start();
        k--;
    }
    else
    {
        if (k < 1) 
        {
            T1.stop();
            Tpulse2 = T1.read_us();
            T1.reset();
            T1.start();
            k++;
        }
    }
}
#endif
void matrice_euler()
{
    tableau_x[coun-1]=acc_x;
    tableau_y[coun-1]=acc_y;
    tableau_z[coun-1]=acc_z;
    t_delta[coun-1]=delta;
}

void read_capteur()
{
    #if (DA_PS_BT) //Digital acc init
        acc_x = -acc.getAcceleroRawY()*ARes;
        acc_y =  acc.getAcceleroRawX()*ARes;
        acc_z =  acc.getAcceleroRawZ()*ARes;
    #elif (AA_PS_BT)                            // !!axis directions are correct!!
        acc_x = (Y*3.3-Y0)/Sy;
        acc_y = -(X*3.3-X0)/Sx;
        acc_z = -(Z*3.3-Z0)/Sz;
    #elif (AA_PS_Op)
        acc_x = Y*4096;
        acc_y = -X*4096;
        acc_z = -Z*4096;
    #elif (DA_PS_Op)
        //acc.getAcceleroRaw(AccData);
        acc_x = -acc.getAcceleroRawY();
        acc_y =  acc.getAcceleroRawX();
        acc_z =  acc.getAcceleroRawZ();
    #endif
    
    #if (PS_MODE)
        pulse();
    #endif
}

void loop ()
{
    read_capteur();
    matrice_euler();
    
    #if (AA_PS_BT || DA_PS_BT)
        if (coun>=10 && count3>=20)
        {
            char s1[50]; //size of the number
            char s2[50]; 
            char s3[50]; 
            char s4[50];
            char s5[50];
    
            myled=!myled;
            coun=0;
            for(int i=0; i<10; i++)
            {
                sprintf(s1, "%g", tableau_x[i]);
                sprintf(s2, "%g", tableau_y[i]);
                sprintf(s4, "%g", tableau_z[i]);
                sprintf(s3, "%g", t_delta[i]);
                #if (PS_MODE)
                    sprintf(s5, "%g", averageBPM);
                    BT.printf("%s;%s;%s;%s;%s|", s1,s2,s4,s3,s5);
                #else
                    BT.printf("%s;%s;%s;%s|", s1,s2,s4,s3);
                #endif
            }
        }
    #else //(DA_PS_Op || AA_PS_Op)
            //increment of measurement: avoids the redundancy of the display on the server
            cptmesure++;
            if(cptmesure == 8)
                cptmesure = 0;
                
            trame2 = (acc_x & 0xFF00) >> 8;         // mask 1111 1111 0000 0000 (ACC 16 bit) int16_t
            trame3 = (acc_x & 0xFF);                // mask 0000 0000 1111 1111 
            trame4 = (acc_y & 0xFF00) >> 8;
            trame5 = (acc_y & 0xFF);
            trame6 = (acc_z & 0xFF00) >> 8;
            trame7 = (acc_z & 0xFF);
            
            verif =  (trame2 << 3) + cptmesure ; 
            
            //first frame: patient + verif (2 bits high)
            trame1 = (patient << 4) + ((verif & 0x700) >> 7);//mask 111 0000 0000
            
            trame8 = (verif & 0xFF);//mask 1111 1111
            
            //fifth frame: patient + increment measurement
            trame9 = (patient << 4) + (cptmesure << 1);
            
/*            IMPORTANT TO UNDERSTAND (ONLY FOR NUCLEO)
            We fill the table which gonna be sent
            TrameTab[0] = 255;  
            TrameTab[1] = trame1;
                
            TrameTab[2] = trame2;   
            TrameTab[3] = trame3;
                
            TrameTab[4] = trame8;
            TrameTab[5] = trame9;
            
            //We sent the table through the serial port
            //Serial2.write(TrameTab,6,0,0);
            //Serial.write to send the information under 8 bits. Serial.print sends a number digit by digit to use to have a display on the monitor.
            //BUT if we will use write() then sketch will stuck after 166 seconds. putc() working same as write().
*/
            Serial2.putc(255);
            Serial2.putc(trame1);
            Serial2.putc(trame2);
            Serial2.putc(trame3);
            Serial2.putc(trame4);
            Serial2.putc(trame5);
            Serial2.putc(trame6);
            Serial2.putc(trame7);
            #if (PS_MODE)
                Serial2.putc((uint8_t)averageBPM);
            #endif
            Serial2.putc(trame8);
            Serial2.putc(trame9);
            #if (!PS_MODE)
                switch(BAUD_RATE)
                {
                    case 4800 :
                        //wait_us(20000);
                        wait_us(41666.66);
                        wait_us(3200);                    
                        break;
                    case 9600 :
                        wait_us(20833.33);
                        wait_us(1100);
                        break;
                    case 19200 :
                        wait_us(10416.66);
                        wait_us(200);
                        break;
                    case 38400 :
                        wait_us(4836.6);//data transfer compensation -351.7us for 38400 baud and 5208.3us delay
                                         //for using the same resistor that we use for optical ECG we should save the equation T_delay = 2*T_transmission 
                        break;
                    default :
                        wait_ms(50);
                 }
             #endif
             #if (PS_MODE)
                 switch(BAUD_RATE)
                 {
                    case 4800 :
                        //wait_us(20000);
                        wait_us(41666.66 + 4166.66);
                        wait_us(3200 + 320);                    
                        break;
                    case 9600 :
                        wait_us(20833.33 + 2083.33);
                        wait_us(1100 + 110);
                        break;
                    case 19200 :
                        wait_us(10416.66 + 1041.66);
                        wait_us(200 + 20);
                        break;
                    case 38400 :
                        wait_us(4836.6 + 520.83);//data transfer compensation -351.7us for 38400 baud and 5208.3us delay
                                         //for using the same resistor that we use for optical ECG we should save the equation T_delay = 2*T_transmission 
                        break;
                    default :
                        wait_ms(50);
                  }
             #endif
    #endif
}

int main()
{
    
    setup();
    t.start();
    Last = t.read_us();
    coun=0;
    count3=0;

    while (true)
    {
        #if (AA_PS_BT || DA_PS_BT) //bluetooth mode
            Now = t.read_us();
            delta = (float)(Now-Last)/1000000.0f;
            if (delta>=0.1f && START==true)
            {
                Last=Now;
                coun+=1;
                if (count3<=81)
                {
                    count3+=1;
                }
                
                loop(); //Get sensor values
            }
            if (BT.readable())
            {
                char c = BT.getc();
                if(c == '1'){
                    //BT.printf("\nOK\n");
                    START=true;
                    count3=0;
                }
                if(c == '0')
                {
                    //BT.printf("\nOK\n");
                    START=false;
                    myled=1;
                    buzz.write(0.50f);
                    wait(3);
                    buzz.write(0.0f);
                }
            }
        #else
            //optical
            loop();
        #endif
    } 
}