Trying to run motors over the internet

I’m currently working on a project where i need to control motors over the Ethernet. I am using an mkr 1000 arduino board and its motor carrier. To create my code I blended/ used as a reference the mkr 1000’s sample code and the average motor test sample code. Along with bits and pieces from online arduino codes.

What my code should be doing:

  • Setting up appropriate things to run (server, motor carrier)
  • opening connections to client
  • if a client connects it should show the appropriate GUI
  • than respond appropriately to changes in url (caused by Javascript stuff)

I keep getting stuck on the last step.

I double checked my javascript so I am 80% sure the fault doesn’t lie there

I littered serial.prints around my arduino code for testing and I know that the setup sections are being run, so that isn’t the issue.

The only thing left that I can think of is the part of the code which takes the url and responds to it.

The reference codes I looked at all used the same or some variation of

if (currentLine.endsWith("GET /#/w")) {
              Serial.println("Forwards");
              M3.setDuty(100);
              M2.setDuty(100);
            }

So it really confused me when it didn’t work.

Any advice?

Note: I already tried the url if statement in the code without the # but it didn’t change anything.

Full Code:

#include <WiFi101.h>
#include <SPI.h>
#include <MKRMotorCarrier.h>

static int batteryVoltage;

char ssid[] = "****";
char pass[] = "****";

int keyIndex = 0;

int status = WL_IDLE_STATUS;
WiFiServer server(80);


int LED = LED_BUILTIN;


/*===================================================================================================*/

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial) {
  }
  
  Serial.println("start of SETUP");

  if (controller.begin())
  {
    Serial.println("MKR Motor Carrier Connected");
  }
  
  else {
    Serial.println("No Motor Carrier");
    while (1);
  }
  
  while ( status != WL_CONNECTED) {
      Serial.print("Attempting to connect to Networked names: ");
      Serial.println(ssid);
      status = WiFi.begin(ssid, pass);
      delay(5000);
    }
    


  pinMode(LED, OUTPUT);
  
  server.begin();
  Serial.println("Start of SERvER");
  WiFiStatus(); 
  Serial.println("Rebooting");
  controller.reboot();
  delay(500);

  float batteryVoltage = (float)battery.getConverted();
  Serial.print("Battery Voltage:");
  Serial.println(batteryVoltage);
  Serial.print("V, Raw");
  Serial.println(battery.getRaw());
}


/*===================================================================================================*/
void loop() {
  // put your main code here, to run repeatedly:

 
  float batteryVoltage = (float)battery.getConverted();

  if (batteryVoltage < 11)
  {
    Serial.println(" ");
    Serial.println("!!!!!!!!!!!!!LOW BATTERY!!!!!!!!!!!!");
    delay(500);
  }


  else {

    
    WiFiClient client = server.available();

    if (client) {
      Serial.println("New CLient");
      String currentLine = "";
      while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n') {
          if (currentLine.length() == 0) {
           client.println("HTTP/1.1 200 OK");
           client.println("Content-type:text/html");
           client.println("");
           client.println("Refresh: 1");
           
               Had to take out javascript stuff because post exceeded word limit

           client.println("");

              break;
            }
            
            else {
              currentLine = "";
            }

          }
          else if (c != '\r') {
            currentLine += c;
          }            

          if (currentLine.endsWith("GET /#/w")) {
              Serial.println("Forwards");
              M3.setDuty(100);
              M2.setDuty(100);
            }
          else if (currentLine.endsWith("GET /#/s")) {
              Serial.println("Backwards");
              M3.setDuty(-100);
              M2.setDuty(-100);
            }
          else if (currentLine.endsWith("GET /#/a")) {
              Serial.println("Left");
              M3.setDuty(100);
              M2.setDuty(0);
            }
          else if (currentLine.endsWith("GET /#/d")) {
              Serial.println("Right");
              M3.setDuty(0);
              M2.setDuty(100);
            }
          else if (currentLine.endsWith("GET /#/q")) {
              Serial.println("Down");
              M1.setDuty(-100);
            }
          else if (currentLine.endsWith("GET /#/e")){
              Serial.println("UP");
              M1.setDuty(100);
             }
          else if (currentLine.endsWith("GET /#")){
              Serial.println("Everything stop");
              M1.setDuty(0);
              M2.setDuty(0);
              M3.setDuty(0);
          }

          else if (!client.connected()){
            client.stop();
            Serial.println("Client Disconnected");
          }

        }
      }
    }
  }

}

void WiFiStatus() {
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

}

If you move the code where you compare the http requests as a described in the post before and change the endsWith to startsWith your code will run much more efficiently, and you will be able to see what is going on much better. Because you are comparing the currentLine only when it is complete.

I removed all code regarding your motor, applied the fix and tried it. Right now, the webpage is not complete, so it will timeout in the browser. But I changed the comparison as below and now I can call the 192.168.x.x/s page and the logic works.

New CLient
GET /s HTTP/1.1
Backwards

#include <WiFi101.h>
#include <SPI.h>
// #include <MKRMotorCarrier.h>

static int batteryVoltage;

#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)

int keyIndex = 0;

int status = WL_IDLE_STATUS;
WiFiServer server( 80 );


int LED = LED_BUILTIN;


/*===================================================================================================*/

