FFT à reprogrammer Gestion des trames réseaux à améliorer (certaines trames ne se transmettent pas)

Dependencies:   mbed SHT21_ncleee HX711 mbed-dsp DS1820

main.cpp

Committer:
Lambdys
Date:
2021-01-25
Revision:
0:4311d41c5fbc

File content as of revision 0:4311d41c5fbc:

/*-------------------------------------*/
/* Ruche connectée B-Smart V15         */
/* Contrôle baremetal                  */
/*                                     */
/* BIROLINI Nikolaï                    */
/* GOURDET Hadrien                     */
/* HULOT Alexandra                     */
/* LEBRETON Maxime                     */
/*                                     */
/* Janvier 2021                        */
/* Polytech Sorbonne                   */
/*-------------------------------------*/

#include "SHT21_ncleee.h"
#include "arm_math.h"
#include "arm_const_structs.h"
#include "DS1820.h"
#include "HX711.h"

#define DEBUG 1

    
HX711 Balance(D11,D10);
Serial pc(USBTX,USBRX);
AnalogOut  MEAS_ENABLE(A3);

//=1 VMEAS
//=0 SIGFOX

Serial sigfox(D1,D0);//TX:PA_2:A7 RX:PA_3:A2


#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define SIZE 7
#define TEMPPRESENCE 35
#define FFT_SIZE 1024

DigitalOut TPL5110_DONE(D5);

typedef struct _frame //champ de bits
{
    unsigned char *field; //tableau de char
    int offset;           //index
    int size;             //taille de la trame en bits
} Frame;

void new_frame(Frame* frame,unsigned char* field)
{
    frame->field = field;
    frame->offset = 0;                                                               //on part du premier char
    frame->size = SIZE*8;
}



int get_bit(Frame *frame) //fonction de debuggage
{
    int char_index = frame->offset / 8;
    int bit_index = 7-(frame->offset % 8);
    frame->offset++;

    return ((frame->field[char_index] & (1 << bit_index)) > 0) ? 1 : 0;
}
void print_frame(Frame *frame) //fonction de debuggage
{
    int cur_offset = frame->offset;
    frame->offset = 0;
    pc.printf("Frame {\r\n\ttaille   : %d / %d\r\n\tbitfield : ", cur_offset, frame->size);
    while (frame->offset < cur_offset)
    {
        printf(get_bit(frame) == 1 ? "1" : "0");
        if (frame->offset % 8 == 0)
            printf(" ");
    }
    pc.printf("\r\n}\r\n");
}
void stock_bit(unsigned char bit, Frame *frame) //set le bit n°offset à 1 si bit>0, sinon à 0
{
    if (frame->offset < frame->size)
    {
        int char_index = frame->offset / 8;          //n° du char
        int bit_index = 7 -(frame->offset % 8);           //n° du bit
        unsigned char char_mask = ~(1 << bit_index); //mask pour garder tous les bits existants sauf celui qui nous intéresse

        frame->field[char_index] = (frame->field[char_index] & char_mask) + ((bit > 0 ? 1 : 0) << bit_index); //place le bit à sa place
        frame->offset++;                                                                                      //bit modifié, on se déplace
    }
}
void stock_int(unsigned int value, int taille_en_bits, Frame *frame) //stocke les bits d'un int
{
    if(DEBUG)
    {
        pc.printf(" Mesure %d ,taille = %d\r\n",value,taille_en_bits);
    }
            
    for (int i = 0; i < taille_en_bits; i++){
        stock_bit(value & (1 << (taille_en_bits - i - 1)), frame);
        //print_frame(frame);
}
}
void validate_frame(Frame *frame) //on met toute la fin à zéro si pas déjà utilisée
{
    while (frame->offset < frame->size)
        stock_bit(0, frame);
}



void send_frame(Frame *frame) //fonction de debuggage
{
    sigfox.printf("AT$SF=");
    if(DEBUG) pc.printf("AT$SF=");
    for ( int i = 0 ; i < frame->size / 8 ; i++) {
        sigfox.printf("%0X", frame->field[i]);
        
        if(DEBUG) pc.printf("%0X", frame->field[i]);
    }
    sigfox.printf("\r\n");
    if(DEBUG) pc.printf("\r\n");
}

