Problem with Serial Controlled I/O

UPDATE:
I have partially found a solution. And I now know how to fix the problem, I just need to know what to write. If I add a delay, say 500 milliseconds, it works OK as long as the user inputs the data before that delay is over. It works, but I don’t like that, I don’t want delays, it needs to work with the user. As in wait for them to input the full string and then move on.

Updated Code Piece: This is the command ‘pinConfig’, the problem is the lack of wait time

    if (commandIn == "pinConfig") //the user wants to configure a pin
    {
      Serial.println("CHOOSE A PIN [2-13]"); //Pins 0-1 are not for user use    
      lcd.clear();
      lcd.print("CHOOSE PIN: 2-13"); //show some info on the LCD
      String serialPin;
      Serial.flush();     
      delay(500); //this delay sort of fixes the problem but I don't like it
      serialPin = Serial.readString(); //serialPin reads the raw input    
      Serial.flush();    
      static int pinNumberSerial = serialPin.toInt(); //pinNumberSerial gets the integer version of the input      
      Serial.print("'");
      Serial.print(serialPin); //The pin number should show up on serial, but it is always zero
      Serial.println("'"); //the quotes are so I can tell if there is nothing there
    }

Hello Community! I have a circuit takes in commands from the serial monitor, and can configure individual pins 2-13 from serial. All of the other commands work, except the ‘configure pin’ command; it should be the way described below:

How it Should Work:

  1. User types in “pinConfig”.
    SCREEN: “CHOOSE A PIN [2-13]”
  2. User types in a pin number (lets say 5).
    SCREEN: “PIN 5 CONFIGURE”
    SCREEN: “INPUT OR OUTPUT [1/2]”
  3. User types in a setting (lets say 1).
    SCREEN: “PIN 5 NOW INPUT”
  4. User is happy and gets ice cream.

How it Really Works:

  1. User types in “pinConfig”
    SCREEN: “CHOOSE A PIN [2-13]”
  2. User types in a pin number (lets say 3)
    SCREEN: nothing
  3. User Resets and tries Everything Again.
    SCREEN: nothing
  4. User checks code and researches, then tries again
    SCREEN: nothing
  5. User gives up and goes to forum

As you can see, this code has a problem with accepting pin numbers after text, I think. I know that it can get to the command, but it wont do anything after the command is started. I’ve tried multiple attempts, but I cant get any further. Any help is appreciated. Thanks!

The Code:

//Created: April 3, 2016 by mike44449
#include <LiquidCrystal.h>
LiquidCrystal lcd(44, 45, 32, 34, 36, 38);  //Pins for Mega 2560

String SerialCommand, commandIn;
int pinNumber = 0;
int pinState;
int pinConfig;
int pinRead;
const int backlight = 53; //Connect the base of the transistor to 53

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  pinMode(backlight, OUTPUT);
  digitalWrite(backlight, HIGH); // turn on the backlight
  
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW); //turn off the onboard LED

  Serial.println("Welcome to the Digital Workstation! v1.5"); //Display some commands and information
  Serial.println("\nCOMMANDS:");
  Serial.println("pinConfig  - SPECIFY A PIN"); //choose a pin to modify
  Serial.println("allON  - ALL PINS HIGH"); //all pins on
  Serial.println("allOFF  - ALL PINS LOW"); //all pins off
  Serial.println("allIN - ALL PINS INPUT"); //all pins are inputs
  Serial.println("allOUT  - ALL PINS OUTPUT"); //all pins are output
  Serial.println("readAll - READ ALL PINS"); //display a summary of pin readings
  Serial.println("backlightON - TURN ON BACKLIGHT"); //turn on the backlight
  Serial.println("backlightOFF  - TURN OFF BACKLIGHT"); //turn off the backlight
  Serial.println("\n--------------------------------------------");
  
  lcd.begin(16, 2);
  
  lcd.print("Welcome!");
  lcd.setCursor(0,1);
  lcd.print("v1.5");
  delay(1500);
  lcd.clear();
  
  lcd.print("ENTER SERIAL"); //flash some instructions for 2 seconds
  delay(2000);
  lcd.clear();
  
  Serial.println("ENTER COMMAND");
}

