Modifying Power Anchor to wireless operation - project

Hi Gianni,

No worries, I’ll get it uploaded to a repository for you which if you log in on GitHub you can hit fork on to make your own copy of it. One of the major advantages of GitHub is that it lets you comment on changes to code, lets multiple people work on it at the same time, and lets anyone point out or make suggestions for how to fix issues (the code also appears here when you paste a link to it)

I’ll dig into this a little more for you, as you may find some of the tricks I’m using to simplify the code helpful, but can you further describe the error you’re getting when you’re running Liams code, we’ll see what we can do to show you how to fix it.

4 Likes

Just updated it a little, other than the WiFi.h library it should compile now. @Liam or @Liam120347 if you’ve got any ideas to fix this up regarding the errors that are being hit feel free to grab the code from the repo I added.

1 Like

Hi Bryce,

I had the previous version compiling alright on my ESP32. I havent played around with the methods that you have used so wont be able to advise on using those.

Hey Gianni,

Changing the pin declarations at the top of the code would be easiest I think, checking which pins are routed from the L298 to the ESP.

Hi Bryce,
the Github entry looks promising. I almost don’t recognise the code. Lots of new commands and learning to do.
I don’t have the hardware at home, so any testing will need to wait till Monday, however, I can still ask questions lol!

1 Like

Hi Bryce, I tried to verify the lates sketch I downloaded from GitHub into the Arduino program but came up with errors. Did you get a chance to trial the sketch before it was uploaded/modified in GitHub?

Hi Gianni,

When verifying/compiling the sketch make sure you have all of the libraries and boards installed and selected. Unfortunatelyhe defaults will throw some errors.

Ok Liam, I’ll check all that. Thanks for replying!

1 Like

Here are the error message copied from the sketch in the Arduino IDE software:

Arduino: 1.8.16 (Windows 10), Board: “Adafruit ESP32 Feather, 80MHz, 921600, None, Default”

C:\Users\gianni.mazzantini\Documents\Arduino\Power_Anchor_Bryce_15_10_21\Power_Anchor_Bryce_15_10_21.ino: In function ‘void loop()’:

Power_Anchor_Bryce_15_10_21:70:68: error: invalid operands of types ‘const char*’ and ‘const char [4]’ to binary ‘operator+’

                     if (header.indexOf("GET /" + motor[0][0] + "/on") >= 0)

                                                                ^

Power_Anchor_Bryce_15_10_21:72:77: error: invalid operands of types ‘const char*’ and ‘const char [10]’ to binary ‘operator+’

                         Serial.println("Motor on GPIO " + motor[0][0] + " starting");

                                                                         ^

Power_Anchor_Bryce_15_10_21:85:73: error: invalid operands of types ‘const char*’ and ‘const char [5]’ to binary ‘operator+’

                     else if (header.indexOf("GET /" + motor[0][0] + "/off") >= 0)

                                                                     ^

Power_Anchor_Bryce_15_10_21:87:77: error: invalid operands of types ‘const char*’ and ‘const char [10]’ to binary ‘operator+’

                         Serial.println("Motor on GPIO " + motor[0][0] + " stopping");

                                                                         ^

Power_Anchor_Bryce_15_10_21:92:73: error: invalid operands of types ‘const char*’ and ‘const char [4]’ to binary ‘operator+’

                     else if (header.indexOf("GET /" + motor[1][0] + "/on") >= 0)

                                                                     ^

Power_Anchor_Bryce_15_10_21:94:77: error: invalid operands of types ‘const char*’ and ‘const char [10]’ to binary ‘operator+’

                         Serial.println("Motor on GPIO " + motor[1][0] + " starting");

                                                                         ^

Power_Anchor_Bryce_15_10_21:96:42: error: ‘motor2Pin1’ was not declared in this scope

                         digitalWrite(motor2Pin1, HIGH);

                                      ^

Power_Anchor_Bryce_15_10_21:97:42: error: ‘motor2Pin2’ was not declared in this scope

                         digitalWrite(motor2Pin2, LOW);

                                      ^

Power_Anchor_Bryce_15_10_21:107:73: error: invalid operands of types ‘const char*’ and ‘const char [5]’ to binary ‘operator+’

                     else if (header.indexOf("GET /" + motor[1][0] + "/off") >= 0)

                                                                     ^

