I need help keeping my loop running.

My program is designed to talk to a device.

If the device responds with !"11" my program states "ini failed".

If the device responds "11" my program states "completed ini" and then, it is supposed to step this code 1 time.

 if (talking == 1){
        currentMillis = millis(); 
        previousMillis = currentMillis; // set the time counter: 
        talking = 2; // lock into the next loop of communication
      }

      while(talking == 2 && currentMillis - previousMillis < interval ){   
        Serial.println(" big dog"); // at way to see progress:
        currentMillis = millis(); // refresh the timer:

      }

After that, it is supposed to step through this code over and over.

 while (talking > 1 && talking < 3) {
        talking = 3;
        interval = 140; // adjusted interval for delay in the loop;
        currentMillis = millis(); 
        previousMillis = currentMillis; // set the time counter: 
        Serial.println("data request");  
        lcd.print("data request"); 
        Serial.print(128, HEX);  
        talking = 4;
        bytecount = 0;
        delay(10);

        while (bytecount < 50 && currentMillis - previousMillis < interval ) {            
          char c = Serial.read();
          readString += c;  
          bytecount = bytecount + 1; 
          currentMillis = millis(); // refresh the timer:
        }

        if (readString.length() > 0 && talking == 4) {
          Serial.println ("bytecounter full");
          Serial.println(readString);
          Serial.println(bytecount);
          // open the file. note that only one file can be open at a time,
          // so you have to close this one before opening another.
          File dataFile = SD.open("datalog.csv", FILE_WRITE);
          Serial.println("file open");
          // if the file is available, write to it:
          if (dataFile) {
            dataFile.println(readString);
            dataFile.close();
            Serial.println("file closed");
            readString = "";    // clear readstring to reuse it           
            talking = 3; // go back to data request:
          }

The problem is it only steps through the second bit of code one time. Here is the whole code.

Thanks in advance for any help.
Mark

// zoomkat 8-6-10 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later
// SD card attached to SPI bus as follows:
// MOSI - pin 11:
// MISO - pin 12:
// CLK - pin 13:
// CS - pin 8:
int startattempt = 0;     //counter for start attempts:
int  talking = 0;        // communication status bit:
String readString;        // storage for incoming characters:
char requestString[8]={
  (128, HEX), (18, HEX),(241, HEX),(2, HEX),(33, HEX), (8, HEX), (174, HEX)};  
char intalk = 0;    // incoming serial hex byte marker:
long rxbyte = 0;         //used for storing incoming :
int txbyte = 0;         //outgoing serial hex byte:
int bytecount = 0;      //may use for counting string inputs:
int outputpin = 1;      //TX pin control to for HIGH/LOW state:
int failurepin = 9;     // led pin to show card failure:
long charAt = 0;        // possibly used to find characters in string:
unsigned long previousMillis = 0;        // will store last time:
unsigned long currentMillis = 0;         // stores current time:
unsigned long interval = 150;           // interval at which to:
int i = 0;
char inChar = 0;
String stringOne = 0;   // string for storing incoming bytes
#include <LiquidCrystal.h>
#include <SD.h>


// initialize the library with the numbers of the interface pins:
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
#include <SD.h>
const int chipSelect = 8;


void setup() {
  Serial.begin(9600); // opens serial port
  // put your setup code here, to run once:  
  // Pin 1 has an LED connected on most Arduino boards:
  lcd.begin(16, 2);    // set up the LCD's number of columns and rows:   
  lcd.setCursor(2,1);
  lcd.print("Ini. SD card");// Print a message to the LCD.
  Serial.print("Ini SD card");


  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    lcd.scrollDisplayLeft(); 
    lcd.print("Card failed, or not present");
    // don't do anything more:
    return;
  }


  Serial.flush() ;

  pinMode(13, OUTPUT);
  Serial.println("serial test 0021"); // so I can keep track of what is loaded
}

void loop() {
  if (talking == 0 &&  startattempt < 100){
    pinMode(outputpin, OUTPUT); // initialize the digital pin 1 as an output to control communication intialization:
    digitalWrite(outputpin, HIGH);
    delay(300);
   
    Serial.begin(9600); // opens serial port, sets data rate to 9600 bps:COULD THE RETURN BIT BE LOST???????????

    if (talking == 0){
      while (Serial.available()) {
        delay(100);  
        char c = Serial.read();
        readString += c;  

      }
    }
    if (readString.length() >0 && talking == 0) {
      Serial.println(readString);
      lcd.clear();     // clear the screen


      if (readString == "11" && talking == 0) {
        readString = "";    // clear readstring to reuse it
        talking = 1;
        digitalWrite(13, HIGH);
        Serial.println("completed ini");
        lcd.print("completed ini");
        Serial.print(129,HEX); 
        
      }
      else { 
        digitalWrite(13, LOW);
        Serial.println(" ini. failed" );
        lcd.print(" ini. failed");
        Serial.println (readString);
        lcd.scrollDisplayLeft(); 
        lcd.print(readString);
        readString = "";    // clear readstring to reuse it
        startattempt = startattempt + 1;

      }
      if (talking == 1){
        currentMillis = millis(); 
        previousMillis = currentMillis; // set the time counter: 
        talking = 2; // lock into the next loop of communication
      }

      while(talking == 2 && currentMillis - previousMillis < interval ){   
        Serial.println(" big dog"); // at way to see progress:
        currentMillis = millis(); // refresh the timer:

      }


      while (talking > 1 && talking < 3) {
        talking = 3;
        interval = 140; // adjusted interval for delay in the loop;
        currentMillis = millis(); 
        previousMillis = currentMillis; // set the time counter: 
        Serial.println("data request");  
        lcd.print("data request"); 
        Serial.print(128, HEX);  
        talking = 4;
        bytecount = 0;
        delay(10);

        while (bytecount < 50 && currentMillis - previousMillis < interval ) {            
          char c = Serial.read();
          readString += c;  
          bytecount = bytecount + 1; 
          currentMillis = millis(); // refresh the timer:
        }

        if (readString.length() > 0 && talking == 4) {
          Serial.println ("bytecounter full");
          Serial.println(readString);
          Serial.println(bytecount);
          // open the file. note that only one file can be open at a time,
          // so you have to close this one before opening another.
          File dataFile = SD.open("datalog.csv", FILE_WRITE);
          Serial.println("file open");
          // if the file is available, write to it:
          if (dataFile) {
            dataFile.println(readString);
            dataFile.close();
            Serial.println("file closed");
            readString = "";    // clear readstring to reuse it           
            talking = 3; // go back to data request:
          } 
          // if the file isn't open, pop up an error:
          else {              
            Serial.println("error opening datalog.txt");
            lcd.print("error opening datalog.txt");
          }

        }
      } 
    }

  }

}

By the way, I apologize for not having the format colors. I can't seem to figure out how to transfer that part to the web.

Mark

By the way, I apologize for not having the format colors. I can't seem to figure out how to transfer that part to the web.

We don't want the colors. They are code embedded in the data that the IDE interprets. The forum does not interpret them the same way...

You have stuff in loop() that belongs in setup(). There is no reason to set pinMode() more than once, or to call Serial.begin() more than once.

  Serial.flush() ;

Do you know what this does? If not, get rid of it.

      while (Serial.available()) {
        delay(100);  
        char c = Serial.read();
        readString += c;  
      }

Why are you delaying here? How does this code know when to stop reading? You need to add end-of-packet markers to the data sent, so you know when a complete packet has arrived.

      while (talking > 1 && talking < 3) {
        talking = 3;

Well, that would explain why the while loop is executed only once. If talking is 2 (the only value that is less than 3 AND greater than 1), you immediately set it to 3. At the end of the while loop, the initial condition is no longer true, so the loop is not executed again.

It looks like your while condition is wrong, because you could be using while(talking == 2) to achieve the same results as your current statement. Presumably you didn't for some reason.

Anything that you want done once, and only once, should be in setup(), rather than trying to force an endless loop() to do it exactly once.

Thank you PaulS for the reply. I have made some of the adjustments.

Except for this part because I still need to work out the packet marker solution.

while (Serial.available()) {
        delay(100);  
        char c = Serial.read();
        readString += c;  
      }

The code now runs the loop over and over but, it ignores my "if" statements in the "setup" area of the code.

// zoomkat 8-6-10 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later
// SD card attached to SPI bus as follows:
// MOSI - pin 11:
// MISO - pin 12:
// CLK - pin 13:
// CS - pin 8:
int startattempt = 0;     //counter for start attempts:
int  talking = 0;        // communication status bit:
String readString;        // storage for incoming characters:
char intalk = 0;    // incoming serial hex byte marker:
long rxbyte = 0;         //used for storing incoming :
int txbyte = 0;         //outgoing serial hex byte:
int bytecount = 0;      //may use for counting string inputs:
int outputpin = 1;      //TX pin control to for HIGH/LOW state:
int failurepin = 9;     // led pin to show card failure:
long charAt = 0;        // possibly used to find characters in string:
unsigned long previousMillis = 0;        // will store last time:
unsigned long currentMillis = 0;         // stores current time:
unsigned long interval = 150;           // interval at which to:
int i = 0;
char inChar = 0;
String stringOne = 0;   // string for storing incoming bytes
#include <LiquidCrystal.h>
#include <SD.h>


// initialize the library with the numbers of the interface pins:
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
#include <SD.h>
const int chipSelect = 8;


void setup() {
  Serial.begin(9600); // opens serial port
  // put your setup code here, to run once:  
  // Pin 1 has an LED connected on most Arduino boards:
  lcd.begin(16, 2);    // set up the LCD's number of columns and rows:   
  lcd.setCursor(2,1);
  lcd.print("Ini. SD card");// Print a message to the LCD.
  Serial.print("Ini SD card");


  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    lcd.scrollDisplayLeft(); 
    lcd.print("Card failed, or not present");
    // don't do anything more:
    return;
  }

  pinMode(13, OUTPUT);
  Serial.println("serial test 0021"); // so I can keep track of what is loaded
  if (talking == 0 &&  startattempt < 100){
    pinMode(outputpin, OUTPUT); // initialize the digital pin 1 as an output to control communication intialization:
    digitalWrite(outputpin, HIGH);
    delay(300);

    if (talking == 0){
      while (Serial.available()) {
        delay(100);  
        char c = Serial.read();
        readString += c;  


    if (readString.length() >0 && talking == 0) {
      Serial.println(readString);
      lcd.clear();     // clear the screen


      if (readString == "11" && talking == 0) {
        readString = "";    // clear readstring to reuse it
        talking = 1;
        digitalWrite(13, HIGH);
        Serial.println("completed ini");
        lcd.print("completed ini");
        Serial.print(129,HEX); 

      }
      else { 
        digitalWrite(13, LOW);
        Serial.println(" ini. failed" );
        lcd.print(" ini. failed");
        Serial.println (readString);
        lcd.scrollDisplayLeft(); 
        lcd.print(readString);
        readString = "";    // clear readstring to reuse it
        startattempt = startattempt + 1;
      }
    }
      }
    }
  }
}
void loop() {

  if (talking == 1){
    currentMillis = millis(); 
    previousMillis = currentMillis; // set the time counter: 
    talking = 2; // lock into the next loop of communication
  }

  while(talking == 2 && currentMillis - previousMillis < interval ){   
    Serial.println(" big dog"); // at way to see progress:
    currentMillis = millis(); // refresh the timer:

  }


  while (talking = 2) {
    talking = 3;
    interval = 140; // adjusted interval for delay in the loop;
    currentMillis = millis(); 
    previousMillis = currentMillis; // set the time counter: 
    Serial.println("data request");  
    lcd.print("data request"); 
    Serial.print(128, HEX);  
    talking = 4;
    bytecount = 0;
    delay(10);

    while (bytecount < 50 && currentMillis - previousMillis < interval ) {            
      char c = Serial.read();
      readString += c;  
      bytecount = bytecount + 1; 
      currentMillis = millis(); // refresh the timer:
    }

    if (readString.length() > 0 && talking == 4) {
      Serial.println ("bytecounter full");
      Serial.println(readString);
      Serial.println(bytecount);
      // open the file. note that only one file can be open at a time,
      // so you have to close this one before opening another.
      File dataFile = SD.open("datalog.csv", FILE_WRITE);
      Serial.println("file open");
      // if the file is available, write to it:
      if (dataFile) {
        dataFile.println(readString);
        dataFile.close();
        Serial.println("file closed");
        readString = "";    // clear readstring to reuse it           
        talking = 3; // go back to data request:
      } 
      // if the file isn't open, pop up an error:
      else {              
        Serial.println("error opening datalog.txt");
        lcd.print("error opening datalog.txt");
      }

    }
  } 
}

Not much point "return"ing from "setup" - it just falls into "loop" a little earlier.

Thank you AWOL for that tip. I am still trying to make the program work. I have made changes, trying different things but, The code still runs the loop over and over but, it ignores my "if" statements in the "setup" area of the code.

Thanks,
Mark

  if (talking == 0 &&  startattempt < 100){
    pinMode(outputpin, OUTPUT); // initialize the digital pin 1 as an output to control communication intialization:
    digitalWrite(outputpin, HIGH);
    delay(300);

Why is setting pin mode conditional? It should always be set, exactly once.

What is the purpose of the delay? Do you like sitting around doing nothing?

The code still runs the loop over and over but, it ignores my "if" statements in the "setup" area of the code.

No, it doesn't. Inside the if statement, you have a while(Serial.available() > 0) statement. Think about whether there is any serial data received yet. You appear to want to wait for a response, but you don't have anything that makes setup() wait for data.

  if (talking == 0 &&  startattempt < 100){

Can they really be anything other than 0? Is this statement accomplishing anything?

      }
    }
      }
    }
  }
}

