Modifying Power Anchor to wireless operation - project

I’ve received the components from Core-electronics today and am wiring them up.
Will I need to use the enable pins on the L298N H-Bridge if I want the motors to go flat out in one direction only?

Also, I will need to modify the code I’ve copied from Rui Santos tutorials.
How is that best discussed on the forum?

2 Likes

Hey Gianni,

In my quest to get a few different outputs I had to copy the code from the LED tutorial and modified the code that toggles the LED’s.

Not quite, the enable pins allow that motors output to be ‘enabled’ then you have to drive the motor with the PWM pins.

4 Likes

So, I will need to use all three wires from the L298N to the ESP32 for each of the motors. That is, six wires in total.
Then, I will need to use the following code to set up the PWM properties in the sketch as well?

// Setting PWM properties
const int freq = 30000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 200;

and:

  // configure LED PWM functionalitites
  ledcSetup(pwmChannel, freq, resolution);
  
  // attach the channel to the GPIO to be controlled
  ledcAttachPin(enable1Pin, pwmChannel);
3 Likes

That is correct, with a H-Bridge, it’s essentially the same as being able to control the motor/s directly from two pins as if you had it hooked up directly to your ESP32 (except it’s not so that you don’t have to worry about the voltage difference of current limits on your board)

Can you post the code that you’re running up in the forum? We can take a look through it for you and see whether there’s anything that sticks out, so to speak :grinning_face_with_smiling_eyes:

2 Likes

We’ll take a look at the sketch first and see what’ll be most appropriate. Also, to save on memory depending on the compiler settings, sometimes it’s less resource intensive to use #define freq 30000 as that simply replaces that keyword (also known as a token) at compile time rather than storing a value in allocated memory which will cause your program to fail to compile if at any point it attempts to edit it.

1 Like

Hey Gianni and any other Makers looking to use multiple devices to control the ESP32.

I did a test and connected my ESP32, phone and PC to the same network, using the webserver (websocket??) guide I linked before I was able to control the onboard LED from two different devices.

3 Likes

That’s great feedback Liam.

What I need to know though is: can we control two different motors wirelessly, from two different devices using the one ESP32?

Regarding the IDE code… I am using Rui Santo’s Web Server tutorial at the moment, but have not been able to get it working with just the two LEDs in the tutorial. Rui’s code uses pins 26 and 27.
My ESP32 is different to Rui’s and I’m using pins 27 and 33.
However, I have yet to control the two LEDs via wifi as I have not set it up correctly/properly yet.

1 Like

Hi Bryce, as mentioned to Liam, I was trying to replicate Rui Santos’s Web Server tutorial using the Adafruit HUZZAH32 version of the ESP32 board (different pins). However, as per Liam’s feedback early on in this forum topic, I needed to set the ESP32 board up as an Access Point.
This morning, after rewiring the breadboard (those pin numbers printed on the board are miniscule!) I was able to control the two LED from my iPhone!!!
Now comes the next part: splicing the Access Point code with the L298N’s code.
The code I used for the Access Point is below:

// 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 output33State = "off";

// Assign output variables to GPIO pins
const int output27 = 27;
const int output33 = 33;

