/* This is a Beta version. last modified 18/08/2012. This library is based on one developed by Arduino Labs and it is modified to preserve the compability with the Arduino's product. The library is modified to use the GSM Shield, developed by www.open-electronics.org (http://www.open-electronics.org/arduino-gsm-shield/) and based on SIM900 chip, with the same commands of Arduino Shield, based on QuectelM10 chip. */ #include "GSM.h" #include "WideTextFinder.h" //De-comment this two lines below if you have the //first version of GSM GPRS Shield //#define _GSM_TXPIN_ 4 //#define _GSM_RXPIN_ 5 //De-comment this two lines below if you have the //second version og GSM GPRS Shield #define _GSM_TXPIN_ 2 #define _GSM_RXPIN_ 3 #ifdef UNO GSM::GSM():_cell(_GSM_TXPIN_,_GSM_RXPIN_),_tf(_cell, 10),_status(IDLE){ }; #endif #ifdef MEGA GSM::GSM(){ _cell.begin(9600); }; #endif int GSM::begin(long baud_rate){ int response=-1; int cont=0; boolean norep=false; boolean turnedON=false; SetCommLineStatus(CLS_ATCMD); _cell.begin(baud_rate); setStatus(IDLE); for (cont=0; cont<3; cont++){ if (AT_RESP_ERR_NO_RESP == SendATCmdWaitResp("AT", 500, 100, "OK", 5)&&!turnedON) { //check power // there is no response => turn on the module #ifdef DEBUG_ON Serial.println("DB:NO RESP"); #endif // generate turn on pulse digitalWrite(GSM_ON, HIGH); delay(1200); digitalWrite(GSM_ON, LOW); delay(10000); norep=true; } else{ #ifdef DEBUG_ON Serial.println("DB:ELSE"); #endif norep=false; } } if (AT_RESP_OK == SendATCmdWaitResp("AT", 500, 100, "OK", 5)){ #ifdef DEBUG_ON Serial.println("DB:CORRECT BR"); #endif turnedON=true; } if(cont==3&&norep){ Serial.println("Trying to force the baud-rate to 9600\n"); for (int i=0;i<8;i++){ switch (i) { case 0: _cell.begin(1200); _cell.print(F("AT+IPR=9600\r")); break; case 1: _cell.begin(2400); _cell.print(F("AT+IPR=9600\r")); break; case 2: _cell.begin(4800); _cell.print(F("AT+IPR=9600\r")); break; case 3: _cell.begin(9600); _cell.print(F("AT+IPR=9600\r")); break; case 4: _cell.begin(19200); _cell.print(F("AT+IPR=9600\r")); break; case 5: _cell.begin(38400); _cell.print(F("AT+IPR=9600\r")); break; case 6: _cell.begin(57600); _cell.print(F("AT+IPR=9600\r")); break; case 7: _cell.begin(115200); _cell.print(F("AT+IPR=9600\r")); break; } } Serial.println("ERROR: SIM900 doesn't answer. Check power and serial pins in GSM.cpp"); return 0; } if (AT_RESP_ERR_DIF_RESP == SendATCmdWaitResp("AT", 500, 100, "OK", 5)&&!turnedON){ //check OK #ifdef DEBUG_ON Serial.println("DB:DIFF RESP"); #endif for (int i=0;i<8;i++){ switch (i) { case 0: _cell.begin(1200); break; case 1: _cell.begin(2400); break; case 2: _cell.begin(4800); break; case 3: _cell.begin(9600); break; case 4: _cell.begin(19200); break; case 5: _cell.begin(38400); break; case 6: _cell.begin(57600); break; case 7: _cell.begin(115200); _cell.print(F("AT+IPR=9600\r")); _cell.begin(9600); delay(500); break; // if nothing else matches, do the default // default is optional } delay(100); #ifdef DEBUG_PRINT // parameter 0 - because module is off so it is not necessary // to send finish AT here DebugPrint("DEBUG: Stringa ", 0); DebugPrint(buff, 0); #endif if (AT_RESP_OK == SendATCmdWaitResp("AT", 500, 100, "OK", 5)){ #ifdef DEBUG_ON Serial.println("DB:FOUND PREV BR"); #endif _cell.print(F("AT+IPR=")); _cell.print(baud_rate); _cell.print("\r"); // send delay(500); _cell.begin(baud_rate); delay(100); if (AT_RESP_OK == SendATCmdWaitResp("AT", 500, 100, "OK", 5)){ #ifdef DEBUG_ON Serial.println("DB:OK BR"); #endif } turnedON=true; break; } #ifdef DEBUG_ON Serial.println("DB:NO BR"); #endif } // communication line is not used yet = free SetCommLineStatus(CLS_FREE); // pointer is initialized to the first item of comm. buffer p_comm_buf = &comm_buf[0]; } SetCommLineStatus(CLS_FREE); if(turnedON){ WaitResp(50, 50); InitParam(PARAM_SET_0); InitParam(PARAM_SET_1);//configure the module Echo(0); //enable AT echo setStatus(READY); return(1); } else{ //just to try to fix some problems with 115200 baudrate _cell.begin(115200); delay(1000); _cell.print(F("AT+IPR=")); _cell.print(baud_rate); _cell.print("\r"); // send return(0); } } void GSM::InitParam(byte group){ switch (group) { case PARAM_SET_0: // check comm line //if (CLS_FREE != GetCommLineStatus()) return; SetCommLineStatus(CLS_ATCMD); // Reset to the factory settings SendATCmdWaitResp("AT&F", 1000, 50, "OK", 5); // switch off echo SendATCmdWaitResp("ATE0", 500, 50, "OK", 5); // setup fixed baud rate //SendATCmdWaitResp("AT+IPR=9600", 500, 50, "OK", 5); // setup mode //SendATCmdWaitResp("AT#SELINT=1", 500, 50, "OK", 5); // Switch ON User LED - just as signalization we are here //SendATCmdWaitResp("AT#GPIO=8,1,1", 500, 50, "OK", 5); // Sets GPIO9 as an input = user button //SendATCmdWaitResp("AT#GPIO=9,0,0", 500, 50, "OK", 5); // allow audio amplifier control //SendATCmdWaitResp("AT#GPIO=5,0,2", 500, 50, "OK", 5); // Switch OFF User LED- just as signalization we are finished //SendATCmdWaitResp("AT#GPIO=8,0,1", 500, 50, "OK", 5); SetCommLineStatus(CLS_FREE); break; case PARAM_SET_1: // check comm line //if (CLS_FREE != GetCommLineStatus()) return; SetCommLineStatus(CLS_ATCMD); // Request calling line identification SendATCmdWaitResp(F("AT+CLIP=1"), 500, 50, "OK", 5); // Mobile Equipment Error Code SendATCmdWaitResp(F("AT+CMEE=0"), 500, 50, "OK", 5); // Echo canceller enabled //SendATCmdWaitResp("AT#SHFEC=1", 500, 50, "OK", 5); // Ringer tone select (0 to 32) //SendATCmdWaitResp("AT#SRS=26,0", 500, 50, "OK", 5); // Microphone gain (0 to 7) - response here sometimes takes // more than 500msec. so 1000msec. is more safety //SendATCmdWaitResp("AT#HFMICG=7", 1000, 50, "OK", 5); // set the SMS mode to text SendATCmdWaitResp(F("AT+CMGF=1"), 500, 50, "OK", 5); // Auto answer after first ring enabled // auto answer is not used //SendATCmdWaitResp("ATS0=1", 500, 50, "OK", 5); // select ringer path to handsfree //SendATCmdWaitResp("AT#SRP=1", 500, 50, "OK", 5); // select ringer sound level //SendATCmdWaitResp("AT+CRSL=2", 500, 50, "OK", 5); // we must release comm line because SetSpeakerVolume() // checks comm line if it is free SetCommLineStatus(CLS_FREE); // select speaker volume (0 to 14) //SetSpeakerVolume(9); // init SMS storage InitSMSMemory(); // select phonebook memory storage SendATCmdWaitResp(F("AT+CPBS=\"SM\""), 1000, 50, "OK", 5); SendATCmdWaitResp(F("AT+CIPSHUT"), 500, 50, "SHUT OK", 5); break; } } byte GSM::WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout, char const *expected_resp_string) { byte status; byte ret_val; RxInit(start_comm_tmout, max_interchar_tmout); // wait until response is not finished do { status = IsRxFinished(); } while (status == RX_NOT_FINISHED); if (status == RX_FINISHED) { // something was received but what was received? // --------------------------------------------- if(IsStringReceived(expected_resp_string)) { // expected string was received // ---------------------------- ret_val = RX_FINISHED_STR_RECV; } else { ret_val = RX_FINISHED_STR_NOT_RECV; } } else { // nothing was received // -------------------- ret_val = RX_TMOUT_ERR; } return (ret_val); } /********************************************************** Method sends AT command and waits for response return: AT_RESP_ERR_NO_RESP = -1, // no response received AT_RESP_ERR_DIF_RESP = 0, // response_string is different from the response AT_RESP_OK = 1, // response_string was included in the response **********************************************************/ char GSM::SendATCmdWaitResp(char const *AT_cmd_string, uint16_t start_comm_tmout, uint16_t max_interchar_tmout, char const *response_string, byte no_of_attempts) { byte status; char ret_val = AT_RESP_ERR_NO_RESP; byte i; for (i = 0; i < no_of_attempts; i++) { // delay 500 msec. before sending next repeated AT command // so if we have no_of_attempts=1 tmout will not occurred if (i > 0) delay(500); _cell.println(AT_cmd_string); status = WaitResp(start_comm_tmout, max_interchar_tmout); if (status == RX_FINISHED) { // something was received but what was received? // --------------------------------------------- if(IsStringReceived(response_string)) { ret_val = AT_RESP_OK; break; // response is OK => finish } else ret_val = AT_RESP_ERR_DIF_RESP; } else { // nothing was received // -------------------- ret_val = AT_RESP_ERR_NO_RESP; } } return (ret_val); } /********************************************************** Method sends AT command and waits for response return: AT_RESP_ERR_NO_RESP = -1, // no response received AT_RESP_ERR_DIF_RESP = 0, // response_string is different from the response AT_RESP_OK = 1, // response_string was included in the response **********************************************************/ char GSM::SendATCmdWaitResp(const __FlashStringHelper *AT_cmd_string, uint16_t start_comm_tmout, uint16_t max_interchar_tmout, char const *response_string, byte no_of_attempts) { byte status; char ret_val = AT_RESP_ERR_NO_RESP; byte i; for (i = 0; i < no_of_attempts; i++) { // delay 500 msec. before sending next repeated AT command // so if we have no_of_attempts=1 tmout will not occurred if (i > 0) delay(500); _cell.println(AT_cmd_string); status = WaitResp(start_comm_tmout, max_interchar_tmout); if (status == RX_FINISHED) { // something was received but what was received? // --------------------------------------------- if(IsStringReceived(response_string)) { ret_val = AT_RESP_OK; break; // response is OK => finish } else ret_val = AT_RESP_ERR_DIF_RESP; } else { // nothing was received // -------------------- ret_val = AT_RESP_ERR_NO_RESP; } } return (ret_val); } byte GSM::WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout) { byte status; RxInit(start_comm_tmout, max_interchar_tmout); // wait until response is not finished do { status = IsRxFinished(); } while (status == RX_NOT_FINISHED); return (status); } byte GSM::IsRxFinished(void) { byte num_of_bytes; byte ret_val = RX_NOT_FINISHED; // default not finished // Rx state machine // ---------------- if (rx_state == RX_NOT_STARTED) { // Reception is not started yet - check tmout if (!_cell.available()) { // still no character received => check timeout /* #ifdef DEBUG_GSMRX DebugPrint("\r\nDEBUG: reception timeout", 0); Serial.print((unsigned long)(millis() - prev_time)); DebugPrint("\r\nDEBUG: start_reception_tmout\r\n", 0); Serial.print(start_reception_tmout); #endif */ if ((unsigned long)(millis() - prev_time) >= start_reception_tmout) { // timeout elapsed => GSM module didn't start with response // so communication is takes as finished /* #ifdef DEBUG_GSMRX DebugPrint("\r\nDEBUG: RECEPTION TIMEOUT", 0); #endif */ comm_buf[comm_buf_len] = 0x00; ret_val = RX_TMOUT_ERR; } } else { // at least one character received => so init inter-character // counting process again and go to the next state prev_time = millis(); // init tmout for inter-character space rx_state = RX_ALREADY_STARTED; } } if (rx_state == RX_ALREADY_STARTED) { // Reception already started // check new received bytes // only in case we have place in the buffer num_of_bytes = _cell.available(); // if there are some received bytes postpone the timeout if (num_of_bytes) prev_time = millis(); // read all received bytes while (num_of_bytes) { num_of_bytes--; if (comm_buf_len < COMM_BUF_LEN) { // we have still place in the GSM internal comm. buffer => // move available bytes from circular buffer // to the rx buffer *p_comm_buf = _cell.read(); p_comm_buf++; comm_buf_len++; comm_buf[comm_buf_len] = 0x00; // and finish currently received characters // so after each character we have // valid string finished by the 0x00 } else { // comm buffer is full, other incoming characters // will be discarded // but despite of we have no place for other characters // we still must to wait until // inter-character tmout is reached // so just readout character from circular RS232 buffer // to find out when communication id finished(no more characters // are received in inter-char timeout) _cell.read(); } } // finally check the inter-character timeout /* #ifdef DEBUG_GSMRX DebugPrint("\r\nDEBUG: intercharacter", 0); < Serial.print((unsigned long)(millis() - prev_time)); DebugPrint("\r\nDEBUG: interchar_tmout\r\n", 0); Serial.print(interchar_tmout); #endif */ if ((unsigned long)(millis() - prev_time) >= interchar_tmout) { // timeout between received character was reached // reception is finished // --------------------------------------------- /* #ifdef DEBUG_GSMRX DebugPrint("\r\nDEBUG: OVER INTER TIMEOUT", 0); #endif */ comm_buf[comm_buf_len] = 0x00; // for sure finish string again // but it is not necessary ret_val = RX_FINISHED; } } return (ret_val); } /********************************************************** Method checks received bytes compare_string - pointer to the string which should be find return: 0 - string was NOT received 1 - string was received **********************************************************/ byte GSM::IsStringReceived(char const *compare_string) { char *ch; byte ret_val = 0; if(comm_buf_len) { /* #ifdef DEBUG_GSMRX DebugPrint("DEBUG: Compare the string: \r\n", 0); for (int i=0; i,,,,, if (AT_RESP_OK == SendATCmdWaitResp("AT+CPMS=\"SM\",\"SM\",\"SM\"", 1000, 1000, "+CPMS:", 10)) { ret_val = 1; } else ret_val = 0; SetCommLineStatus(CLS_FREE); return (ret_val); } int GSM::isIP(const char* cadena) { int i; for (i=0; i=48 && cadena[i] <=57))) return 0; return 1; }