Library 27- Read GPS data on STM32F4 devices
Recently I got a cheap GPS module from ebay, NEO-6M. They said that this is flight controller, but position fix is good only on really flat area. When I made a library, I’ve connected my SDcard to STM32F4 to save data, result are here.
To communicate with STM32F4 device, USART is in use. Most GPS modules have by default 9600 baudrate and 1Hz refresh rate of sending data. I got my GPS configured in 115200 baudrate and 5Hz refresh rate, so when you try example, make sure that you change your baudrate to correct value.
When you plug your GPS to power, it can take some time to get first valid signal from satellites. This time can be up to one minute, according to where you are trying to get signal.
If you are interested in HAL version of the same library, click here.
GPS Library
Features
- Parse GPS data
- Supported NMEA 0183 standard
- Works with GPGGA, GPRMC, GPGSA, GPGSV NMEA statements
- Version 1.1 – August 22, 2014
- Calculate distance between 2 coordinates
- Calculate bearing between 2 coordinates
- Allows you to select custom NMEA statements
Dependencies
- CMSIS
- STM32F4xx
- STM32F4xx RCC
- STM32F4xx GPIO
- STM32F4xx USART
- MISC
- TM
- TM USART
- TM GPIO
- attributes.h
- defines.h
- TM USART
GPS module | STM32F4 | Description |
---|---|---|
RX | PB6 | Receive line for GPS, actually not needed |
TX | PB7 | Transmit line for GPS, this is needed |
This pins are for USART1, if you want your custom USART, add this line below in your defines.h file and edit them:
1 2 3 |
/* Change settings if needed */ #define GPS_USART USART1 #define GPS_USART_PINSPACK TM_USART_PinsPack_2 |
My library basically checks to get all data that are need to display all possible data which library supports. For that, it needs 4 NMEA statements to be returned from GPS module:
- GPGGA: Global Positioning System Fix Data
- GPRMC: Recommended minimum specific GPS/Transit data
- GPGSA: GPS DOP and Active Satellites
- GPGSV: GPS Satellites in view
GPGGA and GPRMC should be returned from all GPS receivers, but others 2 are maybe not. Everything depends on GPS configuration. There are some tools on net, to change GPS module’s settings, like one here.
If for some reason your GPS module does not provide all of your statements, you will not be able to get all possible data. To disable any of your statements, copy statements below in your defines.h file and uncomment line you don’t want to use:
1 2 3 4 |
//#define GPS_DISABLE_GPGGA //Disable GPGGA statement //#define GPS_DISABLE_GPRMC //Disable GPRMC statement //#define GPS_DISABLE_GPGSA //Disable GPGSA statement //#define GPS_DISABLE_GPGSV //Disable GPGSV statement |
When you enable these defines, my library will ignore statements, which are disabled and response like we have new data.
Distance and bearing
These two options were added in version 1.1.
Distance between 2 points can not be provided from GPS receiver, so we have to calculate it. This is useful, if you have let’s say quadcopter and you want to know, how far you are from quad. FIrst coordinate will be quad’s current position from GPS and second point will be set before you start with your flight.
If you want to make let’s say “Return home” function on quadcopter, bearing comes to be very useful. GPS module tells you your direction (included in library) where you are currently moving. Still, first coordinate is from quad’s GPS receiver, and second is where quad started with flight. When you activate “Return home” function, quad will know how far he is from “home” and in which direction (bearing) he has to move according to the north. Then, you just have to compare your calculated bearing with actual direction provided from GPS. And you will know, if he needs to go more left, right, etc.
Custom GPS statements
Library supports by default 4 statements. It assumes that every GPS module should output these 4 statements. But it may happen, that your module outputs data that you need, but are not available with my library by default.
Here is why custom GPS statements come handy. It is possible to define custom statements which will be parsed as strings from GPS receiver directly to user.
For example, let’s say that your module outputs $GPRMB sentence (navigation). From that statement, you want to get “Steering value”, which can be “L” or “R” for Left or Right. Steering value is part 3 inside GPRMB sentence. If you want to include this into your output, you can do this:
1 2 3 4 5 |
/* Set variable */ TM_GPS_Custom_t* GPRMB_3_Pointer; /* $GPRMB statement, term number 3 = Steering value */ GPRMB_3_Pointer = TM_GPS_AddCustom(&GPS_Data, "$GPRMB", 3); |
This statement is now added into main GPS_Data structure and also, pointer to small GPRMB.3 structure is returned.
You just have to make sure, that in this case, GPRMB statement is really returned from module. If module will not return this statement, you will not be able to read anything from library because it will never happen that everything will be updated before new data are available.
How to handle that data, you should look at bottom example about custom GPS statements.
Functions, structs and enumerations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
/** * @brief GPS Result enumeration */ typedef enum { TM_GPS_Result_NewData, /*!< New data are available to operate with */ TM_GPS_Result_OldData, /*!< We don't have new data available yet */ TM_GPS_Result_FirstDataWaiting, /*!< We are waiting for first data from GPS module */ } TM_GPS_Result_t; /** * @brief Speed conversion enumeration * @note Speed from GPS is in knots, use TM_GPS_ConvertSpeed() to convert to useable value */ typedef enum { /* Metric */ TM_GPS_Speed_KilometerPerSecond, /*!< Convert speed to kilo meters per second */ TM_GPS_Speed_MeterPerSecond, /*!< Convert speed to meters per second */ TM_GPS_Speed_KilometerPerHour, /*!< Convert speed to kilo meters per hour */ TM_GPS_Speed_MeterPerMinute, /*!< Convert speed to meter per minute */ /* Imperial */ TM_GPS_Speed_MilePerSecond, /*!< Convert speed to miles per second */ TM_GPS_Speed_MilePerHour, /*!< Convert speed to miles per hour */ TM_GPS_Speed_FootPerSecond, /*!< Convert speed to foots per second */ TM_GPS_Speed_FootPerMinute, /*!< Convert speed to foots per minute */ /* For Runners and Joggers */ TM_GPS_Speed_MinutePerKilometer, /*!< Convert speed to minutes per kilo meter */ TM_GPS_Speed_SecondPerKilometer, /*!< Convert speed to seconds per kilo meter */ TM_GPS_Speed_SecondPer100Meters, /*!< Convert speed to seconds per 100 meters */ TM_GPS_Speed_MinutePerMile, /*!< Convert speed to minutes per mile */ TM_GPS_Speed_SecondPerMile, /*!< Convert speed to seconds per mile */ TM_GPS_Speed_SecondPer100Yards, /*!< Convert speed to seconds per 100 yards */ /* Nautical */ TM_GPS_Speed_SeaMilePerHour, /*!< Convert speed to sea miles per hour */ } TM_GPS_Speed_t; /** * @brief GPS float structure * @note GPS has longitude, latitude, altitude, etc.. in float format. * * But, if you want to make a tracker and save data to SD card, there is a problem, because FATFS library breaks %f with sprintf() function. * * For that purpose I made a new function TM_GPS_ConvertFloat() which converts float number to an integer and decimal part. */ typedef struct { int32_t Integer; /*!< Integer part of float number. */ uint32_t Decimal; /*!< Decimal part of float number, in integer format. */ } TM_GPS_Float_t; /** * @brief Date struct for GPS date */ typedef struct { uint8_t Date; /*!< Date in month from GPS. */ uint8_t Month; /*!< Month from GPS. */ uint8_t Year; /*!< Year from GPS. */ } TM_GPS_Date_t; /** * @brief Time structure for GPS */ typedef struct { uint8_t Hours; /*!< Hours from GPS time. */ uint8_t Minutes; /*!< Minutes from GPS time. */ uint8_t Seconds; /*!< Seconds from GPS time. */ uint8_t Hundredths; /*!< Hundredths from GPS time. */ } TM_GPS_Time_t; /** * @brief Satellite in view description structure */ typedef struct { uint8_t ID; /*!< SV PRN number */ uint8_t Elevation; /*!< Elevation in degrees, 90 maximum */ uint16_t Azimuth; /*!< Azimuth, degrees from true north, 000 to 359 */ uint8_t SNR; /*!< SNR, 00-99 dB (0 when not tracking) */ } TM_GPS_Satellite_t; /** * @brief Custom NMEA statement and term, selected by user */ typedef struct { char Statement[7]; /*!< Statement value, including "$" at beginning. For example, "$GPRMC" */ uint8_t TermNumber; /*!< Term number position inside statement */ char Value[15]; /*!< Value from GPS receiver at given statement and term number will be stored here. @note Value will not be converted to number if needed, but will stay as a character */ uint8_t Updated; /*!< Updated flag. If this parameter is set to 1, then new update has been made. Meant for private use */ } TM_GPS_Custom_t; /** * @brief Main GPS data structure */ typedef struct { #ifndef GPS_DISABLE_GPGGA float Latitude; /*!< Latitude position from GPS, -90 to 90 degrees response. */ float Longitude; /*!< Longitude position from GPS, -180 to 180 degrees response. */ uint8_t Satellites; /*!< Number of satellites in use for GPS position. */ uint8_t Fix; /*!< GPS fix; 0: Invalid; 1: GPS Fix; 2: DGPS Fix. */ float Altitude; /*!< Altitude above the sea. */ TM_GPS_Time_t Time; /*!< Current time from GPS. @ref TM_GPS_Time_t. */ #endif #ifndef GPS_DISABLE_GPRMC TM_GPS_Date_t Date; /*!< Current data from GPS. @ref TM_GPS_Date_t. */ float Speed; /*!< Speed in knots from GPS. */ uint8_t Validity; /*!< GPS validation; 1: valid; 0: invalid. */ float Direction; /*!< Course on the ground in relation to North. */ #endif #ifndef GPS_DISABLE_GPGSA float HDOP; /*!< Horizontal dilution of precision. */ float PDOP; /*!< Position dilution od precision. */ float VDOP; /*!< Vertical dilution of precision. */ uint8_t FixMode; /*!< Current fix mode in use:; 1: Fix not available; 2: 2D; 3: 3D. */ uint8_t SatelliteIDs[12]; /*!< Array with IDs of satellites in use. Only first data are valid, so if you have 5 satellites in use, only SatelliteIDs[4:0] are valid */ #endif #ifndef GPS_DISABLE_GPGSV uint8_t SatellitesInView; /*!< Number of satellites in view */ TM_GPS_Satellite_t SatDesc[30]; /*!< Description of each satellite in view */ #endif TM_GPS_Result_t Status; /*!< GPS result. This parameter is value of @ref TM_GPS_Result_t */ TM_GPS_Custom_t* CustomStatements[GPS_CUSTOM_NUMBER]; /*!< Array of pointers for custom GPS NMEA statements, selected by user. You can use @ref GPS_CUSTOM_NUMBER number of custom statements */ uint8_t CustomStatementsCount; /*!< Number of custom GPS statements selected by user */ } TM_GPS_t; /* Backward compatibility */ typedef TM_GPS_t TM_GPS_Data_t; /** * @brief GPS Distance and bearing struct */ typedef struct { float Latitude1; /*!< Latitude of starting point. */ float Longitude1; /*!< Longitude of starting point. */ float Latitude2; /*!< Latitude of ending point. */ float Longitude2; /*!< Longitude of ending point. */ float Distance; /*!< Distance between 2 points which will be calculated. */ float Bearing; /*!< Bearing from start to stop point according to North. */ } TM_GPS_Distance_t; /** * @} */ /** * @defgroup TM_GPS_Functions * @brief Library Functions * @{ */ /** * @brief Initializes GPS and USART peripheral * @param *GPS_Data: Pointer to @ref TM_GPS_t structure to set default values * @param baudrate: Specify GPS baudrate for USART. Most common are 9600 or 115200 bauds * @note GPS baudrate can have other values. Check GPS datasheet for proper info. * @retval None */ void TM_GPS_Init(TM_GPS_t* GPS_Data, uint32_t baudrate); /** * @brief Update GPS data. * @note This function must be called periodically, as fast as possible. * It basically checks if data is available on GPS USART and parse it to useful data for user. * @note - When you first call this function and there is not available data from GPS, this function will return @ref TM_GPS_Result_FirstTimeWaiting. * - This will be returning all the time we don't have any useful data. * - When first time useful data is received from GPS (everything parsed), @ref TM_GPS_Result_NewData will be returned. * - When we have already new data, next time we call this function, @ref TM_GPS_Result_OldData will be returning until we don't receive new packet of useful data. * @note If you are making GPS logger, then when you receive @ref TM_GPS_Result_NewData it is time to save your data. * @param *GPS_Data: Pointer to working @ref TM_GPS_t structure * @retval Returns value of @ref TM_GPS_Result_t structure */ TM_GPS_Result_t TM_GPS_Update(TM_GPS_t* GPS_Data); /** * @brief Converts speed in knots (from GPS) to user selectable speed * @param speedInKnots: float value from GPS module * @param toSpeed: Select to which speed you want conversion from knot. This parameter ca be a value of TM_GPS_Speed_t enumeration. * @retval Calculated speed from knots to user selectable format */ float TM_GPS_ConvertSpeed(float SpeedInKnots, TM_GPS_Speed_t toSpeed); /** * @brief Converts float number into integer and decimal part * @param num: Float number to split into 2 parts * @param *Float_Data: Pointer to TM_GPS_Float_t structure where to save result * @param decimals: Number of decimal places for conversion * @note Example: You have number 15.002 in float format. * - You want to split this to integer and decimal part with 6 decimal places. * - Call @ref TM_GPS_ConvertFloat(15.002, &Float_Struct, 6); * - Result will be: Integer: 15; Decimal: 2000 (0.002 * 10^6) * @retval None */ void TM_GPS_ConvertFloat(float num, TM_GPS_Float_t* Float_Data, uint8_t decimals); /** * @brief Calculates distance between 2 coordinates on earth and bearing from start to end point in relation to the north * @param *Distance_Data: Pointer to @ref TM_GPS_Distance_t structure with latitude and longitude set values * @note Calculation results will be saved in *Distance_Data @ref TM_GPS_Distance_t structure * @retval None */ void TM_GPS_DistanceBetween(TM_GPS_Distance_t* Distance_Data); /** * @brief Adds custom GPG statement to array of user selectable statements. * Array is available to user using @ref TM_GPS_t workign structure * @note Functions uses @ref malloc() function to allocate memory, so make sure you have enough heap memory available. * @note Also note, that your GPS receiver HAVE TO send statement type you use in this function, or * @ref TM_GPS_Update() function will always return that there is not data available to read. * @param *GPS_Data: Pointer to working @ref TM_GPS_t structure * @param *GPG_Statement: String of NMEA starting line address, including "$" at beginning * @param TermNumber: Position in NMEA statement * @retval Success status: * - NULL: Malloc() failed or you reached limit of user selectable custom statements: * - > NULL: Function succeded, pointer to @ref TM_GPS_Custom_t structure */ TM_GPS_Custom_t * TM_GPS_AddCustom(TM_GPS_t* GPS_Data, char* GPG_Statement, uint8_t TermNumber); /** * @} */ |
Example
- GPS data are displayed to to user on USART3 at 115200 bauds
- TX pin is PB10
Example below produces something similar to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
/** * Keil project for GPS * * Before you start, select your target, on the right of the "Load" button * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision 5 * @packs STM32F4xx Keil packs version 2.2.0 or greater required * @stdperiph STM32F4xx Standard peripheral drivers version 1.4.0 or greater required * * Make sure you have correct baudrate set for your GPS */ #include "defines.h" #include "stm32f4xx.h" #include "tm_stm32f4_gps.h" #include "tm_stm32f4_delay.h" #include <stdio.h> int main(void) { /* Variables used */ TM_GPS_Data_t GPS_Data; TM_GPS_Result_t result, current; TM_GPS_Float_t GPS_Float; TM_GPS_Distance_t GPS_Distance; char buffer[40]; uint8_t i; float temp; /* Initialize system */ SystemInit(); /* Delay init */ TM_DELAY_Init(); /* Initialize GPS on 115200 baudrate */ TM_GPS_Init(&GPS_Data, 115200); /* Initialize USART3 for debug */ /* TX = PB10 */ TM_USART_Init(USART3, TM_USART_PinsPack_1, 115200); /* Version 1.1 added */ /* Set two test coordinates */ GPS_Distance.Latitude1 = 48.300215; GPS_Distance.Longitude1 = -122.285903; GPS_Distance.Latitude2 = 45.907813; GPS_Distance.Longitude2 = 56.659407; /* Calculate distance and bearing between 2 pointes */ TM_GPS_DistanceBetween(&GPS_Distance); /* Convert float number */ TM_GPS_ConvertFloat(GPS_Distance.Distance, &GPS_Float, 6); sprintf(buffer, "Distance is: %d.%06d meters\n", GPS_Float.Integer, GPS_Float.Decimal); TM_USART_Puts(USART3, buffer); TM_GPS_ConvertFloat(GPS_Distance.Bearing, &GPS_Float, 6); sprintf(buffer, "Bearing is: %d.%06d degrees\n\n", GPS_Float.Integer, GPS_Float.Decimal); TM_USART_Puts(USART3, buffer); /* Reset counter */ TM_DELAY_SetTime(0); while (1) { /* Update GPR data */ /* Call this as faster as possible */ result = TM_GPS_Update(&GPS_Data); /* If we didn't receive any useful data in the start */ if (result == TM_GPS_Result_FirstDataWaiting && TM_DELAY_Time() > 3000) { /* If we didn't receive nothing within 3 seconds */ TM_DELAY_SetTime(0); /* Display data on USART */ TM_USART_Puts(USART3, "\nNothing received after 3 seconds. Is your GPS connected and baudrate set correct?\n"); TM_USART_Puts(USART3, "Most GPS receivers has by default 9600 baudrate and 1Hz refresh rate. Check your settings!\n\n"); } /* If we have any unread data */ if (result == TM_GPS_Result_NewData) { /* We received new packet of useful data from GPS */ current = TM_GPS_Result_NewData; /* Is GPS signal valid? */ if (GPS_Data.Validity) { /* If you want to make a GPS tracker, now is the time to save your data on SD card */ /* We have valid GPS signal */ TM_USART_Puts(USART3, "New received data have valid GPS signal\n"); TM_USART_Puts(USART3, "---------------------------------------\n"); #ifndef GPS_DISABLE_GPGGA /* GPGGA data */ TM_USART_Puts(USART3, "GPGGA statement:\n"); /* Latitude */ /* Convert float to integer and decimal part, with 6 decimal places */ TM_GPS_ConvertFloat(GPS_Data.Latitude, &GPS_Float, 6); sprintf(buffer, " - Latitude: %d.%d\n", GPS_Float.Integer, GPS_Float.Decimal); TM_USART_Puts(USART3, buffer); /* Longitude */ /* Convert float to integer and decimal part, with 6 decimal places */ TM_GPS_ConvertFloat(GPS_Data.Longitude, &GPS_Float, 6); sprintf(buffer, " - Longitude: %d.%d\n", GPS_Float.Integer, GPS_Float.Decimal); TM_USART_Puts(USART3, buffer); /* Satellites in use */ sprintf(buffer, " - Sats in use: %02d\n", GPS_Data.Satellites); TM_USART_Puts(USART3, buffer); /* Current time */ sprintf(buffer, " - UTC Time: %02d.%02d.%02d:%02d\n", GPS_Data.Time.Hours, GPS_Data.Time.Minutes, GPS_Data.Time.Seconds, GPS_Data.Time.Hundredths); TM_USART_Puts(USART3, buffer); /* Fix: 0 = invalid, 1 = GPS, 2 = DGPS */ sprintf(buffer, " - Fix: %d\n", GPS_Data.Fix); TM_USART_Puts(USART3, buffer); /* Altitude */ /* Convert float to integer and decimal part, with 6 decimal places */ TM_GPS_ConvertFloat(GPS_Data.Altitude, &GPS_Float, 6); sprintf(buffer, " - Altitude: %3d.%06d\n", GPS_Float.Integer, GPS_Float.Decimal); TM_USART_Puts(USART3, buffer); #endif #ifndef GPS_DISABLE_GPRMC /* GPRMC data */ TM_USART_Puts(USART3, "GPRMC statement:\n"); /* Current date */ sprintf(buffer, " - Date: %02d.%02d.%04d\n", GPS_Data.Date.Date, GPS_Data.Date.Month, GPS_Data.Date.Year + 2000); TM_USART_Puts(USART3, buffer); /* Current speed in knots */ TM_GPS_ConvertFloat(GPS_Data.Speed, &GPS_Float, 6); sprintf(buffer, " - Speed in knots: %d.%06d\n", GPS_Float.Integer, GPS_Float.Decimal); TM_USART_Puts(USART3, buffer); /* Current speed in km/h */ temp = TM_GPS_ConvertSpeed(GPS_Data.Speed, TM_GPS_Speed_KilometerPerHour); TM_GPS_ConvertFloat(temp, &GPS_Float, 6); sprintf(buffer, " - Speed in km/h: %d.%06d\n", GPS_Float.Integer, GPS_Float.Decimal); TM_USART_Puts(USART3, buffer); TM_GPS_ConvertFloat(GPS_Data.Direction, &GPS_Float, 3); sprintf(buffer, " - Direction: %3d.%03d\n", GPS_Float.Integer, GPS_Float.Decimal); TM_USART_Puts(USART3, buffer); #endif #ifndef GPS_DISABLE_GPGSA /* GPGSA data */ TM_USART_Puts(USART3, "GPGSA statement:\n"); /* Horizontal dilution of precision */ TM_GPS_ConvertFloat(GPS_Data.HDOP, &GPS_Float, 2); sprintf(buffer, " - HDOP: %2d.%02d\n", GPS_Float.Integer, GPS_Float.Decimal); TM_USART_Puts(USART3, buffer); /* Vertical dilution of precision */ TM_GPS_ConvertFloat(GPS_Data.VDOP, &GPS_Float, 2); sprintf(buffer, " - VDOP: %2d.%02d\n", GPS_Float.Integer, GPS_Float.Decimal); TM_USART_Puts(USART3, buffer); /* Position dilution of precision */ TM_GPS_ConvertFloat(GPS_Data.PDOP, &GPS_Float, 2); sprintf(buffer, " - PDOP: %2d.%02d\n", GPS_Float.Integer, GPS_Float.Decimal); TM_USART_Puts(USART3, buffer); /* Current fix mode in use */ sprintf(buffer, " - Fix mode: %d\n", GPS_Data.FixMode); TM_USART_Puts(USART3, buffer); /* Display IDs of satellites in use */ TM_USART_Puts(USART3, "- ID's of used satellites: "); for (i = 0; i < GPS_Data.Satellites; i++) { if (i < (GPS_Data.Satellites - 1)) { sprintf(buffer, "%d,", GPS_Data.SatelliteIDs[i]); } else { sprintf(buffer, "%d\n", GPS_Data.SatelliteIDs[i]); } TM_USART_Puts(USART3, buffer); } #endif #ifndef GPS_DISABLE_GPGSV /* GPGSV data */ TM_USART_Puts(USART3, "GPGSV statement:\n"); /* Satellites in view */ sprintf(buffer, " - Satellites in view: %d\n", GPS_Data.SatellitesInView); TM_USART_Puts(USART3, buffer); #endif TM_USART_Puts(USART3, "---------------------------------------\n"); } else { /* GPS signal is not valid */ TM_USART_Puts(USART3, "New received data haven't valid GPS signal!\n"); } } else if (result == TM_GPS_Result_FirstDataWaiting && current != TM_GPS_Result_FirstDataWaiting) { current = TM_GPS_Result_FirstDataWaiting; TM_USART_Puts(USART3, "Waiting first data from GPS!\n"); } else if (result == TM_GPS_Result_OldData && current != TM_GPS_Result_OldData) { current = TM_GPS_Result_OldData; /* We already read data, nothing new was received from GPS */ } } } |
Example 2
- Works on STM32F429-Discovery with included LCD
- Default baudrate for GPS module is 115200
- PA10 is used for receive data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
/** * Keil project for GPS example on STM32F429-Discovery board * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision 5 * * Make sure you have correct baudrate set for your GPS */ #include "defines.h" #include "stm32f4xx.h" #include "tm_stm32f4_gps.h" #include "tm_stm32f4_delay.h" #include "tm_stm32f4_ili9341.h" #include "tm_stm32f4_disco.h" #include <stdio.h> #define START_Y 5 int main(void) { /* Variables used */ TM_GPS_Data_t GPS_Data; TM_GPS_Result_t result, current; TM_GPS_Float_t GPS_Float; TM_GPS_Distance_t GPS_Distance; char buffer[40]; uint8_t i; float temp; uint8_t iOff; /* Initialize system */ SystemInit(); /* Delay init */ TM_DELAY_Init(); /* Initialize leds */ TM_DISCO_LedInit(); /* Initialize GPS on 115200 baudrate */ TM_GPS_Init(&GPS_Data, 115200); /* Initialize ili9341 LCD on STM32F429-Discovery board */ TM_ILI9341_Init(); /* Rotate LCD */ TM_ILI9341_Rotate(TM_ILI9341_Orientation_Portrait_2); /* Go to the begginning of LCD */ iOff = 0; /* Version 1.1 added */ /* Set two test coordinates */ /* from Ljubljana */ GPS_Distance.Latitude1 = 46.050513; GPS_Distance.Longitude1 = 14.512873; /* to New York */ GPS_Distance.Latitude2 = 40.711096; GPS_Distance.Longitude2 = -74.007529; /* Display location */ TM_ILI9341_Puts(10, START_Y + 11 * iOff++, "Ljubljana -> New York", &TM_Font_7x10, 0x0000, 0xFFFF); /* Calculate distance and bearing between 2 pointes */ TM_GPS_DistanceBetween(&GPS_Distance); /* Convert float number */ TM_GPS_ConvertFloat(GPS_Distance.Distance, &GPS_Float, 1); sprintf(buffer, " - Distance: %d.%1d meters", GPS_Float.Integer, GPS_Float.Decimal); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); TM_GPS_ConvertFloat(GPS_Distance.Bearing, &GPS_Float, 3); sprintf(buffer, " - Bearing: %d.%03d degrees", GPS_Float.Integer, GPS_Float.Decimal); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Delay 5s */ Delayms(5000); /* Clear screen */ TM_ILI9341_Fill(0xFFFF); /* Go to the begginning of LCD */ iOff = 0; /* Reset counter */ TM_DELAY_SetTime(0); while (1) { /* Update GPR data */ /* Call this as faster as possible */ result = TM_GPS_Update(&GPS_Data); /* If we didn't receive any useful data in the start */ if (result == TM_GPS_Result_FirstDataWaiting && TM_DELAY_Time() > 3000000) { /* If we didn't receive nothing within 3 seconds */ TM_DELAY_SetTime(0); /* Display data on LCD */ TM_ILI9341_Puts(10, START_Y + 11 * iOff++, "Check your GPS receiver!", &TM_Font_7x10, 0x0000, 0xFFFF); } /* If we have any unread data */ if (result == TM_GPS_Result_NewData) { /* We received new packet of useful data from GPS */ current = TM_GPS_Result_NewData; /* Go to the begginning of LCD */ iOff = 0; /* Is GPS signal valid? */ if (GPS_Data.Validity) { /* If you want to make a GPS tracker, now is the time to save your data on SD card */ /* Toggle GREEN LED */ TM_DISCO_LedToggle(LED_GREEN); /* We have valid GPS signal */ #ifndef GPS_DISABLE_GPGGA /* Latitude */ /* Convert float to integer and decimal part, with 6 decimal places */ TM_GPS_ConvertFloat(GPS_Data.Latitude, &GPS_Float, 6); sprintf(buffer, " - Latitude: %d.%d", GPS_Float.Integer, GPS_Float.Decimal); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Longitude */ /* Convert float to integer and decimal part, with 6 decimal places */ TM_GPS_ConvertFloat(GPS_Data.Longitude, &GPS_Float, 6); sprintf(buffer, " - Longitude: %d.%d", GPS_Float.Integer, GPS_Float.Decimal); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Satellites in use */ sprintf(buffer, " - Sats in use: %02d", GPS_Data.Satellites); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Current time */ sprintf(buffer, " - UTC Time: %02d.%02d.%02d:%02d", GPS_Data.Time.Hours, GPS_Data.Time.Minutes, GPS_Data.Time.Seconds, GPS_Data.Time.Hundredths); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Fix: 0 = invalid, 1 = GPS, 2 = DGPS */ sprintf(buffer, " - Fix: %d", GPS_Data.Fix); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Altitude */ /* Convert float to integer and decimal part, with 6 decimal places */ TM_GPS_ConvertFloat(GPS_Data.Altitude, &GPS_Float, 6); sprintf(buffer, " - Altitude: %3d.%06d", GPS_Float.Integer, GPS_Float.Decimal); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); #endif #ifndef GPS_DISABLE_GPRMC /* Current date */ sprintf(buffer, " - Date: %02d.%02d.%04d", GPS_Data.Date.Date, GPS_Data.Date.Month, GPS_Data.Date.Year + 2000); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Current speed in knots */ TM_GPS_ConvertFloat(GPS_Data.Speed, &GPS_Float, 6); sprintf(buffer, " - Speed in knots: %2d.%06d", GPS_Float.Integer, GPS_Float.Decimal); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Current speed in km/h */ temp = TM_GPS_ConvertSpeed(GPS_Data.Speed, TM_GPS_Speed_KilometerPerHour); TM_GPS_ConvertFloat(temp, &GPS_Float, 6); sprintf(buffer, " - Speed in km/h: %2d.%06d", GPS_Float.Integer, GPS_Float.Decimal); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); TM_GPS_ConvertFloat(GPS_Data.Direction, &GPS_Float, 3); sprintf(buffer, " - Direction: %3d.%03d", GPS_Float.Integer, GPS_Float.Decimal); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); #endif #ifndef GPS_DISABLE_GPGSA /* Horizontal dilution of precision */ TM_GPS_ConvertFloat(GPS_Data.HDOP, &GPS_Float, 2); sprintf(buffer, " - HDOP: %2d.%02d", GPS_Float.Integer, GPS_Float.Decimal); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Vertical dilution of precision */ TM_GPS_ConvertFloat(GPS_Data.VDOP, &GPS_Float, 2); sprintf(buffer, " - VDOP: %2d.%02d", GPS_Float.Integer, GPS_Float.Decimal); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Position dilution of precision */ TM_GPS_ConvertFloat(GPS_Data.PDOP, &GPS_Float, 2); sprintf(buffer, " - PDOP: %2d.%02d", GPS_Float.Integer, GPS_Float.Decimal); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Current fix mode in use */ sprintf(buffer, " - Fix mode: %d", GPS_Data.FixMode); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); /* Display IDs of satellites in use */ sprintf(buffer, "Sats ids: "); for (i = 0; i < GPS_Data.Satellites; i++) { if (i < (GPS_Data.Satellites - 1)) { sprintf(buffer, "%s%d,", buffer, GPS_Data.SatelliteIDs[i]); } else { sprintf(buffer, "%s%d", buffer, GPS_Data.SatelliteIDs[i]); } } TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); #endif #ifndef GPS_DISABLE_GPGSV /* Satellites in view */ sprintf(buffer, " - Satellites in view: %02d", GPS_Data.SatellitesInView); TM_ILI9341_Puts(10, START_Y + 11 * iOff++, buffer, &TM_Font_7x10, 0x0000, 0xFFFF); #endif } else { /* Clear screen */ TM_ILI9341_Fill(0xFFFF); /* Go to the beginning of LCD */ iOff = 0; /* Toggle RED LED */ TM_DISCO_LedToggle(LED_RED); /* GPS signal is not valid */ TM_ILI9341_Puts(10, START_Y + 11 * iOff++, "New received data haven't valid GPS signal!", &TM_Font_7x10, 0x0000, 0xFFFF); } } else if (result == TM_GPS_Result_FirstDataWaiting && current != TM_GPS_Result_FirstDataWaiting) { current = TM_GPS_Result_FirstDataWaiting; TM_ILI9341_Puts(10, START_Y + 11 * iOff++, "Waiting first data from GPS!", &TM_Font_7x10, 0x0000, 0xFFFF); } else if (result == TM_GPS_Result_OldData && current != TM_GPS_Result_OldData) { current = TM_GPS_Result_OldData; /* We already read data, nothing new was received from GPS */ } } } |
Example 3
- Shows how to use custom NMEA statements for your GPS module
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
/** * Keil project for GPS custom statements * * Before you start, select your target, on the right of the "Load" button * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision 5 * @packs STM32F4xx Keil packs version 2.2.0 or greater required * @stdperiph STM32F4xx Standard peripheral drivers version 1.4.0 or greater required * * Make sure you have correct baudrate set for your GPS */ #include "defines.h" #include "stm32f4xx.h" #include "tm_stm32f4_gps.h" #include "tm_stm32f4_delay.h" #include "tm_stm32f4_usart.h" #include <stdio.h> /* Variables used */ TM_GPS_Data_t GPS_Data; TM_GPS_Result_t result, current; TM_GPS_Float_t GPS_Float; TM_GPS_Distance_t GPS_Distance; TM_GPS_Custom_t *GPRMC, *GPGLL, *GPGSA; int main(void) { uint8_t i; /* Initialize system */ SystemInit(); /* Delay init */ TM_DELAY_Init(); /* Initialize GPS on 115200 baudrate */ TM_GPS_Init(&GPS_Data, 115200); /* Initialize USART2 for debug */ /* TX = PA2 */ TM_USART_Init(USART2, TM_USART_PinsPack_1, 115200); /* Register custom GPGxx statements */ /* $GPRMC statement, term number 7 = Speed over ground in knots */ GPRMC = TM_GPS_AddCustom(&GPS_Data, "$GPRMC", 7); /* $GPGLL statement, term number 1 = Current latitude */ GPGLL = TM_GPS_AddCustom(&GPS_Data, "$GPGLL", 1); /* $GPGSA statement, term number 1 = M = Manual, forced to operate in 2D or 3D A=Automatic, 3D/2D */ GPGSA = TM_GPS_AddCustom(&GPS_Data, "$GPGSA", 1); /* Add here more custom tags you want */ /* ... */ /* Reset counter */ TM_DELAY_SetTime(0); while (1) { /* Update GPR data */ /* Call this as faster as possible */ result = TM_GPS_Update(&GPS_Data); /* If we have any unread data */ if (result == TM_GPS_Result_NewData) { /* We received new packet of useful data from GPS */ current = TM_GPS_Result_NewData; /* Is GPS signal valid? */ if (GPS_Data.Validity) { /* If you want to make a GPS tracker, now is the time to save your data on SD card */ /* We have valid GPS signal */ printf("New received data have valid GPS signal\n"); printf("---------------------------------------\n"); /* We have all data from GPS_Data structure valid, you can do here what you want */ /* We will in this example show only custom data to user */ /* Print custom statements */ printf("Custom statements defined by user:\n"); /* Go through all custom statements */ for (i = 0; i < GPS_Data.CustomStatementsCount; i++) { printf(" - Statement: %s; TermNumber: %d; Value: %s\n", GPS_Data.CustomStatements[i]->Statement, /*!< Statement value */ GPS_Data.CustomStatements[i]->TermNumber, /*!< Term number */ GPS_Data.CustomStatements[i]->Value /*!< Value from GPS receiver */ ); } /* You can do it this way too for all your custom statements separatelly */ printf(" - Statement2: %s; TermNumber: %d; Value: %s\n", GPRMC->Statement, GPRMC->TermNumber, GPRMC->Value ); printf("---------------------------------------\n"); } else { /* GPS signal is not valid */ printf("New received data haven't valid GPS signal!\n"); } } else if (result == TM_GPS_Result_FirstDataWaiting && current != TM_GPS_Result_FirstDataWaiting) { current = TM_GPS_Result_FirstDataWaiting; printf("Waiting first data from GPS!\n"); } else if (result == TM_GPS_Result_OldData && current != TM_GPS_Result_OldData) { current = TM_GPS_Result_OldData; /* We already read data, nothing new was received from GPS */ } } } /* printf handler */ int fputc(int ch, FILE* fil) { /* Send over USART */ TM_USART_Putc(USART2, ch); /* Return character */ return ch; } |
View projects at Github, download library below.
Recent comments