void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(output27, OUTPUT);
  pinMode(output33, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output27, LOW);
  digitalWrite(output33, LOW);

  // 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
            if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 on");
              output27State = "on";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 off");
              output27State = "off";
              digitalWrite(output27, LOW);
            } else if (header.indexOf("GET /33/on") >= 0) {
              Serial.println("GPIO 33 on");
              output33State = "on";
              digitalWrite(output33, HIGH);
            } else if (header.indexOf("GET /33/off") >= 0) {
              Serial.println("GPIO 33 off");
              output33State = "off";
              digitalWrite(output33, 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 33  
            client.println("<p>GPIO 33 - State " + output33State + "</p>");
            // If the output33State is off, it displays the ON button       
            if (output33State=="off") {
              client.println("<p><a href=\"/33/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/33/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("");
  }
}

The L298N code I am in the process of modifying and then trying to splice in is:

// Motor A
int motor1Pin1 = 27; 
int motor1Pin2 = 33; 
int enable1Pin = 12; 

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

// Setting PWM properties
const int freq = 30000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 200;

void setup() {
  // sets the pins of Motor A as outputs:
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
  pinMode(enable1Pin, OUTPUT);

// sets the pins of Motor B as outputs:
  pinMode(motor2Pin1, OUTPUT);
  pinMode(motor2Pin2, OUTPUT);
  pinMode(enable2Pin, OUTPUT);

  // configure LED PWM functionalitites
  ledcSetup(pwmChannel, freq, resolution);
  
  // attach the channel to the GPIO to be controlled
  ledcAttachPin(enable1Pin, pwmChannel);

  Serial.begin(115200);

  // testing
  Serial.print("Testing DC Motor...");
}

void loop() {
  // Move the DC motor forward at maximum speed
  Serial.println("Moving Forward");
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, HIGH); 
  delay(2000);

  // Stop the DC motor
  Serial.println("Motor stopped");
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, LOW);
  delay(1000);

  // Move DC motor backwards at maximum speed
  Serial.println("Moving Backwards");
  digitalWrite(motor1Pin1, HIGH);
  digitalWrite(motor1Pin2, LOW); 
  delay(2000);

  // Stop the DC motor
  Serial.println("Motor stopped");
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, LOW);
  delay(1000);

  // Move DC motor forward with increasing speed
  digitalWrite(motor1Pin1, HIGH);
  digitalWrite(motor1Pin2, LOW);
  while (dutyCycle <= 255){
    ledcWrite(pwmChannel, dutyCycle);   
    Serial.print("Forward with duty cycle: ");
    Serial.println(dutyCycle);
    dutyCycle = dutyCycle + 5;
    delay(500);
  }
  dutyCycle = 200;
}

OK, over to you and Liam…

3 Likes

Hi Gianni,

Looks perfect, have you been able to get the LEDs working perfectly?

Weaving the code in will look something like this (I’ve moved the setup and initialisation parts directly across, and dropping in motor speed function) I’ve made a mod so the motors slowly startup when you click the buttons, and the other two buttons to stop both motors, motor A and motor B respectively.
Once you click the buttons they are ‘blocking’ any other input ( the delay() function causes this) so making another action requires a small wait.
Rather than ramping the motor up you could instantaneously start it although that might reduce the life of the motor.

// --------------------------------- Setting up the WiFi connection ---------------------------------
// 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 output33State = "off";

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

