Help with Reading Inputs and Printing responses

Hi there,

I'm totally new to Arduino and programming in general. I have a task that requires me to adapt an exisiting Arduino project. I chose this project and wanted to add a feature of the program talking back to the user based on what the user inputted.

I have no idea how to acomplish this. Some of my research shows that I may need to use arrays but I don't understand wha they do or how to implement them.

I need the program to be able to

  • Read an input as decoded morse code until a special character is detected.
  • Print a response on the serial monitor based on what the input was e.g. User: Hello, Program: Hi

Any help would be really appreciated as I'm really struggling with this.

Thanks in advance, friends!

Have you tried entering the words "morse code" into the search box located in the upper right hand corner of the Arduino Forum screen?

Hi there,

Thanks for ryour response. I should have made it clear that I have the basic morse code decoder working so you can input mose code via a button and it will be translated and printed on the serial monitor.

it's just recognising it as a word and printing a response back to he user I'm struggling with.

Read the forum guidelines and then post the code that you have.

Sounds like, from your very brief description, and the advice you have been given already, that your code is decoding the Morse signals and printing the characters one at a time? So each time it decodes a new character, it forgets the previous one. Obviously, in order to spot the word "hello" it needs to know the latest character and at least the previous 4 characters (more for longer words). You could save each of the last 4 characters in 4 more variables, but this gets a little clunky, and if you need to spot a 13 character word, very clunky! This is where the array comes in useful. An array is a single variable but with many "slots" to hold different values or characters. Your code can refer to each "slot" by its index number. An array with 20 slots has index values 0 to 19. So using an array, your code can easily keep the last 20 decoded characters

Each time a new character is decoded, you can "shunt" all the characters 1 place to the left in the array, losing the oldest one and making space to add the latest one. Once you have that, there is a standard C function, strstr(), for finding a particular word in that array.

Thank you very much for your help. Apologies if I haven’t been clear enough. My exisiting code is below. That explanation of arrays already makes much more sense to me so thank you for that.

/*
  PROGRAM TO DECIPHER MORSE CODE USING A PUSH BUTTON AND DISPLAY IT ON THE SERIAL MONITOR
  DATE: 20 JANUARY 2017
  AUTHORS: PINAKI SADHUKHAN AND PRIYANKA SADHUKHAN
*/

unsigned long signal_len,t1,t2;   //time for which button is pressed
int inputPin = 2;                 //input pin for push button
int ledPin = 4;                   //outpu pin for LED
String code = "";                 //string in which one alphabet is stored

void setup() {
  Serial.begin(9600);
  pinMode(inputPin, INPUT_PULLUP); //internal pullup resistor is used to simplify the circuit
  pinMode(ledPin,OUTPUT);
}

void loop()
{
NextDotDash:
  while (digitalRead(inputPin) == HIGH) {}
  t1 = millis();                            //time at button press
  digitalWrite(ledPin, HIGH);               //LED on while button pressed
  while (digitalRead(inputPin) == LOW) {}
  t2 = millis();                            //time at button release
  digitalWrite(ledPin, LOW);                //LED off on button release
  signal_len = t2 - t1;                     //time for which button is pressed
  if (signal_len > 50)                      //to account for switch debouncing
  {
    code += readio();                       //function to read dot or dash
  }
  while ((millis() - t2) < 500)           //if time between button press greater than 0.5sec, skip loop and go to next alphabet
  {     
    if (digitalRead(inputPin) == LOW)
    {
      goto NextDotDash;
    }
  }
  convertor();                          //function to decipher code into alphabet
}

char readio()
{
  if (signal_len < 600 && signal_len > 50)
  {
    return '.';                        //if button press less than 0.6sec, it is a dot
  }
  else if (signal_len > 600)
  {
    return '-';                        //if button press more than 0.6sec, it is a dash
  }
}

