Receiving specific text to be print on serial monitor - gsm

I have my code which uses the ATMega328p and GSM Shield (Sim900).
The code shows that if the GSM receives specific text as "FILL" keyword, it will print on serial monitor as "FILL in thr", also if the GSM receives "AUTOMATIC" keyword, it will print on serial monitor "AUTOMATIC asd".
The code only works on the first on which is the FILL, but if i texted the keyword AUTOMATIC, nothing happens within the serial monitor.
Is there's something wrong within my code?
#include <SoftwareSerial.h>
#include <string.h>
char str = 0;
char str1 = 0;
SoftwareSerial gsm = SoftwareSerial(2,3);
boolean gsmConnected = false;
void setup()
{
Serial.begin(9600);
gsm.begin(9600);
delay(300);
do // initializing connection between gsm shield and gizduino
{
Serial.println("------------------------------------------");
Serial.println("Initializing GSM Shield Connection..");
delay(500);
Serial.println("Sending AT Command...");
delay(500);
gsm.println("AT");
delay(500);
if(gsm.available())
{
if(gsm.find("OK"))
{
Serial.println("GSM Shield replied 'OK'"); //gsm shield replied "OK"
gsmConnected = true;
gsm.print("\r");
delay(500);
}
else
{
Serial.println("Error!.. GSM Shield Not Communicating");
gsmConnected = false;
}
}
}
while(gsmConnected == false);
Serial.println("Communicating.....");
gsm.print("\r");
delay(500);
gsm.print("AT+CMGF=1\r"); // sms format = text mode
delay(500);
gsm.write(0x1A);
Serial.println("READY!\r");
}
void loop()
{
//IF OWNER TEXTS FILL KEYWORD
if(gsm.available())
{
if(gsm.find("+639229639893") && gsm.find("FILL"))
{
Serial.println("FILL in thr");
}
}
//IF OWNER TEXTS AUTOMATIC KEYWORD
if(gsm.available())
{
if(gsm.find("+639229639893") && gsm.find("AUTOMATIC"))
{
Serial.println("AUTOMATIC asd");
}
}
}

changing your do{} to loop{} should help somewhat, be sure to remove the unnecessary print.ln's
there's a colon at the end of while loop conditional
Good practice to initiate the GSM before you initiate the serial.
Also to set junk data as mobile number when sharing the sketch

Using gsm.find clears the buffer until it finds the keyword..based on your code...the first if statement search for the number and keyword "fill". So even if you text automatic.. the code will first search the keyword fill,, thus removing the keyword "automatic" from the buffer. It's better to store the serial data to a variable array first.

Related

How can I create an automated GPS tracker using A9G AI Thinker module?