void setup()
{
  //Configure pins for Adafruit ATWINC1500 Feather
  //WiFi.setPins( 8, 7, 4, 2 );

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

  // Serial.println( "start of SETUP" );

  // if ( controller.begin() )
  // {
  // Serial.println( "MKR Motor Carrier Connected" );
  // }

  // else
  // {
  // Serial.println( "No Motor Carrier" );
  // while ( 1 );
  // }

  while ( status != WL_CONNECTED )
  {
    Serial.print( "Attempting to connect to Networked names: " );
    Serial.println( ssid );
    status = WiFi.begin( ssid, pass );
    delay( 5000 );
  }

  pinMode( LED, OUTPUT );

  server.begin();
  Serial.println( "Start of SERvER" );
  WiFiStatus();
  Serial.println( "Rebooting" );
  //controller.reboot();
  delay( 500 );

  // float batteryVoltage = ( float )battery.getConverted();
  // Serial.print( "Battery Voltage:" );
  // Serial.println( batteryVoltage );
  // Serial.print( "V, Raw" );
  // Serial.println( battery.getRaw() );
}


/*===================================================================================================*/
void loop()
{
  // put your main code here, to run repeatedly:

  //  float batteryVoltage = ( float )battery.getConverted();
  float batteryVoltage = 12;

  if ( batteryVoltage < 11 )
  {
    Serial.println( " " );
    Serial.println( "!!!!!!!!!!!!!LOW BATTERY!!!!!!!!!!!!" );
    delay( 500 );
  }

  else
  {
    WiFiClient client = server.available();

    if ( client )
    {
      Serial.println( "New CLient" );
      String currentLine = "";
      while ( client.connected() )
      {
        if ( client.available() )
        {
          char c = client.read();
          Serial.write( c );
          if ( c == '\n' )
          {
            if ( currentLine.length() == 0 )
            {
              client.println( "HTTP/1.1 200 OK" );
              client.println( "Content-type:text/html" );
              client.println( "" );
              client.println( "Refresh: 1" );

              //Had to take out javascript stuff because post exceeded word limit

              client.println( "" );

              break;
            }

            else
            {
              if ( currentLine.startsWith( "GET /w" ) )
              {
                Serial.println( "Forwards" );
                // M3.setDuty( 100 );
                // M2.setDuty( 100 );
              }
              else if ( currentLine.startsWith( "GET /s" ) )
              {
                Serial.println( "Backwards" );
                // M3.setDuty( -100 );
                // M2.setDuty( -100 );
              }
              else if ( currentLine.startsWith( "GET /a" ) )
              {
                Serial.println( "Left" );
                // M3.setDuty( 100 );
                // M2.setDuty( 0 );
              }
              else if ( currentLine.startsWith( "GET /d" ) )
              {
                Serial.println( "Right" );
                // M3.setDuty( 0 );
                // M2.setDuty( 100 );
              }
              else if ( currentLine.startsWith( "GET /q" ) )
              {
                Serial.println( "Down" );
                // M1.setDuty( -100 );
              }
              else if ( currentLine.startsWith( "GET /e" ) )
              {
                Serial.println( "UP" );
                // M1.setDuty( 100 );
              }
              else if ( currentLine.startsWith( "GET /" ) )
              {
                Serial.println( "Everything stop" );
                // M1.setDuty( 0 );
                // M2.setDuty( 0 );
                // M3.setDuty( 0 );
              }

              else if ( !client.connected() )
              {
                client.stop();
                Serial.println( "Client Disconnected" );
              }
              currentLine = "";
            }

          }
          else if ( c != '\r' )
          {
            currentLine += c;
          }
        }
      }
    }
  }

}

void WiFiStatus()
{
  Serial.print( "SSID: " );
  Serial.println( WiFi.SSID() );

  IPAddress ip = WiFi.localIP();
  Serial.print( "IP Address: " );
  Serial.println( ip );
}

A simple place to start might be to write some simple code where you send commands via the serial monitor to the board to verify the mechanical/electrical parts connected to the board operate the motor. If you use the forum search box and search for "servo web page" and similar, you will probably see some internet control setups.

Yo, Klaus_K thanks again man for responding to my post. Sorry for making you answer the same question twice but not gonna lie, the first time I kind of skipped over that advice because I didn’t really understand what you wanted me to do and just hoped it would fix it’s self (as things in programming do).

So now, a couple of questions about your advice.

I followed the startsWith for the current line and my code works (some what). Any explanation on why, I thought from my limited understanding I thought current line meant the url, so why would you say start with if the /w is at the end of the url?

Second, the issue with this method is that it doesn’t really work with the hashtag, which is necessary to stop the website from reloading or trying to load a nonexistant url. when I click a button, it works and changes the url but than the webserver loads a different page and i can’t enter any more commands. How can I circumvent this?

Also, here is the websites the html, javascript and css stuff.