void convertor()
{
  static String letters[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
                             ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "E"
                            };
  int i = 0;
  if (code == ".-.-.-")
  {
    Serial.print(".");        //for break
  }
  else
  {
    while (letters[i] != "E")  //loop for comparing input code with letters array
    {
      if (letters[i] == code)
      {
        Serial.print(char('A' + i));
        break;
      }
      i++;
    }
    if (letters[i] == "E")
    {
      Serial.println("<Wrong input>");  //if input code doesn't match any letter, error
    }
  }
  code = "";                            //reset code to blank string
}

You might be able to adapt some of the concepts shown in serial input basics to build your data.

So you want to read in a string like “.- .-” and then parse to aa
If so then check out my Arduino Software Solutions for various ways to read input from Serial and choose which one suites you
Then you need to parse the String into substrings to run your compare.

void setup() {
  Serial.begin(9600);
  for (int i = 10; i > 0; i--) {
    Serial.print(' '); Serial.print(i);
    delay(500);
  }
  Serial.println();
  
  String input = ".- -...";
  
  int startIdx = 0;
  int endIdx = 0;
  while (startIdx >=0) {
    endIdx = input.indexOf(' ',startIdx); // find next space
    String code = input.substring(startIdx,endIdx);
    Serial.println(code); // do your decode here
    if (endIdx <0) {
      break; // finished did not find another space
    }
    startIdx = endIdx +1; // step over the space
  }
}
void loop() {
}

special character is detected.

I am assuming you will decode this special char and break out of the loop.

Post back here with your revised code if you need more help

I’m really sorry I don’t really get it.

I’m trying to break it down into parts to make it a bit more manageable for me.

I want to tackle just having the program print a response based on the input first of all.

I’m using Example 2 from here as a basis.

I think I want to set up an if statement like this:

 if (receivedChars == Hello) {
Serial.println("<Hi there!>");

But I can’t seem to get it working. Here’s the full code. I know I’m probably making a lot of rookie mistakes so I really appreciate the help.

// Example 2 - Receive with an end-marker

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

void setup() {
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
}

void loop() {
    recvWithEndMarker();
    showNewData();
}
 if (receivedChars == Hello) {
Serial.println("<Hi there!>");

void recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
   
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        Serial.print("This just in ... ");
        Serial.println(receivedChars);
        newData = false;
    }
}

The output of the serial receive example (receivedChars) is a string. You can’t use == with strings, use strcmp() instead.

Like so:

// Example 2 - Receive with an end-marker

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

void setup()
{
   Serial.begin(9600);
   Serial.println("<Arduino is ready>");
}

void loop()
{
   recvWithEndMarker();

   if (newData == true)
   {
      if (strcmp(receivedChars, "Hello") == 0)
      {
         Serial.println("<Hi There>");
      }
      else
      {
         Serial.println("invalid input");
      }
      newData = false;
   }
}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (Serial.available() > 0 && newData == false)
   {
      rc = Serial.read();

      // ignore carriage return
      if (rc == '\r')
      {
         return;
      }

      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         ndx = 0;
         newData = true;
      }
   }
}

You have no idea how happy this has made me! It can talk back! Thank you so much.

I managed to add another “if (strcmp(receivedChars,…” so it will respond differently with a different input.

Now, I’m trying to get the serial monitor to print the input before the response so it reads like:

Me: Hi
Bot: Hello, how are you
Me: Good!

I’ve got to the point where it says:

Me:
Hello
Bot: Hi there!
Bot: Sorry, I don’t know that one. Check the README.txt file for a list of words or phrases I know.

Which is good but I want the “Me:” and the “Hello” to be on the same line and I’m not sure why it’s giving me the unrecognised input error. Possibly because it’s taking the “Me:” text as an input?

Any tips would be great! And thanks again. You are a life saver!

Here’s the code so far:

// Example 2 - Receive with an end-marker

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

void setup()
{
   Serial.begin(9600);
     Serial.println("Waking up...");
        delay(1000);
     Serial.println("Snoozing the alarm clock...");
        delay(1000);
     Serial.println("Getting coffee...");
        delay(1000);
     Serial.println("Petting the dog...");
        delay(2000);
     Serial.println("Done!");
        delay(1000);
     Serial.println("Ava: Hi there! I'm Ava; the morse code training bot! I'm designed to help develop your skills in communicating with morse code through conversation. For a list of words or phrases I know, check the README.txt file");
}

void loop()
{
   recvWithEndMarker();

   if (newData == true)
   {
            if (strcmp(receivedChars, "Hello") == 0)
      {
        Serial.println("Me:");
        Serial.println(receivedChars);
        Serial.println("Ava: Hi there!");
      }
      if (strcmp(receivedChars, "Hi") == 0)
      {
         Serial.println("Ava: Hello, how are you?");
      }

            else
      {
         Serial.println("Ava: Sorry, I don't know that one. Check the README.txt file for a list of words or phrases I know.");
      }
      newData = false;
   }
}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (Serial.available() > 0 && newData == false)
   {
      rc = Serial.read();

      // ignore carriage return
      if (rc == '\r')
      {
         return;
      }

      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         ndx = 0;
         newData = true;
      }
   }
}

