STM32 + Guoyun GA6-GPRS/GSM module + MQTT+HTTP protocol to connect China Mobile OneNet to upload GPS data positioning

1, Environment introduction

MCU: STM32F103C8T6

GSM module: GA6 -- Guoyun

Development software: Keil5

Download the complete source code: https://download.csdn.net/download/xiaolong1126626497/18245590

Other reference articles: STM32+ESP8266 uses MQTT protocol to connect to Alibaba cloud Internet of things server

Other reference articles: STM32+ESP8266 uses standard MQTT protocol (MQTTS) to connect China Mobile OneNet IOT server

2, Introduction and debugging of GA6-GSM module

Note: the power supply of GA6-B module must be 5V. The computer USB power supply may be unstable (there is no 5V, only about 4.8V), resulting in the unstable use of the module and no response to the AT command. In the debugging stage, the USB cable of the development board can be connected to the charging treasure or the mobile phone charging plug to get power.

2.1 ga6-b module overview

GA6-B module: 1. Ga6 size: 22.8mm x 16.8mm x 2.2mm; 2. Normal working temperature: - 30 ° C ~ +80 ° C, 3. Limited working temperature: - 40 ° C ~ -30 ° C and + 80 ° C ~+85 ° C* 4. Working voltage: 3.5V-4.2V; 5. Startup voltage > 3.5V; 6. Current consumption in sleep mode is 0.9mA; 7. Four frequency bands: GSM850, EGSM 900, DCS 1800 and PCS1900 can automatically search four frequency bands. l comply with GSM Phase 2 / 2+ l GPRS Class 10; 8. Sensitivity < - 107; 9. Support voice call; 10. Support SMS; 11. Support 2G of China Mobile and China Unicom and global GSM network 12. GPRS data characteristics, maximum data rate, Download 85.6Kbps, upload 42.8Kbps; 13. Support the serial port multiplexing function conforming to GSM 07.10 protocol 14. Support two serial ports, one download serial port and one AT command port; 15. AT command supports standard AT and TCP/IP command interfaces; 16. Support digital audio and analog audio, and support HR, FR, EFR and AMR Speech Coding; 17. Support FCC and CE certification; 18. SMT 42pin package;

Advantages of GA6 module Wide area coverage: GPRS has good coverage in 34 provinces in China, and it is a global 2G communication standard. Basically, where the mobile phone can make calls, you can access the Internet wirelessly through GPRS; Always online: as long as the GPRS application is activated, it will remain online, similar to the wireless private line network service. Billing by volume: Although GPRS service is always online, you don't have to worry about the cost; Because it is only charged when traffic is generated. High speed transmission: at present, GPRS can support the peak transmission rate of 85.6Kbps, and the theoretical peak transmission can reach more than 100 Kbps. Cheap price: compared with the SIM series module, the price is only half of it. It greatly reduces the entry threshold of Internet of things devices. With ultra-small size, ultra-low power consumption and wide operating temperature range, GA6 is an ideal solution for M2M applications. It is suitable for vehicle, industrial and PDA, personal tracking, power environment detection, wireless POS, intelligent metering and other M2M applications, and provides perfect GSM/GPRS short message, data transmission and voice services.

IOT network card:

2.2 GA6 module commissioning

Module default baud rate: 115200 Voltage: 5V TX---URX(GA6 module) RX---UTX(GA6 module)

  1. Message received by module power on serial port assistant:

Note: the voltage must be 5V, otherwise it is useless to send AT command to the module.

  1. Under normal conditions, when the module is plugged into the SIM phone card and the power supply reaches 5V, the module will return the following prompt information when powered on.

When the module displays the "SMS Ready" string prompt, it indicates that the module can normally receive the "AT" instruction.

2.3 introduction and use of common basic instructions

(the end of the instruction needs to be added \ r\n)

1. Check whether the module is normal

Send command to module: AT The module returns normally. This command can detect whether the module is normal: OK

2. Check whether the SIM card is in the card slot

Send command to module: AT+CPIN? If the card is stuck in the card slot, the normal return value of the module: +CPIN:READY OK

3. Query whether the module is registered to the network

Send command to module: AT+CREG? Return value if the module has been registered to the network normally: AT+CREG? +CREG: 1,1 OK

