strcmp brakes Arduino sketch - c++

For a school project, I'm using an Arduino Uno together with a Parallax RFID, a LCD screen and an esp8226-wifi module.
I'm trying to compare the scanned tag with the tags in the database and send the name of the tag owner to a terminal in the Blynk app. Everything works just fine until I put in the function that compares the tags. If I do that, everything stops working, even the code in the setup() part. How can I fix this?
I think the problem has somehing to do with the strcmp.
/* Libraries that need to be manually installed:
Blynk libraries: https://github.com/blynkkk/blynk-library/releases/download/v0.5.0/Blynk_Release_v0.5.0.zip
LiquidCrystal_I2C library: https://cdn.instructables.com/ORIG/FVH/K8OQ/J8UH0B9U/FVHK8OQJ8UH0B9U.zip
*/
#define BLYNK_PRINT Serial
#include <SoftwareSerial.h>
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//Setting up the Blynk wifi connection
#define ESP8266_BAUD 9600
char auth[] = "87b00838cd834e4e87a0422265cc7a9e";
char ssid[] = "bbox2-56b2";
char pass[] = "91C2D797F6";
//Setting up the virtual pins
WidgetTerminal terminal(V1);
BLYNK_WRITE(V1){}
//Setting up the RFID
#define RFIDEnablePin 8
#define RFIDSerialRate 2400
String RFIDTAG=""; //Holds the RFID Code read from a tag
String DisplayTAG = ""; //Holds the last displayed RFID Tag
//Setting up the LCD
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
//Setting up the serial connection
SoftwareSerial EspSerial(2, 3);
ESP8266 wifi(&EspSerial);
void setup()
{
//Serial communication
Serial.begin(RFIDSerialRate);
EspSerial.begin(ESP8266_BAUD);
Serial.begin(RFIDSerialRate);
delay(10);
//Blynk setup
Blynk.begin(auth, wifi, ssid, pass);
//LCD setup
lcd.begin(16,2);//16 kolommen, 2 rijen
lcd.backlight();
//RFID setup
pinMode(RFIDEnablePin,OUTPUT);
digitalWrite(RFIDEnablePin, LOW);
terminal.println("Terminal printing succesfull");
terminal.flush();
}
void loop()
{
if(Serial.available() > 0)
{
ReadSerial(RFIDTAG);
}
if(DisplayTAG!=RFIDTAG)
{
DisplayTAG=RFIDTAG;
// PROBLEM STARTS HERE
//Tag database
char tags[10][10] = {"6196", "6753", "5655", "69EC", "9FFC"};
char owners[10][30] = {"per1", "per2", "per3", "per4", "per5"};
int i = 0;
int j = 0;
int ownerLength = 0;
char lastTag[10];
RFIDTAG.toCharArray(lastTag, 10);
while (i < 10)
{
if (strcmp(tags[i], lastTag) == 0)
{
ownerLength = strlen(owners[i]);
while (j < ownerLength)
{
terminal.print(owners[i][j]);
}
terminal.println("has entered the parking\n\r");
terminal.flush();
break;
}
i++;
}
i = 0;
j = 0;
//PROBLEM ENDS HERE
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Last tag:");
lcd.setCursor(0,1);
lcd.print(RFIDTAG);
digitalWrite(RFIDEnablePin, HIGH);
delay(1000);
digitalWrite(RFIDEnablePin, LOW);
}
Blynk.run();
}
//Function for reading the tag
void ReadSerial(String &ReadTagString)
{
int bytesread = 0;
int val = 0;
char code[10];
String TagCode="";
if(Serial.available() > 0)
{
if((val = Serial.read()) == 10)
{
bytesread = 0;
while(bytesread<10) // Reads the tag code
{
if( Serial.available() > 0)
{
val = Serial.read();
if((val == 10)||(val == 13)) // If header or stop bytes before the 10 digit reading
{
break; // Stop reading
}
code[bytesread] = val; // Add the digit
bytesread++; // Ready to read next digit
}
}
if(bytesread == 10) // If 10 digit read is complete
{
for(int x=6;x<10;x++) //Copy the Chars to a String
{
TagCode += code[x];
}
ReadTagString = TagCode; //Returns the tag ID
while(Serial.available() > 0) //Burn off any characters still in the buffer
{
Serial.read();
}
}
bytesread = 0;
TagCode="";
}
}
}

Related

Serial Communication on Arduino Nano IoT 33

