Please help: sprintf() converts IMEI code to something.

Can someone please help me with this frustrating problem?

I am trying to submit some data to a web server, from an Arduino, using a 3G shield. The problem comes in when trying to submit the IMEI number. sprintf() change it to another value and I simply cannot figure it out.

Here's the sample output from the serial monitor:

GSM serial: 013227000048516
GSM > AT+CREG?
GSM < +CREG: 0,1
GSM < OK
GSM net registred
IMEI : 013227000048516
AT+HTTPPARA="URL","http://www.xxxx.co.za\log.php?imei=1078

Here's the code I'm using right now:

#include <SD.h>

#define PIN_GSM_PWR 46 //PIN GSM POWER
#define GSMBUFFER_LENGTH 32
char GSMbuffer[GSMBUFFER_LENGTH];
char Serial2number[30];
char IMEI_no[30];


int gsmon =0;
int noerror;
int regok=0;
int retry;

const int CS_Pin = 4; // GBoard Pro use Pin 4 for CS
char IMEI_File[ ]="datalog3.txt"; // File to write to
File IMEI_Data;
//char IMEI_no[] = "";

void setup () 
{
  pinMode (PIN_GSM_PWR, OUTPUT);
  digitalWrite(PIN_GSM_PWR, LOW);
  Serial2.begin(4800);
  Serial.begin(115200); //monitor
  Serial.println("GSM Test 03");

 Save_IMEI();
 

} // END setup()




void SendQuery (char * str) {
  while (Serial2.available()) Serial2.read(); //clear GSM buffer
  Serial2.println(str);
  //output monitor
  Serial.print ("GSM > ");
  Serial.println (str);
} // END void SendQuery (char * str)

int ReadAnswer (unsigned long timeout) {
  int i=0;
  unsigned long starttime = millis();
  char c;
  while (millis() - starttime < timeout) {
    if (Serial2.available()) {
      c=Serial2.read();
      if (c == '\r') continue;
      if (c == '\n') {
        if (i ==0) continue;  //free line
        GSMbuffer[i]=0;
         //output monitor
        Serial.print ("GSM < ");
        Serial.println (GSMbuffer);
        return 1;
      }
      else if (i<GSMBUFFER_LENGTH) GSMbuffer[i++]=c;
    }
  }   
  return 0;
} // END int ReadAnswer (unsigned long timeout)


void GSMHandler() {    
  
  //Enable GSM module
  Serial.println ("Go GSM handler...");
  SendQuery ("ATE0");  //echo off
  noerror=ReadAnswer (1000);
  if (!noerror) { //time out 
    Serial.println ("GSM OFF");
    Serial.println ("GSM POWER ON...");
    digitalWrite(PIN_GSM_PWR, HIGH);
    delay(1000);
    digitalWrite(PIN_GSM_PWR, LOW); 
    delay(1000);   
    SendQuery ("ATE0");  
    noerror=ReadAnswer (1000);
  }
  retry=10;
  while (retry>0) {
    if (noerror) {
      if (strcmp (GSMbuffer,"OK")==0) {
        Serial.println ("GSM ON");
        gsmon=1;
        break;
      }
    }  
    delay(100); 
    SendQuery ("ATE0");  
    noerror=ReadAnswer (1000);
    retry--;
  }
  if (!gsmon) {
    Serial.println ("GSM disconnect, error");
    return;
  }
  
  //Disable error mode
  SendQuery ("AT+CMEE=0");  
  noerror=ReadAnswer (1000);
  if (noerror) {
    if (strcmp (GSMbuffer,"OK")!=0) {  //query is not OK
      noerror=0;
    }
  }  
  if (!noerror) {
    Serial.println ("GSM error");
    return;
  }
  
  //Serial number
  SendQuery ("AT+GSN");  
  noerror=ReadAnswer (1000);
  if (noerror) {
    strcpy (Serial2number, GSMbuffer);
  }
  noerror=ReadAnswer (1000);
  if (noerror) {
    if (strcmp (GSMbuffer,"OK")!=0) {  //queri is not OK
      noerror=0;
    }
  }  
  if (!noerror) {
    Serial.println ("GSM error");
    return;
  }
  Serial.print ("GSM serial: ");
  Serial.println (Serial2number);
  
  //GSM wait net registration  
  retry=30;  //wait 30 sec
  while (retry>0) {
    SendQuery ("AT+CREG?");  
    noerror=ReadAnswer (1000);
    if (noerror) {
      if (strcmp (GSMbuffer,"+CREG: 0,1")==0) {  
        regok=1;
      }
    }
    noerror=ReadAnswer (1000);
    if (strcmp (GSMbuffer,"OK")==0) {  //query is OK
      if (regok) break;
    }
    delay(1000); 
    retry--;
  }
  if (!regok) {
    Serial.println ("GSM net not registration, error");
    return;
  }
  Serial.println ("GSM net registred");
  
  char log_data[100];
  Serial.print("IMEI : ");
  Serial.println(Serial2number);
  
 sprintf(log_data, "AT+HTTPPARA=\"URL\",\"http://www.xxxx.co.za\\log.php?imei=%d", Serial2number);

  Serial2.println("AT+HTTPINIT"); 
 Serial2.println(log_data);
  Serial2.println("AT+HTTPACTION=1");
  Serial2.println("AT+HTTPREAD");


 Serial.println(log_data);
  
} // END void GSMHandler() 