The println function will print the text and also send a line feed and carriage return characters (“Hello\r\n”) The line feed and carriage return characters make the next print go on the next line. If you do not want the next text to print on the next line, do not use println(), use print().

The 2 if statements in the loop() function are independant. If the first if is true or false the second if is still executed. If the second if is false, the invalid text is printed. The way to fix it is to make the second if only execute if the first if is false. To do that use else if instead of if. Then the execution of the second is dependent on the state of the first if. If the first if is true the second will not execute. If the first if is false the second will execute.

// Example 2 - Receive with an end-marker

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

void setup()
{
   Serial.begin(9600);
   Serial.println("Waking up...");
   delay(1000);
   Serial.println("Snoozing the alarm clock...");
   delay(1000);
   Serial.println("Getting coffee...");
   delay(1000);
   Serial.println("Petting the dog...");
   delay(2000);
   Serial.println("Done!");
   delay(1000);
   Serial.println("Ava: Hi there! I'm Ava; the morse code training bot! I'm designed to help develop your skills in communicating with morse code through conversation. For a list of words or phrases I know, check the README.txt file");
}

void loop()
{
   recvWithEndMarker();

   if (newData == true)
   {
      if (strcmp(receivedChars, "Hello") == 0)
      {
         Serial.print("Me: ");
         Serial.println(receivedChars);
         Serial.println("Ava: Hi there!");
      }
      else if (strcmp(receivedChars, "Hi") == 0)  // ****** added else if to make a if-else if-else chain
      {
         Serial.println("Ava: Hello, how are you?");
      }

      else
      {
         Serial.println("Ava: Sorry, I don't know that one. Check the README.txt file for a list of words or phrases I know.");
      }
      newData = false;
   }
}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (Serial.available() > 0 && newData == false)
   {
      rc = Serial.read();

      // ignore carriage return
      if (rc == '\r')
      {
         return;
      }

      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         ndx = 0;
         newData = true;
      }
   }
}

See the else structure reference.

1 Like

I can’t thank you enough for your help! I feel bad asking for more but now I’m trying to add the morse decoder part of the project into the code and I’m not sure what I’m doing wrong. I tried Googling some of the errors but I didn’t understand too well.

Here’s the morse decoder I’m trying to integrate:

/*
  PROGRAM TO DECIPHER MORSE CODE USING A PUSH BUTTON AND DISPLAY IT ON THE SERIAL MONITOR
  DATE: 20 JANUARY 2017
  AUTHORS: PINAKI SADHUKHAN AND PRIYANKA SADHUKHAN
*/

unsigned long signal_len,t1,t2;   //time for which button is pressed
int inputPin = 2;                 //input pin for push button
int ledPin = 4;                   //outpu pin for LED
String code = "";                 //string in which one alphabet is stored

void setup() {
  Serial.begin(9600);
  pinMode(inputPin, INPUT_PULLUP); //internal pullup resistor is used to simplify the circuit
  pinMode(ledPin,OUTPUT);
}