I'm having trouble since moving from an Uno to the Nano 33 IoT unit.
I have read up on a lot of info with regards to this specific topic and still I pretty confused as I'm quite use to working with the Software Serial that's not available on the Nano 33.
According to the: https://github.com/ostaquet/Arduino-Nano-33-IoT-Ultimate-Guide Guide using an addition port for serial as I'm all ready using Serial1 TX Pin 0, and RX Pin 1 my Sigfox unit: https://yadom.fr/carte-breakout-sfm10r1.html workes fine. The trouble is with my gps. If i swap the 2 around the GPS works fine and the Sigfox unit doesn't...
#include <TinyGPS++.h>
#include <Arduino.h>
#include "wiring_private.h"
static const uint32_t GPSBaud = 9600;
#define DEBUG 1
TinyGPSPlus gps;
uint8_t msg[12];
Uart mySerial (&sercom0, 5, 6, SERCOM_RX_PAD_1, UART_TX_PAD_2);
// Attach the interrupt handler to the SERCOM
void SERCOM0_Handler()
{
mySerial.IrqHandler();
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // set LED pin as output
digitalWrite(LED_BUILTIN, LOW); // switch off LED pin
pinPeripheral(5, PIO_SERCOM);
pinPeripheral(6, PIO_SERCOM);
if(DEBUG){
Serial.begin(9600);
}
mySerial.begin(GPSBaud);
Serial1.begin(9600);
delay(100);
getID();
delay(100);
getPAC();
}
void loop()
{
msg[0]=0xC0;
msg[1]=0xFF;
msg[2]=0xEE;
sendMessage(msg, 3);
printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
printFloat(gps.hdop.hdop(), gps.hdop.isValid(), 6, 1);
printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
printInt(gps.location.age(), gps.location.isValid(), 5);
printDateTime(gps.date, gps.time);
printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.deg()) : "*** ", 6);
printInt(gps.charsProcessed(), true, 6);
printInt(gps.sentencesWithFix(), true, 10);
printInt(gps.failedChecksum(), true, 9);
Serial.println();
delay(120000);
if (millis() > 5000 && gps.charsProcessed() < 10)
Serial.println(F("No GPS data received: check wiring"));
}
void blink(){
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000);
}
//Get Sigfox ID
String getID(){
String id = "";
char output;
Serial1.print("AT$I=10\r");
while (!Serial1.available()){
blink();
}
while(Serial1.available()){
output = Serial1.read();
id += output;
delay(10);
}
if(DEBUG){
Serial.println("Sigfox Device ID: ");
Serial.println(id);
}
return id;
}
//Get PAC number
String getPAC(){
String pac = "";
char output;
Serial1.print("AT$I=11\r");
while (!Serial1.available()){
blink();
}
while(Serial1.available()){
output = Serial1.read();
pac += output;
delay(10);
}
if(DEBUG){
Serial.println("PAC number: ");
Serial.println(pac);
}
return pac;
}
//Send Sigfox Message
void sendMessage(uint8_t msg[], int size)
{
Serial.println("Sigfox Start");
String status = "";
String hexChar = "";
String sigfoxCommand = "";
char output;
sigfoxCommand += "AT$SF=";
for (int i = 0; i < size; i++)
{
hexChar = String(msg[i], HEX);
//padding
if (hexChar.length() == 1)
{
hexChar = "0" + hexChar;
}
sigfoxCommand += hexChar;
}
Serial.println("Sending Sigfox Message...");
Serial.println(sigfoxCommand);
Serial1.println(sigfoxCommand);
while (!Serial1.available())
{
Serial.println("Waiting for Sigfox Response");
delay(7000);
}
while (Serial1.available())
{
output = (char)Serial1.read();
status += output;
delay(10);
}
Serial.println();
Serial.print("Sigfox Status \t");
Serial.println(status);
}
// This custom version of delay() ensures that the gps object
// is being "fed".
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (mySerial.available())
gps.encode(mySerial.read());
} while (millis() - start < ms);
}
static void printFloat(float val, bool valid, int len, int prec)
{
if (!valid)
{
while (len-- > 1)
Serial.print('*');
Serial.print(' ');
}
else
{
Serial.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
Serial.print(' ');
}
smartDelay(0);
}
static void printInt(unsigned long val, bool valid, int len)
{
char sz[32] = "*****************";
if (valid)
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i<len; ++i)
sz[i] = ' ';
if (len > 0)
sz[len-1] = ' ';
Serial.print(sz);
smartDelay(0);
}
static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
if (!d.isValid())
{
Serial.print(F("********** "));
}
else
{
char sz[32];
sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
Serial.print(sz);
}
if (!t.isValid())
{
Serial.print(F("******** "));
}
else
{
char sz[32];
sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
Serial.print(sz);
}
printInt(d.age(), d.isValid(), 5);
smartDelay(0);
}
static void printStr(const char *str, int len)
{
int slen = strlen(str);
for (int i=0; i<len; ++i)
Serial.print(i<slen ? str[i] : ' ');
smartDelay(0);
}
My problem is hence with the additional port creating via this section:
#include <Arduino.h>
#include "wiring_private.h"
Uart mySerial (&sercom0, 5, 6, SERCOM_RX_PAD_1, UART_TX_PAD_0);
// Attach the interrupt handler to the SERCOM
void SERCOM0_Handler()
{
mySerial.IrqHandler();
}
void setup() {
// Reassign pins 5 and 6 to SERCOM alt
pinPeripheral(5, PIO_SERCOM_ALT);
pinPeripheral(6, PIO_SERCOM_ALT);
// Start my new hardware serial
mySerial.begin(9600);
}
void loop() {
// Do something with mySerial...
}
On the Nano I have my TX on Nano Pin 6 (As it starts at ) and RX on Pin 7 "6" as it starts on 0....
It's swapped as to make RX and TX talk to each other on the board Where RX on the GPS = TX on the Nano, and TX on the GPS = RX on the Nano.
Am I using the wrong pins? AS the GPS doesn't want to respond with pin 5 & 6 pins at all...
The Lights blink on the gps so there's power, and if I swap the Gps with the Sigfox unit The gps works and the Sigfox unit then doesn't.
Am I using the wrong pins on the Nano Board? Please Help....
SERCOM0 with pins 5 and 6 are a good choice for additional Serial interface on Nano 33 IoT.
The variant.cpp file has
+------------+------------------+--------+---------+---------+
| Pin number | NANO Board pin | PIN | SERCOMx | SERCOMx |
| | | | (x/PAD) | (x/PAD) |
+------------+------------------+--------+---------+---------+
| 5 | ~D5 | PA05 | | 0/01 |
| 6 | ~D6 | PA04 | | 0/00 |
So the instantiation should be
Uart mySerial (&sercom0, 5, 6, SERCOM_RX_PAD_1, UART_TX_PAD_0);
you have UART_TX_PAD_2
Pin 5 is RX and pin 6 is TX.
The
pinPeripheral(5, PIO_SERCOM_ALT);
pinPeripheral(6, PIO_SERCOM_ALT);
commands should be after mySerial.begin, because begin does
pinPeripheral(uc_pinRX, g_APinDescription[uc_pinRX].ulPinType);
but .ulPinType is not PIO_SERCOM_ALT.
Working on Nano Pin D5 & D6 of Nano 33 IoT with the updated code above. Thanks to Juraj :-)

