Sunday, March 29, 2009

Sending SMS in PDU mode (GSM)

This topic is not exactly limited to embedded domain. When we want to use sms protocol on GSM network, the communication can be done over a GSM modem. Some GSM modems provide a mean to install a java applet onto modem's firmware itself to control and interact via AT commands. However, usually GSM modem can be controlled using AT commands via serial interface.
The following discussion will focus on how to send an sms in PDU mode via serial interface to modem using AT commands.

Modem Configuration and Data Formatting
  1. Get the serial interface configured according to the baud rate specified in modem's data sheet.
  2. Test the modem's response by sending AT and then enter key ( ASCII - 0x0A,0x0D) from serial interface. Modem will send back OK if the communication between controller and modem is working.
  3. If your SIM requires PIN to unlock, send AT+CPIN="****", where **** are pin number in ASCII. To ensure if SIM is ready, send AT+CPIN? If response is SIM PIN, the SIM card is still waiting for the correct PIN to get unlocked. If response is READY, the communication to GSM network through SIM is ready to begin.
  4. In order to see what are the causes of error when we cannot send AT commands, we have to enable error printing from modem. It can be done by sending AT+CMEE=2. This will switch on verbose error reporting.
  5. In order to get receiving packets from network, we have to configure the modem such that unsolicited report is ON. To accomplish that, send AT+CNMI=0,2,0,1,0.
  6. After all this configuration, we are now ready to send SMS.
  7. Send AT+CMGF=0 to set the modem to PDU mode. ( some modem supports text mode)
  8. Format the PDU as follow
  • Octect (1) SMSC information --> 0x00 [ determined by modem ]
  • Octect (2) PDU-first octect --> 0x11 [ Validity period Type - relative, SMS-submit (yup, we are sending out)]
  • Octect(3) MessageReference--> 0x00 [ the modem decides what was the last counter value for send messages]
  • Octect(4) LenPhNo--> 0x0A [ let say we are sending to singapore handphone +6590123456]
  • Octect(5) Type of Addr --> 0x91 [ International ISDN ]
  • Octect(6-10) PhNoInDecimalSemiOctect format --> 0x56 0x09 0x21 0x43 0x65
  • (note: if phone number is of Odd count, the last nibble is filled with 15(0xf), For example for phone number +65901234567, the formatted octects are 0x56 0x09 0x21 0x43 0x65 0xF7)
  • Octect(11) Protocol Identifier --> 0x00 [ we are sending normal sms and not some special protocol like fax over GSM]
  • Octect(12) Data Coding Scheme --> 0x00 [ 7 bits defaut], however if you want to send UCS-2 format ( other languauge support-e.g. chinese character), set it to 0x19 [UCS2, Class-1 message], Or if you are sending some special data of byte size, use 0x15 [8-bit encoding]
  • Octect(13) Validity Perios --> 0xA7 [12 hours]
  • Octect(14) User Data Len --> (length of your data)
  • Octect(15 - ??) --> DATA
Ok, now we have the data ready to send.

Sending ..
  1. Send AT+CMGS=** to modem. Here, ** is Length of Data excluding SMSC information. Therefore, following the above format, it will be at (Length of your data + 13).
  2. after that, send carriage return+ line feed (0x0d, 0x0a)
  3. Then, Send the above formatted message, followed by (Ctrl+z = 0x0a) [ NOTE here: don't send enter*]
  4. If the message is sucessfuly send, you can read back modem response as OK, +CMGS=**, where ** is last message reference number.
Since we turned on verbose error reporting, we can see the problem in case any error has occured. Bye for now..