void loop()
{
NextDotDash:
  while (digitalRead(inputPin) == HIGH) {}
  t1 = millis();                            //time at button press
  digitalWrite(ledPin, HIGH);               //LED on while button pressed
  while (digitalRead(inputPin) == LOW) {}
  t2 = millis();                            //time at button release
  digitalWrite(ledPin, LOW);                //LED off on button release
  signal_len = t2 - t1;                     //time for which button is pressed
  if (signal_len > 50)                      //to account for switch debouncing
  {
    code += readio();                       //function to read dot or dash
  }
  while ((millis() - t2) < 500)           //if time between button press greater than 0.5sec, skip loop and go to next alphabet
  {     
    if (digitalRead(inputPin) == LOW)
    {
      goto NextDotDash;
    }
  }
  convertor();                          //function to decipher code into alphabet
}

char readio()
{
  if (signal_len < 600 && signal_len > 50)
  {
    return '.';                        //if button press less than 0.6sec, it is a dot
  }
  else if (signal_len > 600)
  {
    return '-';                        //if button press more than 0.6sec, it is a dash
  }
}

void convertor()
{
  static String letters[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
                             ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "E"
                            };
  int i = 0;
  if (code == ".-.-.-")
  {
    Serial.print(".");        //for break
  }
  else
  {
    while (letters[i] != "E")  //loop for comparing input code with letters array
    {
      if (letters[i] == code)
      {
        Serial.print(char('A' + i));
        break;
      }
      i++;
    }
    if (letters[i] == "E")
    {
      Serial.println("<Wrong input>");  //if input code doesn't match any letter, error
    }
  }
  code = "";                            //reset code to blank string
}

And here’s the working chat bot code:

// Example 2 - Receive with an end-marker

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

void setup()
{
   Serial.begin(9600);
     Serial.println("Waking up...");
        delay(1000);
     Serial.println("Snoozing the alarm clock...");
        delay(1000);
     Serial.println("Getting coffee...");
        delay(1000);
     Serial.println("Petting the dog...");
        delay(2000);
     Serial.println("Done!");
        delay(1000);
     Serial.println("Ava: Hi there! I'm Ava; the morse code training bot! I'm designed to help develop your skills in communicating with morse code through conversation. For a list of words or phrases I know, check the README.txt file");
}

void loop()
{
   recvWithEndMarker();

   if (newData == true)
   {
            if (strcmp(receivedChars, "Hello") == 0)
      {
        Serial.print("Me:");
        Serial.println(receivedChars);
        Serial.println("Ava: Hi there!");
      }
     else if (strcmp(receivedChars, "Hi") == 0) // ****** added else if to make a if-else if-else chain
      {
        Serial.print("Me:");
        Serial.println(receivedChars);
         Serial.println("Ava: Hello, how are you?");
      }

            else
      {
         Serial.println("Ava: Sorry, I don't know that one. Check the README.txt file for a list of words or phrases I know.");
      }
      newData = false;
   }

}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (Serial.available() > 0 && newData == false)
   {
      rc = Serial.read();

      // ignore carriage return
      if (rc == '\r')
      {
         return;
      }

      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         ndx = 0;
         newData = true;
      }
   }
}

Finally, here’s my unsuccessful attempt to integrate it:

// Example 2 - Receive with an end-marker
//MORSE CODE SECTION
unsigned long signal_len,t1,t2;   //time for which button is pressed
int inputPin = 2;                 //input pin for push button
int ledPin = 4;                   //outpu pin for LED
String code = "";                 //string in which one alphabet is stored
// END OF MORSE CODE SECTION

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data
boolean newData = false;

void setup()
{
   Serial.begin(9600);
  //MORSE CODE SECTION
   pinMode(inputPin, INPUT_PULLUP); //internal pullup resistor is used to simplify the circuit
  pinMode(ledPin,OUTPUT);
  //END OF MORSE CODE SECTION
     Serial.println("Waking up...");
        delay(1000);
     Serial.println("Snoozing the alarm clock...");
        delay(1000);
     Serial.println("Getting coffee...");
        delay(1000);
     Serial.println("Petting the dog...");
        delay(2000);
     Serial.println("Done!");
        delay(1000);
     Serial.println("Ava: Hi there! I'm Ava; the morse code training bot! I'm designed to help develop your skills in communicating with morse code through conversation. For a list of words or phrases I know, check the README.txt file");
}