void loop() {
  // put your main code here, to run repeatedly:
  //The next few lines of code will handle the commands, like backlight
  lcd.setCursor(0,0);
  
  commandIn = Serial.readString();
  if (commandIn != "") //white there is something in the buffer
  {
    if (commandIn == "allON") //user wants all pins on
    {
      Serial.println("ALL PINS HIGH"); //let the user know with serial and the LCD
      lcd.clear();
      lcd.print("ALL PINS HIGH");
      for(int i = 0; i <= 13; i++) //loop through and write to each pin, 0 to 13
      {
        pinMode(i, OUTPUT); //make sure each pin is counted as an output
        digitalWrite(i, HIGH);
      }
    }
    if (commandIn == "allOFF") //user wants all pins off
    {
      Serial.println("ALL PINS LOW");
      lcd.clear();
      lcd.print("ALL PINS LOW");
      for(int i = 0; i <= 13; i++)//do the same thing as above, but turn the pins off
      {
        pinMode(i, OUTPUT);
        digitalWrite(i, LOW);
      }
    }
    if (commandIn == "backlightON") //user wants the backlight on
    {
      digitalWrite(backlight, HIGH); //turn on the backlight and show some info.
      lcd.clear();
      lcd.print("BACKLIGHT ON");
      delay(500);
      lcd.clear();
      Serial.println("BACKLIGHT ON");
    }
    if (commandIn == "backlightOFF")
    {
      digitalWrite(backlight, LOW); //turn off the backlight and show some info.
      lcd.clear();
      lcd.print("BACKLIGHT OFF");
      delay(500);
      lcd.clear();
      Serial.println("BACKLIGHT OFF");
    }
                              if (commandIn == "pinConfig") //the user wants to configure a pin
                              {
                                //ask the forum, im stuck on this. For now, move on
                              }
    if (commandIn == "allIN") //the user wants all pins to be inputs
    {
      Serial.println("ALL PINS ARE INPUTS"); //let the user know with serial and the LCD
      lcd.clear();
      lcd.print("ALL PINS");
      lcd.setCursor(0,1);
      lcd.print("INPUTS");
      for(int i = 0; i <= 13; i++) //loop through and write to each pin, 0 to 13
      {
        pinMode(i, INPUT); //make sure each pin is counted as an input
      }
    }
    if (commandIn == "allOUT") //all pins to be outputs, the defualt
    {
      Serial.println("ALL PINS ARE OUTPUTS"); //let the user know with serial and the LCD
      lcd.clear();
      lcd.print("ALL PINS");
      lcd.setCursor(0,1);
      lcd.print("OUTPUTS");
      for(int i = 0; i <= 13; i++) //loop through and write to each pin, 0 to 13
      {
        pinMode(i, OUTPUT); //make sure each pin is counted as an input
      }
    }
    if (commandIn == "readAll") //display a summary of the states
    {
      Serial.println("SUMMARY: 13 PINS READ");
      
      for(int i = 0; i <= 13; i++) //loop through and read the pins
      {
        pinRead = digitalRead(i);
        if (pinRead == 1) //the pin is high
        {
          Serial.print("PIN: ");
          Serial.print(i);
          Serial.println(" | STATE: HIGH");
        }
        if (pinRead == 0) //the pin is low
        {
          Serial.print("PIN: ");
          Serial.print(i);
          Serial.println(" | STATE: LOW");
        }
      }
    }
  }
}

Serial_Controlled_PWM.ino (6.14 KB)

Did you try

if (commandIn == "pinConfig") //the user wants to configure a pin
{
     digitsIn=Serial.readString();
     Serial.println(digitsIn);
}

Just to see if you can read anything at that point?

After that uou may need the toInt() function to convert between the character '1' and the digit 1.

I have tried that. When I try to convert it, I get a zero.

Circumstances:
-I enter 'pinConfig'
SCREEN: "CHOOSE A PIN"
-Before I can enter anything,
SCREEN: "0"

The problem is, the variable 'pinNumberSerial' is always set to zero for some reason. I'm guessing
it's because of the string 'serialPin'. If the '.toInt()' function fails, it returns a zero, so there must be
something wrong with the input setup. It must be getting some characters and then when it gets passed through the 'toInt()', it fails. So my guess is the string 'serialPin'. I would like your advice on this.

The Code with the Problem:

    if (commandIn == "pinConfig") //the user wants to configure a pin
    {
      Serial.println("CHOOSE A PIN [2-13]"); //Pins 0-1 are not for user use
      lcd.clear();
      lcd.print("CHOOSE PIN"); //show some info on the LCD
      Serial.flush();
      serialPin = Serial.readString(); //serialPin reads the raw input
      pinNumberSerial = serialPin.toInt(); //pinNumberSerial gets the integer version of the input
      Serial.println(pinNumberSerial); //The pin number should show up on serial, but it is always zero
    }

Does increasing the timout make any difference? By default it only waits 1 second. See setTmeout()

I can fix the problem (somewhat) with either a delay or a slightly longer time out. But I'm trying to avoid a timer or delay of any kind. I am trying to eliminate waiting. Is maybe a loop of some sort possible?

Yes.. but it will require a rethink of your program flow.

The basic serial read without delay is covered on the Serial read() page.

The issue is you will have to gradually accumulate keystrokes into a buffer then go through them looking for expected input. The expected input will change depending on whats gone before. For example what happens if we enter a non-digit after 'pinConfig'? Having found valid input you then have to prune it off the buffer so it doesnt get detected again.