void loop() 
{
  char c;
  if (Serial.available()) {
    c=Serial.read();
    switch (c) {
      case 'h':
        GSMHandler();
        break;
    };
  }
  

} // END loop()
 
void Save_IMEI()
{
//  Serial.println("Initialize SD Card.");
  pinMode(CS_Pin, OUTPUT);

  if (!SD.begin(CS_Pin)) // Test if SD Card initialize 
  {
    Serial.println("SD Card missing, or corrupt.");
    return;
  } // END if (!SD.begin(CS_Pin))
 // Serial.println("SD Card initialized.");
  IMEI_Data = SD.open(IMEI_File);

  if (IMEI_Data.available()) // Test if IMEI_File is available
  {
    Serial.print(IMEI_File);
    Serial.println(" available. Content below: ");
    Serial.println();

    while (IMEI_Data.available()) 
    {
      Serial.write(IMEI_Data.read()); // Read contents of file
//   char   IMEI_no = IMEI_Data.read();
      
    } // END while (IMEI_Date.available())
    IMEI_Data.close(); // Close file
  } 
  else 
  {
    Serial.print(IMEI_File);
    Serial.println(" not available. Creating and adding content...");

    IMEI_Data = SD.open(IMEI_File, FILE_WRITE); // Open file for writing
    if (IMEI_Data)
    {

  SendQuery ("ATE0");  //echo off
  noerror=ReadAnswer (1000);
  if (!noerror) { //time out 
    digitalWrite(PIN_GSM_PWR, HIGH);
   delay(400);
    SendQuery ("ATE0");  
    noerror=ReadAnswer (1000);
  }
  retry=10;
  while (retry>0) {
    if (noerror) {
      if (strcmp (GSMbuffer,"OK")==0) {
 //       Serial.println ("GSM ON");
        gsmon=1;
        break;
      }
    }  
    delay(100); 
    SendQuery ("ATE0");  
    noerror=ReadAnswer (1000);
    retry--;
  }
  if (!gsmon) {
    Serial.println ("GSM disconnect, error");
    return;
  } 
  SendQuery ("AT+CMEE=0");    //Disable error mode
  noerror=ReadAnswer (1000);
  if (noerror) {
    if (strcmp (GSMbuffer,"OK")!=0) {  //query is not OK
      noerror=0;
    }
  }  
  if (!noerror) {
    Serial.println ("GSM error");
    return;
  }
  
  SendQuery ("AT+GSN");    // Get Serial number
  noerror=ReadAnswer (1000);
  if (noerror) {
    strcpy (Serial2number, GSMbuffer);
    Serial.print("IMEI No: ");
    Serial.println(GSMbuffer);
  }
  noerror=ReadAnswer (1000);
  if (noerror) {
    if (strcmp (GSMbuffer,"OK")!=0) {  // query is not OK
      noerror=0;
    }
  }  
  if (!noerror) {
    Serial.println ("GSM error");
    return;
  }
    
//  Serial.print ("GSM serial: ");
//  Serial.println (Serial2number);

    Serial.print("Writing data to ");
      Serial.print(IMEI_Data);
      Serial.println(" ...");
      IMEI_Data.println(Serial2number); // Writing data to file
      IMEI_Data.close(); // Close file when done.
      Serial.println("Done.");
      strcpy (IMEI_no, Serial2number);
//      IMEI_no = Serial2number;
    } // END if (IMEI_File)
  } // END if (SD.available(IMEI_File))

} // END void Save_IMEI()

Serial2number .. is not a number, it's a char array, so in sprintf, replace by %s . :slight_smile:

And if you are wondering, you cannot convert it to a number, because it's too big to be contained in a variable; a unsigned long cannot hold a value greater than 4294967295.

Additionally, instead of using sprintf, in your case you could do this:

Serial2.print( "AT+HTTPPARA=\"URL\",\"http://www.xxxx.co.za\\log.php?imei=" );
Serial2.println( Serial2number );

guix:
Serial2number .. is not a number, it's a char array, so in sprintf, replace by %s . :slight_smile:

And if you are wondering, you cannot convert it to a number, because it's too big to be contained in a variable; a unsigned long cannot hold a value greater than 4294967295.

Additionally, instead of using sprintf, in your case you could do this:

Serial2.print( "AT+HTTPPARA=\"URL\",\"http://www.xxxx.co.za\\log.php?imei=" );

Serial2.println( Serial2number );

Awesome! Thank you very much, this solved my problem.

So, what is the difference with %s and %d in sprintf then?

No problem :wink:

%s is for char arrays (strings), %d is for signed integers (numbers)

More details here: http://www.cplusplus.com/reference/cstdio/printf

Don't forget that, on the Arduino, %f is for question marks.

PaulS:
Don't forget that, on the Arduino, %f is for question marks.

What do you mean?

He means that the first time you try to use %f (for a float) you'll be back asking why it won't work.

It isn't implemented on Arduino.

Delta_G:
He means that the first time you try to use %f (for a float) you'll be back asking why it won't work.

It isn't implemented on Arduino.

Aah, ok... Thanx for the explanation.