4. Close command echo

Send command to module: ATE0 Return value of successful instruction execution: (turn off AT instruction echo to facilitate debugging and improve program efficiency) OK

2.4 introduction to GPRS network communication related instructions

1. Query network connection status

Send command to module: AT+CIPSTATUS The return values of successful instruction execution are as follows (multiple): "IP INITIAL" initialization "IP START" start task IP CONFIG configuration scenario "IP IND" activates GPRS/CSD in the scene "IP GPRSACT" receiving scenario configuration "IP STATUS" obtains the local IP address (refer to AT+CIFSR command) "TCP connecting" is in a TCP connection "UDP connecting" is in a UDP connection "IP CLOSE" TCP/UDP connection closed

2. Attach GPRS network (before network communication, you need to attach GPRS network before normal communication)

Send command to module: AT+CGATT=1 The module is normally attached to the GPRS network, and the return value: (note that it takes some time for the command to attach to the network for the first time, and it needs to wait for a period of time) OK

3. Activate GPRS network

Send instructions to the module: AT+CGACT=1,1 The module activates GPRS network normally. Return value: OK

4. Establish TCP connection: connect to TCP server

Module sending instruction: at + cipstar = "TCP", "183.230.40.33", 80 If the server is connected normally, the return value of successful connection: OK CONNECT OK

Note: the above instruction uses TCP protocol to connect the 183.230.40.33 server, and the port number is 80.

5. Send data

Send command to module: at + cipend If a command is received, the > symbol is returned., Next, you can send the actual data to be sent. When sending the actual data, you do not need to add a carriage return (\ r\n). After the actual data is sent, send an 0x1A immediately to start data transmission. Note: 0x1A is data in hexadecimal format, not a string. If the data is sent successfully, the "SEND OK" string will be returned.

Send data example:

POST /devices/517704007/datapoints HTTP/1.1 api-key:vvQAUiBG=HwKzqGicH=RxBvFCDw= Host:api.heclouds.com Connection:close Content-Length:65 {"datastreams":[{"id":"ds18b20","datapoints":[{"value":66.66}]}]}

3, STM32 code debugging GA6 module

3.1 test GA6 module through STM32 serial port code

Directly connected to the STM32F103C8T6 minimum system board:

Note: if USB is used to supply power to the development board, in order to prevent insufficient voltage, the USB cable should not be connected to the splitter, but directly to the USB port of the computer.

Because the voltage of GA6 module must be 5V to drive, 4.8V is not enough.

The STM32F103C8T6 minimum system board uses serial port 3 to connect with GA6-B module:

5V-----5V GND---G PB10—URX PB11---UTX

After the above prompt appears, if the sending AT can return OK, it indicates that the module has been working normally.

When the module is powered on, the following information will be returned: (Note: the voltage must be 5V)

AT Ready AST_POWERON +NITZ:19/03/20,01:57:46,32 Call Ready +CREG: 1 SMS Ready

3.2 encapsulate standard functions through STM32 (connect OneNet server using HTTP protocol)

GA6_GPRS.c) document code:

#include "ga6_gprs.h"

#define GS6_GSM_CHECK_CNT 10

/*
Function: GA6_GPRS send command
 Function parameters:
        char *cmd     :Instructions sent
        char *check   :Check the returned string
        u32 wait_time :Waiting time (100ms)
        
Note: this function is only applicable to the instruction that returns OK after success
 Return value: 0 indicates success, 1 indicates failure
*/
u8 GA6_GSM_SendCmd(char *cmd,char *check,u32 wait_time)
{
   u32 i,j;
   for(i=0;i<GS6_GSM_CHECK_CNT;i++) //Total number of tests
   {
      USART3_RX_FLAG=0;
      USART3_RX_CNT=0;
      memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));
      USART_X_SendString(USART3,cmd);
      for(j=0;j<wait_time;j++) //Waiting time (ms unit)
      {
          delay_ms(100); //Time of one
          if(USART3_RX_FLAG)
          {
              USART3_RX_BUFF[USART3_RX_CNT]='\0';
              if(strstr((char*)USART3_RX_BUFF,check))
              {
                  return 0;
              }
              else break;
          }
      }
   }
   return 1;
}