I have an AI Thinker A9G module connected to an ESP8266 D1 mini. I have the following script to send and receive AT commands to/from the module. The idea is to get a SMS with the Google maps GPS location of the module onto my mobile phone.
// GPS tracker with AI Thinker A9G module and AZ Delivery D1 Mini ESP8266 module
#include <SoftwareSerial.h>
#define rxPin D7
#define txPin D8
SoftwareSerial A9modem(rxPin, txPin); // Pins D7 Rx and D8 Tx are used as used as software serial pins
String incomingData; // For storing incoming serial data
String gpsData; // For storing location data
char msg;
char call;
void setup()
{
Serial.begin(115200); // Baud rate for serial monitor
A9modem.begin(115200); // Baud rate for GSM shield
Serial.println("GPS/GSM A9G BEGIN");
Serial.println("Enter character for control option: ");
Serial.println("h : to disconnect a call");
Serial.println("s : to send a message");
Serial.println("r : to receive a message");
Serial.println("c : to make a call");
Serial.println("l : to read location");
Serial.println("d : to disconnect gps");
Serial.println();
delay(100);
// Set SMS mode to text mode
A9modem.print("AT+CMGF=1\r");
delay(100);
// Set GSM module to TP show the output on serial out
A9modem.print("AT+CNMI=2,2,0,0,0\r");
delay(100);
}
void loop()
{
ReceiveMessage();
gpsData = incomingData.substring(33, 52);
Serial.print("Location: ");
Serial.println(gpsData);
delay(2000);
if (Serial.available() > 0)
switch(Serial.read())
{
case 's':
SendMessage();
break;
case 'r':
ReceiveMessage();
break;
case 'c':
MakeCall();
break;
case 'h':
HangupCall();
break;
case 'l':
ReadLocation();
break;
case 'd':
DisconnectGps();
break;
}
}
void ReceiveMessage()
{
if (A9modem.available() > 0)
{
incomingData = A9modem.readString(); // Get the data from the serial port
Serial.print(incomingData);
delay(100);
}
}
void SendMessage()
{
A9modem.println("AT+CMGF=1"); // Sets the GSM Module into text mode
delay(1000); // Delay of one second
A9modem.println("AT+CMGS=\"xxxxxxxxxxxxx\"\r"); // Replace your mobile number here
delay(1000);
String sms = "http://maps.google.com/maps?q=" + gpsData; // Create the SMS location string
A9modem.println(sms);
delay(100);
A9modem.println((char)26); // ASCII code of CTRL+Z
delay(1000);
}
void MakeCall()
{
A9modem.println("ATD+xxxxxxxxxxxxx;"); // Replace your mobile number here
Serial.println("Calling "); // Print response over serial port
delay(1000);
}
void HangupCall()
{
A9modem.println("ATH");
Serial.println("Hangup Call");
delay(1000);
}
void DisconnectGps()
{
A9modem.println("AT+GPS=0");
Serial.println("Disconnect GPS");
delay(1000);
}
void ReadLocation()
{
A9modem.println("AT+GPS=1");
delay(1000);
A9modem.println("AT+LOCATION=2"); // Check location every two seconds
delay(2000);
}
So if I use the commands "l" and "s" in Arduino IDE serial monitor everything is working well but I don't know how to change the code in a way that I get a fully automated GPS tracker. The idea is the following: Power on starts the tracker. When gpsData string is not empty the first SMS will be send to my mobile phone. The next SMS follows 20 minutes later and so on until power is switched off. Could you help please?
Thanks in advance!
Finally I came up with this solution but I'm not very happy with it (it is working but I have to restart the module from time to time because there are no GPS data). There are 3 reasons for this: There is no error handling for the GPS function, I set the delays in a more ore less random way to get everything working but I don't know if the values make sense and I don't know if the substring() function is the best way to get the location from the serial response.
// GPS tracker with AI Thinker A9G module and AZ Delivery D1 Mini
ESP8266 module
#include <SoftwareSerial.h>
#define rxPin D7
#define txPin D8
SoftwareSerial A9modem(rxPin, txPin); // Pins D7 Rx and D8 Tx are used as used as software serial pins
String incomingData; // For storing incoming serial data
String gpsData; // For storing location data
int runGps = 1;
int sendSms = 0;
void setup()
{
pinMode(LED_BUILTIN, OUTPUT); // Use builtin LED for correct GPS status
Serial.begin(115200); // Baud rate for serial monitor
A9modem.begin(115200); // Baud rate for GSM shield
// Set SMS mode to text mode
A9modem.print("AT+CMGF=1\r");
delay(300);
// Set GSM module to TP show the output on serial out
A9modem.print("AT+CNMI=2,2,0,0,0\r");
delay(1000);
Serial.end();
delay(500);
}
void loop()
{
Serial.begin(115200);
ReceiveMessage(); // Start a new serial stream
gpsData = incomingData.substring(33, 52); // Strip all unnessesary data from the stream
Serial.print("Location: "); // Check if the location data are correct
Serial.println(gpsData);
delay(1000);
if(runGps == 1) { // Start GPS
ReadLocation();
delay(20000); // Wait for GPS to be ready
}
if(gpsData.length() == 19 && sendSms == 0) { // If the location string is correct send SMS
if (isdigit(gpsData.charAt(0))) { // Check if the stream starts with a number
SendMessage();
digitalWrite(LED_BUILTIN, HIGH);
delay(300);
digitalWrite(LED_BUILTIN, LOW);
delay(300);
digitalWrite(LED_BUILTIN, HIGH);
delay(300);
digitalWrite(LED_BUILTIN, LOW);
delay(300);
digitalWrite(LED_BUILTIN, HIGH);
}
}
if(runGps == 0 && sendSms == 1) {
runGps = 1;
sendSms = 0;
delay(6000); // Make sure that all SMS serial communication is over
while (A9modem.available()) {
A9modem.read(); // Delete all data from serial buffer
}
delay(300000); // If SMS was sent wait 5 minutes before running the main loop again
Serial.end();
delay(500);
}
}
void ReceiveMessage()
{
if (A9modem.available() > 0)
{
incomingData = A9modem.readString(); // Get the data from the serial port
Serial.print(incomingData);
delay(500);
}
}
void SendMessage()
{
sendSms = 1; // Stop starting the SendMessage function
A9modem.println("AT+CMGF=1"); // Sets the GSM Module into text mode
delay(1000);
A9modem.println("AT+CMGS=\"xxxxxxxxxx\"\r"); // Replace your mobile number here
delay(1000);
String sms = "http://maps.google.com/maps?q=" + gpsData; // Create the SMS string
A9modem.println(sms);
delay(500);
A9modem.println((char)26); // ASCII code of CTRL+Z
delay(500);
}
void ReadLocation()
{
runGps = 0; // Stop starting the ReadLocation function
A9modem.println("AT+GPS=1");
delay(1000);
A9modem.println("AT+LOCATION=2"); // Check location every two seconds
delay(2000);
}
Try turning ON the NMEA stream from the A9G. Say you want to get the NMEA data every t seconds, you can add and then call the following function once in the void setup()
void TurnOnNMEA(int t)
{
if(t > 3600)
t = 3600; // Because the max time is 3600s
A9modem.print("AT+GPSRD=");
A9modem.println(t);
while(!A9modem.available()); // wait till the A9G sends a response
char c;
while(A9modem.available())
{
c = A9modem.read();
Serial.print(c);
delay(2); // Time needed for the next character
}
}
This will start the NMEA data stream every t seconds which you can print using the following function,
void ReadNMEA()
{
char c; // Read each character from the stream as it comes
if(A9modem.available())
{
c = A9modem.read();
Serial.print(c);
delay(2); // Time needed for the next character
}
}
Parsing and decoding the NMEA is a bit tricky thing to do. There is a lot of information inside it and the decoding depends on what you want to do with it. If you just want the location, you can parse the $GNGGA line.
When parsing the data, DO NOT USE Arduino String() class. It is a very bad idea when handling this kind of stream. Instead, use char array.

