Waiting for character entry before proceeding with function

Hi everyone,

I am working with code from the SDfat library under examples v1 > lowlatencyloggerMPU6050. There is a section of the code that calls a function to open the bin file created but asks for input of the number first.

I made some changes albeit not as elegant as the original program to add a button press to start and stop the recording part of the program:

Here is the code for my loop:

void loop(void) {

buttonState = digitalRead(buttonPin);

 // Check if the button state has changed
   if (buttonState != lastButtonState) {
    // If the button was pressed (change from HIGH to LOW)
    if (buttonState == LOW) {
      toggleFlag = !toggleFlag;  // Toggle the flag
    }
    delay(50);  // Debounce delay
  }
  
  lastButtonState = buttonState;



  

  if (toggleFlag) 
    {
    ledState = HIGH;
    digitalWrite(ledPin, ledState);
     
    //testSensor();  // function is ON, call the function
   logData();
    } 
  
    else {
        
        if (textPrinted == false) {
            menuSelect();
         }
    else 
    {
    selectOption();
    }

  } 
}



void menuSelect(){

  if (!textPrinted) {
   Serial.println();
   Serial.println(F("type:"));
   Serial.println(F("b - open existing bin file"));
   Serial.println(F("c - convert file to csv"));
   Serial.println(F("d - dump data to Serial"));
   Serial.println(F("e - overrun error details"));
   Serial.println(F("l - list files"));
   Serial.println(F("t - test without logging"));
   // Reset the textPrinted variable to allow printing the text again
  textPrinted = true;
  
  }
}

void selectOption (){

  char c = tolower(Serial.read());
      // Discard extra Serial data.
  while (Serial.available() && Serial.read() >=0);

  
   if (c == 'b') {
     openBinFile();
   } else if (c == 'c') {
     binaryToCsv();
   } else if (c == 'd') {
     dumpData();
   } else if (c == 'e') {
     checkOverrun();
   } else if (c == 'l') {
     Serial.println(F("\nls:"));
     sd.ls(&Serial, LS_SIZE);
     textPrinted = false;
     menuSelect();
   } 
     else if (c == 't') {
    testSensor();
  } 
  
}

I am calling the openBinFile which asks for a two digital character input. Here is the original code:

void openBinFile() {
  char name[FILE_NAME_DIM];
  strcpy(name, binName);
  Serial.println(F("\nEnter two digit version"));
  Serial.write(name, BASE_NAME_SIZE);
  for (int i = 0; i < 2; i++) {
    while (!Serial.available()) {
     yield();
    }
    char c = Serial.read();
    Serial.println("right after char c");
    Serial.write(c);
    Serial.println("after write c");
    Serial.println(c);
    if (c < '0' || c > '9') {
      Serial.println(F("\nInvalid digit"));
      return;
    }
    name[BASE_NAME_SIZE + i] = c;
    Serial.println("name base size:");
    Serial.println(c);
  }
  Serial.println(&name[BASE_NAME_SIZE+2]);
  if (!sd.exists(name)) {
    Serial.println(F("File does not exist"));
    return;
  }
  binFile.close();
  strcpy(binName, name);
  if (!binFile.open(binName, O_RDONLY)) {
    Serial.println(F("open failed"));
    return;
  }
  Serial.println(F("File opened"));
}

Essentially what is happening if I use the original code above is that it will not wait for the character input it just goes straight to the "Invalid digit".

I was able to modify the code to at the very least get it wait for the text entry but it does not seem to read the characters or be able to move forward with the rest of the function. From what I can tell the For loop will read each byte or character inputted and count up to 2 and I think stacks that number for processing?

Here is my modified code:

void openBinFile() {
  char name[FILE_NAME_DIM];
  strcpy(name, binName);
  bool waitForNum = true;
  Serial.println(F("\nEnter two digit version"));
  Serial.write(name, BASE_NAME_SIZE);
  for (int i = 0; i < 2; i++) {
    while (waitForNum == true) {
     yield();
    }
    char c = Serial.read();
    Serial.write(c);
    if (c < '0' || c > '9') {
      Serial.println(F("\nInvalid digit"));
      return;
    }
    name[BASE_NAME_SIZE + i] = c;
    Serial.println(c);

    if ( i == 2) {
      waitForNum = false;
      Serial.println("This has executed");
    }
  }
  Serial.println(&name[BASE_NAME_SIZE+2]);
  if (!sd.exists(name)) {
    Serial.println(F("File does not exist"));
    return;
  }
  binFile.close();
  strcpy(binName, name);
  if (!binFile.open(binName, O_RDONLY)) {
    Serial.println(F("open failed"));
    return;
  }
  Serial.println(F("File opened"));
}

I'm sure I am missing something super basic any help would be appreciated. Thanks!

ouchie.. a forever loop..

as far as original code, your serial monitor is probably sending extra chars new line or CR, you can turn that off so it will just send your numbers..
in the original code add a serial print to print out the invalid char and see what it is, proably wont see it (non printable char) so print it as DEC or HEX Serial.println(c, DEC);

good luck.. ~q

Thanks for the quick reply. I was wondering though why would the serial.avaiable() work with the yield? I guess I just have to wrap my head around that serial available first. Should I be even using the yield or just wrapping the while around more of the code? Thanks!

they are using !Serial.available.. ! is NOT..
so means while not serial available do nothing..
as soon as there is some bytes, will become true and loop will exit..
not in my opinion an ideal why but should work as designed..

~q

that depends on the board..
esp yes, uno or mega, don't think it does anything..
better to leave it as designed..

~q

Thanks very much, confirmed my basic understanding of how that !Serial.available works. I just cant place why it will not work in it's original format. I thought maybe it was someting in my void loop(). I am using an Uno for this. I will keep on plugging away at it. It's the last piece I need to figure out.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.