Data processing. Getting time and date.

(Ok this is my first time doing any data processing, all my other projects have switch inputs / outputs etc.

I have my arduino connected to my phone via the hardware serial port, when I send the command "AT+CCLK?" the phone responds with the current date and time in this format:

"+CCLK: "08/11/25,21:48:48+48""

How would I go about getting the time and date from this and putting them into their own variables such as TIME and DATE?

Ie, DATE would be 25.11.08, and TIME would be 21:48:48.

So "+CCLK:" would be stripped out from the start, and the "+48" would be stripped from the end, and then the date re-arranged and put into a variable, and then the time put into a varible.

I have no idea where to start!

I hope the following sketch will help

// example string in form of: yy/mm/dd,hh:mm:ss
char * rawStr = "+CCLK: \"08/11/25,21:48:48+48\""; // note that escape chars are needed to represent quotes in strings
char * timeStr = rawStr + 8; //ignore first 8 characters


void setup(){
  Serial.begin(9600);
}


// converts two characters from date string into a two digit decimal value
int dateToDecimal(char * date){
    int value = ((date[0] - '0') * 10) +  (date[1] - '0');
    return value;
}

void  loop(){

  int sec, min, hour,  day, month,  year;
  year  = dateToDecimal(&timeStr[0]) ;
  month = dateToDecimal(&timeStr[3]) ;
  day   = dateToDecimal(&timeStr[6]) ;
  hour  = dateToDecimal(&timeStr[9]) ;
  min   = dateToDecimal(&timeStr[12]) ;
  sec   = dateToDecimal(&timeStr[15]) ;
  
  Serial.println("date components are ");
  Serial.println(year);
  Serial.println(month);
  Serial.println(day);
  Serial.println(hour);
  Serial.println(min);
  Serial.println(sec);

  
  delay(10000);
}

In this example sketch we represent the string as follows:
"+CCLK: "08/11/25,21:48:48+48"";

those '' chars are the C escape character and are needed to represent a quotation mark in C string constant but are not part of the string itself. You can read about C escape characters if that is not clear. Anyway, I needed them for the example but your code can probably just parse over the leading characters.

Hrrm, thanks for that. I kind of understand it, but will study it more later to see how it fully works :slight_smile:

Now what im trying to do is send a command to the phone to request the time and date, and then store it in "char * rawStr" for processing later on. Though when I try rawStr = Serial.read(); I get an error compiling

 In function 'void loop()':
error: invalid conversion from 'int' to 'char*'

I suspect Serial.read() is expecting an int instead of char?

Here is my code :slight_smile:

char * rawStr = "";



void setup(){
  Serial.begin(9600);
}


void  loop(){
  Serial.print("AT+CCLK?"); //Send command to phone to request time and date

if (Serial.available() > 0) {
            
            rawStr = Serial.read();            
      }  
  delay(10000);
}

I pulled alot of the code out, for now I just want to get it saving the info that the phone sends in a variable, then try the rest.

Here is some untested code to get you going. It may need some work so you should read about using the arduino Serial. commands to get and parse strings. If there is an expression in the code that you don't understand and its not in the Arduino reference then google can be helpful in finding out how to use it.

Good Luck!

#define CCLK_MSG_LEN 28  // total characters in the CCLK message
#define TIME_STR_LEN 18  // the actual number of characters for date and time

char timeStr[TIME_STR_LEN]; // holds the time string
char timePreamble[] = "CCLK: \"" ; // there is a quotation mark in the string so we need the C escape char

void setup(){
  Serial.begin(9600);
  Serial.print("AT+CCLK?"); //Send command to phone to request time and date
}

boolean getTime(){
  if(Serial.available() >= CCLK_MSG_LEN ){
    if( Serial.read() == '+'){ // check if start of string
      for(int i=0; i < strlen(timePreamble); i++){
        if( Serial.read() != timePreamble[i] )
          return false; // exit if the received data does not match the preamble 
      }
      // we are now at the start of the time data
      for(int i=i; i < TIME_STR_LEN; i++)
        timeStr[i] = Serial.read();
      return true; // we have filled the timeString with valid data   
    }
  }   

  return false; // we dont have a full message starting with the CCLK preamble 
}

// converts two characters from date string into a two digit decimal value
int dateToDecimal(char * date){
  int value = ((date[0] - '0') * 10) +  (date[1] - '0');
  return value;
}

void loop()
{  
  int sec, min, hour,  day, month,  year;

  if(getTime() == true){
    year  = dateToDecimal(&timeStr[0]) ;
    month = dateToDecimal(&timeStr[3]) ;
    day   = dateToDecimal(&timeStr[6]) ;
    hour  = dateToDecimal(&timeStr[9]) ;
    min   = dateToDecimal(&timeStr[12]) ;
    sec   = dateToDecimal(&timeStr[15]) ;

    Serial.println("date components are ");
    Serial.println(year,DEC);
    Serial.println(month,DEC);
    Serial.println(day,DEC);
    Serial.println(hour,DEC);
    Serial.println(min,DEC);
    Serial.println(sec,DEC);

    delay(10000);
  }
}

Hrrm, the phone does not seem to reply when the arduino sends the command. When the arduino sends "ATD777" (command to dial 777), it works perfectly and dials the number so it is receiving the commands.

When I use hyperterminal (through the arduino FTDI chip. I remove the arduino chip) the phone responds correctly.

I connected a serial LCD, and setup software serial, and changed the "Serial.println("date components are ")" lines to mySerial, so they should print to the LCD.

Also watching the TX / RX leds, I can see the arduino is sending the command, but the RX light never blinks so I believe the arduino isnt getting a reply. Though soon as I use hyperterminal it works fine...

I wonder if you are sending a carriage return/linefeed for ATDT command but not for the CCLK? Does your ATDT line use println? If it does then try that with the CCLK command.

If you can't see any difference between how you send the two commands, then you may want to display the return codes from the phone. For testing purposes you can modify the sketch I posted so instead of calling getTime, you just displays the received serial data on your LCD. That may tell you if the phone has accepted your CCLK command, and if so it will show you exactly what data you get back. If its not exactly the same as you posted you will need to modify the getTime code to look for the exact characters (including any carriage return/ linefeed).

Yeah, changing it to println is somthing I also tryed, but it didnt help (same as I used for ATD).

Ill try modifying getTime() tommorow.

You don't need to modify the getTime function, in loop just replace the call to getTime with code that reads a character when its available and sends it to the LCD

void setup(){
Serial.begin(9600);
Serial.print("AT+CCLK?"); //Send command to phone to request time and date
}
void loop(){
if(Serial.available() >0 ){
char c = Serial.read();
// add code here that sends c to your LCD
}
}

Hrrm I think it may be a hardware issue. I can see the TX light working when the arduino is sending commands to the phone, but the RX light never works, so I think the arduino is not receiving the response. Maybe the phone is not powerful enough to drive the arduino and FTDI chip at the same time? With the arduino plugged in and running the simple blink code (dosent initialise UART port on arduino) I can talk to the phone via hyperterminal with no problems. Though soon as i use Serial.begin the arduino does not receive any response, though I am sure the phone is sending it, I dont think the signal is strong enough for the arduino to recognise it.

Does Serial.begin change the state of the UART pins on the arudino, like low / high impedance which may affect it?

Hrrm, If I connect the TX/RX ports of the arduino togethor, and it sends a command, shouldnt it receive that command and print it to the LCD?

I tryed this, and the RX light did not blink with the TX light, which I thought it should...

Ok so I think the problem is that the phone uses a 3.3v signal, which appears to be enough to drive the FTDI chip, but not the arduino. Ill order a level shifting board from sparkfun and give that a go.

You can easily build a level shifter using few components if you want to get somthing going before yr sparkfun order arrives. Some methods were discussed here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1225292345/8

Yes, I read that thread earlier :wink:

Do you think this could possibly be the problem? I have read in alot of places that 3.3v is enough for alot of 5v devices...

Ill get some parts tommorow and give it a go though.

3.3 volts should be more than enough for arduino inputs. But you may need a scope to see exactly how much voltage your phone is providing.

Have you done a test to see if characters are being received by checking if the value of Serial.available increases when the phone sends info. Run a test to see if you get the right number of characters, if you do then the problem is in decoding the incoming data. If nothing is coming in or some characters are lost then it could be something like a voltage level problem

Cheers, Ill give that a go tommorow before I try the level shifting.

Edit: Acutally I just measured the voltage on the TX line of the phone and it is only 2.7v, so I guess that is the issue.

A voltage above 2.5 volts should be detected as HIGH on the digital inputs. If you are sure the signal is at least that level then its probably not a voltage level issue.

Have you done a test to see if Serial.available() increases in value when characters are sent from the phone?

Ok I made a small program to test it.

#include <SoftwareSerial.h>

#define rxPin 2
#define txPin 3

int incoming = 0;

SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);