Nice job of indenting...

PaulS:

  if (talking == 0 &&  startattempt < 100){

pinMode(outputpin, OUTPUT); // initialize the digital pin 1 as an output to control communication intialization:
    digitalWrite(outputpin, HIGH);
    delay(300);



Why is setting pin mode conditional? It should always be set, exactly once.

**I am going to eliminate the conditional until, I figure out how to make a retry sequence.**



What is the purpose of the delay? Do you like sitting around doing nothing?

**I am using PWM to start communication. I actually need another low and high but, I cut them out to simplify also.**



> The code still runs the loop over and over but, it ignores my "if" statements in the "setup" area of the code.


No, it doesn't. Inside the if statement, you have a while(Serial.available() > 0) statement. Think about whether there is any serial data received yet. You appear to want to wait for a response, but you don't have anything that makes setup() wait for data.

**I am thinking that the response may take a moment. I want to receive Hexadecimal "00". I have a bit to learn on how to do that. I will try to fix the if statement.** 



if (talking == 0 &&  startattempt < 100){



Can they really be anything other than 0? Is this statement accomplishing anything?
**I wanted to have a "try again" loop but, I will cut it out to simplify things for now.**





}
    }
      }
    }
  }
}



Nice job of indenting...

**Your right I forgot to auto format after the last couple of changes.**