Power_Anchor_Bryce_15_10_21:109:77: error: invalid operands of types ‘const char*’ and ‘const char [10]’ to binary ‘operator+’

                         Serial.println("Motor on GPIO " + motor[1][0] + " stopping");

                                                                         ^

Power_Anchor_Bryce_15_10_21:131:77: error: invalid operands of types ‘const char*’ and ‘const char [48]’ to binary ‘operator+’

                         client.println("<p><a href=\"/" + motor[0][0] + "/on\"><button class=\"button\">ON</button></a></p>");

                                                                         ^

Power_Anchor_Bryce_15_10_21:135:77: error: invalid operands of types ‘const char*’ and ‘const char [58]’ to binary ‘operator+’

                         client.println("<p><a href=\"/" + motor[0][0] + "/off\"><button class=\"button button2\">OFF</button></a></p>");

                                                                         ^

Power_Anchor_Bryce_15_10_21:139:80: error: invalid operands of types ‘const char*’ and ‘const char [5]’ to binary ‘operator+’

                     client.println("<p>GPIO 15 - State " + motorState[1] + "</p>");

                                                                            ^

Power_Anchor_Bryce_15_10_21:140:83: error: invalid operands of types ‘const char*’ and ‘const char [17]’ to binary ‘operator+’

                     motorState[0] ? client.println("<p>GPIO " + motor[1][0] + " - State OFF</p>") : client.println("<p>GPIO " + motor[1][0] + " - State ON</p>");

                                                                               ^

Power_Anchor_Bryce_15_10_21:140:147: error: invalid operands of types ‘const char*’ and ‘const char [16]’ to binary ‘operator+’

                     motorState[0] ? client.println("<p>GPIO " + motor[1][0] + " - State OFF</p>") : client.println("<p>GPIO " + motor[1][0] + " - State ON</p>");

                                                                                                                                               ^

Power_Anchor_Bryce_15_10_21:142:46: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]

                     if (motorState[1] == "off")

                                          ^

Power_Anchor_Bryce_15_10_21:145:77: error: invalid operands of types ‘const char*’ and ‘const char [48]’ to binary ‘operator+’

                         client.println("<p><a href=\"/" + motor[1][0] + "/on\"><button class=\"button\">ON</button></a></p>");

                                                                         ^

Power_Anchor_Bryce_15_10_21:149:77: error: invalid operands of types ‘const char*’ and ‘const char [58]’ to binary ‘operator+’

                         client.println("<p><a href=\"/" + motor[1][0] + "/off\"><button class=\"button button2\">OFF</button></a></p>");

                                                                         ^

Multiple libraries were found for “WiFi.h”

Used: C:\Users\gianni.mazzantini\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFi

Not used: C:\Program Files (x86)\Arduino\libraries\WiFi

exit status 1

invalid operands of types ‘const char*’ and ‘const char [4]’ to binary ‘operator+’

This report would have more information with
“Show verbose output during compilation”
option enabled in File → Preferences.

… lots of semicolons missing…

Hey Gianni,

I think this one is a type error rather than missing semicolons, you dont need them at the end of a line in an if statement.

// Load Wi-Fi library
#include <WiFi.h>

// Replace with your network credentials
const char* ssid = "ESP32-Access-Point";
const char* password = "123456789";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output27State = "off";
String output15State = "off";

// --------------------------------- Setting up the motors ---------------------------------
// Motor A
int motor1Pin1 = 27;
int motor1Pin2 = 33;
int enable1Pin = 12;

// Motor B
int motor2Pin1 = 15;
int motor2Pin2 = 32;
int enable2Pin = 14;

const int delayTime = 200; // The delay inbetween the motor changing speed - alters the accelleration

const int maxDutyCycle = 200;

int dutyCycleA = 0;
int dutyCycleB = 0;

const int freq = 5000;
const int res = 8;

const int motorAChn = 0;
const int motorBChn = 2;

