0

The program I'm trying to build is:

  1. Type in 1st name, hit enter, type in 2nd name and then hit enter again.
  2. Register those names from string input to char naming in student struct.
  3. Print out the names in serial monitor.
  4. Use those names in the main program.

The problem is I got randomize results whenever I typed in the names.

My target output:

Program Starts
Insert 2 students name:

First student: Adam     //When input -> Adam
Second student: Eve     //When input -> Eve
First student: John    //When input -> John
Second student: Amy    //When input -> Amy
//the sequences should repeat

...but what happened is the sequences of the names randomized. For example:

Program Starts
Insert 2 students name:

First student: Adam
First student: Eve
Second student: John
First student: Amy
//the sequences will keep randomizing

Can anyone point out what I've missed out?

The program:

typedef struct
    {
        char naming[20];         
    }student;

    student record[]{
      {""},
      {""},
    };

    String readString;
    String str=""; 

    // the setup routine runs once when you press reset:
    void setup() {
      Serial.begin(9600);    // initialize serial communication at 9600 bits per second
      while (!Serial);              // wait for Serial Monitor to open
      SerialUSB.println("Program Starts \n Insert 2 students name:");  // Title of sketch 
    }

    void loop() {
        namedata();
        mainprg();
    }

    void namedata() 
    {
    for(uint8_t i = 0; i < sizeof(record)/sizeof(student); i++){
          while (Serial.available()) {
            char c = Serial.read();
            readString += c;
            readString.trim();
          }

          if (readString.length() >0) {
            str = readString;
            str.toCharArray(record[i].naming,20);
            if(i==0){
               Serial.print("First student: ");
            }else if(i==1){ 
               Serial.print("Second student: ");
            }
            Serial.println(record[i].naming);        
          }
            readString="";
        } 
    }

    void mainprg()
    {
      //main program using student`s name
    }

Additional infos:

1.Why use struct? Because I've more data to process/store for one "student" in my main program. 2.Currently using Arduino Yun Mini, Arduino 1.8.7

Thanks in advance!

  • change ++i to i++ – Juraj Jan 28 at 6:07
  • @Juraj Nope still the same, though I also tried if(int i; i<2; i++) to no avail... – Samir Izmier Chong Jan 28 at 6:24
  • your algorithm for reading the names is based on misunderstanding how Serial input works – Juraj Jan 28 at 7:30
  • @Juraj I would appreciate it if you can point me to any info on the topic – Samir Izmier Chong Jan 28 at 7:46
  • 3
    The problem, that Juraj mentioned, is that you seem to think, that all the data from one name input will arrive as a big chunk, so that the while loop will only exit, when a full name has been read. That is not the case. There might be pauses between arbitrary bytes in the stream, for example introduced from the OS of the PC. The while loop will often exit, before a full name is read. You can use the something like the readline function here: majenko.co.uk/blog/reading-serial-arduino – chrisl Jan 28 at 14:45
1

Even though this is not elegant by any means, for now this is what I've came out with:

typedef struct
{
  char naming[20];
} student;

student record[] {
  {""},
  {""},
};

int a = 0;

char buf[20];

// the setup routine runs once when you press reset:
void setup() {
  Serial.begin(9600);    // initialize serial communication at 9600 bits per second
  while (!Serial);              // wait for Serial Monitor to open
  Serial.println("Program Starts \n Insert 2 students name:");  // Title of sketch
}

void loop() {
  if (readline(Serial.read(), buf, 20) > 0) {
    if (a == 0) {
      Serial.print("First student: ");
      strncpy(record[a].naming, buf, 20);
      Serial.println(record[a].naming);
      a = 1;
    }
    else if ( a == 1) {
      Serial.print("Second student: ");
      strncpy(record[a].naming, buf, 20);
      Serial.println(record[a].naming);
    }

  }
}

int readline(int readch, char *buffer, int len) {
  static int pos = 0;
  int rpos;

  if (readch > 0) {
    switch (readch) {
      case '\r': // Ignore CR
        break;
      case '\n': // Return on new-line
        rpos = pos;
        pos = 0;  // Reset position index ready for next time
        return rpos;
      default:
        if (pos < len - 1) {
          buffer[pos++] = readch;
          buffer[pos] = 0;
        }
    }
  }
  return 0;
}

Basically by using int a, the program decides the sequences of the name. Although it will not repeat the sequence after the 2nd input (ie 1st>2nd>1st>2nd), at least the sequence is not randomize anymore.

Btw thanks for the tips @chrisl!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.