Sitemap

RC101–01 — The Foundations

7 min read8 hours ago

--

I just thought to blog the entire learning i did to make the RC car using ESP32.

Aim for the IMPOSSIBLE

Learning the Required C++ for ESP-32

Firstly I didn’t want to copy paste the code and started learning the required C++ for coding the ESP-32. Although I might not code line by line I should be able to know what is responsible for what otherwise I don’t think i really worked on this.

These are some of the few concepts I covered in the Initial hours :

Most of the classical fundamentals of the programming language this is child’s game but i just wanted to be sure i didnt miss out on anything.

Arduino Sketches and Program Structure

An Arduino program is called a sketch.

setup()
Initialization instructions are put inside the setup
and this function runs once when the esp-32 restarts or starts

we could also configure stuff like motor drivers, starting wifi, initializing the oled display here, pinMode configuration is also done here

pinMode(pinNumber, Mode);
to configure a GPIO pin
Mode -> INPUT OUTPUT

void loop()
The function that runs indefinitely through the life time of the esp-32

loop()
As discussed above it keeps repeating itself after the running of setup

Libraries

Header files like Wifi, Wire, WebServer
Wire provides the I2C functionality
and WebServer provides the web-server funcitonality

Serial Communication and Serial Monitor

Serial.begin(115200)
this is the code we write to set the baud rate same for our clean communication.

SERIAL COMMUNICATION AND SERIAL MONITOR

Serial.begin(115200) here is the baud rate of the signal and also called as the communication speed here.

Serial.print()
prints information without moving to the next line.

Serial.println()
is the method to generally print the statements on the serial monitor in our laptop from the esp-32

Serial communication can do more than just display messages onto the screen and setting the baud rate.

We can have 2 way serial communication between ESP and Computer.

Serial.available();
checks whether some thing from the computer is there or not to arrive.

Serial.read();
used to read a character from the input serial buffer.

Digital Signals, GPIO, and Pull Resistors

Digital Signals have 2 logical states HIGH and LOW.
To receive signals from the GPIO pins but the pins may pickup electric noise and produce unpredictable HIGH and LOW signals and this is called floating input using a pull up and pull down resistors avoids this issue.

digitalWrite(pinNumber, Signal)
To send a signal through the GPIO pin we use digitalWrite().
To send HIGH(3.3v) or LOW(0v) signals we use the digitalWrite

digitalRead()
helps us read the digital signals from the sensors

Switching on an LED

In simple terms we keep pinMode(18,INPUT_PULLUP); and Pullup means the signal is always HIGH and when pressed the signal become connected to the GND hence we detect this low signal here and then on the led untill we are detecting the low signal actually when we turn off the switch the internal resistor is connected between the vcc and gpio pin so it actually is working like the setup of a PULLDown right why are we giving and naming it PULLUP so the main thing to understand here comes down the base state the pin is present when the button is not pressed for example

lets take a pullup setup, the name here suggests that the base state is the internal pin is connected to 3.3v through a resistor so that the general state here is HIGH and hence the switch must be connected to the GND and when the switch is pressed the circuit ends up as the GND 0v at the GPIO pin here.

Reading Sensors

Depending on the design of the sensing element the module can give out

  • Digital Output
  • Analog Output
  • a combination of Digital and Analog Output
// READING INPUT FROM A SENSOR
int irPin = 19;
void setup(){
pinMode(irPin,INPUT);
Serial.begin(115200);
}

void loop(){
int val = digitalRead(irPin);
Serial.println(val);
delay(200);
}

/*the actual value of for the color white and black are determined only after the experimentation*/

In simple terms the digital signals are like binary states either HIGH or LOW where as the analog signals are like varying voltages.

Individually they have their own use cases being digital helps us to know the occurrence of an event and analog signals tells how much of a value for a measurement we are measuring.

ADC

Press enter or click to view image in full size

Sensors produces Analog voltages but esp-32 is a digital microcontroller.
So ADC converts the Analog value into a Digital number

Pasted image 20261101004936.png

Get Vinod Muddasu’s stories in your inbox

Join Medium for free to get updates from this writer.

So the approximate reading of the Analog sensor for the max scale are converted and approx values are mapped to the respective digital Signal here

GPIO 34–39 are input-only and do not have internal pull-up/pull-down circuitry.

Complete analog-reading code

void setup() {
Serial.begin(115200);
analogReadResolution(12);
analogSetPinAttenuation(POT_PIN, ADC_11db);
}
void loop() {
int reading = analogRead(POT_PIN);
Serial.print("Potentiometer Reading: ");
Serial.println(reading);
delay(250);
}
  • What does Attenuation mean in the above code?

The ADC has a limited measurable voltage range. Attenuation adjusts the input range to accommodate higher voltages.

