5 Replies Latest reply on Mar 29, 2018 6:28 AM by FGT

    Turn my Morse Code Decoder into a server

    RobertoGarcia

      Hello, all I have two things that I'm trying to bring together. A Morse Code Decoder, ie. an Arduino program that takes the pushes of a momentary push button into a dit if it's a short press or dah if it's a long press, and dynamically decodes the sequence of Morse Code characters into their respective English character representations and displays it on 16x2 LCD screen. I will paste my code here. I've refactored the code but it may still be confusing so feel free to ask me questions. Also I should say that it depends on special hardware from one of Grove's developer kits, but I don't have to change any of their hardware configurations and the code that controls the hardware should be commented on what it's doing in the context of the program:

       

       

      <code>

      //Note: this program uses an LCD screen and a momentary pushbutton from the Grove Kit

       

       

      #include <Wire.h>

      #include "rgb_lcd.h"

       

       

      //hardware constants

      rgb_lcd lcd;

      const int colorR = 66;

      const int colorG = 241;

      const int colorB = 244;

      const int buttonPin = 3;

       

       

      // Set the timer system for the button presses

      long buttonPressTime = 0;

      long longPressTime = 1000;                                            //a long button press is one second, in this morse code implementation

      unsigned long previousMillis = 0;                                     // will store last time LED was updated

      const long interval = 10000;                                          // interval at which to decode a new morse code character (milliseconds)

       

       

      //variables for the decoding algorithm

      String morseVals = String("");                                          //where I will store each morse character that the user enters, will be passed to the loop statement

      char englishChar = ' ';                                                

       

       

      //Text state of the LCD

      int morseColumn = 0;

      int englishColumn = 0;

      const int MORSE_ROW = 0;

      const int ENGLISH_ROW = 1;

       

       

      // Set the state system of the button presses

      boolean isButtonActive = false;                                                                   // for telling if the button is being pressed so that we only have to use digitalRead() once

      boolean isLongPressActive = false;

       

       

       

       

      //helper function for reseting the first row

      void resetMorseRow() {

        for(int i = 0; i < 5; i++){

          lcd.setCursor(i, MORSE_ROW);

          lcd.print(" ");

        }

        morseColumn = 0;

        lcd.setCursor(morseColumn, MORSE_ROW);

      }

       

       

      void setup()

      {

         // set up the LCD

        lcd.begin(16, 2);

        lcd.setRGB(colorR, colorG, colorB);

        //lcd.cursor();                                                                                       //makes the cursor where the next character will be printed at, but only useful for debugging as it looks too much like a dah

        lcd.setCursor(0, 0);

       

      }

       

       

      void loop()

      {

       

        morseDecoder();

       

       

       

      }

       

       

       

       

      void morseDecoder() {

        if (digitalRead(buttonPin) == HIGH) {                                                               // if the button is being pressed ...

          if (isButtonActive == false) {                                                                    // if the last saved state of the button was set to false i.e it's the first run of the program ...

            isButtonActive = true;                                                                          // set it to true

            buttonPressTime = millis();                                                                     // save the time when the button was pressed 

          }

          if ((millis() - buttonPressTime > longPressTime) && (isLongPressActive == false)) {               // if the current time - the time the button was pressed is the long button press time

                                                                                                            // AND the last saved state of the Long button press is set to false (to avoid recording two long presses)

            isLongPressActive = true;                                                                       // set the state of isLongPressActive to true

            lcd.setCursor(morseColumn++,MORSE_ROW);                                                                             // specify the next column in the "morse row"

            lcd.print('_');                                                                                 // print a dah

            morseVals = morseVals + "_";

          }

        }

       

        else {                                                                                                // happens if the long press case failed

          if (isButtonActive == true) {                                                                       // if the button is being pressed

            if (isLongPressActive == true) {                                                                  // if the long press state is set to true ...

              isLongPressActive = false;                                                                      // set it to false

            }

            else {

              lcd.setCursor(morseColumn++,MORSE_ROW);

              lcd.print('.');                                                                                 // print a dit

              morseVals = morseVals + ".";

            }

            isButtonActive = false;                                                                           // set button active to false (we don't check how short a short press is)

          }

        }

       

       

       

       

        //it is my understanding that the character timer does not depend on whether or not a button was presses, just time so save the time for each interval

        unsigned long currentMillis = millis();

       

       

        if ((currentMillis - previousMillis >= interval) || (morseVals.length() >= 5) ) {                   //TODO: this if statement works as a delay right now, but I should I should actually reset the timer whenever the user presses the button

          // save the last time you printed an english character

          previousMillis = currentMillis;

       

       

          // print the character now and move up one row once you finish

          lcd.setCursor(morseColumn, MORSE_ROW);                                                                                 

          //declare the big switch case here

          if(morseVals.equals("._")){

            englishChar = 'A';

          }

           else if(morseVals.equals("_...")) {

            englishChar = 'B';

           }

           else if(morseVals.equals("_._.")) {

            englishChar = 'C';

           }

           else if(morseVals.equals("_..")) {

            englishChar = 'D';

           }

           else if(morseVals.equals(".")) {

            englishChar = 'E';

           }

           else if(morseVals.equals(".._.")) {

            englishChar = 'F';

           }

           else if(morseVals.equals("__.")) {

            englishChar = 'G';

           }

           else if(morseVals.equals("....")) {

            englishChar = 'H';

           }

           else if(morseVals.equals("..")) {

            englishChar = 'I';

           }

           else if(morseVals.equals(".___")) {

            englishChar = 'J';

           }

           else if(morseVals.equals("_._")) {

            englishChar = 'K';

           }

           else if(morseVals.equals("._..")) {

            englishChar = 'L';

           }

           else if(morseVals.equals("__")) {

            englishChar = 'M';

           }

           else if(morseVals.equals("_.")) {

            englishChar = 'N';

           }

           else if(morseVals.equals("___")) {

            englishChar = 'O';

           }

           else if(morseVals.equals(".__.")) {

            englishChar = 'P';

           }

           else if(morseVals.equals("__._")) {

            englishChar = 'Q';

           }

           else if(morseVals.equals("._.")) {

            englishChar = 'R';

           }

           else if(morseVals.equals("...")) {

            englishChar = 'S';

           }

           else if(morseVals.equals("_")) {

            englishChar = 'T';

           }

           else if(morseVals.equals(".._")) {

            englishChar = 'U';

           }

           else if(morseVals.equals("..._")) {

            englishChar = 'V';

           }

           else if(morseVals.equals(".__")) {

            englishChar = 'W';

           }

           else if(morseVals.equals("_.._")) {

            englishChar = 'X';

           }

           else if(morseVals.equals("_.__")) {

            englishChar = 'Y';

           }

           else if(morseVals.equals("__..")) {

            englishChar = 'Z';

           }

           else if(morseVals.equals(".____")) {

            englishChar = '1';

           }

           else if(morseVals.equals("..___")) {

            englishChar = '2';

           }

           else if(morseVals.equals("...__")) {

            englishChar = '3';

           }

           else if(morseVals.equals("...._")) {

            englishChar = '4';

           }

           else if(morseVals.equals(".....")) {

            englishChar = '5';

           }

           else if(morseVals.equals("_....")) {

            englishChar = '6';

           }

           else if(morseVals.equals("__...")) {

            englishChar = '7';

           }

           else if(morseVals.equals("____..")) {

            englishChar = '8';

           }

           else if(morseVals.equals("____.")) {

            englishChar = '9';

           }

           else if(morseVals.equals("_____")) {

            englishChar = '0';

           }   

          else {

            // in this implementation of a morse code device, no valid input within the 10 second counter means that we must print a space character.

            englishChar = ' ';

          }

          //Reset the decoding algorithm dependencies and print the English character

          morseVals = "";

          lcd.setCursor(englishColumn++,ENGLISH_ROW);

          lcd.print(englishChar);

          resetMorseRow();   

        }

       

       

      }

      </code>

       

       

      I now must turn this program into code that the user can control remotely with a browser. I've only run an LED server. This one to be exact: Basic Ethernet Shield Arduino Web Server . You will notice that the guide uses a plain html file instead of AJAX. In my project I'm not using Arduino shield, just an ethernet cable on the built-in ethernet port connected to the board's built-in port. I'm also not using an SD card for the server, but can if I must, I would just need to know how to use it. I want to do my Morse Code Server this way because I don't mind the fact that the user will have to continue reloading the page and I feel like I can't learn all these different web/networking technologies at once. For now I just want my web page to have two buttons, one for sending a dit to the board and another one for sending a dah. Any help will be appreciated.

        • 1. Re: Turn my Morse Code Decoder into a server
          FGT

          Hi RobertoGarcia,

           

          I'm not completely sure I understand your problem/question. Specifically about a web server on the Intel Galileo, I suggest you do not use any code based on the Arduino Ethernet shield, mostly because the Intel Galileo Ethernet I/O does not have any relationship to the SPI port. Take a look at Webserver Ethernet(Galileo) Ex., eglibc img., etc.,

           

          Are you planning to "replace" physical buttons by a web interface?

           

            HTH,

           

          Fernando.

          • 2. Re: Turn my Morse Code Decoder into a server
            RobertoGarcia

            Hello, Fernando,

             

            I am planning to not replace the physical momentary pushbuttons on the web page interface. I want both buttons on the web server and the pushbuttons to do the same functions, send Morse Code characters, either dits or dahs. I just don't know how to write the function that will be used on the web interface.

             

            I'm not using the web ethernet shield, what I'm doing is connecting the ethernet shield straight to the PC computer I'm debugging with from the ethernet port that is built-in to the Intel Galileo board. Because this is the only way I know how to setup a server I would like to do it similarly:

             

            <code>

            /*--------------------------------------------------------------

              Program:      eth_websrv_LED

             

             

              Description:  Arduino web server that serves up a web page

                            allowing the user to control an LED

             

              Hardware:     - Arduino Uno and official Arduino Ethernet

                              shield. Should work with other Arduinos and

                              compatible Ethernet shields.

                            - LED and resistor in series connected between

                              Arduino pin 2 and GND

                          

              Software:     Developed using Arduino 1.0.3 software

                            Should be compatible with Arduino 1.0 +

             

              References:   - WebServer example by David A. Mellis and

                              modified by Tom Igoe

                            - Ethernet library documentation:

                              http://arduino.cc/en/Reference/Ethernet

             

             

              Date:         11 January 2013

             

              Author:       W.A. Smith, http://startingelectronics.org

            --------------------------------------------------------------*/

             

             

            #include <SPI.h>

            #include <Ethernet.h>

             

             

            // MAC address from Ethernet shield sticker under board

            byte mac[] = { 0x98, 0x4F, 0xEE, 0x00, 0x2F, 0x0F };

            IPAddress ip(); // IP address, may need to change depending on network

            EthernetServer server(80);  // create a server at port 80

             

             

            String HTTP_req;          // stores the HTTP request

            boolean LED_status = 0;   // state of LED, off by default

             

             

            void setup()

            {

                Ethernet.begin(mac, ip);  // initialize Ethernet device

                server.begin();           // start to listen for clients

                Serial.begin(9600);       // for diagnostics

              

                pinMode(LED_BUILTIN, OUTPUT);       // On board LED

            }

             

             

            void loop()

            {

                EthernetClient client = server.available();  // try to get client

             

             

                if (client) {  // got client?

                    boolean currentLineIsBlank = true;

                    while (client.connected()) {

                        if (client.available()) {   // client data available to read

                            char c = client.read(); // read 1 byte (character) from client

                            HTTP_req += c;  // save the HTTP request 1 char at a time

                            // last line of client request is blank and ends with \n

                            // respond to client only after last line received

                            if (c == '\n' && currentLineIsBlank) {

                                // send a standard http response header

                                client.println("HTTP/1.1 200 OK");

                                client.println("Content-Type: text/html");

                                client.println("Connection: close");

                                client.println();

                                // send web page

                                client.println("<!DOCTYPE html>");

                                client.println("<html>");

                                client.println("<head>");

                                client.println("<title>Arduino LED Control</title>");

                                client.println("</head>");

                                client.println("<body>");

                                client.println("<h1>LED</h1>");

                                client.println("<p>Click to switch LED on and off.</p>");

                                client.println("<form method=\"get\">");

                                ProcessCheckbox(client);

                                client.println("</form>");

                                client.println("</body>");

                                client.println("</html>");

                                Serial.print(HTTP_req);

                                HTTP_req = "";    // finished with request, empty string

                                break;

                            }

                            // every line of text received from the client ends with \r\n

                            if (c == '\n') {

                                // last character on line of received text

                                // starting new line with next character read

                                currentLineIsBlank = true;

                            }

                            else if (c != '\r') {

                                // a text character was received from client

                                currentLineIsBlank = false;

                            }

                        } // end if (client.available())

                    } // end while (client.connected())

                    delay(1);      // give the web browser time to receive the data

                    client.stop(); // close the connection

                } // end if (client)

            }

             

             

            // switch LED and send back HTML for LED checkbox

            void ProcessCheckbox(EthernetClient cl)

            {

                if (HTTP_req.indexOf("LED2=2") > -1) {  // see if checkbox was clicked

                    // the checkbox was clicked, toggle the LED

                    if (LED_status) {

                        LED_status = 0;

                    }

                    else {

                        LED_status = 1;

                    }

                }

              

                if (LED_status) {    // switch LED on

                    digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)

                    // checkbox is checked

                    cl.println("<input type=\"checkbox\" name=\"LED2\" value=\"2\" \

                    onclick=\"submit();\" checked>LED2");

                }

                else {              // switch LED off

                    digitalWrite(LED_BUILTIN, LOW);

                    // checkbox is unchecked

                    cl.println("<input type=\"checkbox\" name=\"LED2\" value=\"2\" \

                    onclick=\"submit();\">LED2");

                }

            }

            </code>

            • 3. Re: Turn my Morse Code Decoder into a server
              FGT

              Hi RobertoGarcia,

               

              Something sounds strange in

              I want both buttons on the web server and the pushbuttons to do the same functions, send Morse Code characters, either dits or dahs.

              I think it does not make any sense to have both buttons on the web server... who and how send the code characters? and to what other site/application would the web server sent those characters to? Maybe you mean having the buttons in the web interface or web browser where a user may click/select any of them and send it to the web server?

               

              What do you mean by "the function that will be used on the web interface"? Wouldn't be enough to have two web buttons at the web interface? If it is the case, it is not related to Intel Galileo but to web programming/web site design. It's not a problem if that's the case, It's just for making clear the problem/question.

               

              About

              I'm not using the web ethernet shield, what I'm doing is connecting the ethernet shield straight to the PC computer

              Again I'm lost... if you are using an Intel Galileo then you don't have any Ethernet shield...

               

              Do you know the code you included in your post or you are asking about some explanation on it? Actually, if all you want in the web browser are the two Morse dit and dah, then two submit buttons are all you need... or maybe I misunderstood your post... sorry.

               

              Maybe it would be helpful if you describe the web interface for the user on one side and the web server behavior for that web interface on the other...

               

              HTH,

               

              Fernando.

              • 4. Re: Turn my Morse Code Decoder into a server
                RobertoGarcia

                Hi, sorry about the confusion. My assignment is for the user to be able to decode their morse code with both options, the web page that the intel galileo serves and the physical buttons on the galileo board. By buttons on a web browser I mean such as the following syntax:

                 

                <button type="button">Send dit</button>

                 

                And once the user sends those buttons the program will decode the characters into their English characters.

                 

                RobertoGarcia wrote:

                 

                Maybe you mean having the buttons in the web interface or web browser where a user may click/select any of them and send it to the web server?

                Yes this is what I mean, the user would "send" the characters to the Intel Galileo server, and then the rest of the server computes the logic of it, which is the part I'm having trouble getting started. Like, how would Iretrieve the characters once the user sends them by pressing the web buttons.  This is similar to my LCD server code, where the guide I got it from did this:

                // switch LED and send back HTML for LED checkbox

                void ProcessCheckbox(EthernetClient cl)

                {

                    if (HTTP_req.indexOf("LED2=2") > -1) {  // see if checkbox was clicked

                        // the checkbox was clicked, toggle the LED

                        if (LED_status) {

                            LED_status = 0;

                        }

                        else {

                            LED_status = 1;

                        }

                    }

                 

                    if (LED_status) {    // switch LED on

                        digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)

                        // checkbox is checked

                        cl.println("<input type=\"checkbox\" name=\"LED2\" value=\"2\" \

                        onclick=\"submit();\" checked>LED2");

                    }

                    else {              // switch LED off

                        digitalWrite(LED_BUILTIN, LOW);

                        // checkbox is unchecked

                        cl.println("<input type=\"checkbox\" name=\"LED2\" value=\"2\" \

                        onclick=\"submit();\">LED2");

                    }

                }

                 

                Except instead of a checkbox that turns an LED off or on, how do I get the web buttons to transmit characters back to the server, which it will then process in the form of decoding.

                 

                Nextly, sorry I meant to say that I plugged the ethernet port on one end to my PC laptop into the ethernet port on my Galileo. It's the one built-in, not an ethernet shield. I guess my question is about web design/programming and also howto bring it together with Arduino code. I'm new to networking and server programming. Let me know if I may have missed something.

                1 of 1 people found this helpful
                • 5. Re: Turn my Morse Code Decoder into a server
                  FGT

                  Hi RobertoGarcia,

                   

                  Now I think we are in the same page. I think you may use a web page like this one:

                   

                  <html>

                    <HEAD>

                        <TITLE>Morse Code</TITLE>

                        <meta name="viewport" content="user-scalable=no"/>

                    </HEAD>

                   

                  <body>

                   

                  <CENTER>

                      <form action="" method="get">

                        <input style="height:20%;width:40%;font-size:70px" name="." type="submit" value=" . " />

                        <input style="height:20%;width:40%;font-size:70px" name="-" type="submit" value=" - " />

                      </form>

                      <p> <font size="70px"> Text:

                      </font> </p>

                  </CENTER>

                   

                  </body>

                  </html>

                   

                  (you can copy the text and save it to index.html in order to have a quick look at it). The "meta" in the html head would help to see the web page in cell phones and tablets.

                   

                  Taking this html as a "departure point" you would be able to add the decoded characters after "Text: ". Actually, if you take a look at the link I included in a previous post (Webserver Ethernet(Galileo) Ex., eglibc img., etc.) you may read in the last post of the thread how to use the .html in a file, read it and send it to the client from the web server running in the Intel Galileo. However, you will have to process each client request in a similar way of what you are doing now with the led, but storing the "." and "-" in a string and decoding it in a way similar to that you included in the code in the first post.

                   

                  HTH,

                   

                  Fernando.