Hi,
I've recently got a GSM playground shield from HW kitchen and have been trying to get to know it but have encountered a few problems. I've succesfully run their test sketches to send an SMS and run AT commands. So far so good. Then I started writing my own sketches. My first bit of code simply ran through a number of AT comands to fetch basic information from the GSM module such as IMEI, make, model and serial number. I then tried to call the function to check that the shield is registered to a phone network before sending an SMS that contains the information just pulled from the module. The offending lines are highlighted in the sketch.
#include "GSM.h"
#ifndef DEBUG_PRINT
#error "!!! It is necessary to enable DEBUG_PRINT macro in the GSM.h !!!"
#endif
int n=0;
char atCmd[12];
char* atMean;
String x;
int sigStrenth;
char disp[180]; //characters to be displayed
char disp2[180]; //characters to be displayed
int freeMem=0; //available memory
char sms_num[]="0123456789";
int z=0;
long loop_count=0;
byte ret_val2=0;
// definition of instance of GSM class
GSM gsm;
const char* IMEI = "IMEI";
const char* MODEL = "Model";
const char* MAKER = "Maker";
const char* VER = "Version";
const char* STRENGTH = "Sig strength";
const char* REG = "Registered?";
const char* DATE = "Date";
const char* NETOP = "Network";
const char* SERNUM = "Serial Num.";
// sms return variable
char ret_val;
char strOut3[50]; //this will be a trimmed down version of the modem output, so it can be a lot smaller
void setup()
{
// initialization of serial line
gsm.InitSerLine(115200);
#ifdef DEBUG_PRINT
gsm.DebugPrint("Starting TestSMS2.pde A\r\n",0);
// print library version
sprintf(disp,"Debug Library version <%4d>",gsm.LibVer());
gsm.DebugPrint(disp,1);
#endif
//Even before 'Turning On' the module send a reset command. Hopefully this may force it to start behaving itself.
gsm.SendATCmdWaitResp("ATZ", 2000, 200, "OK", 5);
// turn on GSM module
gsm.TurnOn();
// set direction for GPIO pins
gsm.SetGPIODir(GPIO10, GPIO_DIR_OUT);
gsm.SetGPIODir(GPIO11, GPIO_DIR_OUT);
}
void loop()
{
//select a different AT command each time we process the loop
switch (n)
{
case 0:
strcpy(atCmd,"AT+CGSN");
atMean = (char*)IMEI;
break;
case 1:
strcpy(atCmd,"AT+CGMM");
atMean = (char*)MODEL;
break;
case 2:
strcpy(atCmd,"AT+CGMI");
atMean = (char*)MAKER;
break;
case 3:
strcpy(atCmd,"AT+CGMR");
atMean = (char*)VER;
break;
case 4:
strcpy(atCmd,"AT+CSQ");
atMean = (char*)STRENGTH;
break;
case 5:
strcpy(atCmd,"AT+CREG?");
atMean = (char*)REG;
break;
case 6:
strcpy(atCmd,"AT+COPS?");
atMean = (char*)NETOP;
break;
case 7:
strcpy(atCmd,"AT+GSN");
atMean = (char*)SERNUM;
break;
case 8:
strcpy(atCmd,"AT+CCLK?");
atMean = (char*)DATE;
n=-1;
break;
}
n++;
//run the AT command against the modem, each time the loop runs a different AT command will be chosen.
ret_val = gsm.SendATCmdWaitResp(atCmd, 1000, 100, "", 1);
// now we are waiting for response from the GSM module
// ---------------------------------------------------
if (ret_val != AT_RESP_ERR_NO_RESP) {
//Parse the output buffer BEFORE doing any DebugPrint - remember a DebugPrint will alter the output buffer
parseOutput3();
// ----------------------------------------------------------
if (strcmp("Sig strength",atMean)==0)
{
//if we're checking for signal strength, then need to some further parsing
sigStrenth=stripSigStrenth();
sprintf(disp,"Request for <%s>, using <%s>, returned value <%d>. ",atMean, atCmd, sigStrenth);
}
else
{
//result is an array of char, so need to format the output differently
sprintf(disp,"Request for <%s>, using <%s>, returned value <%s>. ",atMean, atCmd, strOut3);
}
//Display the results of whatever the previous AT comand was.
gsm.DebugPrint(disp,1);
//IF THE NEXT THREE LINES ARE ENABLED THE WHOLE SKETCH STOPS WORKING
// ret_val2=gsm.CheckRegistration();
// sprintf(disp2,"After checking reg, result is <%i> (1 means registered). ",ret_val2);
// gsm.DebugPrint(disp2,1);
//IF THE NEXT IF STATEMENT IS UN-COMMENTED THEN THE SKETCH STOPS WORKING
// //The 1st time round the loop the results of the first command will be SMSed, the
// //2nd time round the second command will be sent and so on.
// if ((n==0 && z==0) || (n==1 && z==1) || (n==2 && z==2) || (n==3 && z==3))
// {
// gsm.SendATCmdWaitResp("AT+CMGF=1", 500, 20, "OK", 5); //set modem to text mode
// gsm.DebugPrint("About to send SMS\r\n",1);
// ret_val=gsm.SendSMS(sms_num, disp);
// sprintf(disp,"After sending SMS, result is <%i>. (1 means sent ok) ",ret_val);
// gsm.DebugPrint(disp,1);
// z++;
// }
}
else {
// this should not happen
gsm.DebugPrint("We have received nothing, something is wrong...", 1);
}
//pause and then try another command
delay(1000);
loop_count++;
}
void parseOutput3()
{
strOut3[0]=0; //empty the array
//strip out any non-printing characters from the command buffer. Keep anything that is printable
int i=0;
int y=0;
while (gsm.comm_buf[i] != 0) //check all characters until the end
{
if ((gsm.comm_buf[i] >= 32) && (gsm.comm_buf[i] <= 126))
{
strOut3[y] = char(gsm.comm_buf[i]);
y++;
}
i++;
}
//if the last characters are "OK", then remove them
if ( char(strOut3[y-2])=='O' && char(strOut3[y-1])=='K' )
{
strOut3[y-2]=0;
}
else
{
strOut3[y] =0; //stick a null terminator on the end
}
}
int stripSigStrenth()
{
//Given the modem buffer after requesting the signal strength, try to parse
//it out of the array. The results normaly look like this... "+CSQ: 13,7"
//need to extract the integer between the colon and the space.
char from=':';
char to=',';
char strength[3+1];
bool found1=false;
bool found2=false;
int y=0;
int i=0;
int sigStren=0;
while (strOut3[i] != 0) //check all characters until the end
{
//look for the end character
if (char(strOut3[i]) == to)
{
found2=true;
}
//any character between the start and end is one we're interested in.
if ((found1==true) && (found2==false))
{
//Check that the ascii value of this character is between 48 and 57 - i.e. between numerals 0 and 9
if ((strOut3[i] >='0') && (strOut3[i] <='9') )
{
strength[y] = strOut3[i];
y++;
}
}
if (y >=49)
{
gsm.DebugPrint("Overflow...", 1);
}
//look for the start character
if (char(strOut3[i]) == from)
{
found1=true;
}
strength[y] = '\0'; //terminate with a null character
i++;
}
sigStren=atoi(strength); //Convert strength to an integer
strength[0]='\0'; //release the memory
return sigStren;
}
int availableMemory()
{
int size = 1024; // Use 2048 with ATmega328
//int size = 2048;
byte *buf;
while ((buf = (byte *) malloc(--size)) == NULL)
;
free(buf);
return size;
}
The offending function call (gsm.CheckRegistration) works fine in the other sketches, but when I enable it in this one the sketch still compiles and loads without problems but won't run (it doesn't just crash when it get's there - the whole sketch hangs on the first line)
I'm using an arduino duemilanove with version 21 software and a GSM playground (hardware version 1.6) with the latest version of their libraries. (I have tried to contact them, but no response so far). The shield will send a SMS when using the example sketches, so I'm assuming it's working ok. My sketch is getting sensible results from the AT commands it invokes so I must be talking to it OK. One of the AT commands I'm sending gets the signal strength, and another gets the network registration, so I know I'm connected with an adeqaute signal.
Any help appreciated.
Regards
Mike.