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
Diff: main.cpp
- Revision:
- 0:d7a683cf76d9
- Child:
- 3:cb77ea3370e8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Feb 03 20:31:41 2019 +0000 @@ -0,0 +1,1178 @@ +// Projet HAB "ST in the sky", Polytech Marseille +// Programme de la carte mère du HAB, la STM32 Nucleo-L073RZ +// 20 Janvier 2019 + +/* todo : +- resoudre incompatibilité mbed thermomètre DS18 +- utilisation de l'entrée Reset du module GSM +- check si le lecteur MP3 est bien actif +*/ + +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// + +// Activation des différents modules de ce code (via directives de compilation) +// Permet de désactiver rapidement la compilation de certaines parties du code + +// Commentez les lignes pour désactiver les modules/fonctionnalités : + +#define SD_COMP 1 // Carte SD +#define GSM_COMP 1 // module GSM +#define GPRS_COMP 1 // Données mobiles +#define SMS_COMP 1 // SMS de données toute les 10 min +#define GPS_COMP 1 // module GPS +//#define GPS_DEBUG // Transmission des données serie GPS sur le moniteur série +#define XNUCLEO_COMP 1 // shield capteurs XNUCLEO +#define PT100_COMP 1 // module PT100 +#define CO2_COMP 1 // module CO2 +#define BUZZ_COMP // Buzzer +#define UV_COMP 1 // Capteur UV +#define PHOTORES_COMP 1 // Capteur photoresistance +#define BOSCH_COMP 1 // module triple capteur Bosch +#define MP3_COMP 1 // module lecteur MP3 +//#define LORA_COMP 1 // Carte LoRa +#define O3_COMP 1 // module spi_ozone O3 +//#define DS18_COMP // Capteur temperature DS18 + + +// Assignation des entrées/sorties des différents modules + +// DS18 thermomètre +#define IO_DS18 PC_6 + +// Carte SD +#define IO_SD_MOSI PB_15 // SPI 2 +#define IO_SD_MISO PB_14 +#define IO_SD_SCK PB_13 +#define IO_SD_SS PB_2 + +// Shield XNUCLEO +#define IO_XNUC_SDA PB_9 // I2C 1 +#define IO_XNUC_SCL PB_8 + +// GPS +#define IO_GPS_TX PC_1 // LPUART +#define IO_GPS_RX PC_0 + +// GSM/GPRS/2G+/téléphone +#define IO_GSM_TX PA_0 // UART 4 +#define IO_GSM_RX PA_1 +#define IO_GSM_PWR PC_7 +#define IO_GSM_NET PA_8 +#define IO_GSM_STAT PA_9 +#define IO_GSM_RST PA_7 + +// Thermomètre PT100 (RTD) MAX31865 +#define IO_PT100_MOSI PB_15 // SPI 2 +#define IO_PT100_MISO PB_14 +#define IO_PT100_SCK PB_13 +#define IO_PT100_SS PB_1 + +// Capteur eCO2 TVOC +#define IO_CO2_SDA PB_9 // I2C 1 +#define IO_CO2_SCL PB_8 + +// Triple capteur Bosch (hum, temp, press) +#define IO_BOSCH_SDA PB_9 // I2C 1 +#define IO_BOSCH_SCL PB_8 + +// Lecteur MP3 DFPlayer +#define IO_MP3_TX PB_6 // UART 1 +#define IO_MP3_RX PA_10 + +// LoRa +#define IO_LORA_TX PC_12 // UART 5 +#define IO_LORA_RX PD_2 + +// Ozone O3 +#define IO_O3_MOSI PB_15 // SPI 2 +#define IO_O3_MISO PB_14 +#define IO_O3_SCK PB_13 +#define IO_O3_SS PB_12 + +// Autres +#define IO_BUZZER PB_3 +#define IO_UV PC_2 +#define IO_PHOTORES PC_3 +#define IO_VBATT PB_0 + +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +//////////////////////// Début du code //////////////////////////////// +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// + +//Autres + +#include <stdio.h> +#include <string> +#include "mbed.h" + +Serial serial_pc(SERIAL_TX, SERIAL_RX, 115200); + +#ifdef LORA_COMP // Debut directive de compilation LoRa +// todo: liaison UART avec carte LoRa + watchdog carte mère +Serial lora_serial(IO_LORA_TX, IO_LORA_RX, 9600); + +char chaine_lora[50]; //chaine contenant la trame des données des capteurs à envoyer +#endif // Fin directive de compilation LoRa + + +#ifdef BUZZ_COMP // Debut directive de compilation buzzer +DigitalOut pin_buzzer(IO_BUZZER,0); +#endif // Fin directive de compilation buzzer + +unsigned int compteur = 0; //compteur du nombre de fois que la recolte de données à été effectuée depuis le démarrage + +// Mesure de la tension de la batterie +float vbatt = 0.0; // Tension de la batterie +AnalogIn pin_vbatt(IO_VBATT); + +//chaine contenant la trame des données des capteurs à stocker sur la crate sd et à envoyer par GPRS +char chaine_data[150]; + +///////////////////////////////////////////////////////////////////////// + +//Tickers + +// Ticker executé toute les 5s pour recolter toute les données des capteurs, +// les enregistrer sur la carte SD et les envoyer en UART à la carte LoRa +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 + +// Ticker executé toute les 30 s pour vérifier l'etat du module GSM +#ifdef GSM_COMP // 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 GSM +#ifdef SMS_COMP // Debut directive de compilation SMS de données toutes les 10 min +Ticker ticker_sms_chaine; // Object Ticker +void isr_ticker_sms_chaine(); // Routine ISR appellée lors du tick +void f_ticker_sms_chaine(); // Fonction utile appellée à la suite du tick +bool flag_ticker_sms_chaine = 0; // Flag levé par l'ISR pour appeller la fonction utile +#endif // Fin directive de compilation SMS de données toutes les 10 min + +///////////////////////////////////////////////////////////////////////// + +// Carte SD + +#ifdef SD_COMP // Debut directive de compilation carte SD + +#include "SDFileSystem.h" +SDFileSystem sd(IO_SD_MOSI, IO_SD_MISO, IO_SD_SCK, IO_SD_SS, "sd"); // MOSI, MISO, SCK, SS + +bool flag_sd_ok = 0; // Flag mit à '1' après la 1ere initialisation reussie de la carte SD + +#endif // Fin directive de compilation carte SD + +///////////////////////////////////////////////////////////////////////// + +// Shield capteurs ST X_NUCLEO_IKS01A2 + +#ifdef XNUCLEO_COMP // Debut directive de compilation shield capteurs XNUCLEO + +#include "XNucleoIKS01A2.h" + +// Instantiate the expansion board +static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(IO_XNUC_SDA, IO_XNUC_SCL); // SDA, SCL, option(INT1, INT2) + +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 + +float xnuc_t = 0.0, xnuc_h = 0.0, xnuc_t2 = 0.0, xnuc_p = 0.0; +int32_t xnuc_acc[3]; + +///////////////////////////////////////////////////////////////////////// + +// Module GPS +#ifdef GPS_COMP // Debut directive de compilation module GPS + +#include "GroveGPS.h" +Serial gps_serial(IO_GPS_TX, IO_GPS_RX, 9600); //TX, RX, liaison STM --> GPS +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 + +unsigned int timeUTC = 0; +float lat = 0, lon = 0, alt = 0, speed = 0; + +///////////////////////////////////////////////////////////////////////// + +// Module GSM +#ifdef GSM_COMP // Debut directive de compilation module GSM + +// Flag mis à jour par interruption externe sur la LED NET. +// Passe a true lorsque sa période de clignotement est d'environs 3 s +bool flag_gsm_net_ok = 1; + +// 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 a 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 de le reset trop souvent si +// la connexion est mauvaise. +unsigned int last_reset_gsm = 0; + +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" + +#include <GSM.h> +GSM gsm(IO_GSM_TX, IO_GSM_RX, 9600,"0649980191"); //TX, RX, PWR, NET, STATUS, baudrate, num par defaut + +char * url_srv_paul = "http://37.59.60.112/public/HAB/index.php?message="; // URL du serveur web + +#endif // Fin directive de compilation module GSM + + +///////////////////////////////////////////////////////////////////////// + +// Sonde de température PT100 sur ampli MAX31865 + +#ifdef PT100_COMP // Debut directive de compilation module PT100 + +#include "MAX31865.h" +MAX31865_RTD PT100(MAX31865_RTD::RTD_PT100,IO_PT100_MOSI, IO_PT100_MISO, IO_PT100_SCK, IO_PT100_SS); // MOSI, MISO, SCK, SS : SPI du MAX311865 + +#endif // Fin directive de compilation module PT100 + +double tempPT100 = 0; + +///////////////////////////////////////////////////////////////////////// + +// Capteur eCO2/TVOC SGP30 + +// /!\ Indication : +// Le module eCO2/TVOC produira pendant ~20 s des resultats invalides pendant son echauffement +// eCO2=400 et TVOC=0, patientez quelques instants +// module à allumer 48h à l'avance pour résultats optimums + +#ifdef CO2_COMP // 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 + +int eco2 = 0; +int tvoc = 0; + +///////////////////////////////////////////////////////////////////////// + +// Capteur de temperature (exterieur haut) DS181B20 + +#ifdef DS18_COMP // Debut directive de compilation DS181B20 + +#include "DS1820.h" +DS1820 ds18(IO_DS18); + +#endif // Fin directive de compilation DS181B20 + +float tempDS18 = 0; + +///////////////////////////////////////////////////////////////////////// + +// Capteurs lumière (UV et photoresistance) + +//#ifdef UV_COMP // Debut directive de compilation capteur UV +AnalogIn pin_UV(IO_UV); +//#endif // Fin directive de compilation capteur UV + +//#ifdef PHOTORES_COMP // Debut directive de compilation capteur lumière +AnalogIn pin_photores(IO_PHOTORES); +//#endif // Fin directive de compilation capteur lumière + +float uv = 0; +float photores = 0; + +///////////////////////////////////////////////////////////////////////// + +// Capteur Bosch BME280 (temperature, pression, humidité exterieure) + +#ifdef BOSCH_COMP // Debut directive de compilation Bosch + +#include "BME280.h" +BME280 bosch(IO_BOSCH_SDA, IO_BOSCH_SCL); // SDA, SCL + +#endif // Fin directive de compilation Bosch + +float bosch_t = 0; +float bosch_p = 0; +float bosch_h = 0; + +///////////////////////////////////////////////////////////////////////// + +// Lecteur MP3 DFPlayer + +#ifdef MP3_COMP // 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 + +///////////////////////////////////////////////////////////////////////// + +// Capteur Ozone O3 + +// todo + +#ifdef O3_COMP // Debut directive de compilation spi_ozone + +SPI spi_ozone(PB_15, PB_14, PB_13); // MOSI,MISO,SCK +DigitalOut ozone_SS(IO_O3_SS,1); + +#endif // Fin directive de compilation spi_ozone + +double ozone = 0; + +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +///////////////////// Fonctions annexes /////////////////////////////// +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// + +// Ozone O3 +double lecture_ozone() { + + uint32_t chiffre=0; + uint8_t Buff[4]; + + for(int i=0; i<3;i++) Buff[i] = 0; + + 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; + + double resultat = 0.0; + resultat = 100 - (chiffre/41943.040); // Conversion en %ADC + + return resultat; + +} + +///////////////////////////////////////////////////////////////////////// + +// Fonctions d'activation et de desactivation de l'interruption UART pour GPS + +void irq_gps_off() { + // IRQ OFF : desactivation de l'interruption pour le port UART du GPS + #ifdef GPS_COMP // Debut directive de compilation module GPS + gps_serial.attach(NULL); + #endif // Fin directive de compilation module GPS +} + +void irq_gps_on() { + // IRQ ON : activation de l'interruption pour le port UART du GPS + #ifdef GPS_COMP // Debut directive de compilation module GPS + gps_serial.attach(&isr_gps_serial,Serial::RxIrq); + #endif // Fin directive de compilation module GPS +} + +///////////////////////////////////////////////////////////////////////// + +// SD +#ifdef SD_COMP // 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; + + irq_gps_off(); //désactivation de l'interruption UART pour GPS + + // fichier du type "/sd/data.txt" + FILE *fp = fopen(fichier, "a"); + if(fp == NULL) { + serial_pc.printf("ERREUR : carte SD\n"); + } + else { + fprintf(fp, message); + fprintf(fp, "\n"); + fclose(fp); + } + + irq_gps_on(); //ré-activation de l'interruption UART pour GPS +} + +#endif // Fin directive de compilation carte SD + + +//////////////////////////////////////////////////////////////////////// + +//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))); +} + +///////////////////////////////////////////////////////////////////////// + +// GSM + +#ifdef GSM_COMP // Debut directive de compilation module GSM + +void init_GSM(); + +Timer timer_gsm_net; // Compteur de la période de clignotement de la LED "NET" +unsigned int last_time_gsm_net = 0; + +void isr_net_gsm() { + + // Arret de toute les sources d'interruptions + irq_gps_off(); + gsm_net.disable_irq(); + + + timer_gsm_net.stop(); // Arret du compteur + + last_time_gsm_net = timer_gsm_net.read_ms(); // Lecture du compteur + + serial_pc.printf("last_time_gsm_net : %d\n", last_time_gsm_net); + + // Seulement si la période de clignotement est d'environs 3 s alors le module + // GSM est bien connecté au réseau et est pret a etre utilisé. + if(last_time_gsm_net > 2800 && last_time_gsm_net < 3200) { + flag_gsm_net_ok = 1; + if(flag_gsm_starting == 1) { + init_GSM(); + flag_gsm_starting = 0; + } + } + else flag_gsm_net_ok = 0; + + timer_gsm_net.reset(); // Remise a zéro et départ à nouveau du compteur + timer_gsm_net.start(); + + // Re-allumage des interruptions + irq_gps_on(); + gsm_net.enable_irq(); +} + +///////////////////////////////////////////////////////////////////////// + +// 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 + 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 + + serial_pc.printf("****************\nInit 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****************\n",gsm.sendSMS("+33649980191", "coucou")); + + flag_gsm_starting = 0; // Init logiciel effectué + + // Re-allumage des interruptions + irq_gps_on(); + gsm_net.enable_irq(); + ticker_hab.attach(&isr_ticker_hab, 5.0); + ticker_check_gsm.attach(&isr_ticker_check_gsm, 30.0); +} + +///////////////////////////////////////////////////////////////////////// + +void gsm_pwr_on() { + + // Fonction qui allume le module GSM (matériellement) si besoin + // 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 + 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 + + // Creation et lancement d'un timer de time out du démarrage du module GSM + Timer timer_gsm_init; + timer_gsm_init.start(); + + gsm_pwr = 1; + while(gsm_status == 0) { + wait(0.1); + + if(timer_gsm_init.read() > 5) { + + serial_pc.printf("ERREUR : module GSM absent\n"); + flag_gsm_absent = 1; // Constatation de l'absence du module GSM + timer_gsm_net.stop(); + gsm_pwr = 0; + + // Re-allumage des interruptions + irq_gps_on(); + gsm_net.enable_irq(); + ticker_hab.attach(&isr_ticker_hab, 5.0); + ticker_check_gsm.attach(&isr_ticker_check_gsm, 30.0); + return; + } + } + gsm_pwr = 0; + timer_gsm_net.stop(); + + } + else serial_pc.printf("Module GSM deja allume\n"); + + flag_gsm_absent = 0; // Constatation de la présence du module GSM + + // 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; + + // Re-allumage des interruptions + irq_gps_on(); + gsm_net.enable_irq(); + ticker_hab.attach(&isr_ticker_hab, 5.0); + ticker_check_gsm.attach(&isr_ticker_check_gsm, 30.0); + +} + +#endif // Fin directive de compilation module GSM + +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +/////////////// Tickers, Interruptions, Threads /////////////////////// +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// + +//GSM +#ifdef GSM_COMP // Debut directive de compilation module GSM + +void f_ticker_check_gsm() { + // Fonction du ticker de surveillance du module GSM, lancée toute les 30 s + + // Si module GSM absent, on retourne + if(flag_gsm_absent == 1) return; + + irq_gps_off(); //désactivation de l'interruption UART pour GPS + + // Si le module GSM est éteint, bé on l'allume + if(gsm_status == 0) gsm_pwr_on(); + + // Si module GSM non connecté + if(flag_gsm_net_ok == 0) { + + // Si cela fais plus d'une minute qu'on a démarré alors + if(compteur - last_reset_gsm > 15) { + serial_pc.printf("/:\\ Reset du module GSM...\n"); + + // todo : appui sur bouton reset du module gsm + + + last_reset_gsm = compteur; + } + } + + + // 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 stat = gsm.checkSIMStatus(); + serial_pc.printf("\n-- Check statut SIM : %d --\n", stat); + + if(stat != 0) { + init_GSM(); + } + + irq_gps_on(); //ré-activation de l'interruption UART pour GPS + + + flag_ticker_check_gsm = 0; // Abaissage du flag +} +#endif // Fin directive de compilation module GSM + +///////////////////////////////////////////////////////////////////////// + +//GPS +#ifdef GPS_COMP // Debut directive de compilation module GPS + +// 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 + +//////////////////////////////////////////////////////////////////////// + +// Ticker executé toute les 10 min pour envoier les données par sms +#ifdef GSM_COMP // Debut directive de compilation module GSM +void f_ticker_sms_chaine() { + + gsm.sendSMS("+33649980191", chaine_data); + + flag_ticker_sms_chaine = 0; +} +#endif // Fin directive de compilation module GSM + +//////////////////////////////////////////////////////////////////////// + +/* +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 +*/ + + +void f_ticker_hab() { + + + //DS18 thermomètre pt1 (en 2 parties pour eviter d'attendre) + #ifdef DS18_COMP // Debut directive de compilation DS181B20 + + //todo + + #endif // Fin directive de compilation DS181B20 + + + + // Recuperation donnees capteurs ST X_NUCLEO_IKS01A2 + #ifdef XNUCLEO_COMP // 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_COMP // Debut directive de compilation module PT100 + PT100.read_all(); + if(PT100.status() == 0) { + tempPT100 = PT100.temperature(); + //serial_pc.printf(" T = %f degC \r\n",temp); + } + else { + tempPT100 = 0; + serial_pc.printf("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 // Fin directive de compilation module PT100 + + + // CO2 + #ifdef CO2_COMP // Debut directive de compilation module CO2 + co2.IAQmeasure(); + /*serial_pc.printf("TVOC : %d\n", co2.TVOC); + serial_pc.printf("eCO2: %d\n", co2.eCO2);*/ + 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_COMP // Debut directive de compilation DS181B20 + + //todo + + #endif // Fin directive de compilation DS181B20 + + // Capteurs UV et lumiere + #ifdef UV_COMP // Debut directive de compilation capteur UV + uv = pin_UV.read(); + #endif // Fin directive de compilation capteur UV + #ifdef PHOTORES_COMP // 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_COMP // Debut directive de compilation Bosch + bosch_t = bosch.getTemperature(); + bosch_p = bosch.getPressure(); + bosch_h = bosch.getHumidity(); + //serial_pc.printf("Bosch : %.2f *C, %.2f mbar, %.2f %%\n", bosch.getTemperature(), bosch.getPressure(), bosch.getHumidity()); + #endif // Fin directive de compilation Bosch + + + // Ozone + #ifdef O3_COMP // 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 = pin_vbatt.read()*3.3*11.07+0.52; + + // Recuperation données GPS + #ifdef GPS_COMP // 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*) chaine_data, "%d-%.2f-%d-%f-%f-%.1f-%.1f-%.1f-%.1f-%.3f-%.3f-%.3f-%.1f-%.3f-%.2f-%.2f-%d-%d-%f-%.3f-%.3f", compteur, 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, uv*100.0, photores*100.0); + + + // Affichage des données sur port série debug + serial_pc.printf("*Compteur : %d\n", compteur); + serial_pc.printf("*Tension batterie : %f V\n", vbatt); + #ifdef GPS_COMP // 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_COMP // 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_COMP // 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_COMP // Debut directive de compilation DS181B20 + serial_pc.printf("*Temperature 4 (DS18) : %.3f *C\n", tempDS18); + #endif // Fin directive de compilation DS181B20 + #ifdef BOSCH_COMP // Debut directive de compilation Bosch + serial_pc.printf("*Temperature 5 (Bosch) : %.3f *C\n",bosch_t); + #endif // Fin directive de compilation Bosch + #ifdef XNUCLEO_COMP // 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_COMP // Debut directive de compilation Bosch + serial_pc.printf("*Humidite 2 (Bosch) : %.2f %%\n",bosch_h); + #endif // Fin directive de compilation Bosch + #ifdef XNUCLEO_COMP // 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, 1016)); + #endif // Fin directive de compilation shield capteurs XNUCLEO + #ifdef BOSCH_COMP // Debut directive de compilation Bosch + serial_pc.printf("*Pression 2 (Bosch) : %.2f mbar - altitude calculee : %.2f m\n",bosch_p, altitude(bosch_p, 1016)); + #endif // Fin directive de compilation Bosch + #ifdef CO2_COMP // 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_COMP // Debut directive de compilation capteur UV + serial_pc.printf("*UV : %.3f %%ADC\n", uv*100.0); + #endif // Fin directive de compilation capteur UV + #ifdef PHOTORES_COMP // Debut directive de compilation capteur lumière + serial_pc.printf("*Lum : %.3f %%ADC\n", photores*100.0); + #endif // Fin directive de compilation capteur lumière + #ifdef O3_COMP // 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", chaine_data); + + + // Envoie de la chaine par GPRS au serveur de Paul + #ifdef GSM_COMP // Debut directive de compilation module GSM + #ifdef GPRS_COMP // Debut directive de compilation données mobiles + if(flag_gsm_net_ok == 1) gsm.gprs_message(url_srv_paul , chaine_data); + #endif // Fin directive de compilation données mobiles + //if(flag_gsm_net_ok == 1) serial_pc.printf("SMS : %d\n",gsm.sendSMS("+33649980191", chaine_data)); // Envoi de la chaine par SMS + #endif // Fin directive de compilation module GSM + + // Sauvegarde sur carte SD + #ifdef SD_COMP // Debut directive de compilation carte SD + ecriture_sd("/sd/data.txt", chaine_data); + #endif // Fin directive de compilation carte SD + + + // Creation de la chaine à envoyer à la carte LoRa + #ifdef LORA_COMP // Debut directive de compilation LoRa + sprintf((char*) chaine_lora, "%.2f-%f-%f-%.1f-%.3f", vbatt, lat, lon, alt, tempPT100); + serial_pc.printf(">> %s\n", chaine_lora); + #endif // Fin directive de compilation LoRa + + serial_pc.printf("************************************************\n"); + compteur++; + + flag_ticker_hab = 0; // Abaissage du flag +} + +///////////////////////////////////////////////////////////////////////// + +// 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() ! + +void isr_ticker_hab() { flag_ticker_hab = 1; } +#ifdef GSM_COMP +void isr_ticker_check_gsm() { flag_ticker_check_gsm = 1; } +#endif // Fin directive de compilation module GSM +#ifdef SMS_COMP +void isr_ticker_sms_chaine() { flag_ticker_sms_chaine = 1; } +#endif + +///////////////////////////////////////////////////////////////////////// + +// LoRa + +#ifdef LORA_COMP // Debut directive de compilation LoRa + +void envoi_chaine_lora() { + + lora_serial.printf("%s\n", chaine_lora); + serial_pc.printf("lora!\n"); // debug +} + +void isr_lora_serial() { + + char c = lora_serial.getc(); + if(c == 'a') envoi_chaine_lora(); + #ifdef MP3_COMP // 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_COMP // 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 + serial_pc.printf("--- Programme HAB carte mere ---\n"); + vbatt = 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("Modules compiles :\n"); + + + //Buzzer, léger bip au démarrage + #ifdef BUZZ_COMP + serial_pc.printf("- Buzzer\n"); + pin_buzzer.write(1); + wait(0.1); + pin_buzzer.write(0); + #endif + + // Shield ST X_NUCLEO_IKS01A2 + #ifdef XNUCLEO_COMP + 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); + serial_pc.printf("- XNUCLEO : %.3f *C, %.3f *C, %.3f mbar, %.2f %%\n",xnuc_t, xnuc_t2, xnuc_p, xnuc_h); + + accelerometer->get_x_axes(xnuc_acc); + serial_pc.printf(" accelerometre : x = %ld, y = %ld, z = %ld\n", xnuc_acc[0], xnuc_acc[1], xnuc_acc[2]); + + #endif + + // GSM + #ifdef GSM_COMP + serial_pc.printf("- GSM : "); + gsm_pwr_on(); + #endif + #ifdef GPRS_COMP + serial_pc.printf("- Donnees mobiles\n"); + #endif + + #ifdef PT100_COMP + serial_pc.printf("- PT100 : "); + // 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(); + if(PT100.status() == 0) { + serial_pc.printf("%.3f *C\n",PT100.temperature()); + } + else { + serial_pc.printf("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 + + // 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_COMP + serial_pc.printf("- SD : "); + mkdir("/sd/TEST", 0777); + FILE *fp = fopen("/sd/TEST/sdtest.txt", "w"); + if(fp == NULL) { + serial_pc.printf("ERREUR, ecriture carte SD\n"); + // Desactivation de la sauvegarde sur carte SD + flag_sd_ok = 0; + } + else { + fprintf(fp, "test ecriture"); + fclose(fp); + serial_pc.printf("ecriture ok\n"); + //Activation de la sauvegarde sur carte SD + flag_sd_ok = 1; + } + #endif + + // CO2 + #ifdef CO2_COMP + co2.begin(); + co2.IAQmeasure(); + serial_pc.printf("- CO2 : TVOC = %d, eCO2 = %d\n", co2.TVOC, co2.eCO2); + #endif + + //DS18 thermomètre + #ifdef DS18_COMP // 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 + serial_pc.printf("temp = %3.1f%cC\r\n", tempDS18, 176); + break; + case 1: // no sensor present -> 'tempDS18' is not updated + serial_pc.printf("no sensor present\n\r"); + break; + case 2: // CRC error -> 'tempDS18' is not updated + serial_pc.printf("CRC error\r\n"); + } + } + } + else + serial_pc.printf("No DS1820 sensor found!\r\n"); + + #endif // Fin directive de compilation DS181B20 + + //UV + #ifdef UV_COMP + serial_pc.printf("- UV : %.3f %%ADC\n",pin_UV.read()); + #endif + + //Photoresistance + #ifdef PHOTORES_COMP + serial_pc.printf("- Photoresistance : %.3f %%ADC\n",pin_photores.read()*100.0); + #endif + + // Triple capteur Bosch BME280 + #ifdef BOSCH_COMP // Debut directive de compilation Bosch + serial_pc.printf("- Bosch : %.2f *C, %.2f mbar, %.2f %%\n", bosch.getTemperature(), bosch.getPressure(), bosch.getHumidity()); + #endif // Fin directive de compilation Bosch + + // Lecteur MP3 + // Creer un fichier 0.mp3 à la racine de la carte SD + #ifdef MP3_COMP // Debut directive de compilation lecteur MP3 + serial_pc.printf("- MP3\n"); + 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); + wait(0.5); + mp3.mp3_play(); + #endif // Fin directive de compilation MP3 + + + #ifdef LORA_COMP + serial_pc.printf("- LoRa\n"); + #endif + #ifdef GPS_COMP + serial_pc.printf("- GPS\n"); + #endif + + #ifdef O3_COMP + serial_pc.printf("- Ozone O3 : %f %%ADC\n", lecture_ozone()); + #endif + + + + serial_pc.printf("************************************************\n"); + + ////// Lancement des ticker et des interruptions //////// + + // GPS + // Mise en place de l'interruption pour le port UART du GPS + #ifdef GPS_COMP // 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, 5.0); + + + // GSM + #ifdef GSM_COMP // Debut directive de compilation module GSM + if(flag_gsm_absent == 0) { + + // Interruption sur LED "NET" et compteur de sa période + timer_gsm_net.reset(); // Démarrage du compteur de la période de clignotement de la LED "NET" + timer_gsm_net.start(); + gsm_net.rise(&isr_net_gsm); // Attachement de l'interruption externe sur la LED "NET" + + // Ticker de surveillance GSM toute les 30s + ticker_check_gsm.attach(&isr_ticker_check_gsm, 30.0); + + // Ticker d'envoi de données par sms toute les 10 min + #ifdef SMS_COMP // Debut directive de compilation envoi SMS + ticker_sms_chaine.attach(&isr_ticker_sms_chaine, 600.0); + #endif // Fin directive de compilation SMS de données toutes les 10 min + } + #endif // Fin directive de compilation module GSM + + + // LoRa + // Mise en place de l'interruption pour le port UART LoRa + #ifdef LORA_COMP // 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. + if(flag_ticker_hab == 1) f_ticker_hab(); + + + // Vérification du flag d'interruption pour la routine de vérification + // de l'état du module + #ifdef GSM_COMP // Debut directive de compilation module GSM + if(flag_ticker_check_gsm == 1) 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 GPS_COMP // Debut directive de compilation module GPS + #ifdef SMS_COMP // Debut directive de compilation SMS de données toutes les 10 min + if(flag_ticker_sms_chaine == 1) f_ticker_sms_chaine(); + #endif // Fin directive de compilation SMS de données toutes les 10 min + #endif // Fin directive de compilation module GSM + + } +}