Shared by Polytech Marseille to contribute to the improvement of the mbed community !
Dependencies: Adafruit_SGP30_mbed mbed GSM X_NUCLEO_IKS01A2 max31865 GroveGPS SDFileSystem DFPlayerMini BME280 DS1820
main.cpp
- Committer:
- ayoubzahir
- Date:
- 2019-04-30
- Revision:
- 3:cb77ea3370e8
- Parent:
- 0:d7a683cf76d9
File content as of revision 3:cb77ea3370e8:
///////////////////////////////////////////////////////////////////////// // AMU - Aix-Marseille Université // Polytech Marseille - Microelectronique & Telecommunications (MT) // Projet MT5A "STM32 In the Sky - HAB", 2018-2019 // Enseignants : C.Dufaza & H. Aziza // Etudiants : ... ///////////////////////////////////////////////////////////////////////// // Version avril 2019, C.Dufaza /* todo : - resoudre incompatibilité mbed thermomètre DS18 - utilisation de l'entrée Reset du module GSM - check si le lecteur MP3 est bien actif */ ///////////////////////////////////////////////////////////////////////// //// ... Includes // Activation des différents modules de ce code (via directives de compilation) #include "define_myMODULES.h" // Assignation des entrées/sorties des différents modules #include "define_myIO.h" // Include usuels ... #include <stdio.h> #include <string> #include "mbed.h" ///////////////////////////////////////////////////////////////////////// //// Main code ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// //// Variables globales ... // Compteur du nombre de recolte de données depuis le démarrage unsigned int hab_frame_counter = 1; // Mesure de la tension de la batterie float vbatt = 0.0; AnalogIn pin_vbatt(IO_VBATT); // Trame des données des capteurs à stocker sur la carte sd et au GPRS char sd_gprs_data[SD_GPRS_DATA_SIZE]; // GPS variables unsigned int timeUTC = 0; float lat = 0, lon = 0, alt = 0, speed = 0; // Xnucleo variables float xnuc_t = 0.0, xnuc_h = 0.0, xnuc_t2 = 0.0, xnuc_p = 0.0; int32_t xnuc_acc[3]; // PT100 variables double tempPT100 = 0; // SGP30 variables int eco2 = 0, tvoc = 0; // Temperature DS18 variable float tempDS18 = 0; // UV & Photo variables float uv = 0, photores = 0; // BME280 variables (temperature, pression, humidité exterieure) float bosch_t = 0, bosch_p = 0, bosch_h = 0; // Ozone variable double ozone = 0; ///////////////////////////////////////////////////////////////////////// //// Tickers d'interruption // Ticker executé toute les xx s pour recolter toute les données des capteurs, // les enregistrer sur la carte SD et les envoyer en UART à la carte LoRa #ifdef HAB_FUNCTION // Debut directive de compilation module HAB Ticker ticker_hab; // Object Ticker void isr_ticker_hab(); // Routine ISR appellée lors du tick void f_ticker_hab(); // Fonction utile appellée à la suite du tick bool flag_ticker_hab = 0; // Flag levé par l'ISR pour appeller la fonction utile #endif // Fin directive de compilation module HAB // Ticker executé toute les xx s pour vérifier l'etat du module GSM #ifdef GSM_FUNCTION // Debut directive de compilation module GSM Ticker ticker_check_gsm; // Object Ticker void isr_ticker_check_gsm(); // Routine ISR appellée lors du tick void f_ticker_check_gsm(); // Fonction utile appellée à la suite du tick bool flag_ticker_check_gsm = 0; // Flag levé par l'ISR pour appeller la fonction utile #endif // Fin directive de compilation module GSM // Ticker executé toute les 10 min pour vérifier l'etat du module GPRS SMS #ifdef SMS_FUNCTION // Debut directive de compilation SMS de données toutes les 10 min Ticker ticker_sms_data; // Object Ticker void isr_ticker_sms_data(); // Routine ISR appellée lors du tick void f_ticker_sms_data(); // Fonction utile appellée à la suite du tick bool flag_ticker_sms_data = 0; // Flag levé par l'ISR pour appeller la fonction utile #endif // Fin directive de compilation SMS de données toutes les 10 min ///////////////////////////////////////////////////////////////////////// // UART PC Debug #ifdef DEBUG_SERIAL_PC // ACtivation de la liaison UART PC pour Debug Serial serial_pc(SERIAL_TX, SERIAL_RX, DEBUG_SERIAL_PC_BAUDRATE); #endif ///////////////////////////////////////////////////////////////////////// // Buzzer digital Out pin #ifdef BUZZ_FUNCTION // Debut directive de compilation buzzer DigitalOut pin_buzzer(IO_BUZZER,0); #endif // Fin directive de compilation buzzer ///////////////////////////////////////////////////////////////////////// // Carte SD #ifdef SD_FUNCTION // Debut directive de compilation carte SD #include "SDFileSystem.h" // MOSI, MISO, SCK, SS SDFileSystem sd(IO_SD_MOSI, IO_SD_MISO, IO_SD_SCK, IO_SD_CS, SD_FUNCTION_SDNAME); // flag_sd_ok = 1 après la 1ere initialisation reussie de la carte SD bool flag_sd_ok = 0; #endif // Fin directive de compilation carte SD ///////////////////////////////////////////////////////////////////////// // Lecteur MP3 DFPlayer #ifdef MP3_FUNCTION // Debut directive de compilation lecteur MP3 #include "DFPlayerMini.h" DFPlayerMini mp3(IO_MP3_TX, IO_MP3_RX); //TX, RX #endif // Fin directive de compilation MP3 ///////////////////////////////////////////////////////////////////////// // Module GSM #ifdef GSM_FUNCTION // Debut directive de compilation module GSM #include <GSM.h> // GSM Library // Flag mis à jour par interruption externe sur la LED NET. // Passe a true lorsque sa période de clignotement est d'environ 3s bool flag_gsm_network_ok = 0; // Flag a abaisser lors de la 1ere réponse materielle du module GSM bool flag_gsm_absent = 1; // Flag à lever lors de la confirmation de la présence matérielle du module GSM // et de son démarrage en cours, et à abaisser lorsque celui ci a également démarrer logiciellement bool flag_gsm_starting = 0; // Compteur calé sur le ticker HAB de période ~5 s, qui compte le temps depuis // le dernier reset du module GSM, pour eviter un reset trop fréquent si la connexion est mauvaise. unsigned int last_reset_gsm = 0; // GSM I/O PinInOut DigitalOut gsm_pwr(IO_GSM_PWR); // Sortie d'allumage du GSM // todo sortie RESET du GSM InterruptIn gsm_net(IO_GSM_NET); // Entrée de la LED "NET" DigitalIn gsm_status(IO_GSM_STAT); // Entrée de la LED "STATUS" //TX, RX, PWR, NET, STATUS, baudrate, num par defaut GSM gsm(IO_GSM_TX, IO_GSM_RX, GSM_BAUDRATE, GSM_SIM_NUMBER); // URL du serveur web char * url_srv_polytech = POLYTECH_SERVER; #endif // Fin directive de compilation module GSM ///////////////////////////////////////////////////////////////////////// // Module GPS #ifdef GPS_FUNCTION // Debut directive de compilation module GPS #include "GroveGPS.h" //TX, RX, liaison STM --> GPS Serial gps_serial(IO_GPS_TX, IO_GPS_RX, GPS_BAUDRATE); GroveGPS gps; void isr_gps_serial(); // Fonction d'interuption de reception sur le port UART GPS char timeUTCBuffer[16], latBuffer[16], lonBuffer[16], altBuffer[16], speedBuffer[16]; #endif // Fin directive de compilation module GPS ///////////////////////////////////////////////////////////////////////// // Shield capteurs ST X_NUCLEO_IKS01A2 #ifdef XNUCLEO_FUNCTION // Debut directive de compilation shield capteurs XNUCLEO #include "XNucleoIKS01A2.h" // Instantiate the expansion board: SDA, SCL, option(INT1, INT2) static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(IO_XNUC_SDA, IO_XNUC_SCL); static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor; static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor; static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer; #endif // Fin directive de compilation shield capteurs XNUCLEO ///////////////////////////////////////////////////////////////////////// // Sonde de température PT100 sur ampli MAX31865 #ifdef PT100_FUNCTION // Debut directive de compilation module PT100 #include "MAX31865.h" // MOSI, MISO, SCK, SS : SPI du MAX311865 MAX31865_RTD PT100(MAX31865_RTD::RTD_PT100,IO_PT100_MOSI, IO_PT100_MISO, IO_PT100_SCK, IO_PT100_CS); #endif // Fin directive de compilation module PT100 ///////////////////////////////////////////////////////////////////////// // Capteur de temperature (exterieur haut) DS181B20 #ifdef DS18_FUNCTION // Debut directive de compilation DS181B20 #include "DS1820.h" DS1820 ds18(IO_DS18); #endif // Fin directive de compilation DS181B20 ///////////////////////////////////////////////////////////////////////// // Capteurs lumière (UV et photoresistance) #ifdef UV_FUNCTION // Debut directive de compilation capteur UV AnalogIn pin_UV(IO_UV); #endif // Fin directive de compilation capteur UV #ifdef PHOTORES_FUNCTION // Debut directive de compilation capteur lumière AnalogIn pin_photores(IO_PHOTORES); #endif // Fin directive de compilation capteur lumière ///////////////////////////////////////////////////////////////////////// // Capteur Bosch BME280 (temperature, pression, humidité exterieure) #ifdef BOSCH_FUNCTION // Debut directive de compilation Bosch #include "BME280.h" BME280 bosch(IO_BOSCH_SDA, IO_BOSCH_SCL); // SDA, SCL #endif // Fin directive de compilation Bosch ///////////////////////////////////////////////////////////////////////// // Capteur eCO2/TVOC SGP30, voir note : // Le module eCO2/TVOC produira pendant ~20 s des resultats invalides // eCO2=400 et TVOC=0, patientez quelques instants // module à allumer 48h à l'avance pour résultats optimums #ifdef CO2_FUNCTION // Debut directive de compilation module CO2 #include "Adafruit_SGP30.h" Adafruit_SGP30 co2(IO_CO2_SDA, IO_CO2_SCL); // SDA, SCL #endif // Fin directive de compilation module CO2 ///////////////////////////////////////////////////////////////////////// // Capteur Ozone O3 // ... todo #ifdef O3_FUNCTION // Debut directive de compilation spi_ozone SPI spi_ozone(PB_15, PB_14, PB_13); // MOSI, MISO, SCK DigitalOut ozone_SS(IO_O3_CS,1); #endif // Fin directive de compilation spi_ozone ///////////////////////////////////////////////////////////////////////// // LORA Module #ifdef LORA_FUNCTION // Debut directive de compilation LoRa // todo: liaison UART avec carte LoRa + watchdog carte mère Serial lora_serial(IO_LORA_TX, IO_LORA_RX, LORA_FUNCTION_BAUDRATE); // Chaine de char contenant la trame des données des capteurs à envoyer char lora_data_tx[LORA_FUNCTION_DATASIZE]; #endif // Fin directive de compilation LoRa ///////////////////////////////////////////////////////////////////////// //// Fonctions annexes //////////////////////////////////////////////////////////////////////// // Pression - Altitude double sealevel(double P, double A) // Given a pressure P (mb) taken at a specific altitude (meters), // return the equivalent pressure (mb) at sea level. // This produces pressure readings that can be used for weather measurements. { return (P / pow(1 - (A / 44330.0), 5.255)); } double altitude(double P, double P0) // Given a pressure measurement P (mb) and the pressure at a baseline P0 (mb), // return altitude (meters) above baseline. { return (44330.0 * (1 - pow(P / P0, 1 / 5.255))); } // Initialise l'interruption GPS ... pré-déclaration void irq_gps_on(); void irq_gps_off(); // Permet de gérer les modes On-Off des Interruption & Tickers void all_irq_on_off(int gps_on_off, int gsm_on_off, int ticker_hab_on_off, int ticker_gsm_on_off) { // Interruption GPS On ou Off if(gps_on_off == 1) { irq_gps_on(); } if(gps_on_off == 0) { irq_gps_off(); } // Module GSM Enable ou Disable if(gsm_on_off == 1) { gsm_net.enable_irq(); } if(gsm_on_off == 0) { gsm_net.disable_irq(); } // Ticker HAB Attach ou Detach if(ticker_hab_on_off == 1) { ticker_hab.attach(&isr_ticker_hab, TICKER_HAB_TIME); } if(ticker_hab_on_off == 0) { ticker_hab.detach(); } // Ticker GSM Attach ou Detach if(ticker_gsm_on_off == 1) { ticker_check_gsm.attach(&isr_ticker_check_gsm, TICKER_CHECK_GSM_TIME); } if(ticker_gsm_on_off == 0) { ticker_check_gsm.detach(); } } ///////////////////////////////////////////////////////////////////////// // SD #ifdef SD_FUNCTION // Debut directive de compilation carte SD // Fonction qui ecrit le message dans le fichier passés en arguments sur la carte SD initialisée void ecriture_sd(char * fichier, char * message) { // Si la carte SD n'est pas initialisée on quitte if(flag_sd_ok == 0) return; // On désactive l'interruption UART pour GPS all_irq_on_off(0, 2, 2, 2); // irq_gps_off(); // Fichier en mode a - append ... du type "/sd/data.txt" FILE *fp = fopen(fichier, "a"); if(fp == NULL) { // Erreur d'ouverture du fichier #ifdef DEBUG_SERIAL_PC serial_pc.printf("<<<< ERREUR >>>> carte SD, ouverture fichier impossible\n"); #endif } else { // Fichier correctement ouvert en mode append, écriture puis fermeture fprintf(fp, message); fprintf(fp, "\n"); fclose(fp); } // Ré-activation de l'interruption UART pour GPS all_irq_on_off(1, 2, 2, 2); // irq_gps_on(); } #endif // Fin directive de compilation carte SD ///////////////////////////////////////////////////////////////////////// // GSM #ifdef GSM_FUNCTION // Debut directive de compilation module GSM // Initialise le GSM ... pré-déclaration void init_GSM(); // Variables GSM Timer timer_gsm_network; // Compteur de la période de clignotement de la LED "NET" unsigned int last_time_gsm_network = 0; void isr_network_gsm() { // Arret de toute les sources d'interruptions all_irq_on_off(0, 0, 2, 2); //irq_gps_off(); // Interruption GPS off //gsm_net.disable_irq(); // Disable interrupt GSM timer_gsm_network.stop(); // Arret du timer GSM last_time_gsm_network = timer_gsm_network.read_ms(); // Lecture du timer GSM #ifdef DEBUG_SERIAL_PC //debug_if(DEBUG_SERIAL_PC, "Timer GSM Network (ms) : %d\n", last_time_gsm_network); //serial_pc.printf("Timer GSM Network (ms) : %d\n", last_time_gsm_network); #endif // Seulement si la période de clignotement est d'environs 3s alors le module // GSM est bien connecté au réseau et est pret a etre utilisé. if(last_time_gsm_network > 2800 && last_time_gsm_network < 3200) { #ifdef DEBUG_SERIAL_PC //serial_pc.printf("> Timer GSM Network (ms) : %d\n", last_time_gsm_network); #endif flag_gsm_network_ok = 1; // le GSM est ok if(flag_gsm_starting == 1) { // est-il tjs en démarrage ? init_GSM(); flag_gsm_starting = 0; } } else flag_gsm_network_ok = 0; // le GSM n'est pas ok timer_gsm_network.reset(); // Raz et nouveau départ du timer GSM timer_gsm_network.start(); // On autorise de nouveau les interruptions GPS et GSM all_irq_on_off(1, 1, 2, 2); //irq_gps_on(); //gsm_net.enable_irq(); } // On initialise le GSM void init_GSM() { // Initialise (logiciellement) le module GSM if(gsm_status == 0) return; // Si module GSM arreté ou absent c'est inutile // Arret de toute les sources d'interruptions all_irq_on_off(0, 0, 0, 0); //irq_gps_off(); // Int sur RX UART //gsm_net.disable_irq(); // Int sur LED NET GSM //ticker_hab.detach(); // Ticker HAB //ticker_check_gsm.detach(); // Ticker check GSM #ifdef DEBUG_SERIAL_PC serial_pc.printf(">>> GSM Initialisation <<<\n"); serial_pc.printf(" Init GSM : %d\n",gsm.init()); serial_pc.printf(" Statut SIM : %d\n",gsm.checkSIMStatus()); serial_pc.printf(" Force signal : %d\n",gsm.checkSignalStrength()); serial_pc.printf(" Reglage SMS : %d\n",gsm.settingSMS()); //serial_pc.printf(" Test SMS : %d\n",gsm.sendSMS(GSM_SEND_NUMBER, GSM_SEND_SMS_HELLO)); #endif // On considere le GSM initialisé et n'est donc plus en phase de démarrage flag_gsm_starting = 0; // On autorise de nouveau les interruptions GPS et GSM, ticker HAB all_irq_on_off(1, 1, 1, 1); //irq_gps_on(); //gsm_net.enable_irq(); //ticker_hab.attach(&isr_ticker_hab, TICKER_HAB_TIME); //ticker_check_gsm.attach(&isr_ticker_check_gsm, TICKER_CHECK_GSM_TIME); } // Fonction qui allume le module GSM (matériellement) void gsm_pwr_on() { // Entrée : "bool attendre", specifie si la fonction doit attendre que le // module GSM démarre. if(gsm_status == 0) { // Arret de toute les sources d'interruptions all_irq_on_off(0, 0, 0, 0); // Creation et lancement d'un timer de time out du démarrage du module GSM Timer timer_gsm_init; timer_gsm_init.start(); // On considere que le GSM est sous-tension, on verifiera ... gsm_pwr = 1; while(gsm_status == 0) { wait(0.5); if(timer_gsm_init.read() > 5) { // Si après 5s ... ? #ifdef DEBUG_SERIAL_PC serial_pc.printf("<<<< ERREUR >>>> module GSM absent\n"); #endif flag_gsm_absent = 1; // Constatation de l'absence du module GSM timer_gsm_network.stop(); // Arrêt du timer GSM gsm_pwr = 0; // le GSM n'est donc pas sous tension // On autorise de nouveau les interruptions GPS et GSM, ticker HAB all_irq_on_off(1, 1, 1, 1); return; } } gsm_pwr = 0; timer_gsm_network.stop(); } else #ifdef DEBUG_SERIAL_PC serial_pc.printf("Module GSM deja allume "); #endif // Constatation de la présence du module GSM flag_gsm_absent = 0; // Indication que le module GSM est en train de démarrer materiellement // ou du moins qu'il faudra bientot faire l'init logiciel dès qu'il // sera pret (NET LED avec bonne période de 3s. flag_gsm_starting = 1; // On autorise de nouveau les interruptions GPS et GSM, ticker HAB all_irq_on_off(1, 1, 1, 1); } #endif // Fin directive de compilation module GSM ///////////////////////////////////////////////////////////////////////// // Ozone O3 #ifdef O3_FUNCTION // Debut directive de compilation spi_ozone double lecture_ozone() { // Variables double resultat = 0.0; uint32_t chiffre=0; uint8_t Buff[4]; for(int i=0; i<3;i++) Buff[i] = 0; // Paramètres Ozone spi_ozone.format(8,3); spi_ozone.frequency(1000000); ozone_SS.write(0); // Selection de l'esclave //spi_ozone.write(0x8F); wait_ms(100); Buff[0] = spi_ozone.write(0); Buff[1] = spi_ozone.write(0); Buff[2] = spi_ozone.write(0); Buff[3] = spi_ozone.write(0); ozone_SS.write(1); // Deselection de l'esclave chiffre = ((uint32_t)(Buff[0]) << 24) | ((uint32_t)(Buff[1]) << 16) | ((uint32_t)(Buff[2]) << 8) | (uint32_t)(Buff[3]); chiffre = chiffre >> 7; resultat = 100 - (chiffre/41943.040); // Conversion en %ADC return resultat; } #endif // Fin directive de compilation spi_ozone ///////////////////////////////////////////////////////////////////////// //// Tickers, Interruptions, Threads ///////////////////////////////////////////////////////////////////////// // GSM #ifdef GSM_FUNCTION // Debut directive de compilation module GSM void f_ticker_check_gsm() { // Fonction du ticker de surveillance du module GSM, lancée toute les .. s // Si module GSM absent, on retourne if(flag_gsm_absent == 1) return; // Arret de toute les sources d'interruptions all_irq_on_off(0, 2, 2, 2); // Si le module GSM est éteint, on l'allume if(gsm_status == 0) gsm_pwr_on(); // Si module GSM non connecté if(flag_gsm_network_ok == 0) { // Si cela fait plus de 15 trames que l'on a démarré alors if(hab_frame_counter - last_reset_gsm > 15) { #ifdef DEBUG_SERIAL_PC serial_pc.printf("\n Reset du module GSM ..."); #endif // todo : appui sur bouton reset du module gsm last_reset_gsm = hab_frame_counter; } } // met fin à l'envoi d'un sms, le module reste parfois bloqué dans la // commande d'envoi et ne répond pas "OK" lorsqu'on check power en envoyant "AT" gsm.gprsSerial.putc((char)0x1A); int sim_status = gsm.checkSIMStatus(); #ifdef DEBUG_SERIAL_PC serial_pc.printf("\n>>> Check statut SIM : %d\n", sim_status); #endif if(sim_status != 0) { init_GSM(); } // Il est nécessaire d'initialiser de nouveau le GSM // On autorise de nouveau les interruptions GPS et GSM, ticker HAB all_irq_on_off(1, 2, 2, 2); // Flag ticker GSM inactif flag_ticker_check_gsm = 0; } #endif // Fin directive de compilation module GSM ///////////////////////////////////////////////////////////////////////// // GPS #ifdef GPS_FUNCTION // Debut directive de compilation module GPS ///////////////////////////////////////////////////////////////////////// // GPS = fonctions d'activation et de desactivation de l'interruption UART void irq_gps_off() { // IRQ OFF : desactivation de l'interruption pour le port UART du GPS gps_serial.attach(NULL); } void irq_gps_on() { // IRQ ON : activation de l'interruption pour le port UART du GPS gps_serial.attach(&isr_gps_serial,Serial::RxIrq); } // Routine d'interruption (ISR) pour la reception sur port UART du GPS void isr_gps_serial() { if(gps_serial.readable()) { #ifdef GPS_DEBUG char c = gps_serial.getc(); serial_pc.putc(c); gps.readCharacter(c); #else gps.readCharacter(gps_serial.getc()); #endif } } #endif // Fin directive de compilation module GPS //////////////////////////////////////////////////////////////////////// // SMS (GSM) // Ticker executé toute les xx sec pour envoi des données par sms #ifdef SMS_FUNCTION // Debut directive de compilation module SMS void f_ticker_sms_data() { if(flag_gsm_network_ok == 1) { #ifdef DEBUG_SERIAL_PC serial_pc.printf(">>>>>> Send HAB data to SMS\n"); #endif // Portable personnel de Dufaza gsm.sendSMS(GSM_SEND_NUMBER, sd_gprs_data); // Le SMS a ete envoyé ... flag_ticker_sms_data = 0; } } #endif // Fin directive de compilation module SMS //////////////////////////////////////////////////////////////////////// // HAB // Ticker executé toute les 5 s pour recolter toute les données, // les enregistrer sur la carte SD et les envoyer en UART à la carte LoRa #ifdef HAB_FUNCTION // Debut directive de compilation module HAB void f_ticker_hab() { //DS18 thermomètre pt1 (en 2 parties pour eviter d'attendre) #ifdef DS18_FUNCTION // Debut directive de compilation DS181B20 // todo #endif // Fin directive de compilation DS181B20 // Recuperation donnees capteurs ST X_NUCLEO_IKS01A2 #ifdef XNUCLEO_FUNCTION // Debut directive de compilation shield capteurs XNUCLEO hum_temp->get_temperature(&xnuc_t); hum_temp->get_humidity(&xnuc_h); press_temp->get_temperature(&xnuc_t2); press_temp->get_pressure(&xnuc_p); #endif // Fin directive de compilation shield capteurs XNUCLEO //PT100 #ifdef PT100_FUNCTION // Debut directive de compilation module PT100 PT100.read_all(); if(PT100.status() == 0) { tempPT100 = PT100.temperature(); #ifdef DEBUG_SERIAL_PC //serial_pc.printf(">>>>>> Temp PT100 = %f degC \r\n",tempPT100); #endif } else { tempPT100 = 0; #ifdef DEBUG_SERIAL_PC serial_pc.printf("<<< ERREUR >>> Registre d'erreur PT100 : %d - ",PT100.status( )); if(PT100.status() & MAX31865_FAULT_HIGH_THRESHOLD) { serial_pc.printf("ERREUR PT100 seuil haut franchi\n"); } else if(PT100.status() & MAX31865_FAULT_LOW_THRESHOLD) { serial_pc.printf("ERREUR PT100 seuil bas franchi\n"); } else if(PT100.status() & MAX31865_FAULT_REFIN) { serial_pc.printf("ERREUR REFIN- > 0,85 x V_BIAS\n"); } else if(PT100.status( ) & MAX31865_FAULT_REFIN_FORCE) { serial_pc.printf("ERREUR REFIN- < 0,85 x V_BIAS, FORCE- ouvert\n"); } else if(PT100.status( ) & MAX31865_FAULT_RTDIN_FORCE ) { serial_pc.printf("ERREUR RTDIN- < 0,85 x V_BIAS, FORCE- ouvert\n"); } else if(PT100.status( ) & MAX31865_FAULT_VOLTAGE) { serial_pc.printf("ERREUR sur/sous-tension\n"); } else serial_pc.printf("ERREUR inconnue\n"); #endif } #endif // Fin directive de compilation module PT100 // CO2 #ifdef CO2_FUNCTION // Debut directive de compilation module CO2 co2.IAQmeasure(); #ifdef DEBUG_SERIAL_PC /*serial_pc.printf("TVOC : %d\n", co2.TVOC); serial_pc.printf("eCO2: %d\n", co2.eCO2);*/ #endif eco2 = co2.eCO2; tvoc = co2.TVOC; #endif // Fin directive de compilation module CO2 //DS18 thermomètre pt2 (en 2 parties pour eviter d'attendre) #ifdef DS18_FUNCTION // Debut directive de compilation DS181B20 // todo #endif // Fin directive de compilation DS181B20 // Capteurs UV et lumiere #ifdef UV_FUNCTION // Debut directive de compilation capteur UV uv = pin_UV.read(); #endif // Fin directive de compilation capteur UV #ifdef PHOTORES_FUNCTION // Debut directive de compilation capteur lumière photores = pin_photores.read(); #endif // Fin directive de compilation capteur lumière // Triple capteur Bosch BME280 #ifdef BOSCH_FUNCTION // Debut directive de compilation Bosch bosch_t = bosch.getTemperature(); //bosch_p = bosch.getPressure(); bosch_p = 900.0 ; bosch_h = bosch.getHumidity(); #ifdef DEBUG_SERIAL_PC //serial_pc.printf("-> Bosch : %.2f *C, %.2f mbar, %.2f %%\n", bosch.getTemperature(), bosch.getPressure(), bosch.getHumidity()); #endif #endif // Fin directive de compilation Bosch // Ozone #ifdef O3_FUNCTION // Debut directive de compilation spi_ozone ozone = lecture_ozone(); #endif // Fin directive de compilation spi_ozone // Mesure tension batterie (tension ref* pont diviseur + chute diode) vbatt = ((double) pin_vbatt.read())*3.3*11.07+0.52; // Recuperation données GPS #ifdef GPS_FUNCTION // Debut directive de compilation module GPS gps.getTimestamp(timeUTCBuffer); gps.getLatitude(latBuffer); gps.getLongitude(lonBuffer); gps.getAltitude(altBuffer); gps.getSpeed(speedBuffer); //printf("UTC: %s\t Latitude: %s\t Longitude: %s\t altitude: %s\t speed: %s\n", timeUTCBuffer, latBuffer, lonBuffer, altBuffer, speedBuffer); // Convertion des chaine en entier et flottant timeUTC = atoi(timeUTCBuffer); lat = (float)atof(latBuffer); lon = (float)atof(lonBuffer); alt = (float)atof(altBuffer); speed = (float)atof(speedBuffer); #endif // Fin directive de compilation module GPS // Mise en forme dans un tableau de caractères sprintf((char*) sd_gprs_data, "%d-%.2f-%d-%f-%f-%.1f-%.1f-%.1f-%.1f-%.3f-%.3f-%.3f-%.1f-%.3f-%.2f-%.2f-%d-%d-%f-%.3f-%.3f", hab_frame_counter, vbatt, timeUTC, lat, lon, alt, speed, xnuc_t, xnuc_t2, tempPT100, tempDS18, bosch_t, xnuc_h, bosch_h, xnuc_p, bosch_p, eco2, tvoc, ozone, (double)uv*100.0, (double)photores*100.0); #ifdef DEBUG_SERIAL_PC // Affichage des données sur port série debug serial_pc.printf("\n>>> HAB Frame Counter : %d\n", hab_frame_counter); serial_pc.printf("> Tension batterie : %f V\n", vbatt); #ifdef GPS_FUNCTION // Debut directive de compilation module GPS serial_pc.printf("> Temps UTC : %d\n", timeUTC); serial_pc.printf("> Latitude : %f\n", lat); serial_pc.printf("> Longitude : %f\n", lon); serial_pc.printf("> Altitude : %.2f m\n", alt); serial_pc.printf("> Vitesse : %.2f km/h\n", speed); #endif // Fin directive de compilation module GPS #ifdef XNUCLEO_FUNCTION // Debut directive de compilation shield capteurs XNUCLEO serial_pc.printf("> Temperature 1 (XNUCLEO) : %.3f *C\n", xnuc_t); serial_pc.printf("> Temperature 2 (XNUCLEO) : %.3f *C\n", xnuc_t2); #endif // Fin directive de compilation shield capteurs XNUCLEO #ifdef PT100_FUNCTION // Debut directive de compilation module PT100 serial_pc.printf("> Temperature 3 (PT100) : %.3f *C\n", tempPT100); #endif // Fin directive de compilation module PT100 #ifdef DS18_FUNCTION // Debut directive de compilation DS181B20 serial_pc.printf("> Temperature 4 (DS18) : %.3f *C\n", tempDS18); #endif // Fin directive de compilation DS181B20 #ifdef BOSCH_FUNCTION // Debut directive de compilation Bosch serial_pc.printf("> Temperature 5 (Bosch) : %.3f *C\n",bosch_t); #endif // Fin directive de compilation Bosch #ifdef XNUCLEO_FUNCTION // Debut directive de compilation shield capteurs XNUCLEO serial_pc.printf("> Humidite 1 (XNUCLEO) : %.2f %%\n", xnuc_h); #endif // Fin directive de compilation shield capteurs XNUCLEO #ifdef BOSCH_FUNCTION // Debut directive de compilation Bosch serial_pc.printf("> Humidite 2 (Bosch) : %.2f %%\n",bosch_h); #endif // Fin directive de compilation Bosch #ifdef XNUCLEO_FUNCTION // Debut directive de compilation shield capteurs XNUCLEO serial_pc.printf("> Pression 1 (XNUCLEO) : %.2f mbar - altitude calculee : %.2f m\n", xnuc_p, altitude(xnuc_p, BASE_PRESSURE)); #endif // Fin directive de compilation shield capteurs XNUCLEO #ifdef BOSCH_FUNCTION // Debut directive de compilation Bosch serial_pc.printf("> Pression 2 (Bosch) : %.2f mbar - altitude calculee : %.2f m\n",bosch_p, altitude(bosch_p, BASE_PRESSURE)); #endif // Fin directive de compilation Bosch #ifdef CO2_FUNCTION // Debut directive de compilation module CO2 serial_pc.printf("> eCO2 : %d ppm\n", eco2); serial_pc.printf("> TVOC : %d ppb\n", tvoc); #endif // Fin directive de compilation module CO2 #ifdef UV_FUNCTION // Debut directive de compilation capteur UV serial_pc.printf("> UV : %.3f %%ADC\n", (double)uv*100.0); #endif // Fin directive de compilation capteur UV #ifdef PHOTORES_FUNCTION // Debut directive de compilation capteur lumière serial_pc.printf("> Lum : %.3f %%ADC\n", (double)photores*100.0); #endif // Fin directive de compilation capteur lumière #ifdef O3_FUNCTION // Debut directive de compilation spi_ozone serial_pc.printf("> Ozone O3 : %f %%ADC\n", ozone); #endif // Fin directive de compilation spi_ozone serial_pc.printf("%s\n", sd_gprs_data); #endif // Envoi de la chaine par GPRS au Polytech Server #ifdef GSM_FUNCTION // Debut directive de compilation module GSM #ifdef GPRS_FUNCTION // Debut directive de compilation données mobiles if(flag_gsm_network_ok == 1) { #ifdef DEBUG_SERIAL_PC serial_pc.printf(">>>>>> Send HAB data to Polytech Server\n"); #endif gsm.gprs_message(url_srv_polytech , sd_gprs_data); } #endif // Fin directive de compilation données mobiles /*if(flag_gsm_network_ok == 1) { #ifdef DEBUG_SERIAL_PC serial_pc.printf("SMS : %d\n",gsm.sendSMS("+33676040268", sd_gprs_data)); // Envoi de la chaine par SMS #endif */ #endif // Fin directive de compilation module GSM // Sauvegarde sur carte SD #ifdef SD_FUNCTION // Debut directive de compilation carte SD ecriture_sd(SD_FUNCTION_FILENAME, sd_gprs_data); #endif // Fin directive de compilation carte SD // Creation de la chaine à envoyer à la carte LoRa #ifdef LORA_FUNCTION // Debut directive de compilation LoRa sprintf((char*) lora_data_tx, "%.2f-%f-%f-%.1f-%.3f", vbatt, lat, lon, alt, tempPT100); #ifdef DEBUG_SERIAL_PC serial_pc.printf("%s\n", lora_data_tx); #endif #endif // Fin directive de compilation LoRa #ifdef DEBUG_SERIAL_PC //serial_pc.printf("------------------------------------------------\n"); serial_pc.printf("\n"); #endif // Increment du numéro de la trame transmise hab_frame_counter++; // Flag ticker HAB inactif flag_ticker_hab = 0; } #endif // Fin directive de compilation module HAB ///////////////////////////////////////////////////////////////////////// // Routines d'interruption appelées au tick des tickers et servant juste à lever un flag // Pensez à abaisser le flag dans f_ticker_hab() et f_ticker_gsm() ! #ifdef HAB_FUNCTION void isr_ticker_hab() { flag_ticker_hab = 1; } #endif #ifdef GSM_FUNCTION void isr_ticker_check_gsm() { flag_ticker_check_gsm = 1; } #endif #ifdef SMS_FUNCTION void isr_ticker_sms_data() { flag_ticker_sms_data = 1; } #endif ///////////////////////////////////////////////////////////////////////// // LoRa #ifdef LORA_FUNCTION // Debut directive de compilation LoRa void envoi_lora_data_tx() { lora_serial.printf("%s\n", lora_data_tx); #ifdef DEBUG_SERIAL_PC serial_pc.printf("lora!\n"); // debug #endif } void isr_lora_serial() { char c = lora_serial.getc(); if(c == 'a') envoi_lora_data_tx(); #ifdef MP3_FUNCTION // Debut directive de compilation lecteur MP3 elseif(c == 'b') mp3.mp3_play(); elseif(c == 'c') mp3.mp3_pause(); #endif // Fin directive de compilation lecteur MP3 #ifdef BUZZ_FUNCTION // Debut directive de compilation buzzer elseif(c == 'd') pin_buzzer.write(1); elseif(c == 'e') pin_buzzer.write(0); #endif // Fin directive de compilation buzzer } #endif // Fin directive de compilation LoRa ///////////////////////////////////////////////////////////////////////// ///////////////////////////// MAIN //////////////////////////////////// ///////////////////////////////////////////////////////////////////////// int main() { // Affichage/listage des modules compilés/activés sur port série STLINK #ifdef DEBUG_SERIAL_PC serial_pc.printf("\n\n-----------------------------------------------------------------------------------\n"); serial_pc.printf("--- AMU Aix-Marseille Universit\xE9 - Polytech Marseille MT - STM32 in the Sky HAB ---\n"); vbatt = ((double)pin_vbatt.read())*3.3*11.07+0.52; // Tension batterie (tension ref * pont diviseur + chute diode) serial_pc.printf("- Tension batterie = %f V\n", vbatt); serial_pc.printf("- Liste des Fonctionalit\xE9s & Capteurs op\xE9rationnels ...\n"); #endif //Buzzer, léger bip au démarrage #ifdef BUZZ_FUNCTION #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> Buzzer ON ... "); #endif for(int i=1; i<BUZZ_FUNCTION_DURATION; i++) // #périodes de 1,5kHz { // 333us x 2 = 1,5k Hz pin_buzzer.write(1); wait_us(BUZZ_FUNCTION_HZ); pin_buzzer.write(0); wait_us(BUZZ_FUNCTION_HZ); }; #ifdef DEBUG_SERIAL_PC serial_pc.printf("OFF\n"); #endif #endif // Shield ST X_NUCLEO_IKS01A2 #ifdef XNUCLEO_FUNCTION // Hum, Temp, Press, Temp, Accelero enable hum_temp->enable(); press_temp->enable(); accelerometer->enable(); // Lecture des capteurs hum_temp->get_temperature(&xnuc_t); hum_temp->get_humidity(&xnuc_h); press_temp->get_temperature(&xnuc_t2); press_temp->get_pressure(&xnuc_p); accelerometer->get_x_axes(xnuc_acc); #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> XNucleo = %.3f \xB0 C, %.3f \xB0 C, %.3f mbar, %.2f %%, ",xnuc_t, xnuc_t2, xnuc_p, xnuc_h); serial_pc.printf("Acc x = %ld, y = %ld, z = %ld\n", xnuc_acc[0], xnuc_acc[1], xnuc_acc[2]); #endif #endif // GSM #ifdef GSM_FUNCTION #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> GSM ON "); #endif gsm_pwr_on(); #endif // GPRS SMS #ifdef GPRS_FUNCTION #ifdef DEBUG_SERIAL_PC serial_pc.printf("& GPRS ON\n"); #endif #endif #ifdef PT100_FUNCTION #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> PT100 = "); #endif // Configuration initiale du MAX31865 /* 1: v_biais : Vbias (tension de polarisation) activée (true) ou non (false) 2: conversion_mode : mode de conversion automatique activé (true) ou non (false) 3: one_shot : mesure au coup par coup (true) ou en continue (false) 4: three_wire : mesure 3 fils activée (true) ou 2/4 fils (false) 5: fault_cycle : detection d'erreur (voir datasheet) activée (true) ou non (false) 6: fault_clear : acquittement automatique des erreurs activée (true) ou non (false) 7: filter_50hz : filtre 50 Hz activé (true) ou non (false) 8: low_threshold : seuil d'erreur bas. (0x0000 = 0) 9: high_threshold : seuil d'erreur haut. (0x7fff = 32767) */ PT100.configure(true, true, false, false, MAX31865_FAULT_DETECTION_NONE, true, true, 0x0000, 0x7fff); PT100.read_all(); #ifdef DEBUG_SERIAL_PC if(PT100.status() == 0) { //serial_pc.printf("PT100 OK Temp = %.3f *C\n",PT100.temperature()); serial_pc.printf("PT100 OK\n"); } else { serial_pc.printf("\n!!! Registre d'erreur PT100 = %d - ",PT100.status( )); if(PT100.status() & MAX31865_FAULT_HIGH_THRESHOLD) { serial_pc.printf("ERREUR PT100 seuil haut franchi\n"); } else if(PT100.status() & MAX31865_FAULT_LOW_THRESHOLD) { serial_pc.printf("ERREUR PT100 seuil bas franchi\n"); } else if(PT100.status() & MAX31865_FAULT_REFIN) { serial_pc.printf("ERREUR REFIN- > 0,85 x V_BIAS\n"); } else if(PT100.status( ) & MAX31865_FAULT_REFIN_FORCE) { serial_pc.printf("ERREUR REFIN- < 0,85 x V_BIAS, FORCE- ouvert\n"); } else if(PT100.status( ) & MAX31865_FAULT_RTDIN_FORCE ) { serial_pc.printf("ERREUR RTDIN- < 0,85 x V_BIAS, FORCE- ouvert\n"); } else if(PT100.status( ) & MAX31865_FAULT_VOLTAGE) { serial_pc.printf("ERREUR sur/sous-tension\n"); } else serial_pc.printf("ERREUR inconnue\n"); } #endif #endif // Carte SD, initialisation, et creation d'un fichier de test d'ecriture // /!\ Faire cette étape après l'initialisation du capteur PT100 qui partage le même SPI #ifdef SD_FUNCTION #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> SD = "); #endif //mkdir("/sd/TEST", 0777); FILE *fp = fopen(SD_FUNCTION_TESTFILENAME, "w"); if(fp == NULL) { #ifdef DEBUG_SERIAL_PC serial_pc.printf("ERREUR - Ecriture carte SD\n"); #endif // Desactivation de la sauvegarde sur carte SD flag_sd_ok = 0; } else { fprintf(fp, "AMU - Polytech Marseille - HAB STM32 in the Sky - Test ecriture SD"); fclose(fp); #ifdef DEBUG_SERIAL_PC serial_pc.printf("Ecriture carte SD - ok\n"); #endif //Activation de la sauvegarde sur carte SD flag_sd_ok = 1; } #endif // CO2 #ifdef CO2_FUNCTION co2.begin(); co2.IAQmeasure(); #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> CO2 = TVOC = %d, eCO2 = %d\n", co2.TVOC, co2.eCO2); #endif #endif //DS18 thermomètre #ifdef DS18_FUNCTION // Debut directive de compilation DS181B20 if (ds18.begin()) { while (1) { ds18.startConversion(); // start temperature conversion from analog to digital wait(1.0); // let DS1820 complete the temperature conversion result = ds18.read(tempDS18); // read temperature from DS1820 and perform cyclic redundancy check (CRC) switch (result) { case 0: // no errors -> 'tempDS18' contains the value of measured temperature #ifdef DEBUG_SERIAL_PC serial_pc.printf("temp = %3.1f%cC\r\n", tempDS18, 176); #endif break; case 1: // no sensor present -> 'tempDS18' is not updated #ifdef DEBUG_SERIAL_PC serial_pc.printf("no sensor present\n\r"); #endif break; case 2: // CRC error -> 'tempDS18' is not updated #ifdef DEBUG_SERIAL_PC serial_pc.printf("CRC error\r\n"); #endif } } } else #ifdef DEBUG_SERIAL_PC serial_pc.printf("No DS1820 sensor found!\r\n"); #endif #endif // Fin directive de compilation DS181B20 //UV #ifdef UV_FUNCTION #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> UV = %.3f %%ADC\n",pin_UV.read()); #endif #endif //Photoresistance #ifdef PHOTORES_FUNCTION #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> Photoresistance = %.3f %%ADC\n",(double)pin_photores.read()*100.0); #endif #endif // Triple capteur Bosch BME280 #ifdef BOSCH_FUNCTION // Debut directive de compilation Bosch #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> Bosch = %.2f *C, %.2f mbar, %.2f %%\n", bosch.getTemperature(), bosch.getPressure(), bosch.getHumidity()); #endif #endif // Fin directive de compilation Bosch // Lecteur MP3 // Creer un fichier 0.mp3 à la racine de la carte SD #ifdef MP3_FUNCTION // Debut directive de compilation lecteur MP3 #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> MP3 ON\n"); #endif mp3.mp3_reset(); wait(1); mp3.mp3_set_EQ(0); wait(0.5); mp3.mp3_set_volume(20); wait(0.5); mp3.mp3_set_device(2); // 1,2,3,4,5 : USB,SD,AUX,SLEEP,FLASH wait(0.5); mp3.mp3_single_loop(0); //mp3.mp3_single_play(0) ; wait(0.5); //serial_pc.printf("We are in the MP3 func !!!!!\n\r"); mp3.mp3_play(); #endif // Fin directive de compilation MP3 #ifdef LORA_FUNCTION #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> LoRa ON\n"); #endif #endif #ifdef GPS_FUNCTION #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> GPS ON\n"); #endif #endif #ifdef O3_FUNCTION #ifdef DEBUG_SERIAL_PC serial_pc.printf("-> Ozone O3 = %f %%ADC\n", lecture_ozone()); #endif #endif #ifdef DEBUG_SERIAL_PC serial_pc.printf("\n"); #endif ////// Lancement des ticker et des interruptions //////// // GPS // Mise en place de l'interruption pour le port UART du GPS #ifdef GPS_FUNCTION // Debut directive de compilation module GPS gps_serial.attach(&isr_gps_serial,Serial::RxIrq); #endif // Fin directive de compilation module GPS // Ticker de creation de la chaine de données toute les 5s ticker_hab.attach(&isr_ticker_hab, TICKER_HAB_TIME); // GSM #ifdef GSM_FUNCTION // Debut directive de compilation module GSM if(flag_gsm_absent == 0) { // Interruption sur LED "NET" et compteur de sa période timer_gsm_network.reset(); // Démarrage du compteur de la période de clignotement de la LED "NET" timer_gsm_network.start(); gsm_net.rise(&isr_network_gsm); // Attachement de l'interruption externe sur la LED "NET" // Ticker de surveillance GSM toute les xx sec ticker_check_gsm.attach(&isr_ticker_check_gsm, TICKER_CHECK_GSM_TIME); // Ticker d'envoi de données par sms toute les xx sec #ifdef SMS_FUNCTION // Debut directive de compilation envoi SMS ticker_sms_data.attach(&isr_ticker_sms_data, TICKER_SMS_DATA_TIME); #endif // Fin directive de compilation SMS de données toutes les xx sec } #endif // Fin directive de compilation module GSM // LoRa // Mise en place de l'interruption pour le port UART LoRa #ifdef LORA_FUNCTION // Debut directive de compilation LoRa lora_serial.attach(&isr_lora_serial,Serial::RxIrq); #endif // Fin directive de compilation LoRa /////////////////// BOUCLE PRINCIPALE ///////////////// while(1) { // Vérification du flag d'interruption pour la routine de recuperation // des données des capteurs, enregistrement, envoi LoRa, etc. #ifdef HAB_FUNCTION if(flag_ticker_hab == 1) f_ticker_hab(); #endif // Vérification du flag d'interruption pour la routine de vérification // de l'état du module #ifdef GSM_FUNCTION // Debut directive de compilation module GSM if(flag_ticker_check_gsm == 1) { if ( (altitude(xnuc_p, BASE_PRESSURE) < GSM_START_ALTITUDE ) || (altitude(bosch_p, BASE_PRESSURE) < GSM_START_ALTITUDE) ) { #ifdef DEBUG_SERIAL_PC serial_pc.printf("> Pression 1 (XNUCLEO) : %.2f mbar - altitude GSM : %.2f m\n", xnuc_p, altitude(xnuc_p, BASE_PRESSURE)); serial_pc.printf("> Pression 1 (BOSCH) : %.2f mbar - altitude GSM : %.2f m\n", bosch_p, altitude(bosch_p, BASE_PRESSURE)); #endif f_ticker_check_gsm(); } } #endif // Fin directive de compilation module GSM // Vérification du flag d'interruption pour la routine d'envoi de SMS // de donnée toute les 10 min #ifdef SMS_FUNCTION // Debut directive de compilation SMS de données toutes les 10 min if(flag_ticker_sms_data == 1) f_ticker_sms_data(); #endif // Fin directive de compilation SMS de données toutes les 10 min } }