I gather that you have already seen part 1, part 2, and part 3, and are just as surprised as I am to see part 4 in a trilogy. But yes, I wanted to provide a working arrangement of moving parts so that you can see it actually doing things, and not just think it might do things. Let’s recap on the parts.
This is now assembled on a breadboard, because I haven’t printed the car parts yet. I am not sure whether to solder everything on a solder board or to use a half length board – that remains to be seen until I decide on the size of the car.
The ESP32 is powered by a USB lead from the computer now, but I will probably install a power supply module to the breadboard with a 9V battery. Then I will lead 5V from it to the ESP32 and to the power leads running down the sides of the breadboard. Currently I have 6V delivered to the power leads, and the motor is getting its power from there, but it should run fine with the 5V.
The L293D chip is able to run two DC motors. It is wired to control just one now, and I’ll go through the setup in a moment. The servo is a regular 180 degree micro servo, but the Heltec OLED isn’t able to use the same servo control libraries as other ESP32s. Therefore I run it the old-fashioned way without a library.
The Android Studio emulator can be used as the user interface here, as long as your laptop and the ESP32 are in the same WLAN. It’s actually funny to see it operate just as well as a real app will when you install it on your phone.
The L293D chip
This little thing is a nice tool when you need to run one or two DC motors. It doesn’t cost more than a couple of euros.
Its pinout is as follows, and you can see the wiring on the left side of the chip. VS is 5V in, and GND is the same ground that the ESP32 and the servo are using.
The way it works is that you connect the ESP32 to the ENABLE1 and ENABLE2 pins (if you run two motors) and the motor wires go to the OUTPUT1 and OUTPUT2 pins for motor 1 and likewise to 3 and 4 for motor 2. In the code, you select the pins you want like this (this piece of code is collected from the definitions and the Setup() function):
int motor1Pin1 = 27; int motor1Pin2 = 26; int enable1Pin = 14; // Setting PWM properties const int freq = 30000; const int pwmChannel = 0; const int resolution = 8; int dutyCycle = 200; pinMode(motor1Pin1, OUTPUT); pinMode(motor1Pin2, OUTPUT); pinMode(enable1Pin, OUTPUT); // configure LED PWM functionalitites ledcSetup(pwmChannel, freq, resolution); // attach the channel to the GPIO to be controlled ledcAttachPin(enable1Pin, pwmChannel);
Coding for the operation
The freq, pwmChannel, and resolution settings are needed for the ESP32 power management to work. The motor1Pin1 and 2 are set oppositely to high or low to decide which way to run the motor, and the enable1Pin tells the L293D how fast to run it. The function that runs both the motor and the servo is as follows:
void runMotor(int myDir, int mySpeed) { Serial.println(mySpeed); int finalSpeed; finalSpeed = map(abs(mySpeed), 0, 10, 225, 255); Serial.println(finalSpeed); Serial.println("Moving Forward"); if (mySpeed > 0) { Serial.println("Forward"); digitalWrite(motor1Pin1, HIGH); digitalWrite(motor1Pin2, LOW); } else if (mySpeed < 0) { Serial.println("Back"); digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, HIGH); } else { Serial.println("STOP"); digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, LOW); } ledcWrite(pwmChannel, finalSpeed); myTurn = map (myDir, -10, 11, 36, 180); steeringAnalogWrite(4, myTurn); // set steering }
The value of finalSpeed is derived with the neat Map function. In this function, you have the value from the user interface (-10, 10), and the speed of the motor must be 225 at speed 1 and 255 for speed 10. Therefore you can use the map function to project the speed to a new value with which to drive the motor. It has to be the absolute value, because the direction of the motor turning is set by putting motor 1pin1 HIGH and motor1pin2 to LOW to run forward.
The function steeringAnalogWrite that turns the servo to the desired angle is this:
void steeringAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 180) { // calculate duty, 8191 from 2 ^ 13 - 1 uint32_t duty = (8191 / valueMax) * min(value, valueMax); ledcWrite(channel, duty);
Wrapping up
So, in essence, here you have all the parts assembled. All of this code is now on my GitHub account, so you can download the project in its entirety. The wiring is as follows:
- Lead 6V to the power lines on the side of the breadboard. Be sure of the polarity so as not to fry your servo and cause the magick smoke to escape from the servo, hence rendering it inoperable.
- Lead the servo plus and minus to the power lines
- Lead the servo data wire to ESP32 pin 12
- Lead the L293D pin Enable1 to the ESP32 pin 14
- Lead the L293D pin Input1 to the ESP32 pin 27
- Lead the L293D pin Input2 to the ESP32 pin 26
- Lead the L293D pin Output1 to one of the the motor leads
- Lead the L293D pin Output2 to the other motor lead. If you find that the motor works in the opposite direction you expected, reverse the wires.
And there you have it. If you now make sure the ESP32 code has your WLAN data properly, and you have the laptop running Android Studio in the same WLAN, you should see the system boot up and wait for you to send it commands on the emulator, or, if you have built and installed an APK for your phone, you can use it to run the system.
If anything goes wrong, take two aspirins and call me in the morning.
Hi Sir, nice project.
and now I want to send data from esp32 to app with UDP protocol. so it’s can be bidirectional data communication. thanks…
Glad you liked it. I haven’t done two way comms, but I don’t think it is especially hard to do.