TCP Client using SIM900A GPRS and LPC2148

Introduction


Sim900A Sim900A

SIM900 enables GPRS connectivity to embedded applications. We can implement TCP Client protocol using SIM900 TCP function AT Commands.

The Transmission Control Protocol (TCP) is standard transport layer internet protocol which used in establishing and maintaining communication in between server and client.

It is widely used in IoT (Internet of Things) embedded applications, where every sensor is connected to a server and we have access to control them over the internet.

The GSM/GPRS module uses UART communication to communicate with microcontroller or PC terminal. AT commands are used to configure the module in different modes and to perform various functions like calling, posting data to a site, etc.

For more information about Sim900A and how to use it, refer the topic Sim900A GSM/GPRS Module in the sensors and modules section.

For information about UART in LPC2148 and how to use it, refer the topic UART in LPC2148 in the ARM7-LPC2148 inside section.

 

Interfacing Diagram


Interfacing Sim900A GPRS Module with LPC2148

Interfacing Sim900A GPRS Module with LPC2148

 

Example

Sending data and reading data from a remote server using SIM900A as a TCP Client .

 

Here, we will be using Thingspeak server for demo purpose.

Thingspeak is an open IOT platform where anyone can visualize and analyse live data from their sensor devices. We can also perform data analysis on data posted by remote devices with Matlab code in Thingspeak. To learn more about Thingspeak refer link https://thingspeak.com/pages/learn_more.

Just sign up and create a channel. We have created a channel with the ID and write key as given below on Thingspeak for sending and receiving data.

  • channel ID is = 119922
  • Write Key is = C7JFHZY54GLCJY38

Note:  Do not forget to tick Make Public field in channel setting option on your Thingspeak channel. It makes the channel available to use as public.

 

For TCP Receive method, use AT commands as shown in the screenshot of RealTerm software given below.

The screenshot consists of AT commands (Green) and Responses (Yellow).

TCP GET

TCP Receive Requests (Green) and Responses (Yellow)

 

For TCP SEND method, use AT commands as shown in the screenshot of RealTerm software given below.

The screenshot consists of AT commands (Green) and Responses (Yellow).

TCP POST

TCP SEND Requests (Green) and Responses (Yellow)

 

In below program of TCP Client, do the following

For TCP Client Receive Demo          

#define RECEIVE_DEMO      /* Define RECEIVE demo */

//#define SEND_DEMO  /* Define SEND demo */

For TCP Client Send Demo            

//#define RECEIVE_DEMO    /* Define RECEIVE demo */

#define SEND_DEMO    /* Define SEND demo */

 

Program for TCP Client

/*
  TCP Client using GPRS(SIM800/900) with LPC2148(ARM7)
  http://www.electronicwings.com/arm7/sim900a-gprs-module-interfacing-with-lpc2148
*/

#include <lpc214x.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#define DEFAULT_BUFFER_SIZE		200
#define DEFAULT_TIMEOUT			20000
#define DEFAULT_CRLF_COUNT		2

#define FLUSH_BUFF				1
#define KEEP_BUFF				0

//#define RECEIVE_DEMO
#define SEND_DEMO

enum SIM900_RESPONSE_STATUS {
	SIM900_RESPONSE_WAITING,
	SIM900_RESPONSE_FINISHED,
	SIM900_RESPONSE_TIMEOUT,
	SIM900_RESPONSE_BUFFER_FULL,
	SIM900_RESPONSE_STARTING,
	SIM900_RESPONSE_ERROR
};

uint8_t Response_Status, CRLF_COUNT = 0;
uint16_t Counter = 0;
uint32_t TimeOut = 0;
char RESPONSE_BUFFER[DEFAULT_BUFFER_SIZE];
char CONNECTION_NUMBER[] = "1";

__irq void UART0_Interrupt(void);

void delay_ms(uint16_t j)
{
    uint16_t x,i;
	for(i=0;i<j;i++)
	{
    for(x=0; x<6000; x++);    /* loop to generate 1 milisecond delay with Cclk = 60MHz */
	}
}