PWM

If we want to control the amount of light emitted by an led or else the speed at which motor rotates we use this concept.

for example lets say a motor rotates 100 rpm at maximum for a voltage provided 3.3v but if we want the motor to rotate 50 rpm but the microcontroller cannot provide half the voltage it can only send high or low signals that is where duty cycles comes in and since we want half the maximum percentage we send high signal half the time of a cycle hence achieving the desired output.

but we cannot decide the exact rpm here also it just gives a way to handle the speed here.
PWM frequency is the number of these cycles occurs in one second.

PWM RESOLUTION is the number of different possible duty values we can have in case of a 8 bit resolution we can have 0 - 255 different types of values.

LED Control Peripheral LEDC

ledcWrite(pin, duty);

This is a sample LED PWM Configuration code

void setup(){
Serial.begin(115200);
bool status = ledcAttach(LED_PIN, 5000, 8);
if(status){
Serial.println("LED pin configured for PWM sucessfully");
}else{
Serial.println("LED pin configuration for PWM failed.");
}
}
void loop(){
ledcWrite(LED_PIN,50);
Serial.println("50 is the duty currently.");
delay(2000);
ledcWrite(LED_PIN,255);
Serial.println("255 is the duty currently.");
delay(2000);

for(int i=1; i<=255; i++){
ledcWrite(LED_PIN,i);
delay(10);
}
for(int i=255; i>=0; i--){
ledcWrite(LED_PIN,i);
delay(10);
}
}

Combining Analog Input with PWM Output

Press enter or click to view image in full size

Here lets try to understand the map function since we are mapping values from 0 to 4095 onto 0 to 255 :

map(sensorValue, fromLow, fromHigh, toLow, toHigh);

and this performs a linear conversion.
if we want the converted value within a range we can use constrain :

constrain(value, minimum, maximum);

hence, minimum <= value <= maximum is the range.

int POT_PIN = 34;
void setup(){
Serial.begin(115200);
analogReadResolution(12);
analogSetPinAttenuation(POT_PIN,ADC_11db);
ledcAttach(LED_PIN,5000,8);
}
void loop(){
int sensorValue = analogRead(POT_PIN);
int brightness = map(sensorValue,0,4095,0,255);
brightness = constrain(brightness,0,255);
ledcWrite(LED_PIN,brightness);
Serial.print("Sensor: ");
Serial.print(sensorValue);
Serial.print(" | Brightness: ");
Serial.print(brightness);
delay(100);
}

Delay and Non-Blocking Timing with millis()

DELAY

delay(time in ms) stops the execution of the entire program for the time specified but this might be not the best approach when working with real time robots since we might miss out on the events.
the alternative we use

millis();

this function returns the number of milliseconds elapsed since the start of the program.
we can use this to schedule some functions without stopping the execution of the entire program.
a sample program using millis to understand it in a better way.

const int interval = 1000;
int previousTime = 0;
bool ledState = false;

void setup(){
Serial.begin(115200);
pinMode(LED_PIN,OUTPUT);
}
void loop(){
unsigned long currentTime = millis();
if(currentTime-previousTime >= interval){
previousTime = currentTime;
ledState = !ledState;
digitalWrite(LED_PIN,ledState);
}
}

this switches the led state when the time gap reaches 1s without using any delay

ESP-32 Hardware and Pin Considerations

Some of the sensor modules like HC-SR04 ultrasonic sensor commonly operates at 5v and echos a 5v signal but the GPIO logic of the esp-32 board works at 3.3v helps we need to use a suitable voltage divider or logic level shifter before connecting to the pin directly.

the pins on the esp-32 are mostly configured for special purposes each hence refer a valid source before connecting any GPIO pin on the board.

ADC Pin Selection When Using Wi-Fi

On ESP-32 there are 2 groups of ADC pins ADC1 and ADC2 generally ADC2 impose restrictions when working along with wifi.

GPIO 34 is an ADC1 input on the classic ESP32.

Learning Map

| Component | Programming Concept | Arduino Function / Technique |
|---|---|---|
| ESP32 | Program execution | `setup()`, `loop()` |
| LED | Digital output | `pinMode()`, `digitalWrite()` |
| Push Button | Digital input | `digitalRead()` |
| Digital IR Sensor | Digital input | `digitalRead()` |
| Analog UV Sensor | Analog input | `analogRead()` |
| Motor Driver | PWM and digital output | `ledcAttach()`, `ledcWrite()`, `digitalWrite()` |
| OLED Display | Communication | `Wire.h` and display libraries |
| Wi-Fi Dashboard | Network communication | `WiFi.h`, `WebServer.h` |

END NOTE

These are just some of the basics which are like the prerequisities for any electronic projects one might work on using micro — controllers.

--

--