Controlling a stepper motor using Arduino and serial

I would like to create an Arduino program that receives (via serial) only two commands: "1" and "2".
Through these commands, I would like Arduino to operate a stepper motor like this:
If I write "1" on the serial, the motor must move clockwise
If I write "2" on the serial, the motor must move counterclockwise
I have already written a code that only works halfway:
#include <Stepper.h>
const int stepsPerRevolution = 1500;
int incomingByte;
Stepper myStepper(stepsPerRevolution, 11, 9, 10, 8);
void setup() {
myStepper.setSpeed(20);
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
Serial.print("I received: ");
Serial.println(incomingByte);
if (incomingByte = "1") {
Serial.println("Moving clockwise...");
myStepper.step(stepsPerRevolution);
delay(500);
}
if (incomingByte = "2") {
Serial.println("Moving counterclockwise...");
myStepper.step(-stepsPerRevolution);
delay(500);
}
}
}
When active, the program waits for the commands on the serial port and manages to read them. The problem is that in both cases (1 and 2) the motor moves first clockwise and then subsequently anticlockwise and it is not the result I would like to achieve.
Can you give me a hand in this endeavor?
Use comparison operation instead of assignment operator like so.Double quote around 1 is not required since the variable is int datatype. Use an else command after the first if statement so that only one of the commands will operate.
const int stepsPerRevolution = 1500;
int incomingByte;
Stepper myStepper(stepsPerRevolution, 11, 9, 10, 8);
void setup() {
myStepper.setSpeed(20);
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
Serial.print("I received: ");
Serial.println(incomingByte);
if (incomingByte == 49) {
Serial.println("Moving clockwise...");
myStepper.step(stepsPerRevolution);
delay(500);
}
else
if (incomingByte == 50) {
Serial.println("Moving counterclockwise...");
myStepper.step(-stepsPerRevolution);
delay(500);
}
}
}
Ok, here is the final code; all working!
#include <Stepper.h>
const int stepsPerRevolution = 1500;
int incomingByte;
Stepper myStepper(stepsPerRevolution, 11, 9, 10, 8);
void setup() {
myStepper.setSpeed(20);
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
Serial.print("I received: ");
Serial.println(incomingByte);
if (incomingByte == 49) {
Serial.println("Moving clockwise...");
myStepper.step(stepsPerRevolution);
delay(500);
}
else
if (incomingByte == 50) {
Serial.println("Moving counterclockwise...");
myStepper.step(-stepsPerRevolution);
delay(500);
}
}
}