void UART0_init(void)
{
	PINSEL0 = PINSEL0 | 0x00000005;	/* Enable UART0 Rx0 and Tx0 pins of UART0 */
	U0LCR = 0x83;	/* DLAB = 1, 1 stop bit, 8-bit character length */
	U0DLM = 0x00;	/* For baud rate of 9600 with Pclk = 15MHz */
	U0DLL = 0x61;	/* We get these values of U0DLL and U0DLM from formula */
	U0LCR = 0x03; /* DLAB = 0 */
	U0IER = 0x00000001; /* Enable RDA interrupts */
}

void UART0_TxChar(char ch) /* A function to send a byte on UART0 */
{
	U0IER = 0x00000000; /* Disable RDA interrupts */
	U0THR = ch;
	while( (U0LSR & 0x40) == 0 );	/* Wait till THRE bit becomes 1 which tells that transmission is completed */
	U0IER = 0x00000001; /* Enable RDA interrupts */
}

void UART0_SendString(char* str) /* A function to send string on UART0 */
{
	U0IER = 0x00000000; /* Disable RDA interrupts */
	uint8_t i = 0;
	while( str[i] != '\0' )
	{
		UART0_TxChar(str[i]);
		i++;
	}
	U0IER = 0x00000001; /* Enable RDA interrupts */
}

void Read_Response()
{
	char CRLF_BUF[2];
	char CRLF_FOUND;
	uint32_t TimeCount = 0, ResponseBufferLength;
	while(1)
	{
		if(TimeCount >= (DEFAULT_TIMEOUT+TimeOut))
		{
			Response_Status = SIM900_RESPONSE_TIMEOUT;
			return;
		}

		if(Response_Status == SIM900_RESPONSE_STARTING)
		{
			CRLF_FOUND = 0;
			memset(CRLF_BUF, 0, 2);
			Response_Status = SIM900_RESPONSE_WAITING;
		}
		ResponseBufferLength = strlen(RESPONSE_BUFFER);
		if (ResponseBufferLength)
		{
			delay_ms(1);
			TimeCount++;
			if (ResponseBufferLength==strlen(RESPONSE_BUFFER))
			{
				for (uint16_t i=0;i<ResponseBufferLength;i++)
				{
					memmove(CRLF_BUF, CRLF_BUF + 1, 1);
					CRLF_BUF[1] = RESPONSE_BUFFER[i];
					if(!strncmp(CRLF_BUF, "\r\n", 2))
					{
						if(++CRLF_FOUND == (DEFAULT_CRLF_COUNT+CRLF_COUNT))
						{
							Response_Status = SIM900_RESPONSE_FINISHED;
							return;
						}
					}
				}
				CRLF_FOUND = 0;
			}
		}
		delay_ms(1);
		TimeCount++;
	}
}

void Buffer_Flush()
{
	memset(RESPONSE_BUFFER,0,strlen(RESPONSE_BUFFER));
	Counter = 0;
	TimeOut = 0;
	CRLF_COUNT = 0;
}

void Start_Read_Response()
{
	Response_Status = SIM900_RESPONSE_STARTING;
	do {
		Read_Response();
	} while(Response_Status == SIM900_RESPONSE_WAITING);

}

void GetResponseBody(char* Response, uint16_t ResponseLength)
{

	uint16_t i = 12;
	char buffer[5];
	while(Response[i] != '\r')
	++i;

	strncpy(buffer, Response + 12, (i - 12));
	ResponseLength = atoi(buffer);

	i += 2;
	uint16_t tmp = strlen(Response) - i;
	memcpy(Response, Response + i, tmp);

	if(!strncmp(Response + tmp - 6, "\r\nOK\r\n", 6))
	memset(Response + tmp - 6, 0, i + 6);
}

bool WaitForExpectedResponse(char* ExpectedResponse, bool FlushOrKeep)
{
	delay_ms(200);
	Start_Read_Response();
	if((Response_Status != SIM900_RESPONSE_TIMEOUT) && (strstr(RESPONSE_BUFFER, ExpectedResponse) != NULL))
	{
		if(FlushOrKeep)
		Buffer_Flush();
		return true;
	}
	else
	{
		if(FlushOrKeep)
		Buffer_Flush();
		return false;
	}
}

bool SendATandExpectResponse(char* ATCommand, char* ExpectedResponse)
{
	UART0_SendString(ATCommand);
	UART0_TxChar('\r');
	return WaitForExpectedResponse(ExpectedResponse,FLUSH_BUFF);
}