/*
Function: check the status of GA6
 Return value: 0 indicates success, and other values indicate failure
*/
u8 GA6_GSM_StateCheck(void)
{
    /*1. Check whether the module is normal*/
    if(GA6_GSM_SendCmd("AT\r\n","OK",50))
    {
        return 1; //Module not OK
    }
    
    /*2. Turn off echo function*/
    if(GA6_GSM_SendCmd("ATE0\r\n","OK",50))
    {
        return 2; //Echo failed to close successfully
    }
    
    /*3. Check whether the card is inserted*/
    if(GA6_GSM_SendCmd("AT+CPIN?\r\n","READY",50))
    {
        return 3; //The card wasn't checked
    }
    
    /*4. Check whether the card is registered to the network*/
    if(GA6_GSM_SendCmd("AT+CREG?\r\n","+CREG: 1,1",50))
    {
        return 4; //The card is not registered with the network
    }
    return 0;
}

/*
Function function: connect to TCP server
 Function parameters: 
					char *server_ip : server address
					u32 port :Server port
 Return value: 0 indicates a successful connection to the server, and other values indicate a failed connection to the server
*/
u8 GA6_GSM_ConnectServer(char *server_ip,u32 port)
{
		char cmd_buffer[50];
	 /*1. Check server connection status*/
	 if(GA6_GSM_SendCmd("AT+CIPSTATUS\r\n","CONNECT",50))
   {
		  /*2 Attach GPRS network*/
			if(GA6_GSM_SendCmd("AT+CGATT=1\r\n","OK",50))return 1;
     
		  /*3 Activate GPRS network*/
			if(GA6_GSM_SendCmd("AT+CGACT=1,1\r\n","OK",50))return 2;
     
		  /*4 Connect to the specified server*/
		  //Combination command
			snprintf(cmd_buffer,sizeof(cmd_buffer),"AT+CIPSTART=\"TCP\",\"%s\",%d\r\n",server_ip,port);
		  //Connect server
     //When the server connection is successful, the command will return two statuses: ready connect and connect OK
			if(GA6_GSM_SendCmd(cmd_buffer,"CONNECT",50))return 3;
   }
	 return 0;
}

/*
Function function: send data to the server
 Function parameters:
				u8 *data:First address of data sent
				u32 len :Data length
*/
u8 GA6_GSM_SendDataToServer(u8 *data,u32 len)
{
		char end_char[2];

		end_char[0] = 0x1A;//End character
		end_char[1] = '\0';

		/*2.1 Start data transmission*/
		if(GA6_GSM_SendCmd("AT+CIPSEND\r\n",">",50))return 1;

		/*2.2 Send actual data to be sent*/
		USART_X_SendData(USART3,data,len);

		/*2.3 End data transmission*/
	  if(GA6_GSM_SendCmd(end_char,"SEND OK",100))return 2;
	  
		return 0;
}
  1. GA6_GPRS.h document code:
#ifndef GA6_GPRS
#define GA6_GPRS
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
u8 GA6_GSM_StateCheck(void);
u8 GA6_GSM_SendDataToServer(u8 *data,u32 len);
u8 GA6_GSM_ConnectServer(char *server_ip,u32 port);
u8 GA6_GSM_SendCmd(char *cmd,char *check,u32 wait_time);
#endif
  1. Main.c code
#include "stm32f10x.h"
#include <string.h>
#include <stdio.h>
#include "ga6_gprs.h"
#include "usart.h"
#include "timer.h"
#include "led.h"
#include "key.h"

//u8 onenet_http_cmd[]=
//{
//	"POST /devices/517704007/datapoints HTTP/1.1\r\n"\
//	"api-key:vvQAUiBG=HwKzqGicH=RxBvFCDw=\r\n"\
//	"Host:api.heclouds.com\r\n"\
//	"Connection:close\r\n"\
//	"Content-Length:65\r\n"\
//	"\r\n"\
//	"{\"datastreams\":[{\"id\":\"ds18b20\",\"datapoints\":[{\"value\":88.88}]}]}"
//};

