Pages: [1]   Go Down
Author Topic: Siemens TC35 sending multiple SMS, cannot find bug  (Read 1385 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I have the following hardware; Siemens TC35 GSM, DS18B20 1-wire temperate sensor and an RGB LED hooked up to an Atmega328. This will, when code right!, allow me to interrogate the temperature of my home and allow me to text to switch my heating off/on. RGB LED implemented to test function of TC35.

As per the code below, I can send a text message from my mobile with either; Red, Green, Blue or Off and this controls the state of the RGB LED (which works ok). I can also text "Temp", as in temperature, and the program should respond by texting back the temperature (which it does), however, something in the program is making it send multiple text messages, any ideas what could be causing this? (not all of this is my own work, and mega-credit goes to those who wrote the original code)

Code:
#include <OneWire.h>
int DS18S20_Pin = 4; //DS18B20 Signal pin on digital 4

//Temperature chip i/o
OneWire ds(DS18S20_Pin); // on digital pin 4

#include <SoftwareSerial.h>
SoftwareSerial gsmSerial(2,3);


//-------- TC35 GSM ---------------
int SMS_location_number;
const unsigned int MAX_INPUT = 165; // 160 characters for SMS plus a few extra
static unsigned int input_pos = 0;
const int commandDelay = 250;
int redLED = 5;
int greenLED = 6;
int blueLED = 7;
int LEDstate = 0; //0 = off, 1 = red, 2 = green, 3 = blue
float temperature = 99.99;

void setup() {

  Serial.begin(9600); // set serial monitor to baud 9600
  gsmSerial.begin(9600); // set comms with TC35 to baud 9600
 
  // set RGB LED digital pins
  pinMode(redLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(blueLED, OUTPUT);

  pinMode(8, INPUT); // turns on/resets TC35 by taking pin 8 (IGT on TC35) low for 100ms
  digitalWrite(8, LOW);
  pinMode(8, OUTPUT);
  delay(100);
  pinMode(8, INPUT);
 
  temperature = getTemp(); // get temperature to initialise temp sensor
  delay(1000);
  temperature = getTemp(); // re-read temperature sensor
  Serial.println(temperature);
 
  gsmSerial.println("AT+CMGF=1"); // for txt mode
  delay(commandDelay);
  gsmSerial.println("AT+CNMI=2,1,0,0,1"); // message indication
  delay(commandDelay);
  gsmSerial.println("AT^SMGO=1"); // SMS full indication
  delay(commandDelay);
  gsmSerial.println("AT&W"); // store to memory
  delay(commandDelay);
  gsmSerial.println("AT&V"); //display current configuration
  delay(commandDelay);
 
}//------ End setup -------

void loop() {

  readTC35();
 
}//------ End loop --------

//---------------------------- Read TC35 ------------------------------------

// Read data from the TC35, When a linefeed is read the data is processed

void readTC35(){

  static char input_line [MAX_INPUT];
  //static unsigned int input_pos = 0;

  if (gsmSerial.available () > 0)
  {
    while (gsmSerial.available () > 0) {
      char inByte = gsmSerial.read ();

      switch (inByte)
      {

      case '\n':   // end of text
        input_line [input_pos] = 0;  // terminating null byte

        // terminator reached! process input_line here ...
        process_data (input_line);

        // reset buffer for next time
        input_pos = 0;
        break;

      case '\r':   // discard carriage return
        break;

      default:
        // keep adding if not full ... allow for terminating null byte
        if (input_pos < (MAX_INPUT - 1))
          input_line [input_pos++] = inByte;
        break;

      }  // end of switch
    }  // end of while incoming data
  }  // end of if incoming data
}  // end of readTC35

//---------------------------- process_data --------------------------------

void process_data (char * data){

  // display the data

    Serial.println (data);
 
  if(strstr(data, "^SMGO: 2")){ // SIM card FULL
    delete_All_SMS();           // delete all SMS
  }

  if(strstr(data, "+CMTI:")){    // An SMS has arrived
    char* copy = data + 12;      // Read from position 12 until a non ASCII number to get the SMS location
    SMS_location_number = (byte) atoi(copy);  // Convert the ASCII number to an int
    gsmSerial.print("AT+CMGR=");
    gsmSerial.println(SMS_location_number);  // Print the SMS in Serial Monitor
  }                                          // this SMS data will go through this process_data function again
                                             // any true if statements will execute
 
    if(strstr(data, "Red")){              // If data contains Red
    Serial.println("LED: Red");
    LEDstate = 1;
    delete_one_SMS();
  }
 
    if(strstr(data, "Green")){              // If data contains Green
    Serial.println("LED: Green");
    LEDstate = 2;
    delete_one_SMS();
  }
 
    if(strstr(data, "Blue")){              // If data contains Blue
    Serial.println("LED: Blue");
    LEDstate = 3;
    delete_one_SMS();
  }
 
    if(strstr(data, "Off")){              // If data contains Off
    Serial.println("LED: Off");
    LEDstate = 0;
    delete_one_SMS();
  }
   
    if(strstr(data, "Temp")){              // If data contains Temp
    float temperature = getTemp(); // read temperature sensor
    gsmSerial.print("AT+CMGF=1\r");
    delay(400);
    gsmSerial.println("AT+CMGS=\"+447914527888\""); //AT command to send SMS
    //Serial.println("AT+CMGS=\"+447914527888\""); //AT command to send SMS
    delay(500); //the length of this delay is very important. 400 is too low
    gsmSerial.print("Livingroom Temperature: ");
    gsmSerial.print(temperature); //Print the message
    gsmSerial.print("\x1A");
    delay(15);
    delete_one_SMS();
}

// Set RGB LED to colour
     if (LEDstate == 0) {
    digitalWrite(redLED, LOW);
    digitalWrite(greenLED, LOW);
    digitalWrite(blueLED, LOW);
  }
  if (LEDstate == 1) {   
    digitalWrite(greenLED, LOW);
    digitalWrite(blueLED, LOW);
    digitalWrite(redLED, HIGH);
  }
  if (LEDstate == 2) {
    digitalWrite(redLED, LOW);
    digitalWrite(blueLED, LOW);
    digitalWrite(greenLED, HIGH);
  }
  if (LEDstate == 3) {
    digitalWrite(redLED, LOW);
    digitalWrite(greenLED, LOW);
    digitalWrite(blueLED, HIGH);
  }
}

//--------------------------- end of process_data ---------------------------

void delete_one_SMS(){
  Serial.print("deleting SMS ");
  Serial.println(SMS_location_number);
  gsmSerial.print("AT+CMGD=");
  gsmSerial.println(SMS_location_number);
}

void delete_All_SMS(){
  for(int i = 1; i <= 20; i++) {
    gsmSerial.print("AT+CMGD=");
    gsmSerial.println(i);
    Serial.print("deleting SMS ");
    Serial.println(i);
    delay(500);
  }
}
float getTemp(){
 //returns the temperature from one DS18S20 in DEG Celsius

 byte dataTemp[12];
 byte addr[8];

 if ( !ds.search(addr)) {
   //no more sensors on chain, reset search
   ds.reset_search();
   return -1000;
 }

 ds.reset();
 ds.select(addr);
 ds.write(0x44,1); // start conversion, with parasite power on at the end

 byte present = ds.reset();
 ds.select(addr); 
 ds.write(0xBE); // Read Scratchpad
 
 for (int i = 0; i < 9; i++) { // we need 9 bytes
  dataTemp[i] = ds.read();
 }
 
 ds.reset_search();
 
 byte MSB = dataTemp[1];
 byte LSB = dataTemp[0];

 float tempRead = ((MSB << 8) | LSB); //using two's compliment
 float TemperatureSum = tempRead / 16;
 
 return TemperatureSum;
}
Logged

UK
Offline Offline
Shannon Member
****
Karma: 183
Posts: 11153
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you clarify 'multiple text message'? Is it always the same number of responses per incoming request? There's nothing obvious which would cause a received SMS to be processed multiple times but I wonder whether you may be failing to delete an SMS after processing it and then be getting the same SMS reprocessed subsequently. The comment "this SMS data will go through this process_data function again" suggests you're expecting something of that sort. The comment "Print the SMS in Serial Monitor" is either wrong, or implies that you're doing something unusual with the serial port since the stuff you write to the GSM serial device should not be appearing on the serial monitor.

Also, I noticed that your use of strstr to recognise the commands could result in the data being processed multiple times, if the received data matches more than one of the strings you're looking for.

I don't know if you ever expect to encounter the maximum possible length text, but just for the sake of argument you should declare input_line as an array of length MAX_INPUT+1 to allow space for the terminating char.  Also get rid of the global declaration of input_pos and use the static local instead; no code outside that function has any business messing with it. I don't think it will have been causing you any harm, but I'd recommend that you only call process_data() if input_pos is greater than 0.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you PeterH,

I fully agree with you that some of the code does not make sense, the code is sending between 2 and many SMSs per response which I find strange. I think I will dissect the code and test each stage. All your comments relate to code I never wrote, the code claims to be non-blocking which seems like witchcraft to me!

I have no idea how commands sent to gsmserial.print(): are ending up in the serial monitor unless the TC35 echos commands back to acknowledge, unfortunately the TC35 has a 400+ page datasheet and not quite built up the courage to start reading it just yet!.

I will start dissecting the code and start again from scratch, I will of course post up my findings to help others with this inexpensive GSM module.

If anyone is interested here is the output in the serial monitor after a) initialisation b) me texting the unit with the command "Temp" and it replying twice with the temperature.