bool TCP_ApplicationMode(char* Mode)
{
	UART0_SendString("AT+CIPMODE=");
	UART0_SendString(Mode);
	UART0_TxChar('\r');
	return WaitForExpectedResponse("OK",FLUSH_BUFF);
}

bool TCP_ConnectionMode(char* Mode)
{
	UART0_SendString("AT+CIPMUX=");
	UART0_SendString(Mode);
	UART0_TxChar('\r');
	return WaitForExpectedResponse("OK",FLUSH_BUFF);
}

bool AttachGPRS()
{
	UART0_SendString("AT+CGATT=1\r");
	return WaitForExpectedResponse("OK",FLUSH_BUFF);
}

bool SIM900_Start()
{
	for (uint8_t i=0;i<5;i++)
	{
		if(SendATandExpectResponse("ATE0","OK")||SendATandExpectResponse("AT","OK"))
		return true;
	}
	return false;
}

bool TCP_Shut()
{
	UART0_SendString("AT+CIPSHUT\r");
	return WaitForExpectedResponse("OK",FLUSH_BUFF);
}

bool TCP_Close()
{
	UART0_SendString("AT+CIPCLOSE=1\r");
	return WaitForExpectedResponse("OK",FLUSH_BUFF);
}

bool TCP_Connect(char* APN, char* USERNAME, char* PASSWORD)
{

	UART0_SendString("AT+CREG?\r");
	if(!WaitForExpectedResponse("+CREG: 0,1",FLUSH_BUFF))
	return false;

	UART0_SendString("AT+CGATT?\r");
	if(!WaitForExpectedResponse("+CGATT: 1",FLUSH_BUFF))
	return false;

	UART0_SendString("AT+CSTT=\"");
	UART0_SendString(APN);
	UART0_SendString("\",\"");
	UART0_SendString(USERNAME);
	UART0_SendString("\",\"");
	UART0_SendString(PASSWORD);
	UART0_SendString("\"\r");
	if(!WaitForExpectedResponse("OK",FLUSH_BUFF))
	return false;

	UART0_SendString("AT+CIICR\r");
	if(!WaitForExpectedResponse("OK",FLUSH_BUFF))
	return false;

	UART0_SendString("AT+CIFSR\r");
	if(!WaitForExpectedResponse(".",FLUSH_BUFF))
	return false;

	UART0_SendString("AT+CIPSPRT=1\r");
	return WaitForExpectedResponse("OK",FLUSH_BUFF);
}

uint8_t TCP_Start(char* Domain, char* Port)
{
	UART0_SendString("AT+CIPMUX?\r");
	if(WaitForExpectedResponse("+CIPMUX: 0",FLUSH_BUFF))
	UART0_SendString("AT+CIPSTART=\"TCP\",\"");
	else
	{
		UART0_SendString("AT+CIPSTART=\"");
		UART0_SendString(CONNECTION_NUMBER);
		UART0_SendString("\",\"TCP\",\"");
	}
	
	UART0_SendString(Domain);
	UART0_SendString("\",\"");
	UART0_SendString(Port);
	UART0_SendString("\"\r");
	CRLF_COUNT = 2;

	if(WaitForExpectedResponse("ERROR",KEEP_BUFF)||WaitForExpectedResponse("FAIL",KEEP_BUFF))
	{
		Buffer_Flush();
		return SIM900_RESPONSE_ERROR;
	}
	if(!WaitForExpectedResponse("CONNECT OK",FLUSH_BUFF))
	return SIM900_RESPONSE_TIMEOUT;
	return SIM900_RESPONSE_FINISHED;
}

uint8_t TCP_Send(char* Data)
{
	UART0_SendString("AT+CIPSEND\r");
	delay_ms(1000);
	UART0_SendString(Data);
	UART0_SendString("\r\n");
	delay_ms(1000);
	UART0_TxChar(0x1A);

	if(WaitForExpectedResponse("ERROR",KEEP_BUFF)||WaitForExpectedResponse("FAIL",KEEP_BUFF))
	{
		Buffer_Flush();
		return SIM900_RESPONSE_ERROR;
	}
	if(!(WaitForExpectedResponse("SEND OK",KEEP_BUFF)||WaitForExpectedResponse("DATA ACCEPT",FLUSH_BUFF)))
	{
		Buffer_Flush();
		return SIM900_RESPONSE_TIMEOUT;
	}
	return SIM900_RESPONSE_FINISHED;
}