void stock_temp(Frame *frame, float temp)
{
    temp = min(temp, 45.5f);
    temp = max(temp, -18);
    //temp = max(temp, -10);
    int bits = (int)((temp/2. + 36) * 2 + 0.5f); //round(temp+18)*2
    stock_int(bits, 7, frame);
}

/* Masse test enhanced */
void stock_masse(Frame *frame, float masse)
{
    /*bib = https://apiarobotics.com/fr/connaissances/poids-dune-ruche */
    /*encadrer la masse entre 15kg et 50 kg*/
    masse = max(masse, 15.f);//masse mini = 15kg
    masse = min(masse, 50.f);//masse max = 50kg
    
    if(debug) pc.printf("[MASSE]masse retenue (kg)= %f\n", masse);
    
    /*ajout d'offset */
    masse-=15; //masse mini
    
    /*produit en croix */
    /*10kg = 0x00 */
    /*50kg = 0xff */
    /*précision = 35kg/190 = 184g */
    masse = masse*(255.0-65)/35.0; //produit en croix (35 = masse max - masse mini)
    masse += 65; //offset binaire. Si on veux transmettre une valeur <65 = bug !! (valeur obtenue par tatonnement)
    
    
    int bits = (int)masse;
    
    if(debug) pc.printf("[MASSE]valeur binaire retenue = %d\n", bits);
    
    stock_int(bits,8,frame);
}

void stock_vent(Frame *frame, float vent)
{
    vent = min(vent, 70);
    vent = max(vent, 0);
    int bits = (int)(vent*0.1f + 0.5f);
    stock_int(bits, 3, frame);
}
void stock_humidity(Frame *frame,float humidity)
{   
    humidity = min(humidity,100);
    humidity = max(humidity,20);
    int bits = (int)(humidity*31/100+0.5f);
    stock_int(bits,5,frame);
}
void stock_battery(Frame *frame,float battery)
{   
    battery = min(battery,100);
    battery = max(battery,0);
    int bits = (int)(battery*63/100+0.5f);
    stock_int(bits,6,frame);
}

InterruptIn anemo(D13);//D13
//ATTENTION: ne pas oublier de ratacher l'interupt à une fonction (dans le main)!

AnalogIn analog_battery(A0);
AnalogIn analog_luminosity(A1);
AnalogIn analog_TMP36(A4);
//AnalogIn analog_FFT(A5);
        
//I2C i2c(PB_4, PA_7);//SDA:A12, SCL:A6
I2C i2c(PB_4, PA_7);//SDA:A12, SCL:A6
SHT21 sht(&i2c);

Timer t_anemo;
int cpt_anemo;

void anemo_counter() //IRQ Anémomètre
{
    cpt_anemo++;
    if(debug)pc.printf("WIND ! cpt_anemo = %d \n",cpt_anemo);
}

//FFT

int FFT_compt;
float fmax;
/* Pour simplifier l'interprétation des mesures, un instant est relié à chaque mesure */
float FFT_DUREE[FFT_SIZE];

/* Signal en entrée analogique */
float signal_reel[FFT_SIZE+1];

/* Signal après dérivation */
float signal_reelDiff[FFT_SIZE];

/* Signal avant la FFT (il contient les composantes réeles et complexes (composante complexe nulle)) */
float FFT_in[FFT_SIZE*2];

/* Spectre à la sortie de FFT */
float FFT_out[FFT_SIZE*2];

/* Reference index at which max energy of bin ocuurs */
uint32_t testIndex = 0;

/* Flag FFT complexe. La FFT sera effectuée uniquement sur la composante réele. Donc flag à '0' */
int ifftFlag = 0;

int doBitReverse = 1;
                