Thank you for the additional tips PaulS, I will keep trying,
Mark

Thanks to the forum's help, the code is getting closer to being the way I think it needs to be. I found a "=" instead of "==" that I placed by accident. I also made more corrections thanks to PaulS.

I have 2 problems left to work out.

  1. I want to stop the program and print a failure message if this program goes to the "else" statement.
if (readString == "11" ) {
      readString = "";    // clear readstring to reuse it
      talking = 1;
      digitalWrite(13, HIGH);
      Serial.println("completed ini");
      lcd.print("completed ini");
      Serial.print(129,HEX); 

    }
    else { 
      digitalWrite(13, LOW);
      Serial.println(" ini. failed" );
      lcd.print(" ini. failed");
      Serial.println (readString);
      readString = "";    // clear readstring to reuse it
      talking = 0;

    }
  1. I am not sure of the best way to write data to the SD card to save data quickly and not risk loosing all of the data if there is a problem. I am opening and closing it for every string write.
if (dataFile) {
        dataFile.println(readString);
        dataFile.close();
        Serial.println("file closed");
        readString = "";    // clear readstring to reuse it           
        talking = 1; // go back to data request:
      }

Here is my latest revision of my code

// MOSI - pin 11:
// MISO - pin 12:
// CLK - pin 13:
// CS - pin 8:
int startattempt = 0;     //counter for start attempts:
int  talking = 0;        // communication status bit:
String readString;        // storage for incoming characters:
char intalk = 0;    // incoming serial hex byte marker:
long rxbyte = 0;         //used for storing incoming :
int txbyte = 0;         //outgoing serial hex byte:
int bytecount = 0;      //may use for counting string inputs:
int outputpin = 1;      //TX pin control to for HIGH/LOW state:
int failurepin = 9;     // led pin to show card failure:
long charAt = 0;        // possibly used to find characters in string:
unsigned long previousMillis = 0;        // will store last time:
unsigned long currentMillis = 0;         // stores current time:
unsigned long interval = 150;           // interval at which to time communication events:
int i = 0;
char inChar = 0;
String stringOne = 0;   // string for storing incoming bytes

