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; }