/* Energie maximale */
float maxValue;
AnalogIn analog_FFT(A5);
float Fe= 4000;//Fréquence echantillonage
float Te = 1/Fe;
int MortReine = 0;//Mort de la reine 0 = vivant, 1=mort
int ToutVaBien = 0;//Si tout va bien= 0 sinon = 1
int Stress = 0;//Abeille en stress = 1 sinon 0
int bebe = 0;//Essaimage = 1 sinon 0
int moyenneAmp=0;
int moyenneNorm=0;//Moyenne amplitude sur tout le spectre
int moyEss=0; //Moyenne amplitude entre 200Hz et 500 Hz



int main(void)
{
    TPL5110_DONE=0;
    MEAS_ENABLE = 1;
    anemo.disable_irq();
    anemo.rise(&anemo_counter);//attacher une fonction à l'interrupt
            //--------------------------------------------- données brutes------------------------------------------
        float temp_ext = 10.;              // variable pour la température extérieure
    
        float temp_int_1 = 20.5;            // mesures des 8 sondes de température à l'intérieur de la ruche
        float temp_int_2 = 20.5;
        float temp_int_3 = 20.5;
        float temp_int_4 = 20.5;
        float temp_int_5 = 20.5;
        //float temp_int_6 = 20.5;
        //float temp_int_7 = 20.5;
        //float temp_int_8 = 20.5;
        float temp_int;   //température intérieure moyenne 
        int luminosity = 2;
        float masse = 0;
        float force_vent = 50.0;
        float battery = 2.0;
        float humidity = 56.6;
        int cadre_1_2 = 1;//non utilisé mais crash si 0!
        int cadre_3 = 0;
        int cadre_4 = 0;
        int cadre_5 = 0;
        int cadre_6 = 0;
        int cadre_7 = 0;
        int cadre_8 = 1;//remplacer par reine;
        int cadre_9_10 = 0;//remplacer par presence_ruche;
        int stress = 0;
        int essaimage = 0;
        int reine = 1;
        int abeilles = 0;
        //------------ pour la tx
        
        long masse_valeur_moyenne;
        long masse_valeur;
        float battery_read;
        float luminosity_read;
    
    if(debug)pc.printf("1.Initialisation DS1820\n");
    DS1820 sensor_DS1820_1(D2);
    DS1820 sensor_DS1820_2(D3);
    DS1820 sensor_DS1820_3(D6);
    DS1820 sensor_DS1820_4(D9);
    
    if(debug)pc.printf("1a.Lecture DS1820: 1/4\n");
    sensor_DS1820_1.convertTemperature(true, DS1820::all_devices);     // start temperature conversion
    wait(1);  // let DS1820 complete the temperature conversion
    temp_int_1 = sensor_DS1820_1.temperature();
    
    if(debug)pc.printf("1a.Lecture DS1820: 2/4\n");
    sensor_DS1820_2.convertTemperature(true, DS1820::all_devices);     // start temperature conversion
    wait(1);  // let DS1820 complete the temperature conversion
    temp_int_2 = sensor_DS1820_2.temperature();
    
    if(debug)pc.printf("1a.Lecture DS1820: 3/4\n");
    sensor_DS1820_3.convertTemperature(true, DS1820::all_devices);     // start temperature conversion
    wait(1);  // let DS1820 complete the temperature conversion
    temp_int_3 = sensor_DS1820_3.temperature();
    
    if(debug)pc.printf("1a.Lecture DS1820: 4/4\n");
    sensor_DS1820_4.convertTemperature(true, DS1820::all_devices);     // start temperature conversion
    wait(1);  // let DS1820 complete the temperature conversion
    temp_int_4 = sensor_DS1820_4.temperature();
    
    if(debug)pc.printf("1b.Initialisation et lecture SHT20\n");
    temp_int_5 = sht.readTemp();
    
    temp_int = (temp_int_1 + temp_int_5 + temp_int_5 + temp_int_5 + temp_int_5)/5.0;

    if(debug)pc.printf("[TEMP]: temperature interieure moyenne = %f oC\n",temp_int);
    
    if(debug)pc.printf("1c.Lecture TMP36\n");
    /* https://learn.adafruit.com/tmp36-temperature-sensor */
    temp_ext = analog_TMP36.read();
    temp_ext*=3.3;//mise à l'échelle val analogique 0 à 1 en tension 0 à 3.3V
    temp_ext-=0.500; //-500 mV
    temp_ext/=0.010; //cf datasheet, div par 10 mV
    

    if(debug) pc.printf("[TEMP]: temperature exterieure = %f oC\n",temp_ext);

    if(debug)pc.printf("1.d.Occupation des cadres\n");
    
    if(temp_int_1 >= TEMPPRESENCE) cadre_3 = 1;
    if(temp_int_2 >= TEMPPRESENCE) cadre_4 = 1;
    if(temp_int_3 >= TEMPPRESENCE) cadre_5 = 1;
    if(temp_int_4 >= TEMPPRESENCE) cadre_6 = 1;
    if(temp_int_5 >= TEMPPRESENCE) cadre_7 = 1;
    

    
    
    if(debug)pc.printf("[Temp] cadre_3 actif = %d \n",cadre_3);
    if(debug)pc.printf("[Temp] cadre_4 actif = %d \n",cadre_4);
    if(debug)pc.printf("[Temp] cadre_5 actif = %d \n",cadre_5);
    if(debug)pc.printf("[Temp] cadre_6 actif = %d \n",cadre_6);
    if(debug)pc.printf("[Temp] cadre_7 actif = %d \n",cadre_7);
    
    if((cadre_3)||(cadre_4)||(cadre_5)||(cadre_6)||(cadre_7)) abeilles = 1;
    if(debug)pc.printf("[Temp] abeilles = %d \n", abeilles);
    
    if(!abeilles) reine=0;
    
    if(DEBUG)pc.printf("2a.Mesure masse en cours...\n", masse);
        
    masse_valeur_moyenne = Balance.averageValue(100);
        //tare = 8441392
        // printf("value: %ld\r\n",a - 8441392);
        //avec tare: 0 = 0kg, 42381 = 2kg
    masse_valeur = ( masse_valeur_moyenne - 8441392.0);//Tare
      // printf("value: %ld\r\n",valeur);
       
    masse =(float) masse_valeur*2.113/42381.0;
       
    if(masse>=10.0) cadre_9_10=1;//presence_ruche
    //masse = ((int) masse * 100) / 100;
    //2.113 = from balance précise 
    
   if(debug)pc.printf("[Masse] %f kg\n", masse);
    
    if(DEBUG)pc.printf("3b.Analyse FFT cours...\n");
    
    /*---- Début FFT*/     
        
        for(FFT_compt=0;FFT_compt<FFT_SIZE+1;FFT_compt++)
        {
            signal_reel[FFT_compt]=analog_FFT.read();
        }

        
        //printf("Fréquence échantillonage : %f\n", Fe);
                
        /*Dérivée du signal d'entrée (dérivée avant) */
        for(FFT_compt=0;FFT_compt<FFT_SIZE;FFT_compt++)
        {
            signal_reelDiff[FFT_compt]=(signal_reel[FFT_compt+1]-signal_reel[FFT_compt])/Te;
            //printf("derivee  = %f\n",signal_reelDiff[FFT_compt]);    
        }        
        
        /*remplissage paire (reel), partie imaginaire nulle*/
        for(FFT_compt=0;FFT_compt<FFT_SIZE;FFT_compt++)
        {
            FFT_in[FFT_compt*2]=signal_reelDiff[FFT_compt];
            FFT_in[FFT_compt*2+1]=0;
        }

        /* Process the data through the CFFT/CIFFT module */
        arm_cfft_f32(&arm_cfft_sR_f32_len1024, FFT_in, ifftFlag, doBitReverse);
        
        /* Process the data through the Complex Magnitude Module for
        calculating the magnitude at each bin */
        arm_cmplx_mag_f32(FFT_in, FFT_out, FFT_SIZE);

        /* Suppression des fréqquences situées entre Fe/2 et Fe */        
        for(FFT_compt=FFT_SIZE/2;FFT_compt<FFT_SIZE;FFT_compt++)
        {
            FFT_out[FFT_compt]=0;
        }
        
        /* Calcul la valeur max dans la liste FFT_out, index = frequence et le contenu c'est l'amplitude */
        arm_max_f32(FFT_out, FFT_SIZE, &maxValue, &testIndex);
  
            fmax=testIndex*Fe/FFT_SIZE;
        //Calcul de la moyenne des amplitude
        
        for (int z=0; z<1024;z++)
        {
            moyenneAmp=moyenneAmp+FFT_out[z];
        }
            
        moyenneNorm=moyenneAmp/1024;
            
        if(DEBUG)
        {
            pc.printf("[FFT]moyenne amplitude = %d\n",moyenneNorm);
            pc.printf("[FFT]premier quartile = %.2e\n",FFT_out[256]);
        }
            
        if (FFT_out[256] > 400)
        {
            if (moyenneNorm > 600) reine = 0;
            stress = 1;
        }
            
        for (int q= 0; q<77;q++)//Entre 200Hz et 550Hz
        {
            moyEss=moyEss+FFT_out[51+q];
        }
                
        moyEss=moyEss/77;
            
        if ((moyEss > 300)&&(moyenneNorm <600)) essaimage=1;

         moyEss=0;
                
        moyenneAmp=0;
        moyenneNorm=0;
        
        cadre_8 = reine;
        reine = 1;//sinon crash tx
     
    /*---- Fin FFT*/ 
    
    if(DEBUG)pc.printf("[Son] reine = %\n",reine);
    if(DEBUG)pc.printf("[Son] essaimage = %d\n",essaimage);
    if(DEBUG)pc.printf("[Son] stress = %d\n",stress);
    
    if(DEBUG)pc.printf("4a.mesures diverses%\n");
    humidity =  sht.readHumidity();
    if(DEBUG)pc.printf("[Humidite] %f HR\n",humidity);
    
    battery_read = analog_battery.read();
    
    battery = 67.;// défaillance
        
    if(battery_read >= 0.798) battery = 100.; //4,1 V, 100%
    else if(battery_read >= 0.773) battery = 97.;//3.97 V, 90%
    else if(battery_read >= 0.764) battery = 94.;//3.92 V, 80%
    else if(battery_read >= 0.754) battery = 91.;//3.87 V, 70%
    else if(battery_read >= 0.747) battery = 88.;//3.83 V, 60%
    else if(battery_read >= 0.739) battery = 85.;//3.79 V, 50%
    else if(battery_read >= 0.731) battery = 82.;//3.75 V, 40%
    else if(battery_read >= 0.722) battery = 79.;//3.70 V, 30%
    else if(battery_read >= 0.700) battery = 76.;//3.60 V, 20%
    else if(battery_read >= 0.660) battery = 73.;//3.30 V, 10%
    else if(battery_read >= 0.550) battery = 70.;//2.80 V, 0%
    
    if(debug)
    {
        if(battery_read >= 0.798) pc.printf("[Batterie] 100 / 100\n"); //4,1 V, 100%
        else if(battery_read >= 0.773) pc.printf("[Batterie] 90 / 100\n");//3.97 V, 90%
        else if(battery_read >= 0.764) pc.printf("[Batterie] 80 / 100\n");//3.92 V, 80%
        else if(battery_read >= 0.754) pc.printf("[Batterie] 70 / 100\n");//3.87 V, 70%
        else if(battery_read >= 0.747) pc.printf("[Batterie] 60 / 100\n");//3.83 V, 60%
        else if(battery_read >= 0.739) pc.printf("[Batterie] 50 / 100\n");//3.79 V, 50%
        else if(battery_read >= 0.731) pc.printf("[Batterie] 40 / 100\n");//3.75 V, 40%
        else if(battery_read >= 0.722) pc.printf("[Batterie] 30 / 100\n");//3.70 V, 30%
        else if(battery_read >= 0.700) pc.printf("[Batterie] 20 / 100\n");//3.60 V, 20%
        else if(battery_read >= 0.660) pc.printf("[Batterie] 10 / 100\n");//3.30 V, 10%
        else if(battery_read >= 0.550) pc.printf("[Batterie] 0 / 100\n");//2.80 V, 0%
        else pc.printf("[Batterie] DEFAILLANCE / DEBRANCHEE\n");
    }
    
    luminosity_read = analog_luminosity.read();
    luminosity_read *=10.; //max 10 V
    
    //attention luminosity peut faire crash TX */
    luminosity = 2; //nuit
    
    if(luminosity_read >= 5) luminosity = 7;
    else if(luminosity_read >= 4) luminosity = 6;
    else if(luminosity_read >= 3) luminosity = 5;
    else if(luminosity_read >= 2) luminosity = 4;//tres lumineux
    else if(luminosity_read >= 1) luminosity = 3;//dangereux pour lipo rider pro si cellule solaire > 5 V
    
    if(DEBUG)pc.printf("[Luminosite] raw = %f / 10 \n",luminosity_read);
    if(DEBUG)pc.printf("[Luminosite] %d / 5 \n",luminosity-2);
    
    if(DEBUG)pc.printf("4b.mesure de la vitesse du vent...\n");
    
    /* test luminosity */
    /*    
    while(1)
    {
        luminosity_read = analog_luminosity.read();
        luminosity_read *=10.;
        if(DEBUG)pc.printf("[Luminosite] raw = %f / 1 \n",luminosity_read);
             
        luminosity = 2; //nuit
        if(luminosity_read >= 5) luminosity = 7;
        else if(luminosity_read >= 4) luminosity = 6;
        else if(luminosity_read >= 3) luminosity = 5;
        else if(luminosity_read >= 2) luminosity = 4;//tres lumineux
        else if(luminosity_read >= 1) luminosity = 3;//dangereux pour lipo rider pro si cellule solaire > 5 V
        
        if(DEBUG)pc.printf("[Luminosite] %d / 5 \n",luminosity-2);
        wait(1);
    }
    */
    
    cpt_anemo=0;
    anemo.enable_irq();
    wait(2);
    anemo.disable_irq();
    //un contact par seconde est égal à une vitesse du vent de 2,4 km/h
    //un contact par 2 secondes est égal à une vitesse du vent de 1,2 km/h
        
    force_vent = cpt_anemo*1.2;
    
    if(DEBUG)pc.printf("[Anemometre] vitesse du vent = %f km/h \n",force_vent);
    
    
    
    
    unsigned char field[SIZE];
    Frame frame ;
    //for(;;){
    
    //temp_int=-255.;
 
        //masse=997;
        
        MEAS_ENABLE = 0;//mode SigFox
        new_frame(&frame,field);
        stock_temp(&frame,temp_ext);
        stock_temp(&frame,temp_int);
        stock_int(luminosity,4,&frame);
        stock_masse(&frame, masse);
        stock_vent(&frame,force_vent);
        stock_battery(&frame,battery);
        stock_humidity(&frame,humidity);
        stock_bit(cadre_1_2,&frame);//non utilisé mais crash si 0!
        stock_bit(cadre_3, &frame);
        stock_bit(cadre_4,&frame);
        stock_bit(cadre_5,&frame);
        stock_bit(cadre_6,&frame);
        stock_bit(cadre_7,&frame);
        stock_bit(cadre_8,&frame);//remplacer par reine
        stock_bit(cadre_9_10,&frame);//remplacer par presence_ruche;
        stock_bit(stress,&frame);
        stock_bit(reine,&frame);
        stock_bit(essaimage,&frame);
        stock_bit(abeilles,&frame);
        validate_frame(&frame);
        print_frame(&frame);
        send_frame(&frame);
        wait(8);                          //15 * 60 secondes = 15 minutes d'intervalle
        TPL5110_DONE=1; 
        
        wait(600); 
    //}
    //return EXIT_SUCCESS;
}