#include <LiquidCrystal.h>
#include <SD.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);   // initialize the library with the numbers of the interface pins:
#include <SD.h>
const int chipSelect = 8;



void setup() {

  Serial.begin(9600);     // opens serial port
  lcd.begin(16, 2);    // set up the LCD's number of columns and rows:   
  lcd.setCursor(2,1);  
  lcd.print("Ini. SD card");// Print a message to the LCD.
  Serial.print("Ini SD card"); 
  pinMode(10, OUTPUT); // default chip select pin output, even if you don't use it:
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    lcd.print("Card failed, or not present");
  }

  pinMode(13, OUTPUT);

  Serial.println("serial test"); // so I can keep track of what is loaded:     
  digitalWrite(outputpin, HIGH); // digital pin 1 as an output to control communication intialization:
  delay(300);

  while (i < 2 ) {
    delay(2000); // to allow me to manually enter a number for testing:
    char c = Serial.read();
    readString += c;  
    i = i + 1;
  }

  if (readString.length() > 0 ) {
    Serial.println(readString);


    if (readString == "11" ) {
      readString = "";    // clear readstring to reuse it
      talking = 1;
      digitalWrite(13, HIGH);
      Serial.println("completed ini");
      lcd.print("completed ini");
      Serial.print(129,HEX); 

    }
    else { 
      digitalWrite(13, LOW);
      Serial.println(" ini. failed" );
      lcd.print(" ini. failed");
      Serial.println (readString);
      readString = "";    // clear readstring to reuse it
      talking = 0;

    }
  }
    currentMillis = millis(); 
  previousMillis = currentMillis; // set the time counter: 
}