Code:
19.62
AT+CMGF=1
OK
AT+CNMI=2,1,0,0,1
OK
AT^SMGO=1
OK
AT&W
8,6
+CR: 0
+FCLASS: 0
+CRC: 0
+CMGF: 1
+CSDH: 0
+CNMI: 2,1,0,0,1
+ILRR: 0
+IPR: 0
+CMEE: 0
^SMGO: 1,0
+CSMS: 0,1,1,1
^SACM: 0,"000000","FFFFFF"
^SCKS: 0,1
+CREG: 0,1
+CLIP: 1,2
+CAOC: 0
+COPS: 0,0,"Virgin"

OK

+CMTI: "SM",8
AT+CMGR=8
+CMGR: "REC UNREAD","+447914xxxxxx",,"13/03/12,20:39:50+00"
Temp
deleting SMS 8
†
OK
AT+CMGF=1
OK
AT+CMGS="+447914xxxxxx"
> Livingroom Temperature: 19.69AT+CMGD
deleting SMS 8
+CMGS: 21

OK
AT+CMGF=1
OK
AT+CMGS="+447914xxxxxx"
> *Ëre: 19.69AT+CMGD=
+CMGS: 22

OK

Craig
Logged

Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, I have the same idea as Peter, that you don't actually delete the message the first time you try. I'm pretty sure that the following delay is way too short to have the modem ready to accept the delete command.