client.println("<!DOCTYPE html>");
           client.println("<html>");
           client.println("<head>");
           client.println("    <Title>Robot Controls</Title>");
           client.println("    <h1><b>Robot Control Center</b></h1>");
           client.println("    <style>");
           client.println("        html{");
           client.println("            background-image: url('https://www.compudas.com/wp-content/uploads/2011/02/electronics.x44641.jpg');");
           client.println("            background-size: cover;");
           client.println("            background-attachment: fixed;");
           client.println("        }");
           client.println("");
           client.println("        h1{");
           client.println("            text-align: center;");
           client.println("            color: black;");
           client.println("            font-size: 55px;");
           client.println("        }");
           client.println("");
           client.println("        pre{");
           client.println("            text-align: center;");
           client.println("            color:black;");
           client.println("            font-size: 25px;");
           client.println("            font: bold;");
           client.println("            font-weight:bolder;");
           client.println("        }");
           client.println("    </style>");
           client.println("");
           client.println("    <script>");
           client.println("        var baseURL = '192.168.100.2#';");
           client.println("        window.addEventListener('keydown', logKey);");
           client.println("");
           client.println("        function logKey(e){");
           client.println("            if (e.which == 87){");
           client.println("                window.location.href = '/w';");
           client.println("            }");
           client.println("");
           client.println("            if (e.which == 83){");
           client.println("                window.location.href = '/s';");
           client.println("            }");
           client.println("");
           client.println("            if (e.which == 65){");
           client.println("                window.location.href = '/a';");
           client.println("            }");
           client.println("");
           client.println("            if (e.which == 68){");
           client.println("                window.location.href = '/d';");
           client.println("            }");
           client.println("");
           client.println("            if (e.which == 69){");
           client.println("                window.location.href = '/e';");
           client.println("            }");
           client.println("");
           client.println("            if (e.which == 81){");
           client.println("               window.location.href = '/q';");
           client.println("            }");
           client.println("");
           client.println("            }");
           client.println("");
           client.println("        window.addEventListener('keyup', deleteKey);");
           client.println("");
           client.println("        function deleteKey(i){");
           client.println("            if (i.which == 87){");
           client.println("                history.pushState(null, null, ' ');");
           client.println("            }");
           client.println("");
           client.println("            if (i.which == 83){");
           client.println("                history.pushState(null, null,' ' );");
           client.println("            }");
           client.println("");
           client.println("            if (i.which == 69){");
           client.println("                history.pushState(null, null, ' ');");
           client.println("            }");
           client.println("");
           client.println("            if (i.which == 81){");
           client.println("                history.pushState(null, null, ' ');");
           client.println("            }");
           client.println("");
           client.println("            if (i.which == 65){");
           client.println("                history.pushState(null, null, ' ');");
           client.println("            }");
           client.println("");
           client.println("            if (i.which == 68){");
           client.println("                history.pushState(null, null, ' ');");
           client.println("            }");
           client.println("        }");
           client.println("    </script>");
           client.println("</head>");
           client.println("");
           client.println("<body>");
           client.println("<pre>Welcome, this is the control website for my personal project. If you aren't the owner please click out.");
           client.println("Movement buttons are:");
           client.println("W for forwards");
           client.println("S for backwards");
           client.println("A to turn left");
           client.println("D to turn right");
           client.println("Q to go down");
           client.println("E to go up");
           client.println("</pre></body></html>");

btw dude, you’ve been a real life saver. I’m working on this for my personal project (school work) and nobody at my school knows how to do any more than basic arduino led on and off

I inserted your code and the websites works on my PC on IE and Chrome, but it does not work on iPad Safari. You might want to add some click buttons if you want to use a tablet or phone. :)

Now to your question.

  1. The currentLine contains HTTP requests. They look like this

GET /a HTTP/1.1 Host: 192.168.x.x Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 ... Accept: text/html,application/xh ... Referer: http://192.168.x.x/s Accept-Encoding: gzip, deflate Accept-Language: en-US ...

The software is looking for the one with the GET request.

The software collects the requests one character at a time.

char c = client.read(); ... currentLine += c;

In your original version the currentLine is compared every time a new character is received. That's why it needs to use endsWith. The software looks for "GET /a". As you can see below this happens many times, but only in the first instance it is at the end of the string. The startsWidth would trigger many times.

GET /a GET /a H GET /a HT GET /a HTT ... GET /a HTTP/1.1

In my version, the software waits for the entire HTTP request and then compares the currentLine only once. But now the "GET /a" is at the beginning.

  1. Create the weblinks any way you like and then run the software and look at the HTTP requests. They will tell you what you need to compare.

Note: I know you want the html page look nice, but you do not need the source code to look nice. I would remove all leading space characters. Saves your flash memory.

If anything is unclear, please do not hesitate to ask.

Umm, yeah I think I found the problem. The current line only seems to update whenever the page reloads but the whole point of hashing is to stop the page from constantly reloading and/or redirecting to a non existent page. So the url changes but the currentline doesn't

is there something I can do on the arduino end to fix this? Are there ways of reading the url directly instead of the currentline or updating the currentLine without reloading the page?

Also, I thought the leading spaces were necessary for formating and sytax and stuff?

"is there something I can do on the arduino end to fix this? Are there ways of reading the url directly instead of the currentline or updating the currentLine without reloading the page?"

Sure, if you don't want the client to refresh the web page, you use the status 204 code like below.

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

The currentLine shows you what HTTP requests are send from the browser to the server (your Arduino). Thats what you get.

I found a way to send requests to the server without url changing

I added a javascript function and called it sendCmd. Here is how you use it in your javascript.

sendCmd(‘fwd’);

This can be any text and will create a HTTP request

GET /fwd HTTP/1.1

Here is the entire program with the changes.

#include <WiFi101.h>
#include <SPI.h>
// #include <MKRMotorCarrier.h>

static int batteryVoltage;

#include "arduino_secrets.h"

char ssid[] = SECRET_SSID; 
char pass[] = SECRET_PASS;

int keyIndex = 0;

int status = WL_IDLE_STATUS;
WiFiServer server( 80 );


int LED = LED_BUILTIN;

char jsFunctionSendCmd[] = "function sendCmd(cmd){\nvar xmlhttp;\nif(window.XMLHttpRequest){\nxmlhttp = new XMLHttpRequest();\nxmlhttp.open(\"GET\",cmd,true);\nxmlhttp.send(null);}\n}";