void setup() {
// define pin modes for tx, rx, led pins:
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);

// set the data rate for the SoftwareSerial port
mySerial.begin(9600);
Serial.begin(9600);
backlightOn();
}

void loop() {
Serial.println("AT");
incoming = Serial.available();
delay(100);
selectLineOne();
delay(100);
mySerial.print(incoming);

}

It counts up to 127, then stops there. Im guessing the UART buffer is full at 127 ?

Appears to be working correctly, if I ring the phone it sends "RING" over the serial port (well that what shows up in hyperterminal anyway), and "incoming" increases by 8 each time.

Edit: It is now working correctly and printing to the LCD :smiley: I will tidy up my code and then post it.

#include <SoftwareSerial.h>

#define rxPin 2
#define txPin 3

SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);

void setup() {
// define pin modes for tx, rx, led pins:
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);

// set the data rate for the SoftwareSerial port
mySerial.begin(9600);
Serial.begin(9600);
Serial.println("ATE0"); //Send command to phone to turn off echo
delay(100);
Serial.println("AT+CCLK?"); //Send command to phone to request time and date

}
void loop(){

if(Serial.available() >0 ){
char c = Serial.read();

//selectLineOne();
mySerial.print(c);
}
delay(50); //Need small delay to stop LCD from scrambling.
}