WDT reset cause 4 after reinstalling Arduino

I try to control my LED strip with an Android app.
I reinstalled the Arduino IDE since I didn't like the Windows-store version. The serial monitor broke for whatever reason so I switched back to the Windows-store version.
But now I'm getting a WDT reset error, which I can't seem to overcome.
I'm also using Adafruit_NeoPixel and wherever I put "ledstrip.begin" or "ledstrip.show" seems to break it.
#include <ESP8266WiFi.h>
#include <Adafruit_NeoPixel.h>
byte RED = 14;
byte GREEN = 12;
byte BLUE = 13;
byte PIN_COUNT = 20;
Adafruit_NeoPixel ledstrip = Adafruit_NeoPixel(PIN_COUNT, 6, NEO_RGB + NEO_KHZ800); //(num of leds, )
WiFiServer server(port);
void setup()
{
Serial.begin(115200);
delay(10);
ledstrip.begin();
Serial.print("Connecting to: ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
byte tries;
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
tries++;
Serial.println(".");
if (tries == 5)
{
Serial.println("Connection failed");
return;
}
}
Serial.println("\nWiFi connected");
server.begin();
Serial.println("Server URL: ");
Serial.print(WiFi.localIP());
}
void print_tokens(char* strings)
{
byte index = sizeof(strings);
for (int n = 0; n < index; n++)
{
Serial.println(strings[n]);
}
}
char *tokenize_request(String request)
{
char requestArray[1024];
char *ptr = NULL;
byte index = 0;
char *strings[10];
strcpy(requestArray, request.c_str());
ptr = strtok(requestArray, ";");
while (ptr != NULL) {
strings[index] = ptr;
index++;
ptr = strtok(NULL, ";");
}
return *strings;
}
void loop()
{
WiFiClient responder = server.available();
if (!responder)
{
return;
}
while (!responder.available())
{
delay(1);
}
String request = responder.readStringUntil('#');
char *strings[10] = {tokenize_request(request)};
print_tokens(*strings);
int mode = atoi(strings[0]);
int R = atoi(strings[1]);
int G = atoi(strings[2]);
int B = atoi(strings[3]);
if (mode == 1)
{
ledstrip.setPixelColor(5, R, G, B);
}
if (mode == 0)
{
ledstrip.setPixelColor(5, 0, 0, 0);
}
ledstrip.show();
delay(1);
Serial.println("------------------------------------------------------------------");
}
Serial monitor output:

(Arduino) Can I skip multiple characters in a parseInt()?