void setup()
{
  //Configure pins for Adafruit ATWINC1500 Feather
  //WiFi.setPins( 8, 7, 4, 2 );

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

  // Serial.println( "start of SETUP" );

  // if ( controller.begin() )
  // {
  // Serial.println( "MKR Motor Carrier Connected" );
  // }

  // else
  // {
  // Serial.println( "No Motor Carrier" );
  // while ( 1 );
  // }

  while ( status != WL_CONNECTED )
  {
    Serial.print( "Attempting to connect to network: " );
    Serial.println( ssid );
    status = WiFi.begin( ssid, pass );
    delay( 5000 );
  }

  pinMode( LED, OUTPUT );

  server.begin();
  Serial.println( "Start of server" );
  WiFiStatus();
  Serial.println( "Rebooting" );
  //controller.reboot();
  delay( 500 );

  // float batteryVoltage = ( float )battery.getConverted();
  // Serial.print( "Battery Voltage:" );
  // Serial.println( batteryVoltage );
  // Serial.print( "V, Raw" );
  // Serial.println( battery.getRaw() );
}


void loop()
{
  // put your main code here, to run repeatedly:

  //  float batteryVoltage = ( float )battery.getConverted();
  float batteryVoltage = 12;

  if ( batteryVoltage < 11 )
  {
    Serial.println( " " );
    Serial.println( "!LOW BATTERY!" );
    delay( 500 );
  }

  else
  {
    WiFiClient client = server.available();

    if ( client )
    {
      Serial.println( "New client" );
      String currentLine = "";
      while ( client.connected() )
      {
        if ( client.available() )
        {
          char c = client.read();
          Serial.write( c );
          if ( c == '\n' )
          {
            if ( currentLine.length() == 0 )
            {
              client.println( "<!DOCTYPE html>" );
              client.println( "<html>" );
              client.println( "<head>" );
              client.println( "<Title>Robot Controls</Title>" );
              client.println( "<h1><b>Robot Control Center</b></h1>" );
              client.println( "<style>" );
              client.println( "html{" );
              client.println( "background-image: url('');" );
              client.println( "background-size: cover;" );
              client.println( "background-attachment: fixed;}" );
              client.println( "h1{" );
              client.println( "text-align: center;" );
              client.println( "color: black;" );
              client.println( "font-size: 55px;" );
              client.println( "}" );
              client.println( "" );
              client.println( "pre{" );
              client.println( "text-align: center;" );
              client.println( "color:black;" );
              client.println( "font-size: 25px;" );
              client.println( "font: bold;" );
              client.println( "font-weight:bolder;" );
              client.println( "}" );
              client.println( "</style>" );
              client.println( "" );
              client.println( "<script>" );
              client.println( "var baseURL = '192.168.100.2#';" );
              client.println( "window.addEventListener('keydown', logKey);" );
              client.println( "function logKey(e){" );
              
              client.println( "if(e.which == 87){sendCmd('fwd');}" );
              client.println( "if(e.which == 83){sendCmd('bwd');}" );
              client.println( "if(e.which == 65){sendCmd('left');}" );
              client.println( "if(e.which == 68){sendCmd('right');}" );
              client.println( "if(e.which == 69){sendCmd('up');}" );
              client.println( "if(e.which == 81){sendCmd('down');}" );
              client.println( "}" );
              client.println( "window.addEventListener('keyup', deleteKey);" );

              client.println( "function deleteKey(i){" );
              client.println( "if (i.which == 87){history.pushState(null, null, ' ');}" );
              client.println( "if (i.which == 83){history.pushState(null, null, ' ');}" );
              client.println( "if (i.which == 69){history.pushState(null, null, ' ');}" );
              client.println( "if (i.which == 81){history.pushState(null, null, ' ');}" );
              client.println( "if (i.which == 65){history.pushState(null, null, ' ');}" );
              client.println( "if (i.which == 68){history.pushState(null, null, ' ');}" );
              client.println( "}" );
              client.println( jsFunctionSendCmd );
              client.println( "</script>" );
              client.println( "</head>" );
              client.println( "" );
              client.println( "<body>" );
              client.println( "<pre>Welcome, this is the control website for my personal project. If you aren't the owner please click out." );
              client.println( "Movement buttons are:" );
              client.println( "W for forwards" );
              client.println( "S for backwards" );
              client.println( "A to turn left" );
              client.println( "D to turn right" );
              client.println( "Q to go down" );
              client.println( "E to go up" );
              client.println( "</pre></body></html>" );
              break;
            }
            else
            {
              if ( currentLine.startsWith( "GET /fwd" ) )
              {
                Serial.println( "Forwards" );
                // M3.setDuty( 100 );
                // M2.setDuty( 100 );
              }
              else if ( currentLine.startsWith( "GET /bwd" ) )
              {
                Serial.println( "Backwards" );
                // M3.setDuty( -100 );
                // M2.setDuty( -100 );
              }
              else if ( currentLine.startsWith( "GET /left" ) )
              {
                Serial.println( "Left" );
                // M3.setDuty( 100 );
                // M2.setDuty( 0 );
              }
              else if ( currentLine.startsWith( "GET /right" ) )
              {
                Serial.println( "Right" );
                // M3.setDuty( 0 );
                // M2.setDuty( 100 );
              }
              else if ( currentLine.startsWith( "GET /down" ) )
              {
                Serial.println( "Down" );
                // M1.setDuty( -100 );
              }
              else if ( currentLine.startsWith( "GET /up" ) )
              {
                Serial.println( "UP" );
                // M1.setDuty( 100 );
              }
              else if ( currentLine.startsWith( "GET /" ) )
              {
                Serial.println( "Everything stop" );
                // M1.setDuty( 0 );
                // M2.setDuty( 0 );
                // M3.setDuty( 0 );
              }

              else if ( !client.connected() )
              {
                client.stop();
                Serial.println( "Client Disconnected" );
              }
              currentLine = "";
            }

          }
          else if ( c != '\r' )
          {
            currentLine += c;
          }
        }
      }
    }
  }

}