Pic of LCD and output:

Im not sure what the solid blocks are, maybe a linefeed / carrige return?

Time / Date etc:

Good to hear you have it going, what did you change to make it work?

Yes, the blocks are carriage return and line feeds

You will probably want to add some code that prints a leading zero if the hour/minute/second values are a single digit.

I find the following useful for doing this, change Serial for your LCD

void printDigits(byte digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits,DEC);
}

Just out of curiosity... What phone are you using?

Thanks,

I am not sure what I changed to make it work, it just suddenly started working :o

Thanks for your help mem. :slight_smile:

I am not worried about fixing the time as this was a test to make sure everything worked and to teach my self about it. Eventually I want to build a GPS tracker, so I need to figure out which is the best way to do this, using GPRS or SMS.

Using GPRS I can just send the data straight to a webserver, I can start a GPRS with the arduino, but don't think I can send GET or POST requests over it. I would have to write a program for the phone, which I dont think it supports.

The other way is to use SMS, it would send SMS with the NMEA data to another phone which is connected to a computer which would then show the location in google earth.

Because the T230 does not support "text" mode for sending SMS I will need to use "PDU" mode, so my project now is to have the arduino pack NMEA data into a PDU so it can be sent to another phone. I have found alot of other people encoding and decoding PDU on AVR's but all in assembly, which I dont understand. Decoding PDU's would be nice aswell so it could receive commands via SMS, but not necessary.

I think I need to make a new thread about it.

I am using a Sony Ericsson T230.