Problems with this code to Send and Receive Phone Calls with Sim900

Here is my preliminary code for sending and receiving calls with a sim900 GSM shield and uno. Long story short calling from shield doesn't work and calling to the shield simply plays faint music from the speaker and doesn't generate the ring at all. I've used test code to separately call from the shield and generate a ring and its worked before. (Haven't worked out a test for calling to the shield yet

I'm using this library Google Code Archive - Long-term storage for Google Code Project Hosting.

#include "SIM900.h"
#include <SoftwareSerial.h>

#include "call.h";

//TX and RX changed from default 2 and 3 to 8 and 9 in GSM.cpp

//nonintegrated cradle version
//integrate in delays? 


CallGSM vcs; //call instance

char dialarray[] = {'1','2','3','4','5','6','7','8','9','0'};//array of chars to append to phone number as digits are read in 

//variables to read in dial pulses
int needToPrint = 0;
int count; //dial pulse counts
int lastState = LOW;
int trueState = LOW;
long lastStateChangeTime = 0;

// constants
int dialHasFinishedRotatingAfterMs = 100;
int debounceDelay = 10;

//phone number variables
int numquota = 0;//keeps track of how many digits of the phone number we have entered
char* callednum;//number to call
char transferredchar;//char to append to callednum whenever a new digit is read in


int ringingcounter=0;//keeps track of time ringing
int ringbreak; //breaks out of ringing sequence if button is pressed

//PIN SETUP
int dialPin = 2;
int ringPin = 4;                 // transistor connected to digital pin 4
int  buttonPin = 5;    // the pin that the pushbutton is attached to
int powerPin =7; //keyed to turn on the GSM power






 
void setup()
{
 
  // PIN Setup for Dialing, Button, Power, and Ringing Pins
pinMode(dialPin, INPUT);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ringPin, OUTPUT);     
pinMode(powerPin, OUTPUT);

digitalWrite(powerPin,LOW); //turn on GSM network
delay(1000);
digitalWrite(powerPin,HIGH);
delay(2000);
digitalWrite(powerPin,LOW);

Serial.begin(9600);

//RECEIVE
  // initialize serial communications
  //"Receive Voice Call"

 if (gsm.begin(2400))//fix?
          Serial.println("\nstatus=READY");
     else Serial.println("\nstatus=IDLE");


  // This makes sure the modem notifies correctly incoming events
  vcs.HangUp();
  //"Waiting Call"



}
void loop()
{

 // Check the status of the voice call
  switch (vcs.CallStatus())
  {
    case CALL_NONE: // Nothing is happening or in the process of dialing
       numquota = 0;//reset phonedigit count just in case?

       dial(); //Detect dialing

      if (numquota != 0) //while dialing continue to detect dialing until phone number completed or button is pressed
      {
        while ((numquota != 0 ) && digitalRead(buttonPin)!=LOW)
        dial();
      }
    callednum = ""; //RESET number for next dialing. 
    break;

    case CALL_NO_RESPONSE: // play a tone to indicate a call is taking place. Fix? 

      //"CALLING"
      Serial.println("AT+SIMTONE=1,30,200,200,1000");

      break;

    case CALL_INCOM_VOICE: // If receiving a call, set up ringing and check to see if user answers

      ringingcounter=0; //counter to track time spent ringing and silent
	  ringbreak=0; //value to skip to phone pickup if button is pressed

	  digitalWrite(ringPin, HIGH);   // sets the ring on
			while (ringingcounter<=2000)  // waits for two second
			{
              if (digitalRead(buttonPin)!=LOW && vcs.CallStatus()== CALL_INCOM_VOICE)//if button is pressed and call is still incoming 
			  {
				ringbreak = 1;
				break;
			  }

			delay(100);
			ringingcounter=ringingcounter+100;
			}
     

      digitalWrite(ringPin, LOW);    // sets the ring off
           while (ringingcounter<=6000 && ringbreak == 0)  // waits for four seconds
            {
              if (digitalRead(buttonPin)!=LOW && vcs.CallStatus()== CALL_INCOM_VOICE)//if button is pressed and call is still incoming
			  {
				ringbreak = 1;
				break;
			  }
				delay(100);
			ringingcounter=ringingcounter+100;
			}
		   if (digitalRead(buttonPin)==LOW && vcs.CallStatus()== CALL_INCOM_VOICE)//answer call
		   {
           vcs.PickUp();
		   }
      break;

    case CALL_ACTIVE_VOICE:  // In this case the call would be established
//TALKING. Press Button to hangup.
      while(digitalRead(buttonPin)!=LOW)
	  {
        delay(100);//BRACES?
	  }
      vcs.HangUp();
	  break;
  }
  delay(1000);
//RECEIVE


}