SIM800l V2 Keeps Blinking Every Second

I'm desperately looking for a solution for my SIM800l v2. The network LED just keeps blinking every second. It does not restart but it keeps blinking and not picking up a signal.
I tried powering up using a laptop USB port but it does not solve it. I also used a charger adapter that is 5V and 2A but still does not solve the problem. I also tried changing the sim card but still does not solve the problem.
Here is the Wiring diagram that I followed:
Credits to miliohm.com
Code:
SoftwareSerial sim(10, 11);
int _timeout;
String _buffer;
String number = "+6281222329xxx"; //-> change with your number
void setup() {
//delay(7000); //delay for 7 seconds to make sure the modules get the signal
Serial.begin(9600);
_buffer.reserve(50);
Serial.println("Sistem Started...");
sim.begin(9600);
delay(1000);
Serial.println("Type s to send an SMS, r to receive an SMS, and c to make a call");
}
void loop() {
if (Serial.available() > 0)
switch (Serial.read()) {
case 's':
SendMessage();
break;
case 'r':
RecieveMessage();
break;
case 'c':
callNumber();
break;
}
if (sim.available() > 0)
Serial.write(sim.read());
}
void SendMessage() {
//Serial.println ("Sending Message");
sim.println("AT+CMGF=1"); //Sets the GSM Module in Text Mode
delay(200);
//Serial.println ("Set SMS Number");
sim.println("AT+CMGS=\"" + number + "\"\r"); //Mobile phone number to send message
delay(200);
String SMS = "Hello, how are you? greetings from miliohm.com admin";
sim.println(SMS);
delay(100);
sim.println((char)26);// ASCII code of CTRL+Z
delay(200);
_buffer = _readSerial();
}
void RecieveMessage() {
Serial.println ("SIM800L Read an SMS");
sim.println("AT+CMGF=1");
delay(200);
sim.println("AT+CNMI=1,2,0,0,0"); // AT Command to receive a live SMS
delay(200);
Serial.write ("Unread Message done");
}
String _readSerial() {
_timeout = 0;
while (!sim.available() && _timeout < 12000) {
delay(13);
_timeout++;
}
if (sim.available()) {
return sim.readString();
}
}
void callNumber() {
sim.print (F("ATD"));
sim.print (number);
sim.print (F(";\r\n"));
_buffer = _readSerial();
Serial.println(_buffer);
}
I was also stuck on this for ages. Got a DC-DC converter to ensure I had the right voltage. I connected caps on both sides of the DC-DC. I tried most everything to no avail.
My issue in the end was the inefficiency of breadboards and jumper wires. So if you are using a breadboard or jumper wires, shorten them as much as possible, like 2-3cm to ensure that enough current can be delivered to the SIM800L module
Try to connect a cap as close as possible between Vcc and GND. If the module connects to the network after you entered the SIM pin the current rises and may causes a voltage drop.

Arduino SIM900 GSM how to Join Char on String