__irq void UART0_Interrupt(void)
{
	RESPONSE_BUFFER[Counter] = U0RBR;				/* Copy data to buffer & increment counter */
	Counter++;
	VICVectAddr = 0x00;
}

int main()
{
	char APN[] = "internet";					/* Define APN */
	char Domain[] = "api.thingspeak.com";
	char Port[] = "80";
	#ifdef SEND_DEMO
	char Api_Write_Key[] = "C7JFHZY54GLCJY38";
	char data[60];
	char value[5];
	uint8_t Sample = 0;
	#endif

	#ifdef RECEIVE_DEMO
	char Channel_ID[] = "119922";
	char URL[65];
	#endif
	
	VICVectAddr0 = (unsigned) UART0_Interrupt;	/* UART0 ISR Address */
	VICVectCntl0 = 0x00000026;	/* Enable UART0 IRQ slot */
	VICIntEnable = 0x00000040;	/* Enable UART0 interrupt */
	VICIntSelect = 0x00000000;	/* UART0 configured as IRQ */
	UART0_init();				
	while(!SIM900_Start());
	TCP_Shut();
	TCP_ConnectionMode("0");				/* 0 = Single; 1 = Multi */
	TCP_ApplicationMode("0");				/* 0 = Normal Mode; 1 = Transperant Mode */
	AttachGPRS();
	while(!(TCP_Connect(APN,"","")));
	while(1)
	{
		TCP_Start(Domain,Port);
		#ifdef SEND_DEMO
		memset(data, 0, 60);
		memset(value, 0, 5);
		strcat(data, "GET /update?api_key=");
		strcat(data, Api_Write_Key);
		strcat(data, "&field1=");
		sprintf(value, "%d", Sample++);
		strcat(data, value);
		TCP_Send(data);
		delay_ms(2000);
		TCP_Close();
		#endif
		
		#ifdef RECEIVE_DEMO
		memset(URL, 0, 65);
		strcat(URL, "GET /channels/");
		strcat(URL, Channel_ID);
		strcat(URL, "/feeds/last.txt");
		TCP_Send(URL);
		delay_ms(2000);
		TCP_Close();
		#endif
		delay_ms(15000);
	}
}

 

SIM900 Response

At the client end, we need to check SIM900 responses. We can check it on the serial terminal of PC/Laptop. Connect SIM900 transmit pin (TX) to the receive pin (RX) of LPC2148 and to the receive pin (RX) of usb to serial converter as shown in below figure. Connect usb to serial converter to PC/Laptop. Open the serial terminal on PC/Laptop to see the SIM900 responses for the AT command sent from PIC microcontroller.

LPC2148 Interface with SIM900 GSM along with PC LPC2148 Interface with SIM900 GSM along with PC

 

Now for TCP SEND commands (sent from LPC2148), we can see the below response from SIM900 on the serial terminal for the Thingspeak server.

TCP Send Response

In response with TCP SEND, we get the data entry no. as shown in above figure i.e. 976, 977, and so on.

 

For TCP RECEIVE commands (sent from LPC2148), we can see the below response from SIM900 on the serial terminal for the Thingspeak server.

TCP Send Response

In response with TCP RECEIVE we get the last entry data for field1 on Thingspeak as shown in above figure.

 

Note: Here we are retrieving the last entry data on field1 of Thingspeak server hence we get the last updated data of field1 from the server as shown in above figure i.e. “field1”:”2”. In the program, we used "GET /channels/119922/feeds/last.txt" to receive last updated data only.

 

Updates at Thingspeak server on TCP SEND

For TCP SEND we can see the output at the server end. Here we are using Thingspeak server and sending the incremented count at field1 on a server. We get incremented count at field1 of Thingspeak server as shown in below figure.

Data on Thingspeak Server

 

Data on Thingspeak Server

 


Components Used

ARM7 LPC2148
ARM7 LPC2148
1
SIM900A GSM GPRS Module
SIM900A is dual band GSM/GPRS 900/1800MHz module board used to utilize GSM and GPRS services around the globe. It is used to make/receive voice calls, send/receive text messages, connect to and access the internet over GPRS.
1
CP2103 USB TO UART BRIDGE
CP2103 is single chip USB to UART Bridge. It supports USB 2.0 protocol.
1

Downloads

TCP_Client_uVision_Project Download
Ad