int dial() //code for recognizing and reading in dial pulses
{
  int reading = digitalRead(dialPin);//set pin to read dial pulses

	if ((millis() - lastStateChangeTime) > dialHasFinishedRotatingAfterMs) {
       // the dial isn't being dialed, or has just finished being dialed.
		if (needToPrint) {
       // if it's only just finished being dialed, we need to send the number 
       // and reset the count. 
         transferredchar = dialarray[count-1];
         callednum += transferredchar;
         needToPrint = 0;
         count = 0;
         numquota++;//increment till phone number length reached
	   }
	}

	if (reading != lastState) {
      lastStateChangeTime = millis();
      }
	if ((millis() - lastStateChangeTime) > debounceDelay) {
          // debounce - this happens once it's stablized
		if (reading != trueState) {
              // this means that the switch has either just gone from closed->open or vice versa.
              trueState = reading;
			  if (trueState == HIGH) {
              // increment the count of pulses if it's gone high.
              count++;
              needToPrint = 1; // we'll need to print this number (once the dial has finished rotating)
			  }
			}
		}

    lastState = reading;

    //rotary addition

    if (numquota == 11 ) {//once the last digit has been reached send the number
      gsm.call(callednum, 100);//send number to call
      while(1);
      numquota = 0;//resets phone number digit count
      callednum = "";
      }

}

)

char* callednum;//number to call

A pointer that points nowhere.

    callednum = ""; //RESET number for next dialing.

OK. Now, it points to a constant that is sized to hold exactly 0 characters.

         callednum += transferredchar;

You can't increment a pointer that way. += isn't an append operator, and even if it was, you can't append beyond the space that you (haven't) allocated.

PaulS:

char* callednum;//number to call

A pointer that points nowhere.

    callednum = ""; //RESET number for next dialing.

OK. Now, it points to a constant that is sized to hold exactly 0 characters.

         callednum += transferredchar;

You can't increment a pointer that way. += isn't an append operator, and even if it was, you can't append beyond the space that you (haven't) allocated.

okay I've altered it, dunno if its an improvement. Still no joy so far though for receiving or sending calls. Really hate char* but the call function wants a char* and complains if I use String as an argument.

/*Note:This code is used for Arduino 1.0 or later*/
// libraries RECEIVE
#include "SIM900.h"
#include <SoftwareSerial.h>

#include "call.h";

//TX and RX changed from default 2 and 3 to 8 and 9 in GSM.cpp

//nonintegrated cradle version
//integrate in delays? 


CallGSM vcs; //call instance

char dialarray[] = {'1','2','3','4','5','6','7','8','9','0'};//array of chars to append to phone number as digits are read in 

//variables to read in dial pulses
int needToPrint = 0;
int count; //dial pulse counts
int lastState = LOW;
int trueState = LOW;
long lastStateChangeTime = 0;

// constants
int dialHasFinishedRotatingAfterMs = 100;
int debounceDelay = 10;

//phone number variables
int numquota = 0;//keeps track of how many digits of the phone number we have entered
char* callednum = new char[20];//number to call
char transferredchar;//char to append to callednum whenever a new digit is read in


int ringingcounter=0;//keeps track of time ringing
int ringbreak; //breaks out of ringing sequence if button is pressed

//PIN SETUP
int dialPin = 2;
int ringPin = 4;                 // transistor connected to digital pin 4
int  buttonPin = 5;    // the pin that the pushbutton is attached to
int powerPin =7; //keyed to turn on the GSM power






 
void setup()
{
 
  // PIN Setup for Dialing, Button, Power, and Ringing Pins
pinMode(dialPin, INPUT);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ringPin, OUTPUT);     
pinMode(powerPin, OUTPUT);

digitalWrite(powerPin,LOW); //turn on GSM network
delay(1000);
digitalWrite(powerPin,HIGH);
delay(2000);
digitalWrite(powerPin,LOW);

Serial.begin(9600);