I am currently making an Arduino project with GSM900 GSM GPRS. In this project, I have to receive data sent from a phone. I could easily receive data with a single character, but I can`t join does character to obtain a full word (String). I have to use this full word inside an If statement if this word equals to that other word (string), make something...
#include <SoftwareSerial.h>
// Configure software serial port
SoftwareSerial SIM900(7, 8);
//Variable to save incoming SMS characters
char incoming_char=0;
String newchar = "";
void setup() {
// Arduino communicates with SIM900 GSM shield at a baud rate of 19200
SIM900.begin(19200);
Serial.begin(19200);
// Give time to your GSM shield log on to network
delay(20000);
// AT command to set SIM900 to SMS mode
SIM900.print("AT+CMGF=1\r");
delay(100);
// Set module to send SMS data to serial out upon receipt
SIM900.print("AT+CNMI=2,2,0,0,0\r");
delay(100);
}
void loop() {
if(SIM900.available() >0) {
incoming_char=SIM900.read();
Serial.print(incoming_char);
}
}
I tried putting this command on the the if statement inside the loop, but after i tried comparing the words, it wouldnt work.
void loop() {
if(SIM900.available() >0) {
incoming_char=SIM900.read();
newString = incoming_char + "";
Serial.print(incoming_char);
}
if (newString == "Test"){
Serial.println("It worked");
}
}
The output that i get from the Monitor Serial is this:
+CMT: "+myNumber","","19/09/20,16:31:05-12"
Test
void loop() {
if (SIM900.available() >0) {
incoming_char=SIM900.read();
newString += incoming_char;
Serial.print(incoming_char);
}
if (newString.endsWith("Test")) {
Serial.println("It worked");
}
}
For does who are wondering how it finished:
Thanks to phoenixstudio...
void loop() {
if(SIM900.available() >0) {
incoming_char=SIM900.read();
newString += incoming_char;
Serial.print(incoming_char);
}
if (newString.endsWith("Test1")){
Serial.println("Worked1");
}
if (newString.endsWith("Test2")){
Serial.println("Worked2");
}
if (newString.endsWith("Test3"){
Serial.println("Worked3");
}
}

How to prevent other phone/mobile numbers to send SMS command to Arduino?

INTRO:
I'm a novice when it comes to Arduino programming and using AT commands. I already tried to search the whole internet and asked on Arduino forum, but I have no luck and nobody seems to give me a clear idea about it there.
PROBLEM:
So, I have this code where an SMS command can switch on and off the light and it will response to a specific phone number only. My problem is, the program response even when I'm using different phone numbers. I hope there's a way which it can only whitelist a specific number so no one can prank the program without the owner's knowledge.
FOR EXAMPLE:
The owner's phone number is +631234567890
Some random phone number: +63xxxxxxxxxx
The owner can switch on and off the light. [YES]
But supposedly, the random phone number CAN NOT and will never have the authority to switch the lights on and off. Only the owner can.
HERE'S MY CURRENT CODE: CCTO
#include <SoftwareSerial.h>
SoftwareSerial GPRS(10, 11);
String textMessage;
String lampState;
const int relay = 12;
void setup() {
pinMode(relay, OUTPUT);
digitalWrite(relay, HIGH);
Serial.begin(9600);
GPRS.begin(9600);
delay(5000);
Serial.print("GPRS ready...\r\n");
GPRS.print("AT+CMGF=1\r\n");
delay(1000);
GPRS.print("AT+CNMI=2,2,0,0,0\r\n");
delay(1000);
}
void loop(){
if(GPRS.available()>0){
textMessage = GPRS.readString();
Serial.print(textMessage);
delay(10);
}
if(textMessage.indexOf("ON")>=0){
// Turn on relay and save current state
digitalWrite(relay, HIGH);
lampState = "ON";
Serial.println("Lamp set to ON\r\n");
textMessage = "";
GPRS.println("AT+CMGS=\"+631234567890\"");
delay(500);
GPRS.print("Lamp was finally switched ON.\r");
GPRS.write( 0x1a );
delay(1000);
}
if(textMessage.indexOf("OFF")>=0){
// Turn off relay and save current state
digitalWrite(relay, LOW);
lampState = "OFF";
Serial.println("Lamp set to OFF\r\n");
textMessage = "";
GPRS.println("AT+CMGS=\"+631234567890\"");
delay(500);
GPRS.print("Lamp was finally switched OFF.\r");
GPRS.write( 0x1a );
delay(1000);
}
if(textMessage.indexOf("STATUS")>=0){
String message = "Lamp is " + lampState;
GPRS.print("AT+CMGF=1");
delay(1000);
Serial.println("Lamp state resquest");
textMessage = "";
GPRS.println("AT+CMGS=\"+631234567890\"");
delay(500);
GPRS.print("Lamp is currently ");
GPRS.println(lampState ? "ON" : "OFF");
GPRS.write( 0x1a );
delay(1000);
}
}
How can I do that?
Your textMessage must contain an information about sender and time of the message. Something like this:
+CMGL: 2,"REC UNREAD","+63xxxxxxxxxx",,"07/02/18,00:07:22+32" A simple demo of SMS text messaging.
So, you need to extract the phone number at compare it with the authorized one.
You can define the desired phone number in the code and compare it with the number assigned to the incoming SMS. If the number matches the one in your code, proceed with the algorithm. Otherwise, ignore the message.
Got this code from the official Arduino Forum, which you can check out from the link given at the end. You can code out these two functions:
String CellNumtemp;
String CellNum;
// check if there are incoming SMS
void ricezione(){
Serial.println ("controllo ricezione SMS");
// AT command to set mySerial to SMS mode
mySerial.print("AT+CMGF=1\r");
delay(100);
// Read the first SMS saved in the sim
mySerial.print("AT+CMGR=1\r");
delay(10);
if(mySerial.available()>0){
textMessage = mySerial.readString();
Serial.print(textMessage);
delay(10);
}
// check if the SMS is "STATO"
if(textMessage.indexOf("STATO")>=0){
Serial.println("Invio info stato arnia");
//save the phone number of the senders in a string (this works with italian region you must adapt to yours)
CellNumtemp = textMessage.substring(textMessage.indexOf("+39"));
CellNum = CellNumtemp.substring(0,13);
smsstato();
CellNumtemp = "";
textMessage = "";
}
mySerial.print("AT+CMGD=1\r");
delay(100);
mySerial.print("AT+CMGD=2\r");
delay(100);
}
// Send sms with all the information to the number stored
void smsstato(){
// delete the first SMS
mySerial.print("AT+CMGD=1\r");
delay(100);
mySerial.print("AT+CMGF=1\r");
delay(1000);
mySerial.print("AT+CMGS=\"");
mySerial.print(CellNum);
mySerial.print("\"\r");
delay(1000);
//The text of the message to be sent.
mySerial.print("INFO: Latitudine: ");
mySerial.print(latitude);
mySerial.print(", Longitudine: ");
mySerial.print(logitude);
mySerial.print(", Ampere: ");
mySerial.print(consumotemp);
delay(1000);
mySerial.write(0x1A);
delay(1000);
Serial.println("sms stato");
}```
Thanks to the user ilteo85 on the https://forum.arduino.cc.
Check this out for reference: https://forum.arduino.cc/index.php?topic=637264.0
you could just use the whitelisting function in gsm module
the cmd is
AT+CWHITELIST=mode,index,number
Parameters
0 Disable
1 Enable only call white list
2 Enable only SMS white list
3 Enable call and SMS white list
The index of phone number, scope: 1-30
Phone number to be set
example
AT+CWHITELIST=2,1,+9198xxxxxxx