u8 onenet_http_cmd[]=
{
	"POST /devices/517620924/datapoints HTTP/1.1\r\n"\
	"api-key:OCZ6ghYPdky3=FJQCOEVZbByHRM=\r\n"\
	"Host:api.heclouds.com\r\n"\
	"Connection:close\r\n"\
	"Content-Length:62\r\n"\
	"\r\n"\
	"{\"datastreams\":[{\"id\":\"temp\",\"datapoints\":[{\"value\":88.88}]}]}"
};
//App publishing address: https://open.iot.10086.cn/iotbox/appsquare/appview?openid=905ef1b56ba526fdeee0c69a0787f176

/*
The following programs run correctly and return data:

+NITZ:19/03/20,14:45:27,32

Call Ready

+CREG: 1

SMS Ready
 Send data once!
GA6_GSM_StateCheck=0
GA6_GSM_ConnectServer=0
GA6_GSM_SendDataToServer=0

SEND OK

HTTP/1.1 200 OK
Date: Wed, 20 Mar 2019 14:45:40 GMT
Content-Type: application/json
Content-Length: 26
Connection: close
Server: Apache-Coyote/1.1
Pragma: no-cache

{"errno":0,"error":"succ"}

CLOSED
*/


int main()
{   
  u8 key,state;
  LED_Init();
  KEY_Init();
  BEEP_Init();
  TIM1_Init(72,20000); //Auxiliary serial port 1 receives, and the timeout time is 20ms
  USART_X_Init(USART1,72,115200);
  TIM2_Init(72,20000);//Auxiliary serial port 2 receives, and the timeout time is 20ms
  USART_X_Init(USART2,36,9600);
  TIM3_Init(72,20000);//Auxiliary serial port 3 receives, and the timeout time is 20ms
  USART_X_Init(USART3,36,115200);
  printf("UART1 OK.....\n");
  
  while(1)
  {     
     if(USART3_RX_FLAG)
     {
         USART3_RX_BUFF[USART3_RX_CNT]='\0';
         //printf("buff=%s,cnt=%d\n\n",USART3_RX_BUFF,USART3_RX_CNT);
         printf("%s",USART3_RX_BUFF);
         USART3_RX_CNT=0;
         USART3_RX_FLAG=0;
         memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));
     }
     
     key=KEY_Scanf();
     if(key)
     {
		  LED0=!LED0;
		  LED1=!LED1;
		  printf("Send data once!\n");
		  /*1. Check GSM operation*/
		  state=GA6_GSM_StateCheck();
		  printf("GA6_GSM_StateCheck=%d\n",state);
		  if(!state)
		  {
			/*2. Connect server*/
			state=GA6_GSM_ConnectServer("183.230.40.33",80);
			printf("GA6_GSM_ConnectServer=%d\n",state);
			if(!state)
			{
				/*3. Send data to server*/
				state=GA6_GSM_SendDataToServer(onenet_http_cmd,strlen((char*)onenet_http_cmd));
				printf("GA6_GSM_SendDataToServer=%d\n",state);
			}
			else
			{
				//Manually disconnect the server
				printf("Disconnect server:%d\r\n",GA6_GSM_SendCmd("AT+CIPCLOSE\r\n","OK",5000));
			}
		 }
     }
  }
}

3.3 GA6-B module uses HTTP protocol to connect OneNet server to upload GPS longitude and latitude

In order to improve efficiency, the GPS module can be successfully configured with the following options through the GPS configuration software:

Major modifications:

  1. The default baud rate of GPS module is 9600, which is configured as 115200
  2. The output statement only outputs RMC (recommended positioning information), because now only longitude and latitude information is required.
  3. The system sets the hot start state to improve the positioning speed

