IniSat Modèle 1 Version 2 TP 4 : Etude d'un capteur Exo 1 : Lecture température Exo 2 : GPS, décodage données GGA
Revision 0:de81bcbbbb72, committed 2021-07-07
- Comitter:
- Giamarchi
- Date:
- Wed Jul 07 08:32:08 2021 +0000
- Commit message:
- Correction
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Soft_UART/soft_uart.cpp Wed Jul 07 08:32:08 2021 +0000 @@ -0,0 +1,248 @@ +// Software UART +// +// Generic software uart written in C, requiring a timer set to 3 times +// the baud rate, and two software read/write pins for the receive and +// transmit functions. +// +// * Received characters are buffered +// * putchar(), getchar(), kbhit() and flush_input_buffer() are available +// * There is a facility for background processing while waiting for input +// +// Colin Gittins, Software Engineer, Halliburton Energy Services +// +// The baud rate can be configured by changing the BAUD_RATE macro as +// follows: +// +// #define BAUD_RATE 19200.0 +// +// The function init_uart() must be called before any comms can take place +// +// Interface routines required: +// 1. get_rx_pin_status() +// Returns 0 or 1 dependent on whether the receive pin is high or low. +// 2. set_tx_pin_high() +// Sets the transmit pin to the high state. +// 3. set_tx_pin_low() +// Sets the transmit pin to the low state. +// 4. idle() +// Background functions to execute while waiting for input. +// 5. timer_set( BAUD_RATE ) +// Sets the timer to 3 times the baud rate. +// 6. set_timer_interrupt( timer_isr ) +// Enables the timer interrupt. +// +// Functions provided: +// 1. void flush_input_buffer( void ) +// Clears the contents of the input buffer. +// 2. char kbhit( void ) +// Tests whether an input character has been received. +// 3. char getchar( void ) +// Reads a character from the input buffer, waiting if necessary. +// 4. void turn_rx_on( void ) +// Turns on the receive function. +// 5. void turn_rx_off( void ) +// Turns off the receive function. +// 6. void putchar( char ) +// Writes a character to the serial port. +#include "mbed.h" +#include <stdio.h> + +#define BAUD_RATE 9600 +#define IN_BUF_SIZE 256 + +#define TRUE 1 +#define FALSE 0 + +static unsigned char inbuf[IN_BUF_SIZE]; +static unsigned char qin = 0; +static unsigned char qout = 0; + +static char flag_rx_waiting_for_stop_bit; +static char flag_rx_off; +static char rx_mask; +static char flag_rx_ready; +static char flag_tx_ready; +static char timer_rx_ctr; +static char timer_tx_ctr; +static char bits_left_in_rx; +static char bits_left_in_tx; +static char rx_num_of_bits; +static char tx_num_of_bits; +static int internal_rx_buffer; +static int internal_tx_buffer; +static int user_tx_buffer; + +DigitalOut TX(PA_4); +DigitalIn RX(PA_3); +Ticker ticker; + +//Background functions to execute while waiting for input. +void idle(){ + wait_us(0.2); +} + +//Sets the transmit pin to the high state. +void set_tx_pin_high() { + TX = 1; +} + +//Sets the transmit pin to the low state. +void set_tx_pin_low() { + TX = 0; +} + +//Returns 0 or 1 dependent on whether the receive pin is high or low +int get_rx_pin_status() { + return RX.read(); +} + +void timer_isr(void) { + +char mask, start_bit, flag_in; + +// Transmitter Section + if ( flag_tx_ready ) + { + + if ( --timer_tx_ctr <= 0 ) + { + mask = internal_tx_buffer&1; + internal_tx_buffer >>= 1; + if ( mask ) + { + set_tx_pin_high(); + } + else + { + set_tx_pin_low(); + } + timer_tx_ctr = 3; + if ( --bits_left_in_tx <= 0 ) + { + flag_tx_ready = FALSE; + } + } + } +// Receiver Section + if ( flag_rx_off == FALSE ) + { + if ( flag_rx_waiting_for_stop_bit ) + { + if ( --timer_rx_ctr <= 0 ) + { + flag_rx_waiting_for_stop_bit = FALSE; + flag_rx_ready = FALSE; + internal_rx_buffer &= 0xFF; + if ( internal_rx_buffer != 0xC2 ) + { + inbuf[qin] = internal_rx_buffer; + if ( ++qin >= IN_BUF_SIZE ) + { + qin = 0; + } + } + } + } + else // rx_test_busy + { + if ( flag_rx_ready==FALSE ) + { + start_bit = get_rx_pin_status(); +// Test for Start Bit + if ( start_bit == 0 ) + { + flag_rx_ready = TRUE; + internal_rx_buffer = 0; + timer_rx_ctr = 4; + bits_left_in_rx = rx_num_of_bits; + rx_mask = 1; + } + } + else // rx_busy + { + if ( --timer_rx_ctr<=0 ) + { // rcv + timer_rx_ctr = 3; + flag_in = get_rx_pin_status(); + if ( flag_in ) + { + internal_rx_buffer |= rx_mask; + } + rx_mask <<= 1; + if ( --bits_left_in_rx<=0 ) + { + flag_rx_waiting_for_stop_bit = TRUE; + } + } + } + } + } + } + +void Init_Soft_UART(void) { + flag_tx_ready = FALSE; + flag_rx_ready = FALSE; + flag_rx_waiting_for_stop_bit = FALSE; + flag_rx_off = FALSE; + rx_num_of_bits = 8; //10 + tx_num_of_bits = 10; //10 + + set_tx_pin_high(); + ticker.attach_us(&timer_isr, 1000000.0 / (BAUD_RATE * 3.0)); + } + +char _getchar(void) { + char ch; + do + { + while (qout == qin) + { + idle(); + } + ch = inbuf[qout] & 0xFF; + if (++qout >= IN_BUF_SIZE) + { + qout = 0; + } + } + while (ch == 0x0A || ch == 0xC2); + return(ch); + } + +void _putchar(char ch) { + while ( flag_tx_ready ); + user_tx_buffer = ch; + +// invoke_UART_transmit + timer_tx_ctr = 3; + bits_left_in_tx = tx_num_of_bits; + internal_tx_buffer = (user_tx_buffer<<1) | 0x200;; + flag_tx_ready = TRUE; + } + +void flush_input_buffer(void) { + qin = 0; + qout = 0; + } + +char kbhit(void) { + return( qin!=qout ); + } + +void turn_rx_on(void) { + flag_rx_off = FALSE; + } + +void turn_rx_off(void) { + flag_rx_off = TRUE; + } + +void printStr(char* str) { + int i = 0; + int len = strlen(str); + for(i = 0; i<len; i++){ + wait(0.01); + _putchar(str[i]); + } +} + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Soft_UART/soft_uart.h Wed Jul 07 08:32:08 2021 +0000 @@ -0,0 +1,35 @@ +/* +* Soft UART Library +*/ + +#define BAUD_RATE 9600 + +void idle(); + +//Sets the transmit pin to the high state. +void set_tx_pin_high(void); + +//Sets the transmit pin to the low state. +void set_tx_pin_low(void); + +//Returns 0 or 1 dependent on whether the receive pin is high or low +int get_rx_pin_status(void); + +void timer_isr(void); + +void Init_Soft_UART(void); + +char _getchar(void); + +void _putchar(char ch); + +void flush_input_buffer(void); + +char kbhit(void); + +void turn_rx_on(void); + +void turn_rx_off(void); + +void printStr(char* str); + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gps.h Wed Jul 07 08:32:08 2021 +0000 @@ -0,0 +1,161 @@ +/* L80 QUECTEL GPS Module +* NMEA 0183 messages +*/ +#include "mbed.h" +// Commandes pour paramétrer le taux par seconde depuis chaque seconde (1 Hz) jusqu'à 10 fois par seconde (10Hz) +#define PMTK_SET_NMEA_UPDATE_1HZ "$PMTK220,1000*1F" +#define PMTK_SET_NMEA_UPDATE_5HZ "$PMTK220,200*2C" +#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F" + +// Code pour sélection de trame unique +#define TRAME_RMC "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" +#define TRAME_GGA "$PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" +#define TRAME_RMC_GGA "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28" +#define TRAME_ALL "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28" + +#define Trame_TXT_On "$PQTXT,W,1,1*22" +#define Trame_TXT_Off "$PQTXT,W,0,1*23" + +// Selection de trames +void Select_Trame(char* trame) { + printStr((char*) trame); + printStr((char*)"\r\n"); + } + +// Lecture des trames NMEA du GPS + +char buffer[100]; +uint8_t rx_ptr = 0; +uint8_t rx_ok = 0; + +void Lect_GPS(void) { + + while(!rx_ok) { + + if (kbhit()) { + buffer[rx_ptr] = _getchar(); + + if((buffer[rx_ptr] == 0x0A) || (buffer[rx_ptr] == 0x0D)) // Test touche entrée en mode ASCII + { + buffer[rx_ptr] = 0; // Transforme le tableau en chaine de caractères + rx_ptr = 0; + rx_ok = 1; // Trame disponible pour décodage +// pc.printf("%s\n\r",buffer); // Echo + } + else { + rx_ptr++; + } + } + } + rx_ok = 0; +} + +void Envoi_GPS(void) { + + pc.printf("GPS: %s\n\r",buffer); +} + +void GPS_Init(void) { // Bloquer les tickers pour envoyer une commande + rx_ok = 0; + Select_Trame((char*)Trame_TXT_Off); + Select_Trame((char*)TRAME_GGA); +} + +struct gps { + char *trame; // $GPGGA + char *horaire; // 143512.000 + char *lat; + char *ns; + char *longi; + char *ew; + char *fix; // 0 ou V -> pas de Fix >1 ou A -> Fix + char *nb_sat; + char *prec; + char *alt; + float latitude; + float longitude; + uint16_t altitude; + char fixe; +} gps; + +// Décodage Trame NMEA GGA +void GPS_Decodage (void) { + + if(buffer[0] == '$' && buffer[5] == 'A') { +// pc.printf("GPS: %s\n\r",buffer); // Echo + + gps.trame = strtok(buffer, ","); + gps.horaire = strtok(NULL, ","); + + gps.lat = strtok(NULL, ","); + gps.latitude = atof(gps.lat); + gps.ns = strtok(NULL, ","); +// if(gps.ns == "S") { +// gps.latitude *= -1.0; +// } + gps.longi = strtok(NULL, ","); + gps.longitude = atof(gps.longi); + gps.ew = strtok(NULL, ","); +// if(gps.ew == "W") { +// gps.longitude *= -1.0; +// } + gps.fix = strtok(NULL, ","); + gps.fixe = atoi(gps.fix); + + gps.nb_sat = strtok(NULL, ","); + gps.prec = strtok(NULL, ","); + gps.alt = strtok(NULL, ","); + gps.altitude = atoi(gps.alt); + + if(gps.fixe) { +// Conversion en degrée et minute pour Google Maps + float degrees = trunc(gps.latitude / 100.0f); + float minutes = gps.latitude - (degrees * 100.0f); + gps.latitude = degrees + minutes / 60.0f; + + degrees = trunc(gps.longitude / 100.0f); + minutes = gps.longitude - (degrees * 100.0f); + gps.longitude = degrees + minutes / 60.0f; + + pc.printf("hms : %s\n",gps.horaire); + pc.printf("lat : %fN\n",gps.latitude); + pc.printf("long: %fE\n",gps.longitude); + pc.printf("alt : %d m\n",gps.altitude); + } + } +} +//============================================================================== +// Sélection de la trame GGA - +// Exemple : $GPGGA,143512.000,4347.7852,N,00418.9704,E,1,7,1.29,28.9,M,49.4,M,,*60 + +// UTC Position 143512.000 hhmmss.sss +// Latitude 4347.7852 ddmm.mmmm +// N/S Indicator N N=Nord - S=Sud +// Longitude 00418.9704 ddmm.mmmm +// W/E Indicator E W=Ouest - E=Est +// Position Fix Indicator 1 0-invalid 1-Valid +// Satellites Used 7 de 0 à 12 +// Précision 1.29 1-bon 9-mauvais +// Altitude 28.9 valeur +// Unité pour l'altitude M en mètre +// Autres informations +// Checksum *60 +//============================================================================== +// Sélection de la trame GLL - Géographic position - Latitude/Longitude +// Exemple : $GPGLL,3723.2475, N, 12158.3416, W, 161229.487, A*2C +//============================================================================== +// Sélection de la trame RMC - Utilisation pour les navires +// Exemple : $GPRMC,141147.000,A,4347.7885,N,00418.9737,E,0.00,350.58,280621,,,A*6D + +// UTC Position 141147.000 hhmmss.sss +// Fix Indicator A A-valid V-invalid +// Latitude 4347.7885 ddmm.mmmm +// N/S Indicator N N=Nord - S=Sud +// Longitude 00418.9737 ddmm.mmmm +// W/E Indicator E W=Ouest - E=Est +// Vitesse 0.00 en noeuds +// Route sur le fond 350.58 en degrés +// Date 280621 ddmmaa +// Autres informations +// Checksum *6D +//==============================================================================
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Jul 07 08:32:08 2021 +0000 @@ -0,0 +1,140 @@ +/******************************************************************************* + Université de Montpellier + NemoSpace IUT de Nîmes + IniSat Modèle 1 Version 2 +*******************************************************************************/ +// TP n°4 : Correction + +// Exo 1 : Lecture de la température +// Exo 2 : Sélection des trames GGA ou RMC +// Exo 3 : Décodage des coordonnées GPS + +// La lecture du GPS utilise une liaison série software + +#include "mbed.h" + +#include "platform/mbed_thread.h" +#include "system.h" +#include "user.h" +#include "soft_uart.h" +#include "gps.h" + +uint8_t etat, etat_mem; +uint16_t compteur; +float mes_accu; + +int main() +{ + Init_System(); + etat = 0; + Init_Soft_UART(); + thread_sleep_for(1000); + + while (1) { + thread_sleep_for(1); // Boucle toutes les 1 milliseconde environ + compteur++; +// Gestion des modes avec une machine d'états + switch (etat) { +/******************************************************************************/ +// Mode Init : Mise sous tension +// Initialisation du µC + case 0: + Init_User_Fonctions(); + thread_sleep_for(1000); + Stop_Led(); + GPS_Init(); + Start_Led(); + Set_Led(Ve); + thread_sleep_for(1000); + etat = 1; + break; +/******************************************************************************/ +// Mode Gestion : Gestion des actions +// Contrôle du système + case 1: + mes_accu = Mes_Bat(); + if(mes_accu < BAT_SEUIL_BAS_1) { + etat = 4; + Set_Led(Ro); + } else { + etat = 2; + Set_Led(Ve); + } + thread_sleep_for(1000); + break; +/******************************************************************************/ +// Mode Mission : Acquisition de données +// Mesure Batterie +// Mesure Courant faces solaires +// Stockage + case 2: + Lect_GPS(); + Mes_SP(); + Mes_Temp(); + mes_accu = Mes_Bat(); + if(mes_accu > BAT_SEUIL_HAUT_1) + { + etat = 3; + Set_Led(Ro_Ve); + } + else + { + etat = 1; + } +// thread_sleep_for(1000); + break; +/******************************************************************************/ +// Mode Radio : Transmission de données +// Mise en forme pour affichage + case 3: +// Envoi_GPS(); + GPS_Decodage(); + Envoi_Mes_Bat(); +// Envoi_Mes_SP(); +// Envoi_Mes_Temp(); + +// thread_sleep_for(1000); + etat = 1; + break; +/******************************************************************************/ +// Mode Survie : Attente recharge de l'accu + + case 4: + mes_accu = Mes_Bat(); + if(mes_accu < BAT_SEUIL_BAS_2) { + etat = 5; + Stop_User_Fonctions(); + } + + if(mes_accu > BAT_SEUIL_HAUT_1) { + etat = 1; + Set_Led(Ve); + } + break; +/******************************************************************************/ +// Mode Zombie : Coupure des consommateurs +// Passage en mode faible consommation +// Diminution de la fréquence du CPU +// Passage en mode Sleep + case 5: + sleep(); + mes_accu = Mes_Bat(); + if(mes_accu > BAT_SEUIL_HAUT_1) + etat = 0; + break; +/******************************************************************************/ + default: + etat = 0; + break; +/******************************************************************************/ + } // end switch +/* if(etat != etat_mem) // Debug des états + { + pc.printf("Etat_%d\r\n",etat); + etat_mem = etat; + }*/ + } // end while +} // end main +/******************************************************************************/ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Wed Jul 07 08:32:08 2021 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#cf4f12a123c05fcae83fc56d76442015cb8a39e9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system.h Wed Jul 07 08:32:08 2021 +0000 @@ -0,0 +1,27 @@ +/******************************************************************************* + system.h -> fichier de configuration + + Lignes en Entrées/Sorties + Lignes en Entrées analogiques + Lignes associées aux bus (série, I2C, SPI) +*******************************************************************************/ + +Serial pc(USBTX, USBRX); // Dialogue UART par USB à 9600 Baud sur carte Nucléo + +//DigitalOut DEL(LED1); // Ligne PB_3 sur la carte Nucléo +DigitalOut DEL_R(PB_0); // DEL rouge sur carte CPU +DigitalOut DEL_V(PB_1); // DEL verte sur carte CPU + +DigitalOut ctrl_reg(PA_12); // Controle du régulateur 3.3V sur carte EPS + +AnalogIn batin(PA_0); // Mesure tension batterie sur carte EPS +AnalogIn sp_1in(PA_6); // Mesure courant Solar Panel 1 sur carte EPS +AnalogIn sp_2in(PA_5); // Mesure courant Solar Panel 2 sur carte EPS + +// Divers seuils pour la batterie +#define BAT_SEUIL_HAUT_2 4.2f +#define BAT_SEUIL_HAUT_1 3.7f +#define BAT_SEUIL_BAS_1 3.5f +#define BAT_SEUIL_BAS_2 3.3f + +AnalogIn tempin(PA_1); // Mesute temperature sur carte Sensors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target.json Wed Jul 07 08:32:08 2021 +0000 @@ -0,0 +1,5 @@ +"target_overrides": { + "NUCLEO_L432KC": { + "target.clock_source": "USE_PLL_MSI" + } + } \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/user.h Wed Jul 07 08:32:08 2021 +0000 @@ -0,0 +1,120 @@ +/******************************************************************************* + user.h -> fichier de fonctions + + Gestion des 2 DELs de la carte CPU + Mesure tension batterie + Mesure courant panneaux solaires + Mesure température +*******************************************************************************/ +// Initialistion du µC, Tests divers +/** +* @param null +*/ +void Init_System(void) { +// Hello World + pc.printf("\r\nIniSat V2 : TP4\r\n\n"); + +// Test de l'horloge Systeme +// pc.printf("Horloge CPU a %d Hz\r\n", SystemCoreClock); +} +/******************************************************************************/ +// Gestion des 2 Dels de la carte CPU +Ticker Compteur_Led; +uint16_t cmpt_led; +uint8_t etat_led; +enum {Off, Ro, Ve, Ro_Ve} couleur; + +void Tache_Cmpt_Led(void) { + cmpt_led++; + if(cmpt_led >= 100) { // Période : 1 sec + cmpt_led = 0; + DEL_R = etat_led & 1; + } + else if(cmpt_led == 5) { + DEL_R = 0; + } + else if(cmpt_led == 50) { + DEL_V = etat_led & 2; + } + else if(cmpt_led == 60) { + DEL_V = 0; + } +} + +void Init_Led(void) { + cmpt_led = 0; + etat_led = 0; + Compteur_Led.attach(&Tache_Cmpt_Led,0.01); // 10ms +} + +void Start_Led(void) { + Compteur_Led.attach(&Tache_Cmpt_Led,0.01); // 10ms +} + +void Stop_Led(void) { + Compteur_Led.detach(); +} + +void Set_Led(uint8_t couleur) { + etat_led = couleur; +} +/******************************************************************************/ +// Mesure de la tension de la batterie +float mes_bat; + +float Mes_Bat(void) { + + mes_bat = batin.read()*4.59f + 0.31f; // 3.3 x 13.9/10 + 310mV(D2 carte EPS) + return mes_bat; +} + +void Envoi_Mes_Bat(void) { + + pc.printf("BAT: %.2f V\n",mes_bat); // Format pour Terminal (Putty) +// pc.printf("B%.2f\n",mes_bat); // Format pour Serial Data Plotter +} +/******************************************************************************/ +// Mesure des courants des 2 panneaux solaires +float mes_sp1, mes_sp2; + +void Mes_SP(void) { + + mes_sp1 = sp_1in.read()*165.0; // 3.3 x 50 + mes_sp2 = sp_2in.read()*165.0; // 3.3 x 50 +} + +void Envoi_Mes_SP(void) { + + pc.printf("SP1: %.1f mA\tSP2: %.1f mA\n",mes_sp1,mes_sp2); +} +/******************************************************************************/ +// Fonction pour initialiser les fonctions précédentes + +void Init_User_Fonctions(void) { + + ctrl_reg = 1; // Pour mettre sous tension le moniteur de courant des Solar Panels + Init_Led(); +} +// Fonction pour stopper les fonctions précédentes + +void Stop_User_Fonctions(void) { + + ctrl_reg = 0; + Stop_Led(); +} +/******************************************************************************/ +// Mesure de la température +float mes_temp; + +void Mes_Temp(void) { + + mes_temp = (tempin.read()*3.3f-0.5f)/0.01f; // 3.3 x -500mV +} + +void Envoi_Mes_Temp(void) { + + pc.printf("Temp: %.1f degC\r\n",mes_temp); // Mesure directe +// pc.printf("%.1f\n",mes_temp); // Supervision -> Format pour Serial Data Plotter +} +/******************************************************************************/ + \ No newline at end of file