1. GPS¶
At present, the GPS module model we have tested is the BH-ATGM332D module.
1.1. BH-ATGM332D Introduction¶
BH-ATGM332D is a high-performance, low-power GPS and Beidou dual-mode positioning module designed by Embedfire. It adopts the ATGM332D-5N-31 module solution of Zhongke Microelectronics Company. It can output GPS and Beidou positioning information to the microcontroller system and computer through the serial port. It is simple and convenient to use. Its appearance is shown in the figure below.
BH-ATGM332D module pin description is as follows:
The resources of the BH-ATGM332D module are as follows:
The BH-ATGM332D module and its matching active antenna are connected as follows:
1.2. Test BH-ATGM332D¶
This experiment is demonstrated with the LubanCat-1N board. The operation of other boards is similar to this experiment, so we won’t go into details here. The test system is Debian, and Ubuntu is similar.
1.2.1. Hardware wiring¶
The test uses the serial port on pin 8 and pin 10 on the board. For the specific corresponding serial port number, please view the 40PIN pin diagram.
“RK356x series board 40PIN pin diagram (LubanCat Zero, 1, 2)”
“RK3588 series board 40PIN pin diagram (LubanCat 4, 5)”
The wiring between Lubanmao 1N and GPS module is as follows:
Lubancat -------- GPS module
5V(4) -------- VCC
GND(6) -------- GND
UART_RX(10) -------- TXD
UART_TX(8) -------- RXD
1.2.2. Enable UART serial port¶
From the above pin diagram, we can see that pins 8 and 10 of the Lubancat 1N board correspond to UART3_M1. If you need to use the GPS module, you need to open the /boot/uEnv.txt file to enable the serial port 3 device tree plug-in.
2、Restart the Lubancat.
3、After restarting, check whether there is a newly opened serial device in the dev directory:
ls /dev/tty*
ls /dev/ttyS*
提示
When /dev/ttyS3 exists, it means that the serial port 3 device has been opened.
1.2.3. Verify that the module is working properly¶
To verify whether the module is working, first check whether the power supply is normal and connect according to the above hardware wiring. The LED light of the BH-ATGM332D module will light up.
2、After ensuring that the power supply of the module is normal, enter the following command in the terminal to monitor the information sent by the module.
cat /dev/ttyS3
If the following content is output, it means that the module is working normally:
Pay attention to the input content $GPTXT,01,01,01,ANTENNA OK*35
, which indicates that the module is running normally. Of course, it may also be other situations, such as:
The three states in the picture are open circuit (OPEN), SHORT (short circuit) and OK (normal). Please ensure that the antenna is in the OK state when testing.
If the output data is as shown in the figure below, it means that the module cannot search for satellite signals.
提示
When the module has no signal, the position of the module antenna should be moved. Generally, satellite signals will be poor indoors, so you can test in open areas outdoors (such as rooftops, balconies, and windows).
1.3. NMEA-0183¶
1.3.1. NMEA-0183 Protocol introduction¶
The BH-ATGM332D module outputs positioning data information through the TTL serial port. This information uses the NMEA-0183 4.0 protocol by default. The output information is as shown in the previous log.
NMEA is a standard format developed by the National Marine Electronics Association for marine electronic equipment. It has now become a unified RTCM standard protocol for GPS navigation equipment. The NMEA 4.0 version protocol used by this module supports positioning systems such as GPS, Beidou, and Hignes. NMEA-0183 is a set of standard messages that define receiver output. It comes in several different formats, each is an independently related ASCII format, uses commas to separate data, the data stream length varies from 30-100 characters, and the output is usually selected at per second intervals. The most commonly used format is “GGA”, which includes positioning time, latitude, longitude, altitude, number of satellites used for positioning, DOP value, differential status and correction period, etc. Others include speed, tracking, date, etc. NMEA has become virtually the most common data output format for all positioning receivers.
1.3.2. NMEA decoding library¶
After understanding the NMEA format, we can write the corresponding decoding program, and the programmer Tim (xtimor@gmail.com) provides a very complete NMEA decoding library, which can be downloaded at the following URL: http://nmea .sourceforge.net/ . Using this decoding library directly avoids reinventing the wheel. The source code of the decoding library is also included in the “NMEA0183 decoding library source code” folder of the GPS module information provided by Embedfire. The program provided by Embedfire uses this library to decode NMEA sentences.
The latest version of this decoding library is currently version 0.5.3. It is written in the C programming language, supports windows, winCE, and UNIX platforms, and supports parsing of five statements: GPGGA, GPGSA, GPGSV, GPRMC, and GPVTG (these five statements already provide enough GPS information). The analyzed GPS data information is stored in a structure, with geography-related functions added to support navigation and other data work. In addition to parsing NMEA statements, it can also generate NMEA statements based on random numbers to facilitate simulation. On top of this decoding library, Embedfire extends its support for NMEA-0183 version 4.0.
1.4. Using BH-ATGM332D module on Lubancat¶
This experiment is demonstrated with LubanCat-1N board, and the test system is Debian.
1.4.1. Update software source list¶
sudo apt update
1.4.3. Pull nmealib repository¶
The nmealib warehouse has been released on github and gitee. Embedfire has modified the library to support parsing the NMEA-0183 4.0 protocol.
Pull nmealib repository from github:
git clone https://github.com/Embedfire/nmealib.git
Pull nmealib repository from gitee:
git clone https://github.com/Embedfire/nmealib.git
1.4.4. Routine analysis¶
The nmealib warehouse released by Embedfire has provided relevant demo routines. There are 5 folders in the samples directory, namely: generate, generator, math, parse, and parse_ebf_module.
They all correspond to different routines:
generate/generator |
These two demos generate random NMEA-0183 standard information and can be used for debugging. |
math |
Math library, used to convert these NMEA-0183 standard information into math-related data, such as longitude, latitude, azimuth, etc. |
parse |
Demo of parsing NMEA-0183 standard information. These NMEA-0183 standard information are written in an array. |
parse_ebf_module |
A demo for parsing the NMEA-0183 standard information of the Embedfire Beidou positioning module. It obtains the BH-ATGM332D data by reading the serial port 3 device, and then calls the nmealib library to parse it. |
1.4.5. Modify the serial number of the demo code¶
Before compiling and running the example, you need to modify the serial number of the code. The sample code is as follows:
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 | #include <nmea/nmea.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdint.h>
#include <termios.h>
#include <sys/ioctl.h>
void GMTconvert(nmeaTIME *SourceTime, nmeaTIME *ConvertTime, uint8_t GMT,uint8_t AREA);
void error(const char *str, int str_size)
{
printf("Error: ");
write(1, str, str_size);
printf("\n");
}
int main()
{
int fd;
int len;
nmeaINFO info;
nmeaPARSER parser;
nmeaTIME beiJingTime; //北京时间
double deg_lat;//转换成[degree].[degree]格式的纬度
double deg_lon;//转换成[degree].[degree]格式的经度
char tmp_buf[200];
char buff[4096];
int size, it = 0;
nmeaPOS dpos;
fd = open("/dev/ttymxc2", O_RDONLY);
printf("fopen %d\n", fd);
if(!fd)
return -1;
// nmea_property()->trace_func = &trace;
nmea_property()->error_func = &error;
nmea_zero_INFO(&info);
nmea_parser_init(&parser);
struct termios opt;
//清空串口接收缓冲区
tcflush(fd, TCIOFLUSH);
// 获取串口参数opt
tcgetattr(fd, &opt);
//设置串口输出波特率
cfsetospeed(&opt, B9600);
//设置串口输入波特率
cfsetispeed(&opt, B9600);
//设置数据位数
opt.c_cflag &= ~CSIZE;
opt.c_cflag |= CS8;
//校验位
opt.c_cflag &= ~PARENB;
opt.c_iflag &= ~INPCK;
//设置停止位
opt.c_cflag &= ~CSTOPB;
//更新配置
tcsetattr(fd, TCSANOW, &opt);
while(1)
{
memset(buff, 0, 4096);
size = 0;
len = 0;
nmea_zero_INFO(&info);
nmea_parser_init(&parser);
for(it = 0; it < 32; it++) {
memset(tmp_buf, 0, 100);
size = (int)read(fd, tmp_buf, 100);
if (size > 1) {
memcpy(buff + len, tmp_buf, size);
len += size;
memcpy(buff + len - 1, "\r\n", 2);
len += 1;
}
}
nmea_parse(&parser, buff, len, &info);
// info.lat lon中的格式为[degree][min].[sec/60],使用以下函数转换成[degree].[degree]格式
deg_lat = nmea_ndeg2degree(info.lat);
deg_lon = nmea_ndeg2degree(info.lon);
GMTconvert(&info.utc,&beiJingTime,8,1);
// // /* 输出解码得到的信息 */
printf("\r\n时间:%d-%02d-%02d,%d:%d:%d\r\n", beiJingTime.year+1900, beiJingTime.mon,beiJingTime.day,beiJingTime.hour,beiJingTime.min,beiJingTime.sec);
printf("\r\n纬度:%f,经度%f\r\n",deg_lat,deg_lon);
printf("\r\n海拔高度:%f 米 ", info.elv);
printf("\r\n速度:%f km/h ", info.speed);
printf("\r\n航向:%f 度", info.direction);
printf("\r\n正在使用的GPS卫星:%d,可见GPS卫星:%d",info.satinfo.inuse,info.satinfo.inview);
printf("\r\n正在使用的北斗卫星:%d,可见北斗卫星:%d",info.satinfo.inuse,info.satinfo.inview);
printf("\r\nPDOP:%f,HDOP:%f,VDOP:%f\n",info.PDOP,info.HDOP,info.VDOP);
}
nmea_parser_destroy(&parser);
close(fd);
return 0;
}
|
提示
The code of the example is relatively simple. The main process is to read data from the serial port 3 device. The process of reading data is basically as follows: open the device and configure the parameters for reading information, such as baud rate, stop bit, check bit, etc. Then read the data and cache it in a buff; call the nmea_parse() function to parse the data and print it out.
We need to change line 40 of the code:
fd = open("/dev/ttymxc2", O_RDONLY);
Modify to the currently used serial port as follows:
fd = open("/dev/ttyS3", O_RDONLY);
You can use vim, nano and other text editors to modify it. If it is a desktop image, you can also use gedit. Of course, you can also use VSCode SSH to remotely log in to the board to modify it.
提示
Regarding using VSCode to remotely log in to the board, you can refer to “vscode Convenient Debugging and Development”
1.4.6. Compile & Run¶
Enter the nmealib directory and run the make
command directly to compile. The compilation information is as follows.
You can see that the libnmea.a library file is generated by compilation, and all samples are compiled. The output results are in the build/ directory, and the corresponding executable file is generated. We run directly:
./build/samples_parse_ebf_module
提示
After running, the window will print information such as time, longitude and latitude. Because the antenna is lying flat at this time, the speed and heading data are both 0.
1.5. A brief introduction to the nmea library¶
The above code uses many data structures of the nmea library, so I would like to introduce the relevant knowledge:
1.5.1. Structures nmeaPARSER and nmeaINFO¶
The data types nmeaPARSER and nmeaINFO of the parser and info variables in the above parameters are data structures unique to the NMEA decoding library, as follows:
1 2 3 4 5 6 7 8 9 | typedef struct _nmeaPARSER
{
void *top_node;
void *end_node;
unsigned char *buffer;
int buff_size;
int buff_use;
} nmeaPARSER;
|
提示
As you can see, nmeaPARSER is a linked list. During decoding, the NMEA library will push the input GPS raw data into the linked list of nmeaPARSER structure to facilitate data management and decoding. Before using this structure, you need to call the nmea_parser_init() function to allocate dynamic space. When decoding ends, the nmea_parser_destroy() function is called to release the allocated space.
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 | typedef struct _nmeaINFO
{
int smask; /**< Mask specifying types of packages from which data have been obtained */
nmeaTIME utc; /**< UTC of position */
int sig; /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */
int fix; /**< Operating mode, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */
double PDOP; /**< Position Dilution Of Precision */
double HDOP; /**< Horizontal Dilution Of Precision */
double VDOP; /**< Vertical Dilution Of Precision */
double lat; /**< Latitude in NDEG - +/-[degree][min].[sec/60] */
double lon; /**< Longitude in NDEG - +/-[degree][min].[sec/60] */
double elv; /**< Antenna altitude above/below mean sea level (geoid) in meters */
double sog; /**< 数值 对地速度,单位为节 */
double speed; /**< Speed over the ground in kilometers/hour */
double direction; /**< Track angle in degrees True */
double declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */
char mode; /**< 字符 定位模式标志 (A = 自主模式, D = 差分模式, E = 估算模式, N = 数据无效) */
nmeaSATINFO satinfo; /**< satellites information */
nmeaSATINFO BDsatinfo; /**北斗卫星信息*/
int txt_level;
char *txt;
} nmeaINFO;
|
The description of its structure is as follows:
提示
The good encapsulation characteristics of the NMEA decoding library prevent us from paying attention to the deeper internal implementation. We only need to take a look at the nmeaINFO data structure. All GPS decoding results are stored in this structure. After calling the nmea_parse() function to complete the analysis, directly query the data of the nmeaINFO structure to get the decoding result.