I would like to wait in loop for sms message arrival on my SIM900 and when message is detected , read that message and delete it from the system.
What's bothering me is what if another message comes while I am working on this one (Unsolicited message info).
What is proper algorithm to handle sms reading and deletion?
This is how I do similar task
At start delete all sms from sim memory
Enable new message alerts using AT+CNMI command
Use Interrupt based serial communication and make use of a ring buffer to store all in-coming data
Whenever you will get a new message the modem will send an alert to the controller.
parse the alert message to know the location of sms
After reading the SMS delete the sms
Below is another approach.
/*
* Description: This example shows hot to read a SMS from SIM memory.
* This example only shows the AT commands (and the answers of the module) used
* to read the SMS For more information about the AT commands, refer to the AT
* command manual.
*
* Copyright (C) 2013 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.
*
* 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 0.2
* Author: Alejandro Gallego
*/
int8_t answer;
int x;
int onModulePin= 2;
char SMS[200];
void setup(){
pinMode(onModulePin, OUTPUT);
Serial.begin(115200);
Serial.println("Starting...");
power_on();
delay(3000);
// sets the PIN code
sendATcommand("AT+CPIN=****", "OK", 2000);
delay(3000);
Serial.println("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
answer = sendATcommand("AT+CMGR=1", "+CMGR:", 2000); // reads the first SMS
if (answer == 1)
{
answer = 0;
while(Serial.available() == 0);
// this loop reads the data of the SMS
do{
// if there are data in the UART input buffer, reads it and checks for the asnwer
if(Serial.available() > 0){
SMS[x] = Serial.read();
x++;
// check if the desired answer (OK) is in the response of the module
if (strstr(SMS, "OK") != NULL)
{
answer = 1;
}
}
}while(answer == 0); // Waits for the asnwer with time out
SMS[x] = '\0';
Serial.print(SMS);
}
else
{
Serial.print("error ");
Serial.println(answer, DEC);
}
}
void loop(){
}
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
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;
}
Related
I'm using an 125Khz RFID module RDM6300 with arduino nano.
While the card is near the RFID reader the loop will read the card multiple times. I want it to read only once while the card is near the reader then read it again if a new connection is being made.
*This code is not writen by me, this is the source:
https://github.com/Wookai/arduino-rfid
// define constants for pins
//int SUCCESS = 10;
//int ERROR = 13;
// variables to keep state
int readVal = 0; // individual character read from serial
unsigned int readData[10]; // data read from serial
int counter = -1; // counter to keep position in the buffer
char tagId[11]; // final tag ID converted to a string
char* authorizedTags[4]; // array to hold the list of authorized tags
// fills the list of authorzied tags
void initAuthorizedTags() {
// add your own tag IDs here
authorizedTags[0] = "0400680B85";
authorizedTags[1] = "0400063EB9";
authorizedTags[2] = "040004F3F5";
authorizedTags[3] = "04006813AB";
}
void setup() {
Serial.begin(9600);
// pinMode(SUCCESS, OUTPUT);
//pinMode(ERROR, OUTPUT);
initAuthorizedTags();
}
// check if the tag ID we just read is any of the authorized tags
int checkTag() {
int i;
for (i = 0; i < 4; ++i) {
if (strcmp(authorizedTags[i], tagId) == 0) {
return 1;
}
}
return 0;
}
// convert the int values read from serial to ASCII chars
void parseTag() {
int i;
for (i = 0; i < 10; ++i) {
tagId[i] = readData[i];
}
tagId[10] = 0;
}
// once a whole tag is read, process it
void processTag() {
// convert id to a string
parseTag();
// print it
printTag();
// check if the tag is authorized
if (checkTag() == 1) {
tagSuccess(); // if so, perform an action (blink a led, open a door, etc...)
} else {
tagFailed(); // otherwise, inform user of failure
}
}
void printTag() {
Serial.print("Tag value: ");
Serial.println(tagId);
}
// perform an action when an authorized tag was read
void tagSuccess() {
Serial.println("Tag authorized.");
// here, we simply turn on the success LED for 2s
// digitalWrite(SUCCESS, HIGH);
//digitalWrite(ERROR, LOW);
// delay(2000);
}
// inform the user that the tag is not authorized
void tagFailed() {
Serial.println("Unauthorized access!");
//digitalWrite(SUCCESS, LOW);
// digitalWrite(ERROR, HIGH);
// delay(2000);
}
// this function clears the rest of data on the serial, to prevent multiple scans
void clearSerial() {
while (Serial.read() >= 0) {
; // do nothing
}
}
void loop() {
// turn LEDs off
// digitalWrite(SUCCESS, LOW);
// digitalWrite(ERROR, LOW);
if (Serial.available() > 0) {
// read the incoming byte:
readVal = Serial.read();
// a "2" signals the beginning of a tag
if (readVal == 2) {
counter = 0; // start reading
}
// a "3" signals the end of a tag
else if (readVal == 3) {
// process the tag we just read
processTag();
// clear serial to prevent multiple reads
clearSerial();
// reset reading state
counter = -1;
}
// if we are in the middle of reading a tag
else if (counter >= 0) {
// save valuee
readData[counter] = readVal;
// increment counter
++counter;
}
}
}
Thank you.
Thank you for your answers. I tried to accept the multiple reads and print only one but it keeps printing "already read" instead of reading the card first time, this is the code:
void printTag() {
if(strcmp(tagId,previous)==1){
strcpy(previous, tagId);
Serial.print("Tag value: ");
Serial.println(tagId);
}
else
{
Serial.print("already read");
}
}
I also tried to put the delay after end of tag but it still reads the card multiple times.
I tried another code, it still reads the tag multiple times.
#include <SoftwareSerial.h>
// RFID | Nano
// Pin 1 | D2
// Pin 2 | D3
SoftwareSerial Rfid = SoftwareSerial(2,3);
int timer=0;
int reference = 1000;
int card_status = 0;
void setup() {
// Serial Monitor to see results on the computer
Serial.begin(9600);
// Communication to the RFID reader
Rfid.begin(9600);
}
void read() {
// check, if any data is available
// as long as there is data available...
while(Rfid.available() > 0 ){
// read a byte
int r = Rfid.read();
// print it to the serial monitor
Serial.print(r, DEC);
Serial.print(" ");
}
// linebreak
Serial.println();
timer=0;
}
void loop()
{
if((Rfid.available() > 0 ) && (card_status == 0) )
{
read();
}
if((!Rfid.available() > 0 ) && (card_status == 1) )
{
card_status=0;
}
}
I'm sorry for the late response. I forgot about this topic.
I solved the problem by making the arduino wait for a response after writing the RFID code for the frist time.
I was able to do that because my arduino was sending the code to a C# application via serial port.
Here is how it works: the arduino prints the RFID code on the serial, from there it is picked up by the C# application which searches a database to see if the code is stored there. Depending on the result, the application prints a character('y' or 'n') which is picked up by the arduino. Depending on the character recieved, the arduino lights up a led ( green or red) and makes a noise. Now a new RFID reading can be made.
Here is the code:
#include <SoftwareSerial.h>
#include "RDM6300.h"
SoftwareSerial rdm_serial(8, 9);
RDM6300<SoftwareSerial> rdm(&rdm_serial);
String comanda;
char c="";
int led_verde = 2;
int led_rosu = 7;
int buzzer = 12;
int i;
void buzz(int n = 1)
{
for (int i = 0; i < n; i++) {
digitalWrite(buzzer, LOW);
delay(200);
digitalWrite(buzzer, HIGH);
delay(200);
}
}
void ledVerde()
{
digitalWrite(led_verde, HIGH);
buzz(1);
delay(1000);
digitalWrite(led_verde, LOW);
}
void ledRosu()
{
digitalWrite(led_rosu, HIGH);
buzz(3);
delay(1000);
digitalWrite(led_rosu, LOW);
}
void setup()
{
pinMode(led_verde, OUTPUT);
pinMode(led_rosu, OUTPUT);
pinMode(buzzer, OUTPUT);
digitalWrite(led_verde, LOW);
digitalWrite(led_rosu, LOW);
digitalWrite(buzzer, HIGH);
Serial.begin(9600);
}
void loop()
{
static unsigned long long last_id = 0;
last_id = rdm.read();
rdm.print_int64(last_id);
Serial.println();
rdm_serial.end();
Serial.flush();
while(!Serial.available());
c=Serial.read();
if(c=='y')
{
ledVerde();
c="";
}
if(c=='n')
{
ledRosu();
}
Serial.flush();
last_id="";
c="";
rdm_serial.begin(9600);
}
You can find the RDM6300 library here: https://github.com/arliones/RDM6300-Arduino
Long time passed the original question, but maybe my answer would be useful for future visitors.
The RDM6300 works by:
automatically reading the data, and then
your code transfers the read data to the buffer for further processing.
Imagine it as a Baggage carousel in the airport. There are multiple luggage (data) on the carousel (reader), and you pick them one by one (transferring to buffer).
So, the problem of multiple reads, is that you have got read data in the reader (luggage on the carousel), that your code is gradually transferring them to the buffer (picking the luggage up).
In our example, if you don't like to collect all luggage, you can ask someone to take some of them, before they reach to you.
The below code does this. While you have data in the reader (the card is near to the reader), it transfers data from reader to buffer and then zeros all of them in the buffer:
First, place this code before "void setup()":
boolean multipleRead = false;
This defines a false/true variable to tell if this is the first time you are reading the tag (false), or it's being read multiple times (true).
Then, put this one at the end of the code block that shows the tag is fully read. If you are using Michael Schoeffler's library for your RDM6300/630 RFID, put it after "else if (ssvalue == 3) {":
multipleRead = true;
It change the variable to true, when your tag is read. That tells the program that your first read is done and the next upcoming read(s) would be "multiple read" and you don't want them.
Then put this at the end of the RFID reader code (if your RFID code is under void loop (), put the below code just after "void loop (){":
if (multipleRead) {
while (ssrfid.available() > 0) {
int ssvalue = ssrfid.read(); // read
if (ssvalue == -1) { // no data was read
break;
}
}
for (int x = 0; x < 14; x++)
{
buffer[x] = 0;
}
multipleRead = false;
}
It empties the reader and then zeros the buffer, while there is a card nearby. When you move the card away, multipleRead value would turn to false, which let another RFID reading loop to initiate.
Hope that helped :)
I guess what you want is a edge trigger instead of level trigger with time limit.
For example, you may prefer to read a RFID card when it firstly comes near to the antenna, once only; when it keeps to contact the antenna, still take no more actions. When you remove the card and place it again near to the antenna, the MCU starts to read the card again.
If so, the following code could be for your reference. What I have done is just to add 1 more flag to keep checking the card_status before checking if a RFID card comes near to the antenna.
int card_status = 0; //0:readable; 1:not-readable
if ( (Serial.available() > 0) && (card_status == 0) ) {
card_status = 1; //disable to read card after exit this loop
//your code, a card is near to the antenna, try to read it.
readVal = Serial.read();
if (readVal == 2) {
counter = 0; // start reading
} else if (readVal == 3) {
processTag();
clearSerial();
counter = -1;
} else if (counter >= 0) {
readData[counter] = readVal;
++counter;
}
}
reset the card status when no RFID signal comes in && card status is true,
if ( (!(Serial.available() > 0)) && (card_status == 1) ) {
card_status = 0; //enable to read card again
//no signal, no card is near to the antenna.
}
You can set a delay (e.g. delay(2000)) after reading the (end of tag). A delay of (say) 2 seconds will allow the user to move the card far enough away from the reader. Note that delay is a blocking command which might not suit your purposes, in which case you could be looking at using the millis count to activate/deactivate the Serial.read.
Another option is to accept the multiple reads, but keep a state of which card has been read. If the new card number is the same as the old card number (within a reasonable timeframe) then just ignore.
Hello. I am using this example from cooking hacks to make a HTTP GET call to my server.(bottom of the page)
http://www.cooking-hacks.com/documentation/tutorials/arduino-3g-gprs-gsm-gps
My end goal would be to get one word from a php page to my Arduino Uno.
But I am running in to problems because my Arduino has a limited buffer and the header size is bigger than its buffer.
My header size is 363
And my download size is 12
The max size is 64
Because of this my code is not working. I want to only get the 12 but don't know how to do this I hope someone can help me point me in the right direction.
* Description: This example shows how to do a GET method. So the buffer of
* is limited, we recommend to use the GET method with short answer for the
* requested webs.
* This example shows the AT commands (and the answers of the module) used
* to work with HTTP. For more information about the AT commands,
* refer to the AT command manual.
*
* Copyright (C) 2013 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.
*
* 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 0.2
* Author: Alejandro Gallego
*/
int8_t answer;
int onModulePin = 2, aux;
int data_size = 0;
int end_file = 0;
char aux_str[100];
char data[250];
int x = 0;
long previous;
char url[ ]="rubenvandijk.com";
int port= 80;
char request[ ]="GET /misc/twittertest5/get_tweet.php HTTP/1.1\r\nHost: rubenvandijk.com\r\n";
void setup(){
pinMode(onModulePin, OUTPUT);
Serial.begin(115200);
Serial.println("Starting...");
power_on();
delay(3000);
// sets the PIN code
sendATcommand("AT+CPIN=0000", "OK", 2000);
delay(3000);
while( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) ||
sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 );
// sets APN, user name and password
sendATcommand("AT+CGSOCKCONT=1,\"IP\",\"prepaidinternet\"", "OK", 2000);
sendATcommand("AT+CSOCKAUTH=1,1,\"\",\"\"", "OK", 2000);
}
void loop(){
// request the url
sprintf(aux_str, "AT+CHTTPACT=\"%s\",%d", url, port);
answer = sendATcommand(aux_str, "+CHTTPACT: REQUEST", 60000);
if (answer == 1)
{
Serial.println(request);
//Serial.println(host);
//Serial.println("Content-Length: 0");
// Sends <Ctrl+Z>
aux_str[0] = 0x1A;
aux_str[1] = 0x00;
answer = sendATcommand(aux_str, "+CHTTPACT: DATA,", 60000);
x=0;
do{
if (answer == 1)
{
data_size = 0;
while(Serial.available()==0);
aux = Serial.read();
do{
data_size *= 10;
data_size += (aux-0x30);
while(Serial.available()==0);
aux = Serial.read();
}
while(aux != 0x0D);
Serial.print("Data received: ");
Serial.println(data_size);
if (data_size > 0)
{
while(Serial.available() < data_size);
Serial.read();
for (int y = 0; y < data_size; y++)
{
data[x] = Serial.read();
x++;
}
data[x] = '\0';
}
else
{
Serial.println("Download finished");
}
}
else
{
Serial.println("Error getting the url");
data_size = 0;
}
answer = sendATcommand2("", "+CHTTPACT: DATA,", "+CHTTPACT:0", 20000);
}while (answer != 1);
if (answer == 2)
{
Serial.print("Data received hallo:");
Serial.println(data);
}
else
{
Serial.println("Error getting data");
}
}
else
{
Serial.println("Error waiting the request");
}
delay(10000);
}
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_answer1,
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){
response[x] = Serial.read();
x++;
// check if the desired answer is in the response of the module
if (strstr(response, expected_answer1) != NULL)
{
answer = 1;
}
}
// Waits for the asnwer with time out
}
while((answer == 0) && ((millis() - previous) < timeout));
return answer;
}
int8_t sendATcommand2(char* ATcommand, char* expected_answer1,
char* expected_answer2, 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){
response[x] = Serial.read();
x++;
// check if the desired answer is in the response of the module
if (strstr(response, expected_answer1) != NULL)
{
answer = 1;
}
// check if the desired answer is in the response of the module
if (strstr(response, expected_answer2) != NULL)
{
answer = 2;
}
}
// Waits for the asnwer with time out
}
while((answer == 0) && ((millis() - previous) < timeout));
return answer;
}
It now returns
�Starting...
AT
AT+CPIN=0000
AT+CREG?
AT+CGSOCKCONT=1,"IP","prepaidinternet"
AT+CSOCKAUTH=1,1,"",""
AT+CHTTPACT="rubenvandijk.com",80
GET /misc/twittertest5/get_tweet.php HTTP/1.1
Host: rubenvandijk.com
Data received: 524
It gets stuck at
if (data_size > 0)
{
while(Serial.available() < data_size);
Serial.read();
I have several ideas you can try...
1) Process your incoming data one line at a time, don't buffer it all up to process.
2) Add some special characters to your web server response, toss all the data until you see that character or sequence. Say add a # symbol in front of the data you want, as bytes come in only buffer up those after the #.
3) use a circular buffer and let it overwrite till all the data is received, leaving you the last X bytes in the buffer, process by working backwards from the buffer tail.
Number 1 is the best answer, number 2 is the easiest.
The idea is:
Connect arduino to PC via USB port (Windows 7, administrator logged
in)
System automatically execute command (for example: shutdown -s
-t 3600)
Is it possible to make that without using proxy application on host?
Here are two code snippets that address the fundamentals of this question. First, is a sketch that issues a "DIR" command. Obviously, this could be any command.
#include <stdio.h>
uint8_t command[] = "dir\0";
void setup()
{
Serial.begin(9600);
delay(10000);
Serial.write(command, 4);
}
void loop() {}
Second, is C code that reads COM5 and after receiving a string issues a command.
/*
* main.c
*
* Created on: Sep 29, 2013
* Author: Jack Coleman
*
* This software is for demonstration purposes only.
*
*/
#include <stdio.h>
#include <Windows.h>
//
// create a console that accepts data
// from a com port and issues it as system commands.
//
void display_config(COMMCONFIG *config_comm)
{
printf("BaudRate = ");
switch (config_comm->dcb.BaudRate)
{
case CBR_9600 : printf("9600\n");
}
printf("Parity = %d\n", config_comm->dcb.Parity);
printf("StopBits = %d\n", config_comm->dcb.StopBits);
printf("ByteSize = %d\n", config_comm->dcb.ByteSize);
fflush(stdout);
}
main() // Version 0
{
HANDLE hCOM5;
int config_size;
COMMCONFIG config_comm;
int retc;
int nr_read;
char *comm_char;
char sysline[271];
hCOM5 = CreateFile("COM5", GENERIC_READ, 0, 0,
OPEN_EXISTING, 0, NULL);
if (hCOM5 <= 0)
{
printf("unable to open COM5");
return;
}
GetCommConfig(hCOM5, &config_comm, &config_size);
config_comm.dcb.BaudRate = CBR_9600;
config_comm.dcb.Parity = NOPARITY;
config_comm.dcb.StopBits = ONESTOPBIT;
config_comm.dcb.ByteSize = 8;
retc = SetCommConfig(hCOM5, &config_comm, config_size);
if (retc == 0)
{
printf("SetCommConfig failed.\n");
return;
}
display_config(&config_comm);
// wait here for a possible, initial
// series of 0xFF.
comm_char = sysline;
do
{
ReadFile(hCOM5, comm_char, 1, &nr_read, NULL);
printf("%x nr_read = %d\n", *comm_char, nr_read);
fflush(stdout);
} while (nr_read == 0);
while (nr_read == 1)
{
if (*comm_char == 0x00)
{
printf("%s\n", &sysline[0]);
fflush(stdout);
system(&sysline[0]);
break;
} else {
comm_char++;
}
ReadFile(hCOM5, comm_char, 1, &nr_read, NULL);
printf("%02x\n", *comm_char);
fflush(stdout);
}
return;
}
This was a fun little coding problem. Several lessons were learned: 1) when communicating via a serial line, the C program will simply wait until the first byte is transmitted by the Arduino. There are no syncing chars to preface the data transmission (that is, if there are any they get stripped out by the system code); 2) It is possible to get zero (0) for the number of bytes read.
Could this be used to use an Arduino to issue a shut down command? Yes, but the program would have to be started (i.e. scheduled) and then it would wait for the Arduino to speak.
I'm using an Arduino UNO with attached IComsat SIM900 GSM/GPRS shield.
Using the following tutorial: Arduino Live GPS Tracker I'm stuck with the AT+CREG? command, which checks if the SIM-card is registered at the provider.
The following logic is used:
In the GSM_HTTP.INO file within the "void setup()" function, the following line gets executed modem.checkNetwork();
void setup() {
Serial.begin(9600);
Serial.println("GM862 monitor");
modem.switchOn(); // switch the modem on
delay(4000); // wait for the modem to boot
modem.init(); // initialize the GSM part of Module
modem.version(); // request modem version info
while (!modem.isRegistered()) {
delay(1000);
modem.checkNetwork(); // check the network availability
}
}
The function "checkNetwork()" is part of the included library GSM862.cpp and looks like this:
void GM862::checkNetwork() {
char buf[BUF_LENGTH];
char result;
requestModem("AT+CREG?", 1000, true, buf);
result = buf[21];
if (result == '1') {
state |= STATE_REGISTERED;
}
else {
state &= ~STATE_REGISTERED;
}
}
Now this is the important part: The value of "result" that gets received by the function "requestModem" returns cryptic values, but no netword status (number 0-5) which is why there is a endless loop trying to register without error or success message.
As this function gets the "buf" variable out of the function "requestModem" in GSM862.cpp, I've had a look at it as well:
byte GM862::requestModem(const char *command, uint16_t timeout, boolean check, char *buf) {
byte count = 0;
*buf = 0;
modem->flush();
modem->println(command);
count = getsTimeout(buf, timeout);
return count;
}
In order to have a look into the relevant variables for debugging purposes I've changed the last two functions into the following code:
-->checkNetwork
void GSM862::checkNetwork() {
char buf[BUF_LENGTH];
char result;
requestModem("AT+CREG?", 1000, true, buf);
result = buf[21];
Serial.print("Debugging buf2:");
Serial.print(buf[21]);
Serial.print("Debugging buf2:");
Serial.print(buf[1]);
Serial.print("Debugging buf2:");
Serial.print(buf[0]);
Serial.print("Debugging result2:");
Serial.println(result);
if (result == '1') {
state |= STATE_REGISTERED;
Serial.println("Network registered, home network...");
}
else {
state &= ~STATE_REGISTERED;
if(result == '0'){
Serial.println("Network not registered, not searching for a new operator to register to...");
}
if(result == '2'){
Serial.println("Still searching for an operators network to register to...");
}
if(result == '3'){
Serial.println("Network registration denied...");
}
if(result == '4'){
Serial.println("Network registration state unknown, probably still starting up...");
}
if(result == '5'){
Serial.println("Network registered, roaming...");
}
}
}
--> request Modem
byte GSM862::requestModem(const char *command, uint16_t timeout, boolean check, char *buf) {
byte count = 0;
*buf = 0;
modem->flush();
modem->println(command);
count = getsTimeout(buf, timeout);
Serial.print("Debugging command1:");
Serial.println(command);
Serial.print("Debugging count1:");
Serial.println(count);
Serial.print("Debugging buf1:");
Serial.println(buf);
Serial.print("Debugging timeout1:");
Serial.println(timeout);
return count;
}
Like I've mentioned above, it seems that the value out of "result" of the function "checkNetwork" which is actually the value of "buf[21]", displays a cryptic value when displayed on the terminal via Serial.println();
Do you have any idea why or what the exact problem is?
Network registration information (CREG) output depends on modem configuration.
By sending "AT+CREG=0" one can disable network registration code (which is your case)
By sending "AT+CREG=1" one can enable network registration
By sending "AT+CREG=2" one can enable network registration code with
location information (location area code and cell ID)
Options 2. and 3. will also automatically emit +CREG messages upon modem boot/network change.
ps: one should not forget to save current AT configuration by executing AT&W
more details on CREG can be found in "SIM900 AT COMMAND MANUAL"
I have 2 Arduinos Leonardo and I want them to communicate itself, so I did the following code:
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
}
void loop() {
String outMessage = ""; // String to hold input
while (Serial.available() > 0) { // check if at least 1 char is available
char inChar = Serial.read();
outMessage.concat(inChar); // add inChar to outMessage
}
if (outMessage != "") {
Serial.println("Sent: " + outMessage); // View Arduino 1 in Serial Monitor 1
Serial1.print(outMessage); // Send to Arduino 2
}
while (Serial1.available() > 0) {
Serial.print("Received: "); // View Arduino 1 in Serial Monitor 2
Serial.print(Serial1.read()); // Received from Arduino 1
Serial.println();
}
}
I want to send a message from Arduino 1, print in Serial Monitor and send via TX1 to Arduino 2 and vice-versa. The problem is that I don't receive what I was expecting. For instance if I type test:
Arduino 1:
Sent: test
Arduino 2:
Received: t
Received: e
Received: s
Received: t
I also tryed to do the receiving side like the sending side and use Serial.write but with no sucess.
Is there a easier way to do that or to fix it?
Thanks
Has mentioned by Hans, you need a protocol.
This is what I use to consider a message in Arduino to be a complete message:
char inData[10];
int index;
boolean started = false;
boolean ended = false;
String message =("I am Arduino 1 and I am ready");
void setup(){
Serial.begin(9600);
Serial.println(message);
}
void loop()
{
while(Serial.available() > 0)
{
char aChar = Serial.read();
if(aChar == '>')
{
started = true;
index = 0;
inData[index] = '\0';
}
else if(aChar == '<')
{
ended = true;
}
else if(started)
{
inData[index] = aChar;
index++;
inData[index] = '\0';
}
}
if(started && ended)
{
int inInt = atoi(inData);
Serial.println(inInt);
}
// Get ready for the next time
started = false;
ended = false;
index = 0;
inData[index] = '\0';
}
So, basically a message is considered completed only if it is between the special characters ><, like this: >message<. Then you can do the same on reading.
It does not have to be too complicated. If you look carefully at your last whlie-loop you can see that the software does not get a chance to read more than one character each time it passes through the loop. So that is what you get: one character at a time.
In your first while-loop you did better: you collected all the incoming letters until nothing was available and then sent them all at once. So if you make your last loop look more like the first one, you'll get a better result.
As mentioned a protocol to frame messages is needed between devices. A quick way to do this is to use Bill Porter's EasyTransfer library which does exactly what you are trying to do, over either UART or I2C. It has several examples.
Serial.read() reads only one byte every time you use it. A simple solution would be to store each byte on a char array while Serial.available>0 and then print the String with the whole message that was sent.
char message[40];
int count = 0;
while(Serial.available()>0){
message[count++] = Serial.read();
}
Serial.println(message);