Hi,
I’m attempting to connect one gear motor and one servo motor to an ESP32 DEVKIT V1 DOIT board. I am using the L298N Motor Driver, using one side only. I have connected a battery pack (~6 volt battery total) to the 12 Volt connector on the Driver. I left the jumper in place and so the driver should be running on the battery.
I am using the RandomNerd motor tutorial code for the motor. I have the tied the ESP32 ground pin, motor ground wire and the servo ground wire together at the driver.
Here is the pertinent servo code and its placement into the tutorial script:
if (header.indexOf("GET /forward") >= 0) { Serial.println("Forward"); //forward button pressd digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, HIGH); myservo.write(0); // tell servo to go to position 0 delay(15); // waits 15ms for the servo to reach the position
The motor behaves as expected only when I exclude the: myservo.attach(servoPin); code in the Setup. When the code is included the motor hums but the servo responds.
Summary: I can get either device to work but not together, What am I doing wrong.
Thanks in advance
Mike
Hi.
What pin are you using to connect the servo?
Do you use any PWM signal to control the dc motor speed?
If both use the same PWM channel, you may have unexpected results.
If you canprovide more details about your project, maybe I can help you better.
Regards,
Sara
Thank you Sara for your quick response. I am using pin 13 as the signal input to the servo. I hadn’t thought about a PWM channel for the servo. Here is the code I attempted to use – Thanks again:
/*********
Rui Santos
Complete project details at http://randomnerdtutorials.com
*********/
// Load Wi-Fi library
#include <WiFi.h>
#include <Servo.h>
Servo myservo; // create servo object to control a servo
static const int servoPin = 13;
// Replace with your network credentials
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Motor 1
int motor1Pin1 = 27;
int motor1Pin2 = 26;
int enable1Pin = 14;
// Motor 2
int motor2Pin1 = 33;
int motor2Pin2 = 25;
int enable2Pin = 32;
// Setting PWM properties
const int freq = 30000;
/*The const keyword stands for constant.
It is a variable qualifier that modifies the behavior of the variable,
making a variable “read-only”. This means that the variable can be used
just as any other variable of its type, but its value cannot be changed
For an LED, a frequency of 5000 Hz is fine to use*/
const int pwmChannel = 0;
/*choose a PWM channel. There are 16 channels from 0 to 15. */
const int resolution = 8;
/*from 1 to 16 bits*/
int dutyCycle = 0;
// Decode HTTP GET value
String valueString = String(5);
int pos1 = 0;
int pos2 = 0;
void setup() { //The setup() function only runs once when your ESP first boots.
Serial.begin(115200);
/* SUMMARY OF MOTOR DECLARIATIONS IN SETUP
1. pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);
2. ledcSetup(pwmChannel, freq, resolution)
3. ledcAttachPin(enable2Pin, pwmChannel)
4. ledcWrite(pwmChannel, dutyCycle)*/
Serial.println (“new_motor_driver code”); //*****IMPORTANT TO ESTABLISH WHAT CODE VERSION IS BEING RUN***************
// Set the Motor pins as outputs
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);
// Configure PWM channel functionalitites ***FUNCTION DEFINED***
ledcSetup(pwmChannel, freq, resolution); //***MOTOR DRIVE FUNCTION*****
// Attach the PWM channel 0 to the enable pins which are the GPIOs to be controlled
ledcAttachPin(enable1Pin, pwmChannel);
ledcAttachPin(enable2Pin, pwmChannel); //enablePin, int enable2Pin = 32; defined in VARIABLES section
// Produce a PWM signal to both enable pins with a duty cycle 0
ledcWrite(pwmChannel, dutyCycle);
// Connect to Wi-Fi network with SSID and password
Serial.print(“new_motor_driver_REV_FIRST_WITH_TEMP_SERVO”);
Serial.print(“Connecting to “);
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(“.”);
}
// Print local IP address and start web server
Serial.println(“”);
Serial.println(“WiFi connected.”);
Serial.println(“IP address: “);
Serial.println(WiFi.localIP());
server.begin();
myservo.attach(servoPin);
myservo.write(90); // tell servo to go to INITIAL FORWARD POSITION
delay(15); // waits 15ms for the servo to reach the position
Serial.println(“RUDDER IN FORWARD POSITION”); //PROVIDES AN INDICATON THAT THE MOTOR HAS BEEN ASKED TO RUN AFTER THE BROWSER COMMAND
}
void loop(){ //****************continuing to look for laptop input*****************
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();
// Controls the motor pins according to the button pressed
if (header.indexOf(“GET /forward”) >= 0) {
Serial.println(“Forward”); //forward button pressd
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
myservo.write(0); // tell servo to go to position in variable ‘0 position’
delay(15); // waits 15ms for the servo to reach the position
Serial.println(“motorPin2 is high”); //PROVIDES AN INDICATON THAT THE MOTOR HAS BEEN ASKED TO RUN AFTER THE BROWSER COMMAND
} else if (header.indexOf(“GET /left”) >= 0) {
Serial.println(“Left”); //left button pressd
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
myservo.write(90); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
} else if (header.indexOf(“GET /stop”) >= 0) {
Serial.println(“Stop”); //stop button pressd
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, LOW);
myservo.write(0); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
} else if (header.indexOf(“GET /right”) >= 0) {
Serial.println(“Right”); //right button pressd=
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, LOW);
myservo.write(180); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
} else if (header.indexOf(“GET /reverse”) >= 0) {
Serial.println(“Reverse”); //reverse button pressd
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
myservo.write(0); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
}
// 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 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 { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-color: #4CAF50;”);
client.println(“border: none; color: white; padding: 12px 28px; text-decoration: none; font-size: 26px; margin: 1px; cursor: pointer;}”);
client.println(“.button2 {background-color: #555555;}</style>”);
client.println(“<script src=\”https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\”></script></head>”);
// Web Page
client.println(“<p><button class=\”button\” onclick=\”moveForward()\”>FORWARD</button></p>”);
client.println(“<div style=\”clear: both;\”><p><button class=\”button\” onclick=\”moveLeft()\”>LEFT </button>”);
client.println(“<button class=\”button button2\” onclick=\”stopRobot()\”>STOP</button>”);
client.println(“<button class=\”button\” onclick=\”moveRight()\”>RIGHT</button></p></div>”);
client.println(“<p><button class=\”button\” onclick=\”moveReverse()\”>REVERSE</button></p>”);
client.println(“<p>Motor Speed: <span id=\”motorSpeed\”></span></p>”);
client.println(“<input type=\”range\” min=\”0\” max=\”100\” step=\”25\” id=\”motorSlider\” onchange=\”motorSpeed(this.value)\” value=\”” + valueString + “\”/>”);
client.println(“<script>$.ajaxSetup({timeout:1000});”);
client.println(“function moveForward() { $.get(\”/forward\”); {Connection: close};}”);
client.println(“function moveLeft() { $.get(\”/left\”); {Connection: close};}”);
client.println(“function stopRobot() {$.get(\”/stop\”); {Connection: close};}”);
client.println(“function moveRight() { $.get(\”/right\”); {Connection: close};}”);
client.println(“function moveReverse() { $.get(\”/reverse\”); {Connection: close};}”);
client.println(“var slider = document.getElementById(\”motorSlider\”);”);
client.println(“var motorP = document.getElementById(\”motorSpeed\”); motorP.innerHTML = slider.value;”);
client.println(“slider.oninput = function() { slider.value = this.value; motorP.innerHTML = this.value; }”);
client.println(“function motorSpeed(pos) { $.get(\”/?value=\” + pos + \”&\”); {Connection: close};}</script>”);
client.println(“</html>”);
/*Request example: GET /?value=100& HTTP/1.1 –
sets PWM duty cycle to 100% = 255*/
if(header.indexOf(“GET /?value=”)>=0) {
/* SLIDER INPUTS
Description
Locates a character or String within another String. By default,
searches from the beginning of the String, but can also start from
a given index, allowing for the locating of all instances of the
character or String.
Syntax
myString.indexOf(val)
myString.indexOf(val, from)
Parameters
myString: a variable of type String.
val: the value to search for. Allowed data types: char, String.
from: the index to start the search from.*/
pos1 = header.indexOf(‘=’); //client.println(“function motorSpeed(pos) { $.get(\”/?value=\” + pos + \”&\”); {Connection: close};}</script>”);
pos2 = header.indexOf(‘&’); //client.println(“function motorSpeed(pos) { $.get(\”/?value=\” + pos + \”&\”); {Connection: close};}</script>”);
valueString = header.substring(pos1+1, pos2); //the previous functions provide the valueString range
Serial.println (“after Get – pos1=”);
Serial.println (pos1);
Serial.println (“after Get – pos2=”);
Serial.println (pos2);
Serial.println (“after GET – valueString=”);
Serial.println (valueString);
Serial.println (“******”);
if (valueString == “0”) {
Serial.println (“valueString (slider position) found to be 0 and here is the value=”);
Serial.println (valueString);
Serial.println (“******”);
/*Set motor speed value, check, if zero than true and make motorPins low
and duty cyle 0*/
ledcWrite(pwmChannel, 0);
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, LOW);
}
else {
dutyCycle = map(valueString.toInt(), 25, 100, 200, 255);
ledcWrite(pwmChannel, dutyCycle);
Serial.println (“dutyCycle when motor speed is not 0 =”);
Serial.println(dutyCycle);
Serial.println (“when motor speed is not 0 =”);
Serial.println(“pwmChannel=”);
Serial.println(pwmChannel);
Serial.println (“valueString (slider position) found NOT TO BE 0 and here is the value=”);
Serial.println (valueString);
Serial.println (“******”);
}
}
// 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 //B
currentLine = “”;
} //B
} else if (c != ‘\r’) { // if you got anything else but a carriage return character, //A
currentLine += c; // add it to the end of the currentLine
} //A
}
}
// Clear the header variable
header = “”;
// Close the connection
client.stop();
Serial.println(“Client disconnected.”);
Serial.println(“”);
}
}
Hi.
The servo library uses PWM to control the servo motor.
The DC motor is also being controlled with PWM.
What may be happening is they are not going well with each other because they might be using the same PWM channel.
So, I would suggest that you use a different PWM channel for the DC motor.
For example, channel 2:
const int pwmChannel = 2;
I hope this helps.
Regards,
Sara