Processing IDE data is not being sent to arduino properly

I want to send processing IDE data to arduino. But led is not working. It worked fine once. But not working now :( Serial port name is exactly same in arduino as it is found by processing.
Processing code:
import processing.serial.*;
Serial myPort; // Create object from Serial class
void setup()
{
size(200,200); //make our canvas 200 x 200 pixels big
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
}
//send a 1
void draw() {
if (mousePressed == true)
{ //if we clicked in the window
myPort.write('1'); //send a 1
println("1");
} else
{ //otherwise
myPort.write('0'); //send a 0
}
}
Arduino code:
char val='0'; // Data received from the serial port
int ledPin = 13; // Set the pin to digital I/O 13
void setup() {
pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
Serial.begin(9600); // Start serial communication at 9600 bps
}
void loop() {
//digitalWrite(ledPin, HIGH); // turn the LED on
if (Serial.available())
{ // If data is available to read,
val = Serial.read(); // read it and store it in val
}
if (val == '1')
{ // If 1 was received
digitalWrite(ledPin, HIGH); // turn the LED on
} else {
digitalWrite(ledPin, LOW); // otherwise turn it off
}
delay(10); // Wait 10 milliseconds for next reading
}
Processing
You can simply say if(mousePressed)..., there is no need to say == true (it's implied)
Arduino
You're correct to check if(Serial.available()) before trying to overwrite val with whatever character you read from there. However, the rest of your code inside loop() is executing regardless of this check. There is no reason to repeatedly write a pin to LOW or HIGH if it is already there. In fact, you will be more responsive if you only delay on loops where you find a character available for reading.
I'd recommend you add some print statements to your Arduino code so you can get a look at what you're reading.
Also, could it be that your hardware is connected improperly or that your LED is simply burnt out?

Resources