// Motor B
int motor2Pin1 = 15;
int motor2Pin2 = 33;
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;

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

  // --------------------------------- Init. the motor pins ---------------------------------
  // sets the pins of Motor A as outputs:
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
  pinMode(enable1Pin, OUTPUT);    // Used for PWM control - I've opted for using analogWrite

  // sets the pins of Motor B as outputs:
  pinMode(motor2Pin1, OUTPUT);
  pinMode(motor2Pin2, OUTPUT);
  pinMode(enable2Pin, OUTPUT);

  // --------------------------------- 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) {
                analogWrite(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;
              analogWrite(enable1Pin, dutyCycleA);

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

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

            } else if (header.indexOf("GET /33/off") >= 0) {  // Stop motor B
              Serial.println("Motor on GPIO 33 stopping");
              output33State = "off";
              
              dutyCycleB = 0;
              analogWrite(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 33
            client.println("<p>GPIO 33 - State " + output33State + "</p>");
            // If the output33State is off, it displays the ON button
            if (output33State == "off") {
              client.println("<p><a href=\"/33/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/33/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("");
  }
}
1 Like

Hi Liam,

Yes, the LED worked exactly like the Web Server tutorial described once I changed the pins, added the Access Point code and made some wiring adjustments to the bread board circuitry.

With regards to the slow start up and delay, I’m not sure that will suit how the motors are used (the students will be building balsa wood airplanes which will need the motor to have fast startup to get the models airbourne, then be able to have instantaneous changes in motor speed to control the model’s lift. This is because they will eventually finish the project by having dogfights with each other, so the motor needs to react as soon as possible to the student’s input).

The above is what we will need to achieve in order to call this exercise a success.

I’ll upload the sketch and run it so I can supply more feedback.

2 Likes

Hey Gianni,

Ahh ok, I’m on the same page now! Swapping out the loop and using a delay for a non-blocking function like millis() - millis() - Arduino Reference

I’ll leave this here as reference for the next iteration :smiley:

Liam.

1 Like

Liam, I’m getting a whole lot of error messages when I tried to compile the sketch.
See below:

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

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

Power_Anchor_Liam_14_10_21:100:51: error: ‘analogWrite’ was not declared in this scope

             analogWrite(enable1Pin, dutyCycleA);

                                               ^

Power_Anchor_Liam_14_10_21:113:49: error: ‘analogWrite’ was not declared in this scope

           analogWrite(enable1Pin, dutyCycleA);

                                             ^

Power_Anchor_Liam_14_10_21:123:51: error: ‘analogWrite’ was not declared in this scope

             analogWrite(enable2Pin, dutyCycleB);

                                               ^

Power_Anchor_Liam_14_10_21:137:49: error: ‘analogWrite’ was not declared in this scope

           analogWrite(enable1Pin, dutyCycleB);

                                             ^

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

‘analogWrite’ was not declared in this scope

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

Please advise.

Cheers and thanks.

2 Likes

Liam, are we missing some code in the void setup section for the analogWrite command?

Nah… it looks like the analogWrite function does not work with an ESP32. There seems to be workarounds but I don’t know how to implement them.

Do I need this function? What does it do? Based on my description on how the motors are required to be controlled, is this something we need to keep in the code?

1 Like

Hi Gianni,

I just got a message from Liam who has moded the code for you, he’s not available on the forum at the moment, but came up with this for you:

Oops! The different compilers got me. You dont need the analogWrite function, thats used to do PWM on a different board programmed in Arduino (Used on the Uno a lot!). Its just a different way of doing PWM. The LED side is a bit closer to how the microcontroller works at a lower level.

I came across this tutorial that allows for PWM control as well: How to control DC motors using ESP32 and L298N over WiFi - YouTube

Here is also the revised code, it has compiled onto my ESP32 board ok, but im not sure if the pins are correct.

// --------------------------------- Setting up the WiFi connection ---------------------------------
// 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 output33State = "off";

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

// Motor B
int motor2Pin1 = 15;
int motor2Pin2 = 33;
int enable2Pin = 14;    // PWM pin

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);

  //swapped out analogWrite() for ledc functions as analogWrite isnt included for this compiler
  
  // 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 /33/on") >= 0) {   // Start motor B
              Serial.println("Motor on GPIO 33 starting");
              output33State = "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 /33/off") >= 0) {  // Stop motor B
              Serial.println("Motor on GPIO 33 stopping");
              output33State = "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 33
            client.println("<p>GPIO 33 - State " + output33State + "</p>");
            // If the output33State is off, it displays the ON button
            if (output33State == "off") {
              client.println("<p><a href=\"/33/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/33/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("");
  }
}

Liam.

2 Likes

Thanks Liam and Bryce. I will update the sketch and try to run it in the project.
Will let you know how it goes.

2 Likes

Hi Liam and Bryce,
I changed the commands from anologWrite to ledcWrite, removed the PWM part of the sketch checked the correct pins were selected in the sketch and clicked compile. Error!
Went back through the sketch and found where I had not done the changes and it worked a bit.
I replaced the bridge between the two sets of enable pins on the L298N and it worked a bit more.

What it is currently doing is switching the motors on at full speed, but the only way to turn them off at the moment is to hit the reset button on the ESP32 or turn the power off.
That is, the on/off buttons on my device are changing status from on to off, but they do not seem to be electrically connected to turn the motors off!? Here is the code as it currently stands:

// 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 look forward to your feedback.

Thanks again Liam. Thanks for your help as well Bryce.

1 Like

Hi Gianni,

There might be a bit of a delay as there are still blocking functions in the code.
Do you still have the ESP hooked up to a computer? You should be able to see what the controller is doing at different points by using the serial monitor.

You should be able to copy the whole code by clicking in the top right of the code box and overwriting your code in the IDE.

2 Likes

Hi Gianni,

Have you used GitHub before?

It’s a completely free version management platform that’s usually used by developers working on team projects to be able to make commits for history, branches for breaking out changes and pull requests to merge all of the code back together again.

If you haven’t used it before, I wouldn’t worry about it, but putting this on a public Repo will make it much easier to edit and share issues/solutions from here rather than copying and pasting code (although this seems to be working fine for now :grinning_face_with_smiling_eyes:):

If you’d like, I can make a public repo for it for you, I’ve been making quite a few changes mainly for efficiency, but should help troubleshoot the issues for you too.

1 Like

Hi Liam, I didn’t overwrite the code because your version does not have the right pins quoted, so I didn’t want to go through it to change them. That’s why I just copied and pasted your new code.

1 Like

Thanks for your input Bryce.

I have read a couple of items in GitHub when Google searches lead me there, but I’m not “up” on it. But go right ahead and “make a public repo for it” (whatever that means) if you think it will make the process more efficient. I’m really learning as I go and the learning curve has some serious percentage inclines at the moment. I only hope my head does not do what it did to the bloke in the movie “Scanners”… lol.

1 Like