Quantcast
Viewing all articles
Browse latest Browse all 42

Getting Started with Sim900

Hi there. Today we are going to get a closer look at Sim900 radio module which we mentioned in our last post.

So here we are with a board with Sim900 radio module, where the main contacts have already been withdrawn into the contact area for SIM card. Also, serial interface connections, as well as outlets for microphone and linear output, are available.

Image may be NSFW.
Clik here to view.
image

We also have USB2UART controller. Note that drivers installation procedure on Mac OS X for various controllers may differ, so take this fact into account when choosing a controller type.

To make sure that the drivers are installed, type in the Terminal:

ls /dev/tty.*

Next we have to find our device. Here’s what our device looks like:

/dev/tty.PL2303-00001014

Connect contacts. Rx/Tx voltage of UART signals is 3.3V, which permits to connect contacts to the board directly. 5V power supply is provided by UART as well. Thus, we are using all the UART contacts: Rx/Tx, +5V and GND.

Image may be NSFW.
Clik here to view.
image

Sim900 module by default requires 115200 bit/s connection speed, 8 bits per symbol and 1 stop bit. All other options should be disabled.

UART is rather simple serial interface, even simpler than Serial Com port, but we can use the same components for work with it, limited only by the data exchange on the specified transfer speed.

OS X lets us work with serial port via tеrmios, which is the part of POSIX. All we have to do is tune port settings and try to transfer data.

For data exchange we’ll use Swift programming language. Here’s how setting port options looks like:

 func openWithDevicePath(devicePath:String, error:NSErrorPointer?) -> Bool
    {
        let d : Int32 = open(devicePath, O_RDWR | O_NOCTTY | O_NDELAY)
        if  d == -1
        {
            if let err = error
            {
                err.memory = NSError(domain: "could not open device", code: -1, userInfo: nil)
            }
            
            return false
        }
        
        var tty = UnsafeMutablePointer.alloc(1)
        
        if tcgetattr(d, tty) != 0
        {
            close(d)
            
            if let err = error
            {
                err.memory = NSError(domain: "tcgetattr failed", code: -1, userInfo: nil)
            }
            
            return false
        }
        
        if cfsetospeed (tty, 115200) == -1
        {
            close(d)
            
            if let err = error
            {
                err.memory = NSError(domain: "cfsetospeed failed", code: -1, userInfo: nil)
            }
            
            return false
        }
        
        if cfsetispeed (tty, 115200) == -1
        {
            close(d)
            
            if let err = error
            {
                err.memory = NSError(domain: "cfsetispeed failed", code: -1, userInfo: nil)
            }
            
            return false
        }
        
        tty.memory.c_cflag = (tty.memory.c_cflag & ~UInt(CSIZE)) | UInt(CS8);   // 8-bit chars
        
        tty.memory.c_iflag = ~UInt(IGNBRK)                                      // ignore break processing
        tty.memory.c_lflag = 0                                                  // no signaling chars, no echo,
        tty.memory.c_oflag = 0                                                  // no remapping, no delays
        
        tty.memory.c_iflag &= ~(UInt(IXON) | UInt(IXOFF) | UInt(IXANY))         // shut off xon/xoff ctrl
        tty.memory.c_cflag |= (UInt(CLOCAL) | UInt(CREAD))                      // ignore modem controls,
        tty.memory.c_cflag &= ~(UInt(PARENB) | UInt(PARODD))                    // shut off parity
        tty.memory.c_cflag |= 0
        tty.memory.c_cflag &= ~UInt(CSTOPB)                                     // One stop bit
        tty.memory.c_cflag &= ~((UInt(CCTS_OFLOW) | UInt(CRTS_IFLOW)))          // Disable RTS/CTS
        
        if tcsetattr (d, TCSANOW, tty) != 0
        {
            close(d)
            
            if let err = error
            {
                err.memory = NSError(domain: "cfsetispeed failed", code: -1, userInfo: nil)
            }
            
            return false
        }
        
        sim900descriptor = d
        
        return true
    }

The function should be always called before starting work with Sim900. The data is sent and received via read and write functions, that’s why the command execution will be realized via timer. Receiving data from the device is similar to the work of Terminal. In the next posts we’ll give a closer examination of Pooling mode, where the data is received.

So let’s execute a simple command to test connection to the module - “AT”.
main function in Swift looks like:

var error : NSError?
let sim900descriptor = sim900DescriptorWithDevicePath("/dev/tty.PL2303-00001014", &error)
if sim900descriptor == -1
{
    if let e = error
    {
        println("Error: \(e.localizedDescription)")
    }
    
    exit(1)
}

let cmd = "AT\r\n"

write(sim900descriptor, cmd, UInt(countElements(cmd)))

sleep(2)

var buffer = UnsafeMutablePointer.alloc(Int(128))
memset(buffer, 0, 128)

let bitesReaded = read(sim900descriptor, buffer, 127)

if let response = String.fromCString(buffer)
{
    println("Response: \(response)")
}

Data is transferred via write call, as you’ve probably noticed.
If OK is returned, data transfer settings are correct.
Here’s a sample which allows sending an SMS message and making an outgoing call. Let’s describe two simple commands.

We are going to dial a telephone number, so we need to pass a command in “ATD;” format, which has the following look:

   func dialNumber(phoneNumber:String)
    {
        let dialCmd = "ATD\(phoneNumber);\r\n"
        
        write(sim900descriptor, dialCmd, UInt(countElements(dialCmd)))
    }

Making a call is that easy. Sending an SMS message is a little harder and may remind you sending POST request to the Internet. Once the command is received, the module will wait for the body of the letter and 1A symbol.

To do this, we’ll use command of “AT+CMGS=” format. Once it is sent, send the body of the message with 0x1A symbol in the end, in case the module didn’t return an error.

Look, that’s dead simple:

    func sendMessage(message:String, toNumber:String)
    {        
        let smsCmd = "AT+CMGS=\"\(toNumber)\"\r\n"
        
        write(sim900descriptor, smsCmd, UInt(countElements(smsCmd)))
        
        sleep(1);
        
        write(sim900descriptor, message, UInt(countElements(message)))
                
        write (sim900descriptor, UnsafePointer([0x1A] as Array), 1);
    }

We use read function to get all the data during application work:

 func availableData() -> String?
    {
        var buffer = UnsafeMutablePointer.alloc(Int(128))
        memset(buffer, 0, 128)
        
        let bitesReaded = read(sim900descriptor, buffer, 127)
        
        if bitesReaded > 0
        {
            return String.fromCString(buffer)
        }
        
        return nil
    }

Image may be NSFW.
Clik here to view.
image

You can download xcode project of the test application from this post here: sim900_practice.zip

Subscribe here:

https://www.facebook.com/develtima
https://twitter.com/develtima


Viewing all articles
Browse latest Browse all 42

Trending Articles