void WiFiStatus()
{
  Serial.print( "SSID: " );
  Serial.println( WiFi.SSID() );

  IPAddress ip = WiFi.localIP();
  Serial.print( "IP Address: " );
  Serial.println( ip );
}

You do not need the leading spaces for formating for your browser. Its just for you. There are only a few languages that need the indentation for instance python. Most language do not. I removed a lot of formating to get the character count below 9000 for this post.

Sometimes the page needs to be reloaded. If you see “New client” as last message, simply reload the page in the browser.

Zoomkat, damn, i didn't know I could do that. However the issue was that although I didn't want to reload the page, it was necessary to do so to update the currentLine.

Klaus_K I implemented the XMl HttpRequest stuff but there still seems to be an issue. You said to reload the page if it finished with new client but that's all it does. I load the page, new client, all the Get stuff, ok. I try clicking a few buttons, nothing.

So I reload the page, while the page is reloading I have time to enter 6 button presses before it prints new client and stops taking commands again. Everything else works fine, motors run when proper button is pressed etc. but the currentLine doesn't update unless constantly reloaded manually. What should I do?

Also, I tried disconnecting the arduino board from my computer while still powering the boards with a battery, to see how it would work without the wire connection. Everything is still the same except the serial monitor doesn't update anymore whenever the currentLine updates. How does this work? I thought the currentLine was read off of the serial monitor.

If anybody has any suggestions or advice to any of these questions you are more than welcome to post response

My current Code if anybody wants to double check it

#include <WiFi101.h>
#include <SPI.h>
#include <MKRMotorCarrier.h>

static int batteryVoltage;

char ssid[] = "**********";
char pass[] = "**********";

int keyIndex = 0;

int status = WL_IDLE_STATUS;
WiFiServer server(80);

int LED = LED_BUILTIN;
/*===================================================================================================*/

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial) {
  }
  
  Serial.println("start of SETUP");

  if (controller.begin())
  {
    Serial.println("MKR Motor Carrier Connected");
  }
  
  else {
    Serial.println("No Motor Carrier");
    while (1);
  }
  
  while ( status != WL_CONNECTED) {
      Serial.print("Attempting to connect to Networked names: ");
      Serial.println(ssid);
      status = WiFi.begin(ssid, pass);
      delay(5000);
    }
     
  server.begin();
  Serial.println("Start of SERvER");
  WiFiStatus(); 
  Serial.println("Rebooting");
  controller.reboot();
  delay(500);
  
  float batteryVoltage = (float)battery.getConverted();
  Serial.print("Battery Voltage:");
  Serial.println(batteryVoltage);
  Serial.print("V, Raw");
  Serial.println(battery.getRaw());
}
/*===================================================================================================*/
void loop() {
  // put your main code here, to run repeatedly:
  float batteryVoltage = (float)battery.getConverted();
  if (batteryVoltage < 11)
  {
    Serial.println(" ");
    Serial.println("!!!!!!!!!!!!!LOW BATTERY!!!!!!!!!!!!");
    Serial.println("Shut Down IMMENANT");
    Serial.println("Current Voltage");
    Serial.println(batteryVoltage);
    M3.setDuty(0);
    digitalWrite(LED, LOW);
    delay(500);
  }
  else {
    WiFiClient client = server.available();
    if (client) {
      Serial.println("New CLient");
      String currentLine = "";
      while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n') {
          if (currentLine.length() == 0) {
           client.println("HTTP/1.1 200 OK");
           client.println("Content-type:text/html");
           client.println("");
           client.println("<!DOCTYPE html>");
           client.println("<html>");
           client.println("<head>");
           client.println("<Title>Robot Controls</Title>");
           client.println("<h1><b>Robot Control Center</b></h1>");
           client.println("<style>");
           client.println("html{");
           client.println("background-image: url('https://www.compudas.com/wp-content/uploads/2011/02/electronics.x44641.jpg');");
           client.println("background-size: cover;");
           client.println("background-attachment: fixed;}");
           client.println("");
           client.println("h1{");
           client.println("text-align: center;");
           client.println("color: black;");
           client.println("font-size: 55px;}");
           client.println("");
           client.println("pre{");
           client.println("text-align: center;");
           client.println("color:black;");
           client.println("font-size: 25px;");
           client.println("font: bold;");
           client.println("font-weight:bolder;}");
           client.println("</style>");
           client.println("");
           client.println("<script>");
           client.println("window.addEventListener('keydown', logKey);");
           client.println("");
           client.println("function logKey(e){");
           client.println("if(e.which == 87){");
           client.println("   sendCmd('fwd');");
           client.println("}");
           client.println("");
           client.println("if(e.which == 83){");
           client.println("   sendCmd('bwd');");
           client.println("}");
           client.println("");
           client.println("if(e.which == 65){");
           client.println("   sendCmd('left');");
           client.println("}");
           client.println("");
           client.println("if(e.which == 68){");
           client.println("   sendCmd('right');");
           client.println("}");
           client.println("");
           client.println("if(e.which == 69){");
           client.println("   sendCmd('up');");
           client.println("}");
           client.println("");
           client.println("if(e.which == 81){");
           client.println("   sendCmd('down');");
           client.println("}");
           client.println("");
           client.println("}");
           client.println("");
           client.println("window.addEventListener('keyup', deleteKey);");
           client.println("");
           client.println("function deleteKey(i){");
           client.println("if(i.which == 87||i.which==83||i.which==69||i.which==81||i.which==65||i.which==68){");
           client.println("   sendCmd('');");
           client.println("}");
           client.println("}");
           client.println("function sendCmd(cmd){");
           client.println("  var xmlhttp;");
           client.println("  if(window.XMLHttpRequest){");
           client.println("     xmlhttp = new XMLHttpRequest();");
           client.println("     xmlhttp.open(\"GET\",cmd,true);");
           client.println("     xmlhttp.send(null);}");
           client.println("    }");
           client.println("</script>");
           client.println("</head>");
           client.println("");
           client.println("<body>");
           client.println("<pre>Welcome, this is the control website for my personal project. If you aren't the owner please click out.");
           client.println("Movement buttons are:");
           client.println("W for forwards");
           client.println("S for backwards");
           client.println("A to turn left");
           client.println("D to turn right");
           client.println("Q to go down");
           client.println("E to go up");
           client.println("</pre></body></html>");
           client.println("");
              break;
            }
            else {
              currentLine = "";
            }
          }
          else if (c != '\r') {
            currentLine += c;
          }            
          if (currentLine.startsWith("GET /fwd")) {
              M3.setDuty(100);
              M2.setDuty(100);
            }
          else if (currentLine.startsWith("GET /bwd")) {
              M3.setDuty(-100);
              M2.setDuty(-100);
            }
          else if (currentLine.startsWith("GET /left")) {
              M3.setDuty(100);
              M2.setDuty(0);
            }
          else if (currentLine.startsWith("GET /right")) {
              M3.setDuty(0);
              M2.setDuty(100);
            }
          else if (currentLine.startsWith("GET /down")) {
              M1.setDuty(-100);
            }
          else if (currentLine.startsWith("GET /up")){
              M1.setDuty(100);
             }
          else if (currentLine.startsWith("GET /")){
              M1.setDuty(0);
              M2.setDuty(0);
              M3.setDuty(0);
          }
          else if (!client.connected()){
            client.stop();
            Serial.println("Client Disconnected");
          }
        }
      }
    }
  }
}
void WiFiStatus() {
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  long rssi = WiFi.RSSI();
  Serial.print("Singal Strenght (RSSI):");
  Serial.println(rssi);
  Serial.println(" dBm");
}