void loop() {


  Serial.println (talking);

  while (talking == 1 && currentMillis - previousMillis < interval){
    Serial.println(" big dog"); // at way to see progress:
    currentMillis = millis(); 
    
  }


  
    talking = 3;  // lock into the next loop of communication
    interval = 140; // adjusted interval for delay in the loop;
    currentMillis = millis(); 
    previousMillis = currentMillis; // set the time counter: 
    Serial.println("data request");  
    lcd.print("data request"); 
    Serial.print(128, HEX);  
       bytecount = 0;
    delay(10);

    while (bytecount < 50 && currentMillis - previousMillis < interval ) {            
      char c = Serial.read();
      readString += c;  
      bytecount = bytecount + 1; 
      currentMillis = millis(); // refresh the timer:
    }

    if (readString.length() > 0 && talking == 3) {
      Serial.println ("bytecounter full");
      Serial.println(bytecount);
      // open the file. note that only one file can be open at a time,
      // so you have to close this one before opening another.
      File dataFile = SD.open("datalog.csv", FILE_WRITE);
      Serial.println("file open");
      // if the file is available, write to it:
      if (dataFile) {
        dataFile.println(readString);
        dataFile.close();
        Serial.println("file closed");
        readString = "";    // clear readstring to reuse it           
        talking = 1; // go back to data request:
      } 
      // if the file isn't open, pop up an error:
      else {              
        Serial.println("error opening datalog.txt");
        lcd.print("error opening datalog.txt");
      }

    }
  }