Code:
  gsmSerial.print("\x1A"); // this is where the phone actually starts sending the message
  delay(15); // this is almost no delay
  delete_one_SMS(); // most likely, the phone is still sending the message and waiting to send its OK response

The library (assuming we are talking of the same library, the one I know is https://github.com/lthiery/GSMSerial) defines the following:
Code:
#define TXT_SEND_DELAY 9000

Not a small difference with your value.

A couple of questions out of personal curiosity: is there a reason for coding all these gsmSerial.print() instead of using some of the library functions (e.g. gsmSerial.sendTxt())? How did you address the problem of logical level conversion between 2.65V CMOS levels on the GSM side and 5V TTL levels on the Arduino side?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A couple of questions out of personal curiosity: is there a reason for coding all these gsmSerial.print() instead of using some of the library functions (e.g. gsmSerial.sendTxt())? How did you address the problem of logical level conversion between 2.65V CMOS levels on the GSM side and 5V TTL levels on the Arduino side?

Oh $#!t, never realisied that it was 2.65V, i've been bit banging it with the 5v arduino (so far no problems!). It is on a sainsmart TC35 shield and any diagrams to hook it up show direct connection of the TX, RX & GND??.

I am only using the SoftwareSerial library but will definitely be investigating the GSMserial library. (and the delays). thank you spatula
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have now researched methods of changing between the 3.3v (for GSM) and 5v (arduino) and think for simplicity I will try voltage dividing with a couple of resistors (10k/20k) on the Tx of the arduino. I do not think I need anything on the Rx line (softwareSerial) as it appears to be reading the lower voltage signal ok?

Any comments on this method from the electronics experts?

Craig
Logged

Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Not an electronics expert myself (that's why I was asking smiley-wink). But it sounds reasonable to me. I understand you should only ensure that the logical HIGH is not above 3.3 and doesn't fall below 2V. For extra safety you could put a diode on the RX side, just to prevent spikes traversing the wire in the wrong direction.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi everyone, i'm new in this forum.
I did try the past code for my project and after the "recognition" with command AT&W, in serial display, the system didn't give me an answer about the command "+CMTI".
I have sent a message with the text "Red" for turn on the LED
But the system didin't works.
Anyone can help me?
Logged

Pages: [1]   Go Up
Jump to: