Search code examples
arduino-idekeypadarduino-c++

How to use serial.available twice in void loop?


I am using keypad(4x4) with arduino nano and then serially communicating arduino nano and nodemcu. My code for arduino nano is:

#include <SoftwareSerial.h>
#include <Password.h>
#include <Keypad.h>
Password ssid = Password( "1234" );
Password pass = Password( "56789" );
Password connection = Password( "C" );

const byte ROWS = 4; // Four rows
const byte COLS = 4; // Three columns

char hexaKeys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = { 2,3,4,10 };
byte colPins[COLS] = { 11,7,8,9 };
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS );
SoftwareSerial s(5,6);
//void checkPassword();
void setup(){
  Serial.begin(9600);
  s.begin(9600);
  customKeypad.addEventListener(keypadEvent); //add an event listener for this keypad
  Serial.println("enter SSID: ");    
}

void loop()
{
  char customKey = customKeypad.getKey(); //storing pressed key value in a char
  if (customKey) {
    if(s.available() > 0) {
      switch (customKey) {
        case '1':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case '2':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case '3':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case '4':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case '5':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case '6':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case '7':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case '8':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case '9':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case '0':
          Serial.println(customKey);
          s.write(customKey);
          //s.write("\nPassword verified\nPress C to connect\n");
          break;
        case '*':
          Serial.println(customKey);
          s.write(customKey);
          //s.write();
          //s.write("\nSSID verified\nEnter your Password\n");
          //checkPassword();
          break;
        case '#':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case 'A':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case 'B':
          Serial.println(customKey);
          s.write(customKey);
          break;
        case 'C':
          Serial.println(customKey);
          s.write(customKey);
          //s.write("\nConnecting to..");
          break;
        case 'D':
          Serial.println(customKey);
          s.write(customKey);
          break;
      }
    }
  }
}

void keypadEvent(KeypadEvent key){

  switch (customKeypad.getState()) {
    case PRESSED:
      // Serial.println(key);
      //s.write(key);
      switch (key) {

        case '*': 
          checkPassword();
          break;

        case '#': 
          ssid.reset();
          pass.reset();
          connection.reset();
          break;

        default: 
          ssid.append(key);
          pass.append(key);
          connection.append(key);
      }
  }
}

void checkPassword(){

  if (ssid.evaluate()) {
    Serial.println();
    Serial.println("SSID verified");
    Serial.print("enter password: ");  
  } else if (pass.evaluate()){ 
    Serial.println();
    Serial.println("Password verified");
    Serial.println("press C to connect"); 
  } else if (connection.evaluate()) { 
    Serial.println();
    Serial.println("Connecting to....");
  } else {
    Serial.println("Wrong");
  }
}

and my nodemcu code is:

#include <String.h>
#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
SoftwareSerial s(D6,D5); // (Rx, Tx)
String shab;
String shab2;
String arr[40];
String arr1[40];
const char* shab1="";
const char* shab3="";
std::string str;
int i,k;

void setup() {
  s.begin(9600);
  Serial.begin(9600);
  Serial.print("enter ssid: ");
}

void loop() {

  s.write("s");
  while(s.available() >0) {
    char data=s.read();
    shab += data;
    Serial.print(data);
  }

  int len=shab.length();
  if (shab.charAt(len-1)=='*') {
    for(i=0;i<shab.length();i++) {
      arr[i]=shab.substring(0,len-1);
    }
    shab1 = arr[0].c_str();
    Serial.println();
    Serial.println(shab1);
    Serial.print("Enter ur password: ");
    // delay(7000);


    // while(true){
    while(s.available() >0) {
      char data1=s.read();
      shab2 += data1;
      Serial.print(data1);
    //}
      int len1=shab2.length();
      if(shab2.charAt(len1-1)=='*') {
        for(k=0;k<shab2.length();k++) {
          arr1[k]=shab2.substring(0,len1-1);
        }
        shab3 = arr1[0].c_str();
        Serial.println();
        Serial.println(shab3);
        Serial.println("Connecting to wifi: ");
        delay(2000);
        Serial.println(shab1);
        Serial.flush();
        WiFi.begin(shab1,shab3);
        while (WiFi.status() != WL_CONNECTED) {
          delay(500);
          Serial.print(".");
        }
        Serial.println(" IP address: ");
        Serial.print(WiFi.localIP());
        delay(2000);
       // } 
      } 
    }

    while(1) {
      delay(1000);
    }
  }
}

Now the problem is that when i enter the password from keypad, this while(s.available>0) line when given second time, it does not work. This does not print anything on the serial monitor. Can anyone please help me?


Solution

  • The problem is that after Serial.print("Enter ur password: ");, the program immediately evaluates s.available(). Since nothing is available, it goes into the infinite loop at the end of loop() and never gets out of it.

    If you want to read incoming data until you receive '*', you can do something like this.

    Serial.print("Enter ur password: ");
    
    bool entered = false;
    while (entered == false) { // loop until entered becomes true
        yield();
        while (s.available() > 0) {
            char data1 = s.read();
            shab2 += data1;
            Serial.println(data1);
            int len1 = shab2.length();
    
            if (shab2.charAt(len1-1) == '*') {
                // do whatever you need to do
                entered = true;  // now you can get out of the loop
            } 
        }
    }