4712 views|4 replies

270

Posts

0

Resources
The OP
 

【ESP32-C3-DevKitM-1】ESP32-C3 obtains time and positioning information from GPS module [Copy link]

 This post was last edited by 怀穿少年梦 on 2021-7-29 12:04

This time, we use ATGM332D GPS module to obtain the current time and positioning information. ATGM332D GPS module has dual-mode function, supports China's BDS system and the US GPS system, and has a positioning accuracy of less than 2.5 meters (in open areas). The module is powered by 3.3-5V , and the power consumption is less than 25mA . It has onboard E2PROM and onboard XH414 charging electronics to accelerate hot start satellite search. The first positioning time takes a long time (maybe several minutes). The interface is serial communication, so the serial port is used to receive information. Its pin circuit diagram and physical diagram are shown below.

Pins used :

PIN4 TXD

PIN5 RXD

3.3V VCC

Gnd G

Programming

1. Configure UART interface parameters, baud rate, stop bit, parity, etc.

The steps to write a serial port program are shown in the figure below.

    uart_config_t uart_config = {
        .baud_rate = 9600,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    //Install UART driver, and get the queue.
    uart_driver_install(UART_PORT_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart1_queue, 0);
    uart_param_config(UART_PORT_NUM, &uart_config);

    //Set UART pins (using UART0 default pins ie no changes.)
    uart_set_pin(UART_PORT_NUM, UART_TXD, UART_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

  1. Writing a decoding function

Parse according to the serial port data

void parseGpsBuffer()
{
	char *subString=NULL;
	char *subStringNext;
	char i = 0;
	if (Save_Data.isGetData)
	{
		Save_Data.isGetData = false;
		printf("**************\r\n");
		printf(Save_Data.GPS_Buffer);

		
		for (i = 0 ; i <= 6 ; i++)
		{
			if (i==0)
			{
				if ((subString = strstr(Save_Data.GPS_Buffer, ",")) == NULL)
					errorLog(1);	//解析错误
			}
			else
			{
				subString++;
				if ((subStringNext = strstr(subString, ",")) != NULL)
				{
					//char usefullBuffer[2]; 
					switch(i)
					{
						case 1:memcpy(Save_Data.UTCTime, subString, subStringNext - subString);break;	//获取UTC时间
						//case 2:memcpy(usefullBuffer, subString, subStringNext - subString);break;	//获取UTC时间
						case 2:memcpy(Save_Data.latitude, subString, subStringNext - subString);break;	//获取纬度信息
						case 3:memcpy(Save_Data.N_S, subString, subStringNext - subString);break;	//获取N/S
						case 4:memcpy(Save_Data.longitude, subString, subStringNext - subString);break;	//获取经度信息
						case 5:memcpy(Save_Data.E_W, subString, subStringNext - subString);break;	//获取E/W

						default:break;
					}
					subString = subStringNext;
					Save_Data.isParseData = true;
                    Save_Data.isUsefull = true;
				}
				else
				{
					errorLog(2);	//解析错误
				}
			}


		}
	}
}

  1. Write a print decoding function

Is to print relevant data

void printGpsBuffer()
{
	if (Save_Data.isParseData)
	{
		Save_Data.isParseData = false;
        
		printf("\r\n");
		printf("Save_Data.UTCTime = ");
		printf(Save_Data.UTCTime);
		printf("\r\n");

		if(Save_Data.isUsefull)
		{
			Save_Data.isUsefull = false;
			printf("Save_Data.latitude = ");
			printf(Save_Data.latitude);
			printf("\r\n");


			printf("Save_Data.N_S = ");
			printf(Save_Data.N_S);
			printf("\r\n");

			printf("Save_Data.longitude = ");
			printf(Save_Data.longitude);
			printf("\r\n");

			printf("Save_Data.E_W = ");
			printf(Save_Data.E_W);
			printf("\r\n");
		}
		else
		{
			printf("GPS DATA is not usefull!\r\n");
		}
		
	}
}

4. Main function

Using UART Event Detection Mode

#include "SHT3X.h"
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include <stdio.h>
#include <stdlib.h>
#include "esp_log.h"
#include "driver/uart.h"
#include "uart.h"

static const char *TAG = "uart_events";

#define UART_PORT_NUM 1
#define PATTERN_CHR_NUM    (2)
static QueueHandle_t uart1_queue;
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
#define UART_RXD 5
#define UART_TXD 4
extern _SaveData Save_Data;
static void uart_event_task(void *pvParameters)
{
    uint8_t i = 0;
    uint8_t j = 0;
    uart_event_t event;
    size_t buffered_size;
    uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE);
    for(;;) {
        //Waiting for UART event.
        if(xQueueReceive(uart1_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
            bzero(dtmp, RD_BUF_SIZE);
            ESP_LOGI(TAG, "uart[%d] event:", UART_PORT_NUM);
            switch(event.type) {
                //Event of UART receving data
                /*We'd better handler data event fast, there would be much more data events than
                other types of events. If we take too much time on data event, the queue might
                be full.*/
                case UART_DATA:
                   // ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
                    uart_read_bytes(UART_PORT_NUM, dtmp, event.size, portMAX_DELAY);
                  //  ESP_LOGI(TAG, "[DATA EVT]:");
                   // uart_write_bytes(UART_PORT_NUM, (const char*) dtmp, event.size);
                    for(i=0;i< event.size;i++)
                    {   
                        //printf("%c",dtmp);
                        if(dtmp == '$' && dtmp[i+4] == 'G' && dtmp[i+5] == 'A')			//确定是否收到"GPRMC/GNRMC"这一帧数据
                            {
                                j=i;
                                memset(Save_Data.GPS_Buffer, 0, GPS_Buffer_Length);      //清空
                                for (i = 0 ; i <= 79 ; i++)
                                {
                                    Save_Data.GPS_Buffer = dtmp[i+j+6];
                                }
                                
                                Save_Data.isGetData = true;
                                memset(dtmp, 0, event.size);      //清空	

                            }
                            else
                            {
                            printf("接收失败\r\n");
                            }
                    }
                            parseGpsBuffer();
                            printGpsBuffer(); 
                    break;
                //Event of HW FIFO overflow detected
                case UART_FIFO_OVF:
                    ESP_LOGI(TAG, "hw fifo overflow");
                    // If fifo overflow happened, you should consider adding flow control for your application.
                    // The ISR has already reset the rx FIFO,
                    // As an example, we directly flush the rx buffer here in order to read more data.
                    uart_flush_input(UART_PORT_NUM);
                    xQueueReset(uart1_queue);
                    break;
                //Event of UART ring buffer full
                case UART_BUFFER_FULL:
                    ESP_LOGI(TAG, "ring buffer full");
                    // If buffer full happened, you should consider encreasing your buffer size
                    // As an example, we directly flush the rx buffer here in order to read more data.
                    uart_flush_input(UART_PORT_NUM);
                    xQueueReset(uart1_queue);
                    break;
                //Event of UART RX break detected
                case UART_BREAK:
                    ESP_LOGI(TAG, "uart rx break");
                    break;
                //Event of UART parity check error
                case UART_PARITY_ERR:
                    ESP_LOGI(TAG, "uart parity error");
                    break;
                //Event of UART frame error
                case UART_FRAME_ERR:
                    ESP_LOGI(TAG, "uart frame error");
                    break;
                //UART_PATTERN_DET
                case UART_PATTERN_DET:
                    uart_get_buffered_data_len(UART_PORT_NUM, &buffered_size);
                    int pos = uart_pattern_pop_pos(UART_PORT_NUM);
                   // ESP_LOGI(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", pos, buffered_size);
                    if (pos == -1) {
                        // There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not
                        // record the position. We should set a larger queue size.
                        // As an example, we directly flush the rx buffer here.
                        uart_flush_input(UART_PORT_NUM);
                    } else {
                        uart_read_bytes(UART_PORT_NUM, dtmp, pos, 100 / portTICK_PERIOD_MS);
                        uint8_t pat[PATTERN_CHR_NUM + 1];
                        memset(pat, 0, sizeof(pat));
                        uart_read_bytes(UART_PORT_NUM, pat, PATTERN_CHR_NUM, 100 / portTICK_PERIOD_MS);
                     //   ESP_LOGI(TAG, "read data: %s", dtmp);
                      //  ESP_LOGI(TAG, "read pat : %s", pat);
                    }
                    break;
                //Others
                default:
                    ESP_LOGI(TAG, "uart event type: %d", event.type);
                    break;
            }
        }
    }
    free(dtmp);
    dtmp = NULL;
    vTaskDelete(NULL);
}

void app_main(void)
{
    esp_log_level_set(TAG, ESP_LOG_INFO);

    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    uart_config_t uart_config = {
        .baud_rate = 9600,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    //Install UART driver, and get the queue.
    uart_driver_install(UART_PORT_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart1_queue, 0);
    uart_param_config(UART_PORT_NUM, &uart_config);

    //Set UART log level
    esp_log_level_set(TAG, ESP_LOG_INFO);
    //Set UART pins (using UART0 default pins ie no changes.)
    uart_set_pin(UART_PORT_NUM, UART_TXD, UART_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    //Set uart pattern detect function.
    uart_enable_pattern_det_baud_intr(UART_PORT_NUM, '+', PATTERN_CHR_NUM, 9, 0, 0);
    //Reset the pattern queue length to record at most 20 pattern positions.
    uart_pattern_queue_reset(UART_PORT_NUM, 20);

    //Create a task to handler UART event from ISR
    xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 12, NULL);
}

5. Effect

UTC time is the world time, Beijing time needs to add 8 hours to it.

This post is from Domestic Chip Exchange

Latest reply

There are a lot of codes for parsing NMEA that you can find, but it is troublesome to write them yourself!   Details Published on 2021-7-29 16:57

赞赏

1

查看全部赞赏

 
 

1942

Posts

2

Resources
2
 

Not bad!

This post is from Domestic Chip Exchange

Comments

Thanks for the encouragement  Details Published on 2021-7-29 18:12
 
 
 

7422

Posts

2

Resources
3
 

There are a lot of codes for parsing NMEA that you can find, but it is troublesome to write them yourself!

This post is from Domestic Chip Exchange

Comments

Thanks for the reminder, I will optimize it later  Details Published on 2021-7-29 18:13
Personal signature

默认摸鱼,再摸鱼。2022、9、28

 
 
 

270

Posts

0

Resources
4
 

Thanks for the encouragement

This post is from Domestic Chip Exchange
 
 
 

270

Posts

0

Resources
5
 
freebsder posted on 2021-7-29 16:57 There are many codes for parsing NMEA that you can find. After all, it is troublesome to write them yourself!

Thanks for the reminder, I will optimize it later

This post is from Domestic Chip Exchange
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list