Pretty much what the title says. From the arduino website:
Syntax
Serial.parseInt()
Serial.parseInt(char skipChar)
Parameters
skipChar: used to skip the indicated char in the search. Used for example to skip thousands divider.
Am I able to use a charmap or something similar to skip multiple characters?
Maybe you could read from Serial, but take digits only? And then parse string? Dirty example:
val = 0;
while (Serial.available() > 0) {
int c = Serial.read();
if (isDigit(c)) {
val = val * 10 + c; // Thanks to #Danny_ds for this
}
}
// Print *val*
I ended up using a very different method to get it working by using char arrays and not relying on timing. So far it has worked perfectly. I was using this to get my arduino to work as a temp monitor.
How it communicates the temperatures
PC > OpenHardwaremonitor > WMI > Batch Script (shown below) > COM Port > Arduino > LCD
This was the only way that I could get cpu temps correctly because it's so old
Batch code:
#echo off
mode COM3: baud=9600 data=8 >nul
wmic /namespace:\\root\openhardwaremonitor path sensor where "Identifier='/intelcpu/0/temperature/0' or Identifier='/nvidiagpu/0/temperature/0'" get Value /every:2|findstr [0-9]>COM3
Arduino code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
bool sounded = false;
int cpu = 0;
int gpu = 0;
char invalids[3] = {10, 32, '\0'}; // line feed, space
boolean newData = false;
const byte numChars = 8;
char charMap[numChars];
char tempChars[numChars];
void setup() {
pinMode(6, OUTPUT); // character intensity
pinMode(8, OUTPUT); // buzzer
pinMode(10, OUTPUT); // backlight
lcd.begin(16, 2);
Serial.begin(9600);
analogWrite(6, 100); // set intensity without POT
analogWrite(10, 168); // ~3.3v
analogReference(EXTERNAL);
lcd.print("CPU: ");
lcd.print((char)223);
lcd.print("C AIR:");
lcd.setCursor(0, 1);
lcd.print("GPU: ");
lcd.print((char)223);
lcd.print("C ");
lcd.print((char)223);
lcd.print("F");
}
void loop() {
recvWithoutWhitespace();
if (newData == true) {
parseData();
lcd.setCursor(4, 0);
lcd.print(cpu);
lcd.setCursor(4, 1);
lcd.print(gpu);
int reading = analogRead(A0);
float degreesF = (((reading * 3.3 / 1024 - 0.5) * 100) * 1.8) + 32.0;
lcd.setCursor(11, 1);
lcd.print((int)(degreesF+0.5));
if(!sounded && (cpu > 75 || gpu > 85)) { // used for buzzer alarm
tone(8, 500);
delay(250);
noTone(8);
delay(250);
tone(8, 500);
delay(250);
noTone(8);
delay(250);
tone(8, 500);
delay(250);
noTone(8);
sounded = true;
} else if(sounded && (cpu <= 75 && gpu <= 85)) {
sounded = false;
}
newData = false;
}
}
void recvWithoutWhitespace() {
static byte ndx = 0;
static byte control = 0; // switch control variable
char endMarker = 13; // ASCII code for carriage return
char rc;
char * check;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
check=strchr(invalids,rc); //checks if any spaces or line feeds get in
if (check==NULL){
if (rc != endMarker) {
charMap[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
switch(control) { // expect 4 CRs in format: (num)CRCR(num)CRCR
case 0:
control = 1; // skip first of 2 CRs
break;
case 1:
charMap[ndx] = 44; // put comma in place of CR between numbers as delimeter
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
control = 2;
break;
case 2:
control = 3; // skip first of 2 CRs
break;
case 3:
charMap[ndx] = '\0'; // string terminator in place of last CR
ndx = 0;
control = 0;
newData = true;
break;
}
}
}
}
}
void parseData() {
strcpy(tempChars, charMap); //strtok is destructive so copy string temporarily
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars, ",");
cpu = atoi(strtokIndx); // convert cpu to an integer
strtokIndx = strtok(NULL, ",");
gpu = atoi(strtokIndx); // convert gpu to an integer
}

how can I display/save the value of what return an AT command