void loop()
   //MORSE CODE SECTION
   {
NextDotDash:
  while (digitalRead(inputPin) == HIGH) {}
  t1 = millis();                            //time at button press
  digitalWrite(ledPin, HIGH);               //LED on while button pressed
  while (digitalRead(inputPin) == LOW) {}
  t2 = millis();                            //time at button release
  digitalWrite(ledPin, LOW);                //LED off on button release
  signal_len = t2 - t1;                     //time for which button is pressed
  if (signal_len > 50)                      //to account for switch debouncing
  {
    code += readio();                       //function to read dot or dash
  }
  while ((millis() - t2) < 500)           //if time between button press greater than 0.5sec, skip loop and go to next alphabet
  {     
    if (digitalRead(inputPin) == LOW)
    {
      goto NextDotDash;
    }
  }
{  convertor();                          //function to decipher code into alphabet
}
{
  if (signal_len < 600 && signal_len > 50)
  {
    return '.';                        //if button press less than 0.6sec, it is a dot
  }
  else if (signal_len > 600)
  {
    return '-';                        //if button press more than 0.6sec, it is a dash
  }
}
char readio()
{
  if (signal_len < 600 && signal_len > 50)
  {
    return '.';                        //if button press less than 0.6sec, it is a dot
  }
  else if (signal_len > 600)
  {
    return '-';                        //if button press more than 0.6sec, it is a dash
  }
}
//END OF MORSE CODE SECTION

   recvWithEndMarker();

   if (newData == true)
   {
            if (strcmp(receivedChars, "Hello") == 0)
      {
        Serial.print("Me:");
        Serial.println(receivedChars);
        Serial.println("Ava: Hi there!");
      }
     else if (strcmp(receivedChars, "Hi") == 0)
      {
        Serial.print("Me:");
        Serial.println(receivedChars);
         Serial.println("Ava: Hello, how are you?");
      }

            else
      {
         Serial.println("Ava: Sorry, I don't know that one. Check the README.txt file for a list of words or phrases I know.");
      }
      newData = false;
   }

}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (Serial.available() > 0 && newData == false)
   {
      rc = Serial.read();

      // ignore carriage return
      if (rc == '\r')
      {
         return;
      }

      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         ndx = 0;
         newData = true;
      }
   }
}
  
  //MORSE COURSE SECTION
void convertor()
{
  static String letters[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
                             ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "E"
                            };
  int i = 0;
  if (code == ".-.-.-")
  {
    Serial.print(".");        //for break
  }
  else
  {
    while (letters[i] != "E")  //loop for comparing input code with letters array
    {
      if (letters[i] == code)
      {
        Serial.print(char('A' + i));
        break;
      }
      i++;
    }
    if (letters[i] == "E")
    {
      Serial.println("<Wrong input>");  //if input code doesn't match any letter, error
    }
  }
  code = "";                            //reset code to blank string
}
// END OF MORSE CODE SECTION

Thanks again for any help you’re willing to provide. I think I’m slowly understanding more how it works.

What is the problem with the code? I mean, what does the code actually do and how is that different from what you want the code to do?

Posted code is missing the readio() function.

Sorry should have made that more clear. I want it to work like the chat bot (which you helped with and is now working fine) but instead of typing to the chat bot, you use the button on the Arduino to talk in morse and it’s decoded on screen and responded to.

Right now, I have a working chat bot that you can type to and a working morse decoder that doesn’t talk back. So I’m trying to integrate the two.

My attempt to integrate them just results in errors which I don’t really understand. See below. It’s confusing to me that they both work individually but don’t work together.

Arduino: 1.8.13 (Windows 10), Board: “Arduino Uno”

C:\Users\jonat\iCloudDrive\University\TR2\Playful Interaction\Assessment\Attempt to Add Morse Code\Attempt_to_Add_Morse_Code\Attempt_to_Add_Morse_Code.ino: In function ‘void loop()’:

Attempt_to_Add_Morse_Code:46:13: error: ‘readio’ was not declared in this scope

 code += readio();                       //function to read dot or dash

         ^~~~~~

C:\Users\jonat\iCloudDrive\University\TR2\Playful Interaction\Assessment\Attempt to Add Morse Code\Attempt_to_Add_Morse_Code\Attempt_to_Add_Morse_Code.ino:46:13: note: suggested alternative: ‘fread’

 code += readio();                       //function to read dot or dash

         ^~~~~~

         fread

C:\Users\jonat\iCloudDrive\University\TR2\Playful Interaction\Assessment\Attempt to Add Morse Code\Attempt_to_Add_Morse_Code\Attempt_to_Add_Morse_Code.ino:60:12: warning: return-statement with a value, in function returning ‘void’ [-fpermissive]

 return '.';                        //if button press less than 0.6sec, it is a dot

        ^~~

C:\Users\jonat\iCloudDrive\University\TR2\Playful Interaction\Assessment\Attempt to Add Morse Code\Attempt_to_Add_Morse_Code\Attempt_to_Add_Morse_Code.ino:64:12: warning: return-statement with a value, in function returning ‘void’ [-fpermissive]

 return '-';                        //if button press more than 0.6sec, it is a dash

        ^~~

Attempt_to_Add_Morse_Code:68:1: error: a function-definition is not allowed here before ‘{’ token

{

^

exit status 1

‘readio’ was not declared in this scope

There are problems with your curly brackets, to start. The definition of the readio() function is inside of the loop() function. You cannot have a function definition inside of another function. Use the IDE autoformat tool (ctrl-t or Tools, Auto Format) and you can see.

A feature of the IDE is that if you place the cursor to the right of a curly bracket or parenthesis, the matching bracket or parenthesis will be highlighted.

And in C++ we do not use labels and goto. NextDotDash should be made a function.

See the comments in the code. Once you move the function definition(s) outside of loop() and fix the curly bracket problems the code may compile. Give it a try and if it will not work, post the new version and the error message (like you did before) or tell us what the code does that you don’t like.

// Example 2 - Receive with an end-marker
//MORSE CODE SECTION
unsigned long signal_len, t1, t2; //time for which button is pressed
int inputPin = 2;  // *** this could be const byte instead of int to save some SRAM                 
int ledPin = 4;    // *** this could be const byte instead of int to save some SRAM   
String code = "";                 //string in which one alphabet is stored
// END OF MORSE CODE SECTION

const byte numChars = 32;  // *** is this enough bytes to store the entire incoming message?
char receivedChars[numChars];   // an array to store the received data
boolean newData = false;

void setup()
{
   Serial.begin(9600);
   //MORSE CODE SECTION
   pinMode(inputPin, INPUT_PULLUP); //internal pullup resistor is used to simplify the circuit
   pinMode(ledPin, OUTPUT);
   //END OF MORSE CODE SECTION
   Serial.println("Waking up...");
   delay(1000);
   Serial.println("Snoozing the alarm clock...");
   delay(1000);
   Serial.println("Getting coffee...");
   delay(1000);
   Serial.println("Petting the dog...");
   delay(2000);
   Serial.println("Done!");
   delay(1000);
   Serial.println("Ava: Hi there! I'm Ava; the morse code training bot! I'm designed to help develop your skills in communicating with morse code through conversation. For a list of words or phrases I know, check the README.txt file");
}

void loop()
//MORSE CODE SECTION
{
NextDotDash:  // *** we don't use labels and goto in C++.  Make this into a function
   while (digitalRead(inputPin) == HIGH) {}
   t1 = millis();                            //time at button press
   digitalWrite(ledPin, HIGH);               //LED on while button pressed
   while (digitalRead(inputPin) == LOW) {}
   t2 = millis();                            //time at button release
   digitalWrite(ledPin, LOW);                //LED off on button release
   signal_len = t2 - t1;                     //time for which button is pressed
   if (signal_len > 50)                      //to account for switch debouncing
   {
      code += readio();                       //function to read dot or dash
   }
   while ((millis() - t2) < 500)           //if time between button press greater than 0.5sec, skip loop and go to next alphabet
   {
      if (digitalRead(inputPin) == LOW)
      {
         goto NextDotDash;  // *** we don't use got in C++
      }
   }
   { // *** what is this { for?
      convertor();  // *** is this a function call or part of a function defintition?                       
   }  // *** what is this } for?
   {
      if (signal_len < 600 && signal_len > 50)
      {
         return '.';                        //if button press less than 0.6sec, it is a dot
      }
      else if (signal_len > 600)
      {
         return '-';                        //if button press more than 0.6sec, it is a dash
      }
   }
   char readio()  // *** this function definition is inside of loop().  Where should loop() end
   {
      if (signal_len < 600 && signal_len > 50)
      {
         return '.';                        //if button press less than 0.6sec, it is a dot
      }
      else if (signal_len > 600)
      {
         return '-';                        //if button press more than 0.6sec, it is a dash
      }
   }
   //END OF MORSE CODE SECTION

   recvWithEndMarker();

   if (newData == true)
   {
      if (strcmp(receivedChars, "Hello") == 0)
      {
         Serial.print("Me:");
         Serial.println(receivedChars);
         Serial.println("Ava: Hi there!");
      }
      else if (strcmp(receivedChars, "Hi") == 0)
      {
         Serial.print("Me:");
         Serial.println(receivedChars);
         Serial.println("Ava: Hello, how are you?");
      }

      else
      {
         Serial.println("Ava: Sorry, I don't know that one. Check the README.txt file for a list of words or phrases I know.");
      }
      newData = false;
   }

}  // *** this now ends the loop() function.  You have at least one function defined inside of loop().  
   // *** You need to move function defintions to outside of loop()
void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (Serial.available() > 0 && newData == false)
   {
      rc = Serial.read();

      // ignore carriage return
      if (rc == '\r')
      {
         return;
      }

      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         ndx = 0;
         newData = true;
      }
   }
}