//RECEIVE
  // initialize serial communications
  //"Receive Voice Call"

 if (gsm.begin(2400))//fix?
          Serial.println("\nstatus=READY");
     else Serial.println("\nstatus=IDLE");


  // This makes sure the modem notifies correctly incoming events
  vcs.HangUp();
  //"Waiting Call"



}
void loop()
{

 // Check the status of the voice call
  switch (vcs.CallStatus())
  {
    case CALL_NONE: // Nothing is happening or in the process of dialing
       numquota = 0;//reset phonedigit count just in case?

       dial(); //Detect dialing

      if (numquota != 0) //while dialing continue to detect dialing until phone number completed or button is pressed
      {
        while ((numquota != 0 ) && digitalRead(buttonPin)!=LOW)
        dial();
      }
    callednum[0] = '\0'; //RESET number for next dialing. 
    break;

    case CALL_NO_RESPONSE: // play a tone to indicate a call is taking place. Fix? 

      //"CALLING"
      Serial.println("AT+SIMTONE=1,30,200,200,1000");

      break;

    case CALL_INCOM_VOICE: // If receiving a call, set up ringing and check to see if user answers

      ringingcounter=0; //counter to track time spent ringing and silent
	  ringbreak=0; //value to skip to phone pickup if button is pressed

	  digitalWrite(ringPin, HIGH);   // sets the ring on
			while (ringingcounter<=2000)  // waits for two second
			{
              if (digitalRead(buttonPin)!=LOW && vcs.CallStatus()== CALL_INCOM_VOICE)//if button is pressed and call is still incoming 
			  {
				ringbreak = 1;
				break;
			  }

			delay(100);
			ringingcounter=ringingcounter+100;
			}
     

      digitalWrite(ringPin, LOW);    // sets the ring off
           while (ringingcounter<=6000 && ringbreak == 0)  // waits for four seconds
            {
              if (digitalRead(buttonPin)!=LOW && vcs.CallStatus()== CALL_INCOM_VOICE)//if button is pressed and call is still incoming
			  {
				ringbreak = 1;
				break;
			  }
				delay(100);
			ringingcounter=ringingcounter+100;
			}
		   if (digitalRead(buttonPin)==LOW && vcs.CallStatus()== CALL_INCOM_VOICE)//answer call
		   {
           vcs.PickUp();
		   }
      break;

    case CALL_ACTIVE_VOICE:  // In this case the call would be established
//TALKING. Press Button to hangup.
      while(digitalRead(buttonPin)!=LOW)
	  {
        delay(100);//BRACES?
	  }
      vcs.HangUp();
	  break;
  }
  delay(1000);
//RECEIVE


}


int dial() //code for recognizing and reading in dial pulses
{
  int reading = digitalRead(dialPin);//set pin to read dial pulses

	if ((millis() - lastStateChangeTime) > dialHasFinishedRotatingAfterMs) {
       // the dial isn't being dialed, or has just finished being dialed.
		if (needToPrint) {
       // if it's only just finished being dialed, we need to send the number 
       // and reset the count. 
         transferredchar = dialarray[count-1];
         callednum[numquota]= transferredchar;
         callednum[numquota+1]= '\0';
         needToPrint = 0;
         count = 0;
         numquota++;//increment till phone number length reached
	   }
	}

	if (reading != lastState) {
      lastStateChangeTime = millis();
      }
	if ((millis() - lastStateChangeTime) > debounceDelay) {
          // debounce - this happens once it's stablized
		if (reading != trueState) {
              // this means that the switch has either just gone from closed->open or vice versa.
              trueState = reading;
			  if (trueState == HIGH) {
              // increment the count of pulses if it's gone high.
              count++;
              needToPrint = 1; // we'll need to print this number (once the dial has finished rotating)
			  }
			}
		}

    lastState = reading;

    //rotary addition

    if (numquota == 11 ) {//once the last digit has been reached send the number
      gsm.call(callednum, 100);//send number to call
      while(1);
      numquota = 0;//resets phone number digit count
      callednum[0] = '\0';
      }

}

Really hate char* but the call function wants a char* and complains if I use String as an argument.

Well, I would to. You need to come to grips with the relationship between pointers and arrays. The function wants a pointer to the start of an array, but you need to allocate and populate an array, then pass the array (technically, the address of the first element of the array) to the function.

char* callednum = new char[20];//number to call

What's wrong with a nice simple"

char callednum[20];

Have you tried something far simpler, like just hard-coding a number to call? What part of the program are you debugging?

PaulS:

Really hate char* but the call function wants a char* and complains if I use String as an argument.

Well, I would to. You need to come to grips with the relationship between pointers and arrays. The function wants a pointer to the start of an array, but you need to allocate and populate an array, then pass the array (technically, the address of the first element of the array) to the function.

char* callednum = new char[20];//number to call

What's wrong with a nice simple"

char callednum[20];

Have you tried something far simpler, like just hard-coding a number to call? What part of the program are you debugging?

the number cannot be hardcoded for my purpose. Upon looking at the serial output the problem might have to do with issues with the TX and RX pins I'm using.

the number cannot be hardcoded for my purpose

Perhaps not in the end. But, if you are not interested in getting the sketch to work step by step, I'll bow out, and leave you to solve it on your own.

PaulS:

the number cannot be hardcoded for my purpose

Perhaps not in the end. But, if you are not interested in getting the sketch to work step by step, I'll bow out, and leave you to solve it on your own.

I simply meant that the purpose of the sketch was not to send a hardcoded number. When I took a look at the serial output it looks like the problem has to do with the Tx and rx through software serial. It keeps on giving me an error that the sim900 doesn't respond. At first I assumed it was because I was using pin 2 for another purpose but even if I comment the offending code out I still get the same error in the serial output. Interestingly using code at http://wiki.epalsite.com/index.php?title=SIM900_Quad-Band_GPRS_shield_with_Micro_SD_card_slot#Example1-Make_a_phone_call works fine even though it uses the same serial pins 2,3 at the same time I'm using pin 2 for dial pulses. I might have junk the library and see if I can make a go of it with simple AT commands.