Good day all!
I am working on a project with Arduino UNO and a SIM908.
I am trying to understand the AT command.
When I enter
Serial.print("AT")
Serial.println("AT+CGPSSTATUS?");
Serial retuen a value and I would like to save that value into a buffer
char buffer[size]
I do not want to have other string than the return value of an AT command.
I also red that document
SIM908 AT Command Manual_V1.01
At the page 13, you can read (NB. < CR>< LF> : I added a space after the first <, other there are not display)
The "AT" or "at" prefix must be set at the beginning of each Command
line. To terminate a Command line enter < CR>. Commands are usually
followed by a response that includes. "< CR>< LF>< CR>< LF>"
Throughout this document, only the responses are presented, < CR>< LF>
are omitted intentionally
Then, I am asking how I can "extract" the response between < CR>< LF> and < CR>< LF>
Looking at this exemple (let me know if I am wrong), how can I detect the < CR>< LF>
void setup()
{
char buffer[200];
Serial.println("AT+CGPSSTATUS?");
}
void loop()
{
if (Serial.available())
{
// HERE I SHOULD CHECK IF CR ANF LF
Serial.write(Serial.read());
// AND SAVE IT IN buffer. IS'T NOT?
}
}
}
Do you see what I means?
How could you help me to store in a buffer, only the return value of an AT command?
Many thank for your help
It's very interresting what you show me. Here is how I adapt my code
I adapted my code and by the way I created a file for testing Serail while we send a AT command.
The concern function are loop() and read_AT_string(). (I renamed the read_String to read_AT_string().
Here my code and I explain, after the issue, regardin your proposal
#include <SoftwareSerial.h>
int baud_rate = 9600;
int pin_gsm = 3;
int pin_gps = 4;
int pin_power = 5;
//int pin_dtr = 6;
boolean debug = true;
boolean raedy_to_go = false;
// Reading String
#define BUFFERSIZE 200
char buffer[BUFFERSIZE];
char inChar;
int index;
void setup()
{
Serial.begin(baud_rate);
delay(5000); // Wait for 5sec after begin
if(debug)
{
Serial.println(F("\n****************************"));
Serial.println(F("STARTING SYSTEM Read AT stream"));
Serial.println(F("******************************"));
}
pinMode(pin_gsm,OUTPUT); // Set the pins
pinMode(pin_gps,OUTPUT);
pinMode(pin_power,OUTPUT);
powerUpSim908:
if(powerUpSim908())
{
delay(1000);
if(gps_power()){
gsm_enable();
raedy_to_go = true;
if(debug)
{
Serial.println(F("\n****************************"));
Serial.println(F("READY TO GO\n"));
Serial.println(F("****************************\n"));
}
}
else
{
raedy_to_go = false;
if(debug)
{
Serial.println(F("\nNOT READY TO GO.\nGPS could not be power\nRestart the module\nor/and check the battery level.\n"));
}
goto powerUpSim908;
}
}
else
{
raedy_to_go = false;
if(debug)
{
Serial.println(F("\nNOT READY TO GO.\nCheck the battery level.\n"));
}
};
}
void loop()
{
/*
if (Serial.available())
{
Serial.print("Character received: ");
Serial.write(Serial.read());
Serial.println("");
}
*/
if(raedy_to_go)
{
read_AT_string("AT",5000);
delay(10000);
}
}
char read_AT_string(char* command, int timeout)
{
unsigned long previous;
previous = millis();
Serial.println(F("\nDISPLAY BUFFER:"));
index=0;
Serial.println(command);
do
{
if(Serial.available() > 0) // Don't read unless
// there you know there is data
{
Serial.println("1");
if (Serial.peek() == 13) // check if CR (without reading)
{
Serial.println("13");
if(Serial.available() > 0)
{
Serial.read(); // read and ignore
if (Serial.peek()==10) // then check if LF (without reading)
{
Serial.println("10");
if(index < Serial.readBytesUntil(13, buffer, BUFFERSIZE-1)) // One less than the size of the buffer array
{
Serial.println("b");
inChar = Serial.read(); // Read a character
buffer[index] = inChar; // Store it
index++; // Increment where to write next
buffer[index] = '\0'; // Null terminate the string
}
}
}
}
}
}while(((millis() - previous) < timeout));
Serial.println(buffer);
buffer[0]='\0';
Serial.println(F("END DISPLAY BUFFER"));
}
/* FUNCTION */
boolean powerUpSim908(void)
{
if(debug)
{
Serial.println(F("Powering up SIM908"));
}
boolean turnedON = false;
//uint8_t answer=0;
int cont;
for (cont=0; cont<3; cont++)
{
digitalWrite(pin_power,HIGH);
delay(1500);
digitalWrite(pin_power,LOW);
Serial.println(F("Checking if the module is up"));
if(sendATcommand("AT", "OK", 5000))
{
cont = 4; // Leave the loop
turnedON = true;
}
else
{
turnedON = false;
if(debug)
{
Serial.println(F("\nTrying agin to turn on SIM908"));
}
};
}
if(turnedON)
{
if(debug)
{
Serial.println(F("Module is tunrned up\n"));
}
}
else
{
if(debug)
{
Serial.println(F("Module is NOT tunrned ON\n"));
}
}
return turnedON;
}
boolean sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout)
{
uint8_t x=0;
bool answer=false;
//åchar response[100];
//buffer[0]='\0';
unsigned long previous;
//memset(response, '\0', 100); // Initialice the string
//Serial.println(response);
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();
index=0;
do
{
if(Serial.available() > 0)
// there you know there is data
{
if(index < BUFFERSIZE-1) // One less than the size of the array // Same as buffer size
{
inChar = Serial.read(); // Read a character
buffer[index] = inChar; // Store it
index++; // Increment where to write next
//Serial.println(index);
buffer[index] = '\0'; // Null terminate the string
}
}
}while(((millis() - previous) < timeout));
if(strstr(buffer,"NORMAL POWER DOWN") != NULL)
{
answer = false;
}
else if (strstr(buffer, expected_answer) != NULL) // check if the desired answer (OK) is in the response of the module
{
/*
Serial.println(F("### BUFFER"));
Serial.println(buffer);
Serial.println(F("### END BUFFER"));
*/
answer = true;
}
else
{
answer = false;
}
if(debug)
{
if(answer)
{
//Serial.println(F("Expected answer : OK!\n"));
}
else
{
//Serial.println(F("Expected answer : KO!\n"));
};
}
return answer;
}
void gps_enable(void)
{
if(debug)
{
Serial.println(F("\nEnabling GPS ..."));
}
digitalWrite(pin_gps,LOW); //Enable GPS mode
digitalWrite(pin_gsm,HIGH); //Disable GSM mode
delay(2000);
}
void gsm_enable(void)
{
if(debug)
{
Serial.println(F("\nEnabling GSM ..."));
}
digitalWrite(pin_gsm,LOW); //Enable GSM mode
digitalWrite(pin_gps,HIGH); //Disable GPS mode
delay(2000);
}
/* UTILISTIES */
/* GPS */
boolean gps_power(void) //turn on GPS power supply
{
/*
Serial.println("AT");
delay(2000);
*/
boolean gpspwr = false;
boolean gpsrst = false;
if(sendATcommand("AT+CGPSPWR=1","OK",2000))
{
gpspwr = true;
if(debug)
{
Serial.println("turn on GPS power supply => OK");
}
}
else
{
if(debug)
{
Serial.println("turn on GPS power supply => KO");
}
};
//delay(1000);
if(sendATcommand("AT+CGPSRST=1","OK",2000))
{
gpsrst = true;
if(debug)
{
Serial.println("reset GPS in autonomy mode => OK");
}
}
else
{
if(debug)
{
Serial.println("reset GPS in autonomy mode => KO");
}
}; //reset GPS in autonomy mode
delay(1000);
if(gpspwr && gpsrst)
{
return true;
}else
{
return false;
}
}
At the read_AT_string, the first if(Serial.peek()==13) always return false.
1 is printed, but '13' is not, then I supposed
if(Serial.peek()==13)
return false
Here is what is printed within 5 sec
AT DISPLAY BUFFER:
1
1
1
1
1
1
1
1
1
[...] // It prints 1 until now
1
END DISPLAY BUFFER
Here a piece of code to detect and remove CR+LF (Attention: if A CR is read but it's not followed by a LF, it is removed as well):
if (Serial.peek()==13) { // check if CR (without reading)
Serial.read(); // read and ignore
if (Serial.peek()==10) // then check if LF (without reading)
Serial.read();
}
To read the rest of the response from Serial you could use:
buffer[Serial.readBytesUntil(13, buffer, 199)]=0; // readbytes returns the number of bytes read
You then have to discard the ending CRLF (same as above).
Edit
There are several issues with the code that you've posted in a separate answer.
When you powerUpSim908() you have to be aware that the gsm module may send unrequested data (see documentation, chapter 1.4):
Note: A HEX string such as "00 49 49 49 49 FF FF FF FF" will be sent
out through serial port at the baud rate of 115200 immediately after
SIM908 is powered on. The string shall be ignored since it is used for
synchronization with PC tool. Only enter AT Command through serial
port after SIM908 is powered on and Unsolicited Result Code "RDY" is
received from serial port.
This means that before you send anything, you have to discard this data by reading it. I guess this is why you don't get CRLF when reading the response: you first get the HEX string or "RDY".
Then readBytesUntil() reads as many bytes as available (maxi 199 in my example above), stores them in the buffer. It stops reading when it encounters the byte 13 (i.e.CR). There is no need to loop on an index. The function returns the number of chars that could be read, and it doesn't put an ending 0 at the end of the buffer (i.e. no valid C string). If you want to use the function in another way than what I proposed, you must store the length returned, because you have no other way to find it out later on.