//MORSE COURSE SECTION
void convertor()
{
   static String letters[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
                              ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "E"
                             };
   int i = 0;
   if (code == ".-.-.-")
   {
      Serial.print(".");        //for break
   }
   else
   {
      while (letters[i] != "E")  //loop for comparing input code with letters array
      {
         if (letters[i] == code)
         {
            Serial.print(char('A' + i));
            break;
         }
         i++;
      }
      if (letters[i] == "E")
      {
         Serial.println("<Wrong input>");  //if input code doesn't match any letter, error
      }
   }
   code = "";                            //reset code to blank string
}
// END OF MORSE CODE SECTION
while (digitalRead(inputPin) == HIGH) {}
   t1 = millis();                            //time at button press
   digitalWrite(ledPin, HIGH);               //LED on while button pressed
   while (digitalRead(inputPin) == LOW) {}
   t2 = millis();                            //time at button release

If the button switch is wired to ground as it should be (you are enabling the internal pullup) then the switch input will read HIGH when the switch is NOT pressed and LOW when the switch is pressed.

1 Like

Hi again,

I’ve decided to decrease the scope of my project as I was really struggling to put it all together.

Now, the morse code part of the project has been removed so it is just a chat bot.

I have 3 goals that I need to acheive:

  1. I want to be able to press the button on my Arduino Uno R3 board OR the enter key on my keyboard to send the message typed out in the Serial Monitor input field. From my research, I’m not sure if this will be possible with the Uno as I looked into using the keyboard library but it doesn’t seem to work with the Uno.

  2. I want the LED on my Arduino Uno R3 board to blink when there is a message that has not been replied to (Unless it is the ''Goodbye" message.

  3. I want to have multiple possible responses to a given input message sent by the user and have the responses chosed at random. e.g. User says “Hi”, Chat bot can says: “Hello” OR “Hey” OR "How’s it going?’. Chat bot says “Hey” as a result of random chance.

Any ideas as to how I can go about implementing these?

Thanks again!

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