This tutorial allows the user to move a servo sending text messages with the mobile phone. Depending on the number received by the module, the servo is placed in one position or another corresponding to the indicated degrees.
Ingredients:
Preparation Time: 30 minutes
Buy nowThis project can be developed with Arduino or Intel Galileo. It is also compatible with Raspberry Pi using the Raspberry Pi to Arduino shields connection bridge.
For further information about the GPRS+GPS (SIM908) Shield, consult the main tutorial.
Connect the GPRS antenna to the shield and then, connect the shield to the Arduino or to Raspberry Pi connection bridge. Connect servo in the breadboard as you can see in the next diagram.
Connect two wires, red and black, to the two long rows on the side of the breadboard to provide access to 3.3 volt supply and ground. Servo has 3 wires with different colors. Connect Black/Brown wire to GND, Red wire to 3.3 volt and the remaining wire, Yellow/Orange, to pin 9 of Arduino. Pin 9 has PWM control so you can move your servo from 0 to 180 degrees.
Arduino:
/* * GPRS+GPS Quadband Module (SIM908) * * Copyright (C) Libelium Comunicaciones Distribuidas S.L. * http://www.libelium.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * a * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Version: 1.0 * Design: David GascĂłn * Implementation: Victor Boria */ #include <Servo.h> //Include the servo-motor library //Enter here you data const char pin_number[] = "****"; // Write the pin number of the SIM card Servo myServo; // Create a servo object int angle; // Variable to hold the angle for the servo motor int8_t answer; int onModulePin = 2; char aux_string[50]; unsigned long previous; int count; void setup() { myServo.attach(9); // Attaches the servo on pin 9 to the servo object myServo.write(90); // Set the servo in the center position pinMode(onModulePin, OUTPUT); Serial.begin(115200); Serial.println("Starting..."); power_on(); // Powering the module delay(3000); //sets the PIN code sprintf(aux_string, "AT+CPIN=%s", pin_number); sendATcommand(aux_string, "OK", 2000); delay(3000); Serial.println("Connecting to the network..."); while ( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) || sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 ); Serial.print("Setting SMS mode..."); sendATcommand("AT+CMGF=1", "OK", 1000); // sets the SMS mode to text sendATcommand("AT+CPMS=\"SM\",\"SM\",\"SM\"", "OK", 1000); // selects the memory sendATcommand("AT+CNMI=2,1,0,0", "OK", 1000); // Sets mode to wait for an incoming SMS Serial.println("Waiting incoming SMS"); } void loop() { answer = sendATcommand("", "+CMTI: ", 1000); //Detect incomming SMS if (answer == 1) { count = 0; previous = millis(); do { while (((millis() - previous) < 1000) && (Serial.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } // Condition to avoid an overflow if ( millis() < previous) previous = millis(); //Search a "," in the command received } while (((millis() - previous) < 1000) && (Serial.read() != ',')); previous = millis(); do { while (((millis() - previous) < 1000) && (Serial.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } aux_string[count] = Serial.read(); count++; // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } while ((aux_string[count - 1] != '\r') && ((millis() - previous) < 1000) && (count < 30)); aux_string[count - 1] = '\0'; count = atoi(aux_string); Serial.print(F("SMS index: ")); Serial.println(count, DEC); Serial.println(aux_string); if (count != 0) { //Check the comunication with the module sendATcommand("AT", "OK", 1000); //Read the received SMS snprintf(aux_string, sizeof(aux_string), "AT+CMGR=%d", count); answer = sendATcommand(aux_string, "+CMGR:", 1000); if (answer == 1) { previous = millis(); do { while (((millis() - previous) < 1000) && (Serial.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } while (((millis() - previous) < 1000) && (Serial.read() != '\n')); count = 0; previous = millis(); do { while (((millis() - previous) < 1000) && (Serial.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } aux_string[count] = Serial.read(); count++; // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } while ((strstr(aux_string, "OK") == NULL) && ((millis() - previous) < 1000) && (count < 30)); aux_string[count - 1] = '\0'; Serial.print("Received SMS: "); Serial.println(aux_string); //Conversion de string a int angle = atoi(aux_string); //The servo turn the angle read in the SMS myServo.write(angle); } } } } void power_on() { uint8_t answer = 0; // checks if the module is started answer = sendATcommand("AT", "OK", 2000); if (answer == 0) { // power on pulse digitalWrite(onModulePin, HIGH); delay(3000); digitalWrite(onModulePin, LOW); // waits for an answer from the module while (answer == 0) { // Send AT every two seconds and wait for the answer answer = sendATcommand("AT", "OK", 2000); } } } int8_t sendATcommand(char * ATcommand, char * expected_answer, unsigned int timeout) { uint8_t x = 0, answer = 0; char response[100]; unsigned long previous; memset(response, '\0', 100); // Initialice the string delay(100); while ( Serial.available() > 0) Serial.read(); // Clean the input buffer if (ATcommand[0] != '\0') { Serial.println(ATcommand); // Send the AT command } x = 0; previous = millis(); // this loop waits for the answer do { // if there are data in the UART input buffer, reads it and checks for the asnwer if (Serial.available() != 0) { response[x] = Serial.read(); x++; // check if the desired answer is in the response of the module if (strstr(response, expected_answer) != NULL) { answer = 1; } } // Waits for the asnwer with time out } while ((answer == 0) && ((millis() - previous) < timeout)); return answer; }
Raspberry Pi:
/* * GPRS+GPS Quadband Module (SIM908) * * Copyright (C) Libelium Comunicaciones Distribuidas S.L. * http://www.libelium.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * a * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Version: 1.0 * Design: David GascĂłn * Implementation: Marcos MartĂnez */ //Include arduPi library #include "arduPi.h" int8_t sendATcommand(const char* ATcommand, const char* expected_answer, unsigned int timeout); void power_on(); void servoWrite(int servo, int angle); int servo = 9; int angle; unsigned int us; //Enter here you data const char pin_number[] = "****"; // Write the pin number of the SIM card int8_t answer; int onModulePin = 2; char aux_string[50]; unsigned long previous; int count; void setup() { pinMode(onModulePin, OUTPUT); pinMode(servo, OUTPUT); Serial.begin(115200); printf("Starting...\n"); power_on(); // Powering the module delay(3000); //sets the PIN code sprintf(aux_string, "AT+CPIN=%s", pin_number); sendATcommand(aux_string, "OK", 2000); delay(3000); printf("Connecting to the network...\n"); while ( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) || sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 ); printf("Setting SMS mode...\n"); sendATcommand("AT+CMGF=1", "OK", 1000); // sets the SMS mode to text sendATcommand("AT+CPMS=\"SM\",\"SM\",\"SM\"", "OK", 1000); // selects the memory sendATcommand("AT+CNMI=2,1,0,0", "OK", 1000); // Sets mode to wait for an incoming SMS printf("Waiting incoming SMS\n"); } void loop() { answer = sendATcommand("", "+CMTI: ", 1000); //Detect incomming SMS if (answer == 1) { count = 0; previous = millis(); do { while (((millis() - previous) < 1000) && (Serial.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } // Condition to avoid an overflow if ( millis() < previous) previous = millis(); //Search a "," in the command received } while (((millis() - previous) < 1000) && (Serial.read() != ',')); previous = millis(); do { while (((millis() - previous) < 1000) && (Serial.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } aux_string[count] = Serial.read(); count++; // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } while ((aux_string[count - 1] != '\r') && ((millis() - previous) < 1000) && (count < 30)); aux_string[count - 1] = '\0'; count = atoi(aux_string); printf("SMS index: %i %s\n",count,aux_string); if (count != 0) { //Check the comunication with the module sendATcommand("AT", "OK", 1000); //Read the received SMS snprintf(aux_string, sizeof(aux_string), "AT+CMGR=%d", count); answer = sendATcommand(aux_string, "+CMGR:", 1000); if (answer == 1) { previous = millis(); do { while (((millis() - previous) < 1000) && (Serial.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } while (((millis() - previous) < 1000) && (Serial.read() != '\n')); count = 0; previous = millis(); do { while (((millis() - previous) < 1000) && (Serial.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } aux_string[count] = Serial.read(); count++; // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } while ((strstr(aux_string, "OK") == NULL) && ((millis() - previous) < 1000) && (count < 30)); aux_string[count - 1] = '\0'; printf("Received SMS: %s\n",aux_string); //Conversion de string a float angle = atof(aux_string); //The servo turn the angle read in the SMS servoWrite(servo,angle); } } } } void power_on() { uint8_t answer = 0; // checks if the module is started answer = sendATcommand("AT", "OK", 2000); if (answer == 0) { // power on pulse digitalWrite(onModulePin, HIGH); delay(3000); digitalWrite(onModulePin, LOW); // waits for an answer from the module while (answer == 0) { // Send AT every two seconds and wait for the answer answer = sendATcommand("AT", "OK", 2000); } } } int8_t sendATcommand(const char* ATcommand, const char* expected_answer, unsigned int timeout){ uint8_t x=0, answer=0; char response[100]; unsigned long previous; memset(response, '\0', 100); // Initialize the string delay(100); while( Serial.available() > 0) Serial.read(); // Clean the input buffer Serial.println(ATcommand); // Send the AT command x = 0; previous = millis(); // this loop waits for the answer do{ if(Serial.available() != 0){ // if there are data in the UART input buffer, reads it and checks for the asnwer response[x] = Serial.read(); printf("%c",response[x]); x++; // check if the desired answer is in the response of the module if (strstr(response, expected_answer) != NULL) { printf("\n"); answer = 1; } } } // Waits for the asnwer with time out while((answer == 0) && ((millis() - previous) < timeout)); return answer; } void servoWrite(int servo, int angle) { for(int i=0; i<20; i++){ us = (angle*11) + 450; // Convert angle to microseconds digitalWrite(servo, HIGH); delayMicroseconds(us); digitalWrite(servo, LOW); delay(50); // Refresh cycle of servo } } int main (){ setup(); while(1){ loop(); } return (0); }
Intel Galileo:
/* * GPRS+GPS Quadband Module (SIM908) * * Copyright (C) Libelium Comunicaciones Distribuidas S.L. * http://www.libelium.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * a * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Version: 1.0 * Design: David GascĂłn * Implementation: Jorge Casanova, Luis MartĂn */ #include <Servo.h> //Include the servo-motor library //Enter here you data const char pin_number[] = "****"; // Write the pin number of the SIM card Servo myServo; // Create a servo object int angle; // Variable to hold the angle for the servo motor int8_t answer; int onModulePin = 2; char aux_string[50]; unsigned long previous; int count; void setup() { myServo.attach(9); // Attaches the servo on pin 9 to the servo object myServo.write(90); // Set the servo in the center position pinMode(onModulePin, OUTPUT); Serial.begin(115200); Serial1.begin(115200); Serial.println("Starting..."); power_on(); // Powering the module delay(3000); //sets the PIN code sprintf(aux_string, "AT+CPIN=%s", pin_number); sendATcommand(aux_string, "OK", 2000); delay(3000); Serial.println("Connecting to the network..."); while ( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) || sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 ); Serial.print("Setting SMS mode..."); sendATcommand("AT+CMGF=1", "OK", 1000); // sets the SMS mode to text sendATcommand("AT+CPMS=\"SM\",\"SM\",\"SM\"", "OK", 1000); // selects the memory sendATcommand("AT+CNMI=2,1,0,0", "OK", 1000); // Sets mode to wait for an incoming SMS Serial.println("Waiting incoming SMS"); } void loop() { answer = sendATcommand("", "+CMTI: ", 1000); //Detect incomming SMS if (answer == 1) { count = 0; previous = millis(); do { while (((millis() - previous) < 1000) && (Serial1.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } // Condition to avoid an overflow if ( millis() < previous) previous = millis(); //Search a "," in the command received } while (((millis() - previous) < 1000) && (Serial1.read() != ',')); previous = millis(); do { while (((millis() - previous) < 1000) && (Serial1.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } aux_string[count] = Serial1.read(); count++; // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } while ((aux_string[count - 1] != '\r') && ((millis() - previous) < 1000) && (count < 30)); aux_string[count - 1] = '\0'; count = atoi(aux_string); Serial.print("SMS index: "); Serial.println(count, DEC); Serial.println(aux_string); if (count != 0) { //Check the comunication with the module sendATcommand("AT", "OK", 1000); //Read the received SMS snprintf(aux_string, sizeof(aux_string), "AT+CMGR=%d", count); answer = sendATcommand(aux_string, "+CMGR:", 1000); if (answer == 1) { previous = millis(); do { while (((millis() - previous) < 1000) && (Serial1.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } while (((millis() - previous) < 1000) && (Serial1.read() != '\n')); count = 0; previous = millis(); do { while (((millis() - previous) < 1000) && (Serial1.available() == 0)) { // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } aux_string[count] = Serial1.read(); count++; // Condition to avoid an overflow if ( millis() < previous) previous = millis(); } while ((strstr(aux_string, "OK") == NULL) && ((millis() - previous) < 1000) && (count < 30)); aux_string[count - 1] = '\0'; Serial.print("Received SMS: "); Serial.println(aux_string); //Conversion de string a int angle = atoi(aux_string); //The servo turn the angle read in the SMS myServo.write(angle); } } } } void power_on() { uint8_t answer = 0; // checks if the module is started answer = sendATcommand("AT", "OK", 2000); if (answer == 0) { // power on pulse digitalWrite(onModulePin, HIGH); delay(3000); digitalWrite(onModulePin, LOW); // waits for an answer from the module while (answer == 0) { // Send AT every two seconds and wait for the answer answer = sendATcommand("AT", "OK", 2000); } } } int8_t sendATcommand(char * ATcommand, char * expected_answer, unsigned int timeout) { uint8_t x = 0, answer = 0; char response[100]; unsigned long previous; memset(response, '\0', 100); // Initialice the string delay(100); while ( Serial1.available() > 0) Serial1.read(); // Clean the input buffer if (ATcommand[0] != '\0') { Serial1.println(ATcommand); // Send the AT command } x = 0; previous = millis(); // this loop waits for the answer do { // if there are data in the UART input buffer, reads it and checks for the asnwer if (Serial1.available() != 0) { response[x] = Serial1.read(); x++; // check if the desired answer is in the response of the module if (strstr(response, expected_answer) != NULL) { answer = 1; } } // Waits for the asnwer with time out } while ((answer == 0) && ((millis() - previous) < timeout)); return answer; }
If you are interested in Internet of Things (IoT) or M2M projects check our open source sensor platform Waspmote which counts with more than 100 sensors available to use 'off the shelf', a complete API with hundreds of ready to use codes and a low consumption mode of just 0.7µA to ensure years of battery life.
Know more at:
Get the Starter Kits at:
Cooking Hacks makes electronics affordable, easy to learn and fun.
The e-commerce for worldwide community of developers, designers, inventors and makers who love creating electronics with sensors, robotics, Arduino and Raspberry Pi.
Cooking Hacks is a brand by Libelium.
In order to comply with the provisions in Spanish Data Protection Act (L.O. 15/1999 of 13th December) and its implementing Regulation (R.D. 1720/2007, of 21st December), LIBELIUM hereby informs its Customers and websites users that any personal data supplied through the forms contained in its websites shall be recorded in a file named “CUSTOMERS” for which LIBELIUM is responsible, located at LIBELIUM´s registered address and which has been registered with the Spanish General Registry for Data Protection (Registro General de Protección de Datos de la Agencia Española de Protección de Datos).
Except for those fields expressly requesting compulsory filling, answers to the questions contained in any form are voluntary and therefore, the lack of answer does not imply a reduction of the quantity or quality of LIBELIUM´s services. The aim of this data collection are to provide access to LIBELIUM´s online shop, to send information on LIBELIUM´s Product(s) and services as well as to collect Customer’s acceptance to the terms of use of the forums and other sections in LIBELIUM´s websites. By filling these forms Customers consent in receiving promotional offers concerning LIBELIUM´s Product(s) and services. You further consent further that LIBELIUM may make such data available to its services suppliers to the sole purpose of enabling service provision.
Any User providing personal data through any of the forms in LIBELIUM´s websites shall count on a 30 day period to inform LIBELIUM in writing of his/her refusal to the processing of his/her personal data. Unless this communication is made, it shall be deemed that the User consents the processing of his/her personal data according to the terms set forth in these T&C. All personal data collected shall be processed by using the security measures requested by Law to avoid their loss, damage or access by any unauthorised third party. User may nevertheless be aware of the fact that the existing security measures for computer systems on the Internet are not entirely trustworthy. Should you think that your email address has been disclosed to us without your consent, do not hesitate to inform us thereof. Users may at any time exercise their rights of access, rectification, update, cancellation and objection, as well as revoke the consent granted for all of any of the above-mentioned processings, by sending a written statement to LIBELIUM, either through the “Contact” section in our website http://www.libelium.com or by post to the following address: LIBELIUM COMUNICACIONES DISTRIBUIDAS, S.L., C/ Escatrón 16 (Edificio LIBELIUM) C.P: 50014 Zaragoza (Spain).
To exercise the above-mentioned rights you must indicate your name, ID/passport number, full address, date and signature, including any document supporting your request, in case it is needed; a copy of your ID card/passport must be enclosed, unless you use an electronic signature. User shall be liable for the veracity of data provided and only in case of holders of parental rights concerning children under fourteen and in connection with said children, shall LIBELIUM accept the disclosure of personal data concerning third parties. Users shall assume all liability for direct or consequential damages arising out of or in connection with the provision of false, inaccurate, incomplete or non updated data.
Furthermore, LIBELIUM reserves its right to exclude from any service for which prior registration is required, to any User having provided false data or failing to comply with these T&C, notwithstanding any other legal action to which LIBELIUM may be entitled. LIBELIUM reserves its right to modify its Privacy Policy or these T&C to adapt them to the regulations in force or for any other reason. Provided that the use of LIBELIUM´s websites by Users shall be deemed as User’s acceptance of LIBELIUM´s Privacy Policy and T&C, User is hereby requested to check these T&C and any further amendments from time to time.
Privacy Policy
Users may visit LIBELIUM´s websites without disclosing neither their identity nor any personal data. LIBELIUM´s servers may only collect domain names but not email addresses of their visitors. This kind of information is used to elaborate reports on visit statistics, the time spent in the websites, websites accessed, the general origin of visitors (through “Favourites”, search engines, links from other websites, etc.) to the sole purposes of getting information on how the websites are used and improving their contents and services.
Linked sites LIBELIUM´s websites may provide links to other sites but LIBELIUM assumes no liability on the privacy policies adopted by the linked sites, directly or indirectly. Links to other sites are provided as a suggestion only and do not imply LIBELIUM´s warranty or liability concerning their quality, accuracy or contents of the information provided therein.
LIBELIUM does not warrant the veracity or accuracy of the information disclosed by its suppliers or third parties whose products or services are offered through LIBELIUM, their origin, ownership or the use or practical implementation made by Customers.