The below two continuous rotation servo routerbot control code shows the concept of initially delivering a control web page to the client browser, then when commands are received by the Arduino server, the servo commands are executed and the browser is told it will not be receiving a new web page and not to attempt to refresh the current page. Very simple web control approach.

//zoomkat 11-20-12//routerbot code
//for use with Arduino IDE 1.0
//open serial monitor to see what the arduino receives
//address will look like http://192.168.1.102:84 when submited
//servos are continous rotation for drive wheels 

#include <SPI.h>
#include <Ethernet.h>
#include <Servo.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port
String readString, servo1, servo2; //strings to hold data
Servo myservo1, myservo2;  // create servo object to control a servo 
//Servo myservo2;
//////////////////////
void setup(){
  //start Ethernet
  Ethernet.begin(mac,ip,gateway,gateway,subnet);
  server.begin();

  //enable serial data print 
  Serial.begin(9600); 
  myservo1.attach(7);
  myservo2.attach(6);
  Serial.println("routerbot-11-20-12"); // so I can keep track of what is loaded
}

void loop(){
  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        //read char by char HTTP request
        if (readString.length() < 100) {
          //store characters to string 
          readString += c; 
        } 
        //if HTTP request has ended
        if (c == '\n') {
          ///////////////
          //readString looks like "GET /?-1500-1500 HTTP/1.1"
          Serial.print(readString);
          //now output HTML data header
          if(readString.indexOf('?') >=0) { //don't send new page
            client.println(F("HTTP/1.1 204 Zoomkat"));
            client.println();
            client.println();  
          }
          else {   
            client.println(F("HTTP/1.1 200 OK")); //send new page on browser request
            client.println(F("Content-Type: text/html"));
            client.println();
            client.println(F("<HTML><HEAD>"));
            client.println(F("<H3>Zoomkat's Routerbot
Web Control Page
11-20-12</H3>"));
            client.println(F("<TITLE>Zoomkat's Routerbot Control Page</TITLE>"));
            client.println(F("</HEAD><BODY>"));
            client.println(F("Foward&nbsp;&nbsp;&nbsp;-*Stop*-&nbsp;&nbsp;&nbsp;Reverse
"));
            client.println(F("<a href=/?-1000-2000 target=inlineframe>F-F</a>|"));
            client.println(F("<a href=/?-1450-1550 target=inlineframe>S-F</a>|"));
            client.println(F("<a href=/?-1500-1500 target=inlineframe>*-Stop-*</a>|"));
            client.println(F("<a href=/?-1550-1450 target=inlineframe>S-R</a>|"));
            client.println(F("<a href=/?-2000-1000 target=inlineframe>F-R</a>|

"));
            client.println(F("Turn-L&nbsp;&nbsp;&nbsp;-*Stop*-&nbsp;&nbsp;&nbsp;Turn-R
"));
            client.println(F("<a href=/?-1000-1000 target=inlineframe>F-L</a>|"));
            client.println(F("<a href=/?-1450-1450 target=inlineframe>S-L</a>|"));
            client.println(F("<a href=/?-1500-1500 target=inlineframe>*-Stop-*</a>|"));
            client.println(F("<a href=/?-1550-1550 target=inlineframe>S-R</a>|"));
            client.println(F("<a href=/?-2000-2000 target=inlineframe>F-R</a>|
"));
            client.println(F("<IFRAME name=inlineframe style='display:none'>")); 
            client.println(F("</IFRAME>

"));
            client.println(F("<a href=\"#\"onClick=\"MyWindow=window.open('http://192.168.1.102:84/',"));
            client.println(F("'MyWindow','width=200,height=200');\">Popout Control Window</a>"));
            client.println(F("</body></html>"));
          }
          delay(1);
          //stopping client
          client.stop();

          if (readString.length() >0) {
            //Serial.println(readString);
            servo1 = readString.substring(7, 11);
            servo2 = readString.substring(12, 16);

            int n1 = servo1.toInt();
            int n2 = servo2.toInt();

            Serial.println("the numbers are :");
            Serial.println(n1);  //print to serial monitor to see number results
            Serial.println(n2);
            Serial.println("");
            myservo1.writeMicroseconds(n1); //set servo position 
            myservo2.writeMicroseconds(n2);
            //clearing string for next read            
            readString="";
            servo1="";
            servo1="";
          } 
        }
      }
    }
  }
}

The currentLine is not read from the Serial Monitor. It is a buffer that stores the HTTP request. We are sending the currentLine to the Serial Monitor for debugging only.

By moving your code around you are back at where you started. Print the currentLine variable before the part where you test and then watch the Serial Monitor.

Serial.println( currentLine ); if (currentLine.startsWith("GET /fwd")) { ...

It will look like the following with hundreds of lines every time you send a HTTP request. That means you are comparing the HTTP request hundreds of times.

G GE GET GET GET / GET /f GET /fw GET /fwd GET /fwd ...

The function startWith is something you only want to run when absolutly necessary. It is a computational expensive function. You need to run trough two arrays and compare each character. You want to wait until you have the entire HTTP request. Thats why I moved the code before the currentLine = ""; because we know that you clear a buffer after you have read a message.

Still doesn’t work.

Klaus_K
I went back to your post on Dec 6 with all the code and added in all the stuff I was missing or needed to change. The program still doesn’t work however.

There is still the issue where I need to manually reload the webpage for the currentLine to update.

I added the Serial.println( currentLine ); thing infront of the if statement but instead of going

G
GE
GET
GET /
etc.

it goes

(Serial Set Up Stuff)

New Client
GET / HTTP/1.1
(rest of currentLine info)

New Client

(I have to reload page)

New Client
GET /fwd HTTP/1.1
GET /fwd HTTP/1.1
(rest of currentLine info but double side by side)

New Client
GET /bwd HTTP/1.1
GET /bwd HTTP/1.1
(rest of currentLine info but double side by side)

New Client

and than I have to reload and it starts over.

To find the issue start your Chrome browser, open the webpage and press F12. This will open the browser debug. Click on the network tab. Now when you press one of your control buttons (WASD) you will see the request and the status is 200 OK. But when you press the button a few times more it changes to pending (see screenshot).

That means when we send the request, the browser expects an answer, but we do not send one, we just control the motor.

Now, add the confirmation to the function where we work on the request. See below. Then do the same test again. Now you should see 204 in the Status instead of 200 and you can press forward as often as you want.

if ( currentLine.startsWith( "GET /fwd" ) )
{
  client.println( "HTTP/1.1 204" ); // need to send confirmation
  
  M3.setDuty( 100 );
  M2.setDuty( 100 );
}

I can push the button a few times per second, but I cannot keep it pushed. This will be too fast for the Arduino to send the answers. I suspect there is some potential for improvements.

For now add the confirmation to all commands and your motors should move in all direction.

ChromeNetwork.jpg

Yup, works just like you said it would. I can now give a few commands, the currentLine updates like 3 times every second, and holding down the button seems to work for me.

The same issue keeps reoccurring though, the new client thing and me having to reload. When I spam a bunch of buttons it can go on for a while but as soon as I take a short break, it prints new client and I have to reload.

I looked through the code to try and understand it more but it just confused me.

Serial.println(“New Client”);

is before the while statement and the while statement should consistently be true because I never disconnected from the website so why does it go all the way back to the top and keep printing new client?

Also, nicely explained, the code’s starting to make sense now.

"I never disconnected from the website so why does it go all the way back to the top and keep printing new client?"

As best as I remember web connections are usually not designed to be persistent. Not sure if that has anything to do with your issue.

I am certain zoomkat is right. In HTTP 1 the connection is usually closed when the page is rendered. In HTTP2 you can keep the connection open. I do not think for your application this makes any difference. Every GET request is a new TCP/IP packet anyways. Your webpage is completely stateless (which is good).

There are improvements you can do in your program. Here are a few easy points you could look at.

  1. After you send the last html tag, close the connection. This removes the loading cursor in the browser tab.

client.println( “” );
client.stop();
break;

  1. Limit the amounts of GET requests you are sending. The browser can send many more requests than your board can handle. So, in your logKey function you could add some time logic to send a different request when the key is pressed continuously. e.g. fast forward /ffwd

  2. See what other GET request you get from your browser and make sure they are handled. Right now, everything stops e.g.

GET /favicon.ico HTTP/1.1
Everything stop

  1. Separate the HTML and JavaScript from your code. Place the files on a SD card. This way you can modify the webpage without changing your code.

Allright, it’s been a while but I finally got the code to work. I’ve implemented the timeout system and everything. Big thanks Klaus_K and zoomkat. So full final code:
Got rid of HTML and CSS stuff because of word limit.

#include <WiFi101.h>
#include <SPI.h>
#include <MKRMotorCarrier.h>

static int batteryVoltage;

char ssid[] = "********";
char pass[] = "*********";

int keyIndex = 0;

int status = WL_IDLE_STATUS;
WiFiServer server(80);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial) {
  }
  
  Serial.println("start of SETUP");

  if (controller.begin())
  {
    Serial.println("MKR Motor Carrier Connected");
  }
  
  else {
    Serial.println("No Motor Carrier");
    while (1);
  }
  
  while ( status != WL_CONNECTED) {
      Serial.print("Attempting to connect to Networked names: ");
      Serial.println(ssid);
      status = WiFi.begin(ssid, pass);
      delay(5000);
    }
     
  server.begin();
  Serial.println("Start of SERvER");
  WiFiStatus(); 
  Serial.println("Rebooting");
  controller.reboot();
  delay(500);
  
  float batteryVoltage = (float)battery.getConverted();
  Serial.print("Battery Voltage:");
  Serial.println(batteryVoltage);
  Serial.print("V, Raw");
  Serial.println(battery.getRaw());
}

void loop() {
  // put your main code here, to run repeatedly:
  float batteryVoltage = (float)battery.getConverted();
  if (batteryVoltage < 11)
  {
    Serial.println(" ");
    Serial.println("!!!!!!!!!!!!!LOW BATTERY!!!!!!!!!!!!");
    Serial.print("Current Voltage: ");
    Serial.println(batteryVoltage);
    M3.setDuty(0);
    M2.setDuty(0);
    M1.setDuty(0);
    delay(500);
  }
  else {
    WiFiClient client = server.available();
    if (client) {
      Serial.println("New CLient");
      String currentLine = "";
      while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n') {
          if (currentLine.length() == 0) {
           client.println("HTTP/1.1 200 OK");
           client.println("Content-type:text/html");
           client.println("");
           client.println("<!DOCTYPE html>");
           client.println("<html>");
           client.println("<script>");
           client.println("var flag = true;");
           client.println("var limit = 1000;");
           client.println("window.addEventListener('keydown', logKey);");
           client.println("function logKey(e){");
           client.println("if(flag){");
           client.println("if (e.which == 87){");
           client.println("flag = false;");
           client.println("   sendCmd('fwd');");
           client.println("setTimeout(()=>{");
           client.println("flag = true;");
           client.println("}, limit);");
           client.println("}");
           client.println("else if (e.which == 83){");
           client.println("   sendCmd('bwd');");
           client.println("flag = false;");
           client.println("setTimeout(()=>{");
           client.println("flag =true;");
           client.println("}, limit);");
           client.println("}");
           client.println("else if (e.which == 65){");
           client.println("   sendCmd('left');");
           client.println("flag = false;");
           client.println("setTimeout(()=>{");
           client.println("flag =true;");
           client.println("}, limit);");
           client.println("}");
           client.println("else if (e.which == 68){");
           client.println("   sendCmd('right');");
           client.println("flag = false;");
           client.println("setTimeout(()=>{");
           client.println("flag =true;");
           client.println("}, limit);");
           client.println("}");
           client.println("else if (e.which == 69){");
           client.println("   sendCmd('down');");
           client.println("flag = false;");
           client.println("setTimeout(()=>{");
           client.println("flag =true;");
           client.println("}, limit);");
           client.println("}");
           client.println("else if (e.which == 81){");
           client.println("sendCmd('right');");
           client.println("flag = false;");
           client.println("setTimeout(()=>{");
           client.println("flag =true;");
           client.println("}, limit);");
           client.println("}");
           client.println("else if (e.which == 32){");
           client.println("   sendCmd('up');");
           client.println("flag = false;");
           client.println("setTimeout(()=>{");
           client.println("flag =true;");
           client.println("}, limit);");
           client.println("}");
           client.println("} }");
           client.println("window.addEventListener('keyup', deltKey);");
           client.println("function deltKey(i){");
           client.println("if (i.which == 87 || i.which == 83 || i.which == 65 || i.which == 68 || i.which == 69 || i.which == 81 || i.which == 32){");
           client.println("   sendCmd('empty');");
           client.println("}");
           client.println("}");
           client.println("function sendCmd(cmd){");
           client.println("  var xmlhttp;");
           client.println("  if(window.XMLHttpRequest){");
           client.println("     xmlhttp = new XMLHttpRequest();");
           client.println("     xmlhttp.open(\"GET\",cmd,true);");
           client.println("     xmlhttp.send(null);}");
           client.println("    }");
           client.println("</script>");
           client.println("</pre></body></html>");
           client.println("");

           client.stop(); 
           break;
            }
         else {
            if (currentLine.startsWith("GET /fwd")) {
                client.println("HTTP/1.1 204");
                M3.setDuty(100);
                M2.setDuty(100);
              }
            else if (currentLine.startsWith("GET /bwd")) {
                client.println("HTTP/1.1 204");
                M3.setDuty(-100);
                M2.setDuty(-100);
              }
            else if (currentLine.startsWith("GET /left")) {
                client.println("HTTP/1.1 204");
                M3.setDuty(100);
                M2.setDuty(0);
              }
            else if (currentLine.startsWith("GET /right")) {
                client.println("HTTP/1.1 204");
                M3.setDuty(0);
                M2.setDuty(100);
              }
            else if (currentLine.startsWith("GET /down")) {
                client.println("HTTP/1.1 204");   
                M1.setDuty(-100);
              }
            else if (currentLine.startsWith("GET /up")){
                client.println("HTTP/1.1 204");
                M1.setDuty(100);
              }
            else if (currentLine.startsWith("GET /empty")){
                client.println("HTTP/1.1 204");
                M1.setDuty(0);
                M2.setDuty(0);
                M3.setDuty(0);
            }
            currentLine = "";
         }
        }
        else if (c != '\r') {
          currentLine += c;
       }
      }   
    }
  }
 }
}
void WiFiStatus() {
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  long rssi = WiFi.RSSI();
  Serial.print("Singal Strenght (RSSI):");
  Serial.println(rssi);
  Serial.println(" dBm");
}