There are three types of latitude and longitude formats: Degree: (ddd.ddddd °) decimal part (5 digits) Degrees Minute: (ddd ° mm.mmm ') decimal part (3 digits) Degrees Points Second: (ddd ° mm 'ss') Relationship: One degree (°) equals 60 minutes (') equals 3600 seconds ("): Integer degree (d) is equal to the integer part (dd) of the decimal degree: The minute (m) is equal to the integer part (dd) of the decimal degree minus 60 times the integer degree (d): Seconds (s) equals decimal degrees (dd) minus integer degrees (d) minus minutes (M) divided by 60 times 3600:

  1. GPS.c file code example:
#include "gps.h"
/*
Function function: get the position of the cnt comma from buf
 Return value: 0 ~ 254, representing the offset of the comma position
255,Indicates that the cnt comma does not exist
*/
u8 GPS_GetCommaOffset(char *buf,u8 cnt)
{
	char *p=buf;
	while(cnt)
	{
		if(*buf=='*'||*buf<' '||*buf>'z')return 255;//If '*' or illegal characters are encountered, the cx comma does not exist
		if(*buf==',')cnt--;
		buf++;
	}
	return buf-p; //Calculate offset
}


/*
Function function: obtain GPS longitude and latitude data value
 Function parameters:
        double *Longitude  :longitude
        double *latitude   :latitude
 Return value: 0 indicates successful positioning, 1 indicates failed positioning

Description: parse the $GNRMC command to get the latitude and longitude
$GNRMC,023705.000,A,2842.4164,N,11549.5713,E,1.73,91.65,150319,,,A*41

Example of conversion formula:
Longitude: dddmm Mmmm east longitude 11408.4790 (08.4790 / 60) = 114.141317
 Latitude: ddmm Mmmm n 2236.9453 22 + (36.9453 / 60) = 22.615755
*/
u8 GPS_GNRMC_Decoding(char *gps_buffer,double *Longitude,double *latitude)
{
    u8 Offset;
    u32 int_data;
    double s_Longitude,s_latitude;
    char *p;

    /*1. Determine whether the next positioning is successful*/
    p=strstr(gps_buffer,"$GNRMC");
    if(!p)return 1;
    
    Offset=GPS_GetCommaOffset(p,2);
    if(Offset==255)return 2;
    if(*(p+Offset)!='A')return 3; //Inaccurate positioning
    
    /*2. Get latitude*/
    Offset=GPS_GetCommaOffset(p,3);
    if(Offset==255)return 4;
    sscanf(p+Offset,"%lf",&s_latitude);
   // printf("latitude before conversion:% lf\r\n",s_latitude);
  
    s_latitude=s_latitude/100;
    int_data=s_latitude;//Get the integer part of latitude
    s_latitude=s_latitude-int_data;//Get the decimal part of latitude
    s_latitude=(s_latitude)*100;
    *latitude=int_data+(s_latitude/60.0); //Get the converted value
   // printf("converted latitude:% lf\r\n",*latitude);
 
    /*3. Get longitude*/
    Offset=GPS_GetCommaOffset(p,5);
    if(Offset==255)return 5;
    sscanf(p+Offset,"%lf",&s_Longitude);
   // printf("longitude before conversion:% lf\r\n",s_Longitude);
    
    s_Longitude=s_Longitude/100;
    int_data=s_Longitude;//Get the integer part of longitude
    s_Longitude=s_Longitude-int_data; //Get the decimal part of longitude
    s_Longitude=s_Longitude*100;
    *Longitude=int_data+(s_Longitude/60.0);
   // printf("converted longitude:% lf\r\n",*Longitude);
    
    return 0;
}
  1. GPS.h code example
#ifndef GPS_H
#define GPS_H
#include "stm32f10x.h"
#include <string.h>
#include "usart.h"
u8 GPS_GNRMC_Decoding(char *gps_buffer,double *Longitude,double *latitude);
#endif

Main.c code example

#include "stm32f10x.h"
#include <string.h>
#include <stdio.h>
#include "ga6_gprs.h"
#include "usart.h"
#include "timer.h"
#include "led.h"
#include "key.h"
#include "gps.h"

char onenet_http_cmd[1024];
//App publishing address: https://open.iot.10086.cn/iotbox/appsquare/appview?openid=fd1307a02210acbef4b34de89d6cfe21

/*
GPS Wiring mode: connect TX pin of GPS module to PA3. (receiving pin of serial port 2)
GPS The baud rate of the module is 9600 by default (in order to improve the speed, the baud rate of GPS can be set to 115200 - which can be set directly through the upper computer software)
GPS Module model: ATGM336H-5N
 Power supply: 3V
*/


/*
GA6-GSM Wiring mode: connect UTX pin of GA6-GSM module with PB11 and URX pin with PB10. (receiving pin of serial port 3)
GA6-GSM  The baud rate of the module is 115200 by default
GA6-GSM  Module model: Guoyun GA6-B
 Power supply: 5V
*/

int main()
{   
  double Longitude,latitude;
  u8 state;
  u32 time_cnt=0;
  u16 data_tx_len=0;
  char temp_buff[50];
  
  LED_Init();
  KEY_Init();
  BEEP_Init();
  TIM1_Init(72,20000); //Auxiliary serial port 1 receives, and the timeout time is 20ms
	USART_X_Init(USART1,72,115200);
  TIM2_Init(72,20000);//Auxiliary serial port 2 receives, and the timeout time is 20ms
  USART_X_Init(USART2,36,115200);   //Connected to GPS module
  TIM3_Init(72,20000);//Auxiliary serial port 3 receives, and the timeout time is 20ms
  USART_X_Init(USART3,36,115200); //Connected to GSM module
  printf("UART1 OK.....\n");
  
  while(1)
  {     
      //Receive the return value of GPRS module
     if(USART3_RX_FLAG)
     {
         USART3_RX_BUFF[USART3_RX_CNT]='\0';
         //printf("buff=%s,cnt=%d\n\n",USART3_RX_BUFF,USART3_RX_CNT);
         printf("%s",USART3_RX_BUFF);
         USART3_RX_CNT=0;
         USART3_RX_FLAG=0;
         memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));
     }
     
     //Receive the return value of GPS module
     if(USART2_RX_FLAG)
     {
         USART2_RX_BUFF[USART2_RX_CNT]='\0';
         //printf("USART2_RX_BUFF=%s",USART2_RX_BUFF);
       
         //Analyze GPS data to obtain longitude and latitude
         if(GPS_GNRMC_Decoding((char*)USART2_RX_BUFF,&Longitude,&latitude))
         {
            printf("GPS seek failed! Please locate in an open place\r\n");
         }
         else //Successful positioning
         {
             if(time_cnt>=8000) //Once every 8 seconds
             {
                data_tx_len=71;
                sprintf(temp_buff,"%lf",Longitude);
                data_tx_len+=strlen(temp_buff);
               
                sprintf(temp_buff,"%lf",latitude);
                data_tx_len+=strlen(temp_buff); //Get the length of data sent
               
                snprintf(onenet_http_cmd,sizeof(onenet_http_cmd),
                  "POST /devices/517704007/datapoints HTTP/1.1\r\n"\
                  "api-key:vvQAUiBG=HwKzqGicH=RxBvFCDw=\r\n"\
                  "Host:api.heclouds.com\r\n"\
                  "Connection:close\r\n"\
                  "Content-Length:%d\r\n"\
                  "\r\n"\
                  "{\"datastreams\":[{\"id\":\"gps\",\"datapoints\":[{\"value\":{\"lon\":%lf,\"lat\":%lf}}]}]}",
                   data_tx_len,Longitude,latitude
                  );
                printf("data_tx_len=%d\r\n",data_tx_len);
                printf("longitude:%lf,latitude:%lf\r\n",Longitude,latitude);
 
                time_cnt=0;
                LED0=!LED0;
                LED1=!LED1;
                /*1. Check GSM operation*/
                state=GA6_GSM_StateCheck();
                printf("GA6_GSM_StateCheck=%d\n",state);
                if(!state)
                {
                    /*2. Connect server*/
                    state=GA6_GSM_ConnectServer("183.230.40.33",80);          
                    printf("GA6_GSM_ConnectServer=%d\n",state);
                    if(!state)
                    {
                      /*3. Send data to server*/
                    state=GA6_GSM_SendDataToServer((u8*)onenet_http_cmd,strlen((char*)onenet_http_cmd));
                      printf("GA6_GSM_SendDataToServer=%d\n",state);
                    }
                    else
                    {
                        //Manually disconnect the server
                     printf("Disconnect server:%d\r\n",GA6_GSM_SendCmd("AT+CIPCLOSE\r\n","OK",5000));
                    }
                }
             }
         }
         USART2_RX_CNT=0;
         USART2_RX_FLAG=0;
         memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));
     }
     
    time_cnt++;
    delay_ms(1);
  }
}
  1. Effects displayed on Web pages:

Added by rayzun on Tue, 18 Jan 2022 08:12:05 +0200