void setup() {
  Serial.begin(115200);

  // --------------------------------- Init. the motor pins ---------------------------------
  // sets the pins of Motor A as outputs:
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
 
  // sets the pins of Motor B as outputs:
  pinMode(motor2Pin1, OUTPUT);
  pinMode(motor2Pin2, OUTPUT);

  // attaching pins to timers and setting up PWM
  ledcSetup(motorAChn, freq, res);
  ledcSetup(motorBChn, freq, res);

  // attaching the timers to pins
  
  ledcAttachPin(enable1Pin, motorAChn);
  ledcAttachPin(enable2Pin, motorBChn);
  

  // --------------------------------- Init. the Wifi point and connect to WiFi --------------------------------

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Setting AP (Access Point)...");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

  server.begin();
}

void loop() {
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {             // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // turns the GPIOs on and off
            // **************************** Here is the code we are after, all of the code surrounding this handles the webserver itself ********

            
            if (header.indexOf("GET /27/on") >= 0) {        // Start motor A
              Serial.println("Motor on GPIO 27 starting");
              output27State = "on";
              
              digitalWrite(motor1Pin1, HIGH);
              digitalWrite(motor1Pin2, LOW);
              
              
              while (dutyCycleA <= maxDutyCycle) {
                ledcWrite(enable1Pin, dutyCycleA);
                
                Serial.print("Forward with duty cycle(MotorA): ");
                Serial.println(dutyCycleA);
                
                dutyCycleA = dutyCycleA + 5;
                delay(delayTime);
              }
            } else if (header.indexOf("GET /27/off") >= 0) {  // Stop motor A
              Serial.println("Motor on GPIO 27 stopping");
              output27State = "off";

              dutyCycleA = 0;
              ledcWrite(enable1Pin, dutyCycleA);

            } else if (header.indexOf("GET /15/on") >= 0) {   // Start motor B
              Serial.println("Motor on GPIO 15 starting");
              output15State = "on";

              digitalWrite(motor2Pin1, HIGH);
              digitalWrite(motor2Pin2, LOW);
              
              while (dutyCycleB <= maxDutyCycle) {
               ledcWrite(enable2Pin, dutyCycleB);
                
                Serial.print("Forward with duty cycle(MotorB): ");
                Serial.println(dutyCycleB);
                
                dutyCycleB = dutyCycleB + 5;
                delay(delayTime);
              }

            } else if (header.indexOf("GET /15/off") >= 0) {  // Stop motor B
              Serial.println("Motor on GPIO 15 stopping");
              output15State = "off";
              
              dutyCycleB = 0;
              ledcWrite(enable1Pin, dutyCycleB);
            }

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>ESP32 Web Server</h1>");

            // Display current state, and ON/OFF buttons for GPIO 27
            client.println("<p>GPIO 27 - State " + output27State + "</p>");
            // If the output27State is off, it displays the ON button
            if (output27State == "off") {
              client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
            }

            // Display current state, and ON/OFF buttons for GPIO 15
            client.println("<p>GPIO 15 - State " + output15State + "</p>");
            // If the output15State is off, it displays the ON button
            if (output15State == "off") {
              client.println("<p><a href=\"/15/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/15/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

I’d try running this code, just make sure to change the pin numbers in the motor setup section.

Hi Liam, Should I be using the sketch you just sent me?

1 Like

Hi Gianni,

Yeah I’d give it a shot, just make sure the pin declarations are correct before uploading it.

1 Like

I’m still uncertain as to what to do with the enable pins on the L298N? Do I use the jumpers (and not the wires) or do I remove the jumpers and use the wires?

1 Like

Hi Gianni,

The enable pins let you vary the speed of the motor through a pulsed signal (PWM) with the jumpers on the EN pin it will always run at 100%. The code that I sent through uses the functionality, but if you need 0 delay you can add the jumpers back on and make a couple of modifications to allow the motors to be switched instantly(or close to).

Yes! I need the motors to come on instantly we the press the button… no delay needed or in fact, wanted.
What are the modification I need to make?
BTW: sketch is not compiling… "expected ‘}’ at end of input error code.

Is there a command in the drop down menus of the IDE that allows me to check the errors one a the time?

Sketch has compiled!!!

Hi Gianni,

I’ve made the mod here myself, unfortunately not. The IDE will throw all of the errors at you in the output log.

Re: the code, taking a look at the logic table for the motor here: Motor Driver Module-L298N - Wiki

If you send both of the outputs HIGH or LOW then it will put the motor into a breaking mode.

// Load Wi-Fi library
#include <WiFi.h>

// Replace with your network credentials
const char* ssid = "ESP32-Access-Point";
const char* password = "123456789";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output27State = "off";
String output15State = "off";

// --------------------------------- Setting up the motors ---------------------------------
// Motor A
int motor1Pin1 = 27;
int motor1Pin2 = 33;
//int enable1Pin = 12;

// Motor B
int motor2Pin1 = 15;
int motor2Pin2 = 32;
//int enable2Pin = 14;

//const int delayTime = 200; // The delay inbetween the motor changing speed - alters the accelleration
//
//const int maxDutyCycle = 200;
//
//int dutyCycleA = 0;
//int dutyCycleB = 0;
//
//const int freq = 5000;
//const int res = 8;
//
//const int motorAChn = 0;
//const int motorBChn = 2;

void setup() {
  Serial.begin(115200);

  // --------------------------------- Init. the motor pins ---------------------------------
  // sets the pins of Motor A as outputs:
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
 
  // sets the pins of Motor B as outputs:
  pinMode(motor2Pin1, OUTPUT);
  pinMode(motor2Pin2, OUTPUT);

//  // attaching pins to timers and setting up PWM
//  ledcSetup(motorAChn, freq, res);
//  ledcSetup(motorBChn, freq, res);
//
//  // attaching the timers to pins
//  
//  ledcAttachPin(enable1Pin, motorAChn);
//  ledcAttachPin(enable2Pin, motorBChn);
  

  // --------------------------------- Init. the Wifi point and connect to WiFi --------------------------------

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Setting AP (Access Point)...");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

  server.begin();
}

void loop() {
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {             // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // turns the GPIOs on and off
            // **************************** Here is the code we are after, all of the code surrounding this handles the webserver itself ********

            
            if (header.indexOf("GET /27/on") >= 0) {        // Start motor A
              Serial.println("Motor on GPIO 27 starting");
              output27State = "on";
              
              digitalWrite(motor1Pin1, HIGH);
              digitalWrite(motor1Pin2, LOW);
              
              

            } else if (header.indexOf("GET /27/off") >= 0) {  // Stop motor A
              Serial.println("Motor on GPIO 27 stopping");
              output27State = "off";

//              dutyCycleA = 0;
//              ledcWrite(enable1Pin, dutyCycleA);
              digitalWrite(motor1Pin1, LOW);
              digitalWrite(motor1Pin2, LOW);

            } else if (header.indexOf("GET /15/on") >= 0) {   // Start motor B
              Serial.println("Motor on GPIO 15 starting");
              output15State = "on";

              digitalWrite(motor2Pin1, HIGH);
              digitalWrite(motor2Pin2, LOW);

              

            } else if (header.indexOf("GET /15/off") >= 0) {  // Stop motor B
              Serial.println("Motor on GPIO 15 stopping");
              output15State = "off";
              
//              dutyCycleB = 0;
//              ledcWrite(enable1Pin, dutyCycleB);

              digitalWrite(motor2Pin1, LOW);
              digitalWrite(motor2Pin2, LOW);
            }

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>ESP32 Web Server</h1>");

            // Display current state, and ON/OFF buttons for GPIO 27
            client.println("<p>GPIO 27 - State " + output27State + "</p>");
            // If the output27State is off, it displays the ON button
            if (output27State == "off") {
              client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
            }

            // Display current state, and ON/OFF buttons for GPIO 15
            client.println("<p>GPIO 15 - State " + output15State + "</p>");
            // If the output15State is off, it displays the ON button
            if (output15State == "off") {
              client.println("<p><a href=\"/15/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/15/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

PS: When doing a project my goto for writing up some code is first a flowchart where I can draw out decisions then jump into the code from there. Here’s an awesome resource for Arduino as well: Arduino Workshop for Beginners - Tutorial Australia

1 Like

I’ve typed in all those forward slashes you used in the sketch… I assume I can delete them if I am no longer going to used them. Correct?

1 Like

Hi Gianni,

Yeah any lines that have been commented wont be compiled and put on the microcontroller.

1 Like

It works!!

What I’d like to achieve now is the ability to have one button only, on two different devices.
So that each student has access to control only one of the motors.

Will this be possible?

1 Like