ESP32-CAM is a camera module based on ESP32. It comes with an OV2640 2 MP camera and provides onboard SD memory card slot.
It is suitable for home smart devices, wireless monitoring, and other IoT applications.
ESP32 CAM module has on board PSRAM.
The OV2640 camera module on the ESP32 Camera board can support a max resolution of 1600 x 1200 pixels, however without PSRAM the camera frame buffer can only support a max resolution of 800×600 pixels
Boards with PSRAM (typically 4MB) can support the max resolution and also support 2 concurrent frame buffers. This provides for a better streaming experience as while one frame is being sent , the camera is working on capturing the next frame.
Always Power up the module using 5V .Powering the board with 5V increases stability .
The camera module has no USB input.So we need a FTDI programmer or USB-TTL module to upload program.In this testing we make use of an USB-TTL module built on CP2102 IC.
Connection between ESP CAM & USB-TTL is simple.
We make use of the 5v power from USB module itself.
Gnd is connected to Gnd pin of Camera module.
Rx of USB module to Tx (printed as UOT) of Camera module.
Tx of USB module to Rx (printed as UOR) of ESP CAM.
Do not use 3.3 V AS POWER SOURCE .
For PROGRAM Mode the GPIO0 pin must be connected to GND.
Plug in the USB-TTL module to PC and note the COM port allotted under Device Manager.
To use Arduino IDE for programming , we need to install the ESP32 boards Manager for Arduino.
From Arduino IDE open File—> Preferences
Copy and paste the following json link for additional Boards Manager :
ULTRASONIC sensor is popular in many applications where measuring distance or sensing objects are required.
The module has two eyes in the front which forms the Ultrasonic transmitter and Receiver.
1.Vcc The Vcc pin powers the sensor, typically with +5V,The current consumed by the sensor is less than 15mA
2.Trigger
Trigger pin is an Input pin. This pin has to be kept high for 10us to initialize measurement by sending Ultrasonic burst of 40KHz.
3.Echo
Echo pin is an Output pin. This pin goes high for a period of time which will be equal to the time taken for the US wave to return back from object to the sensor.
4.Ground
To start the measurement, the trigger pin has to be made high for 10uS and then turned off.
This action will trigger an ultrasonic wave at frequency of 40Hz from the transmitter and the receiver will wait for the wave to return.
Once the wave is returned after it getting reflected by any object the Echo pin goes high for a particular amount of time which will be equal to the time taken for the wave to return back to the sensor.
The amount of time during which the Echo pin stays high is measured by the esp32 as it gives the information about the time taken for the wave to return back to the Sensor. Using this information the distance is measured
As the ultrasonic sensor requires 5v , we use a separate power source.
This sensor will not operate on 3.3v.
Vcc –> 5v
Gnd to Gnd
Trigger –> GPIO 5
Echo –> GPIO 18
Both Gnd of 3.3v & that of 5v to be made common.
As the ECHO PIN of ultrasonic gives 5v level , we need a LEVEL SHIFTER in between ECHO & GPIO18
OLED connections :
Vcc to 3.3v
Gnd – Gnd
SCL –> GPIO 22
SDA –> GPIO 21
We use THONNY PYTHON to test and upload code.
2 library modules are required.
One ssd1306.py for OLED
hcsr04.py module for ultrasonic measurement support.
Pulse width modulation is used in a variety of applications particularly for control. It can be used for the dimming of LEDs, varying speed of motors and controlling the angle of servo motors
In ESP32 PWM can be initiated on all output-enabled pins.
PWM is digital, which means that it has two states: on and off.The amount of current that flows to a device like LED can be controlled by varying the time each pulse stays ON.
The longer each pulse is on, the brighter the LED will be.
DUTY CYCLE refers the amount of time the pulse is ON.
For a square wave the DUTY cycle is 50 % , the pulse is ON for 50% of the time and OFF for 50%
If duty cycle is 100% then the output is equal to Vcc ( 3.3v here) and LED will be full lit.
If duty cycle is 0% , the signal is flat and equal to Gnd voltage 0.
Connect an LED at GPIO 15.
Short lead of LED goes to Gnd through a Resistor 1k.
We shall use THONNY PYTHON IDE to test and upload python code on to ESP32.
Refer to my previous blog on how to use Thonny Python
Let us use the interpreter of Thonny Python to test the code.
First import from machine module the Pin & PWM classes.
Pin module is to control the GPIO pins.
Then create a PWM object called led and pass on the GPIO Pin 15.
Once the led object is created you can use the methods like duty to set the duty cycle and freq to set the frequency.
Duty cycle can be from 0 to 1023.
512 represents 50% , and 1023 = 100%. duty cycle.
led.freq(1) makes the LED flash once per second.
You can create the PWM object and pass on the duty,freq in a single line of code.
To stop PWM use the method deinit().
Now let us give the LED a fade effect using PWM.
Micropython executes boot.py file on power on.
Then it looks out for main.py file to execute.
In case you need your own naming for file , then create that file and import the module and place a call for the function inside main.py.
Though boot.py file has nothing to execute inside , this file exists by default in Micropython.
Inside main.py file
import fadeled
fadeled.ledpwm()
fadeled is the module we have to create
& ledpwm() is the function in that module.
Without creating this new module we could have named the file as main.py and write the complete code inside main.py
In the never ending loop while True: , we change the duty cycle from 0 to 1023
using in range function.
This gives a fading effect on LED.
Note the indentation after each colon : in python code.
This space or indentation represents braces.
Click on File –> Save as
and select Micropython device to save.
Save the file as fadeled.py
Like this save the main.py file also to ESP32.
Now click on F5 or the green arrow button on top to execute.
You can see the LED fading effect.
The PWM method can be used to position the SERVO motor from 0 to 180 degrees.
All servo motors have 3 wires.Red to 5v, Black or Brown to Gnd
Orange wire is Signal (pwm)
Connect the Servo signal pin at GPIO 23.
As servo requires 5V we use an external power source of 5 Volt.
The Gnd of 5V source and the Gnd of ESP 32 must be made common i.e connected together.This is a must while using 2 different power sources.
Frequency (1/period) is specific to controlling a servo.
A typical servo motor expects to be updated every 20 ms with a pulse between 1 ms and 2 ms, or in other words, between a 5 and 10% duty cycle on a 50 Hz waveform.
So frequency of 50 hz is a must to control most Servos .This gives a 20 msec pulse.
With a 1.5 ms pulse, the servo motor will be at the natural 90 degree position. With a 1 ms pulse, the servo will be at the 0 degree position, and with a 2 ms pulse, the servo will be at 180 degrees.
Duty cycle from 20 to 120 facilitates position of servo fro 0 to 180 degrees.
servo object is created by passing on PWM Pin as GPIO 23 and frequency as 50
1/50hz = 0.02 = 20 msec which is required to update most servos.
We set the duty cycle to 20 to position servo at 9 degree.
Normally in a Home Network we have a Router which is connected to Internet Service Provider.
This Router can be Ethernet capable, wireless capable or both.Nowadays mostly Routers are WIFI enabled.Over WIFI you can connect your laptop,mobile or ESP32 to the Router to get internet access.
In this scenario the ROUTER acts as ACCESS POINT & the devices that connect to it act as CLIENTS.
In Micropython CLIENT is also called as STATION.
When a Client/Station connects with the Router , the Router provides an IP address to the device connected.
Suppose the IP of Router is 192.168.0.1 which is also called as GATEWAY IP (this IP is printed on the back of Router) , the Clients will be given IP in the range 192.168.0.xxx .
The last octet only will change on first come first basis.That means the IP offered by DHCP method is DYNAMIC which changes on next power on.
To make it STATIC you can open the Gateway IP on a browser to set up configuration of Router.Here you can note the MAC address of the CLIENT and set the IP to static , so that it will be always offered the same IP on every power ON.
In the second scenario STATION INTERFACE
the ESP32 device can act as ACCESS POINT instead of Router & other devices like mobile or ESP modules can connect with it over WI FI.
In this post we shall explore the ways by which ESP32 acts as a CLIENT/STATION and connect with an ACCESS POINT like Router over WIFI automatically on Power ON.
For Micropython IDE we use THONNY PYTHON
Refer my previous post on getting started with Thonny python
This interface can be managed using the network module from MicroPython.
First import the network module.
Then create an object that represents this interface:
Create a WLAN network interface object. One of the Supported interfaces are
network.STA_IF (station or client, connects to upstream WiFi access points)
Make that network interface active.
Scan for the available wireless networks using
station.scan()
Scanning is only possible on STA interface. Returns list of tuples with the information about surrounding WiFi access points:
The tuples returned here have the parameters of each available Wi-Fi connection. In particular, the first element in each tuple is the SSID name, the third element is the channel number, and the fourth is the RSSI or signal strength indicator.
(ssid, bssid, channel, RSSI, authmode, hidden)
ssid is the service set identifier
bssid is hardware address of an access point, in binary form, returned as bytes object. You can use ubinascii.hexlify() to convert it to ASCII form.
RSSI signal strength in negative value
There are five values for authmode: 0- open ,1 –WEP , 2 –WPA-PSK , 3- WPA2-PSK ,4 WPA/WPA2-PSK
and two for hidden: 0 (false)-VISIBLE, 1- HIDDEN
You can check the connection using method isconnected()
As we have not yet connected it returns FALSE.
Connect to WI FI using your SSID name and its password.
ifconfig() method returns the parameters of the connection
IP Address allotted along with Subnet mask,Gateway IP & DNS Server
As we have tested the connection using Micropython Interpreter , we can implement auto connection to WIFI as follows :
Micropython executes
boot.py
on power up first.Then it looks out for
main.py
Under Thonny python IDE click File –> New
This file we shall save as boot.py
For intimation we shall include only a print statement
print(‘RUN : boot.py’)
Click on File –> Save As
You get 2 options 1. to store on your computer for later modification
2. On the Micropython device (ESP32) directly.
Provide the file name as boot.py and save it on MicroPython device.
Again File –> New
to create the second file main.py
Here we import module ConnectWifi & call the function connect()
The module & function have to be created by us.
For now save it on ESP32 as file main.py.
Remember not to change the file name, as Micropython will look to execute only main.py automatically.
Finally we have to create the file ConnectWifi.py
and create the function connect()
In this function replace the ssid,password with that of yours.
ESP32 is a powerful device for IOT development with WIFI & Bluetooth.Compared to NodeMCU it has more ADC pins , DAC & much more.
ESP32 can be programmed by many ways including Arduino core.
This post is on programming ESP32 using MICROPYTHON.
MicroPython is a lean and fast implementation of the Python 3 programming language that is optimised to run on a microcontroller.
MicroPython has advantages over traditional programming software such as C/C++ because it is essentially a live development environment and you write and debug code much faster…in fact 5-10 times faster than C++.
when a device boots up using MicroPython it does not consume much memory and thus doesn’t incur current drain.Micropython also has a number of Micropython specific libraries for accessing hardware level features.
Adafruit also introduced CircuitPython ,Soon after MicroPython started picking up the pace. However, CircuitPython offers support for the Adafruit range of hardware only.
Python allows for rapid feedback. This is because you can interactively enter commands and get a response using the REPL –read–eval–print loop. You could even tweak your code and run it right away, rather than iterating through code-compile-upload-execute cycles.
This post is on implementing MICROPYTHON on ESP32.
As a programming environment , many IDE s are available , of which THONNY IDE is simple & powerful.
Thonny IDE : An integrated development environment (IDE– Integrated Development Environment) for Python that is designed for beginners. It stands out for its simplicity of installation and use, ease of writing and debugging of code, possibility of incorporating plugins and its good documentation.
uPyCraft IDE : It is anIDE specifically oriented for MicroPython, which makes it one of the besteditorsfor this use. It allows you to upload the MicroPython firmware to the microcontroller in a very simple way (as an alternative toesptool.py)
Visual Studio Code (VSCode) , using the PyMakr extension: It is avery sophisticatedIDE , which supports many practical functionalities working with code, but is only recommended for advanced users
PYCHARM is for advanced users.There is community edition for free.There’s a PyCharm plugin that adds MicroPython support to your IDE. It’s available right in the plugin marketplace
visit https://thonny.org/ & download the installer relevant for you (available for Windows,Mac & Linux)
Install THONNY IDE by double clicking the downloaded installer.
Open THONNY IDE .
The top portion is the EDITOR where you write your Micropython code.
Bottom is the SHELL.
As we’ve not yet installed Micropython interpreter, the Shell displays the default Python prompt.
‘>>>’ is the prompt of the interactive Python interpreter, meaning that the interpreter is ready to get Python statements typed in.
The PROMPT Is called CHEVRONS.
To get the Micropython prompt, click on Tools –> Options
Under options window click on INTERPRETER.
Under first drop down menu select MICROPYTHON (ESP32)
Under Port , select the port number where ESP32 is connected.
Click on Firmware install bar.
r
Micropython firmware .bin file can be downloaded from
We can see this listing in Thonny using the function help(machine).
To control an LED on / off, the following must be done:
First, the Pin class of the machine module is imported , which allows controlling the inputs / outputs (General Purpose Input / Output – GPIO -) of the microcontroller – and therefore, of its corresponding pins on the board. Since pin 02 ( GPIO 02 ) is connected to the integrated LED, you also have control over it.
Then an object that we will call pin_02 is initialized to identify it, turning GPIO 02 “2” into an output pin “ Pin.OUT ”.
Among the classes of the module, the class
Pin()
is used to create objects to control inputs / outputs of the microcontroller ( GPIO ), which will help us to turn on /off the LED.
Additionally, if we ask for information about the classPin() we can see that it has 5 methods – Pin.init (), Pin.value (), Pin.off (), Pin.on () and Pin.irq () – :
In order to use this class , we need to know how your constructor and its methods work .
The constructor is the subroutine whose mission is to initialize the object . The constructor of the Pin class is:
class machine.Pin (id, mode, pull, *, alt)
The arguments of the constructor are:
The arguments to turn on the blue LED integrated in the ESP32 DEVKIT board will be the following:
id “ 2 ” since the on board LED is connected with pin 02 ( GPIO 02 ).
mode “ Pin.OUT ” to make pin 02 become a voltage output pin .
pull “ None ” to not configure pull-up or pull-down resistors (they are only useful in the case of being an input pin – Pin.IN -). It is not necessary to define this argument.
value “ 1 ” to turn on the LED-3.3V voltage output.
Once the code has been executed, we will have initialized an object , which has been assigned the name pin_02 , whose initial values convert pin 2 (GPIO 02) into an output pin and its status is on (3.3V voltage) .
The methods that we can use once the object is created allow us to manipulate (modify) its functionalities . In the Pin class we have the following:
Pin.init () : Modify theinitial arguments of the constructor . You can modify the mode , pull , * (value) and altargumentswhen new values are defined.
Pin.value () : allows you to read the presence / absence of input voltage of the pin (without an argument is provided) or set an output voltage on the pin providing the argument. The arguments can be “ 0 ” off (0.0V) and “ 1 ” on (3.3V). Booleans can be usedas arguments.
Pin.off () : Sets a pin output voltage of 0.0V- off.
Pin.on () : sets an output voltage of the 3.3V pin – on -.
Pin.irq () : enables external interruptions in the pin , as long as it is an input pin .
Put together
First from machine module import the class Pin.
Then assign the built in LED GPIO pin 2 & declare it as Pin.OUT
The pin that is connected to the led is instantiated & the second argument is set as OUT ,indicating
that the pin acts as OUTPUT.
t
Now led.value(1) makes the on board LED ON.
led.value ( 0) makes it OFF.
We have controlled the LED from Interpreter. Now we shall write the complete code in the EDITOR Section to blink the LED repeatedly.
Here we make use of the sleep class of time function to introduce delay.
Never ending loop is created using
while True:
Notice the loop starts by colon : & instead of braces micropython uses indentation.
Click File –> Save as
& select Micropython device
Provide the file name as main.py
You can notice , by default already boot.py is available on device.
Micropython will first execute boot.by & then looks out to execute file named main.py.
So you cannot upload file in other name to execute.If you use some other name , then the file will be executed once.After power reboot it will not execute.
Once the file is stored click on F5 or the Run green button.
The script is uploaded and the on board LED blinks.
To stop execution you can press the STOP Red button.
Now the chevrons >>> appear at the shell.
You can write new code & save it to device , again in the name main.py.
In the previous post we have seen the installation of PLATFORM IO on VS CODE.
While connecting the ESP32 to PC the PLATFORM IO detects AND ASSIGNS the COM port automatically.
To see the COM port click on DEVICES icon.
Refresh button can be pressed if new connection is made.
If more than one COM port is listed , then you can select the COM port manually.
In this demo ,I ‘ve connected another USB-TTL device with CP2102. To another USB port ESP32
is connected.
Click the Refresh button under DEVICES to view all the COM Ports.Here COM5 is allotted to ESP32 &
COM21 to USB-TTL device.
TO SELECT COM port 5 Manually, open the platform.ino file.
Add this line at the end.
upload_port=COM5
Save & upload code to see COM port 5 selected & used.
Now let us see the solution for the error we encountered in previous post.
Under Arduino.h we received a Squiggle red line indicating error & Intellisense regarding Arduino core was not effective. Arduino.h file was not recognized.
If you move the cursor over the Squiggles you see a balloon.Clicking on this shows some solution for the problem.But this was not successful.
Finally I got the solution from Plaform IO forum.
Just DELETE the folder .vscode under Explorer.
Right click .vscode folder & just DELETE it.
Now close the VS code & restart again .
The Squiggles are gone & new .vscode folder is automatically created.
Now Intellisense regarding Arduino.h is working Fine
Select the version 2.7.xx to install & not the 3.7.xx version.
2.7 version best supports Platform IO.
While installing Python , ensure that you enable ADD PYTHON.EXE to PATH & entire feature is installed on your local hard drive.
Finish the PYTHON installation & start with VS CODE installation.
Ensure to tick mark ADD TO PATH during installation.
Once the installation is over , click FINISH to launch VS CODE.
A dark IDE APPEARS after a while.
TO the left side of IDE you see a list of control Icons.
Click on EXTENSIONS ICON to visit the market place add on s.
A new search bar appears , where you type in PLATFORM IDE.
Select the PLATFORM IDE & click on the green INSTALL button.
Installation takes a while & finally the PLATFORM IO ICON appears.
The first initialization requires Internet connection and may take a while(need to install dependent toolchains, frameworks, SDKs).
At the bottom of IDE PLATFORM IO control Icons appear.
If you prefer a light skin , go to File –> Preferences & click on Color Theme.
From the list of Skins you can select a light skin .
You need to click on Platform IO Home button for the new skin to be effective.
At the center of IDE you can see some PLATFORM IO icons to add Libraries , Boards , Platforms& Devices
Under QUICK ACCESS list click on + New Project to create a new one.
You can also click on Project examples or Import Project to download one.
Provide a name to the project.
Against Board , search for ESP32 & select the correct board you’re using.Mine is DO IT ESP32 DEVKIT V1.
Against Framework select ARDUINO.
Click OK to create the Project.
Now under the left side Explorer window , the new Project (led_blink) appears
Locate the folder src , under which you find main.cpp file.
Click on it.
Here is where you write your code.
The code starts with #include <Arduino.h>
If you find a squiggle under line beneath it , then the path to header file is not defined.
The solution to this problem is explained in next post.
For now, proceed with the code.The squiggle indicates error & Intellisense regrading Arduino core will not show up.But you can complete typing the code & upload.Everything else works fine.
Let us blink the inbuilt LED on board ESP32 which is mapped to GPIO2.
While typing the code you can see the Code completion in action , which is handy while working on big projects.You need not remember the variables & functions declared.
Click on the tick mark at the bottom row of icons to Build or Compile the code.
Or you can directly click on ARROW button to upload the code.
While Upload is in progress PRESS & HOLD the BOOT button on ESP32 .
Once the code is uploaded , you can see the on board Blue LED blinking.
Now let us explore the Serial monitor capability of the IDE.
Under setup() add
Serial.begin(9600);
The default baud rate is 9600.
Under loop() function Serial.println the message LED ON or LED off.
Upload the code & then click on the PLUG symbol seen at the bottom row of Icons.
Now the Serial monitor opens displaying the LED ON OFF message/
To change the BAUD RATE , click on platformio.ini file under project files.
At the right side you see the platform,board & framework setting we selected while creating the project.
At the bottom add this line
monitor_speed=115200
where 115200 is the new Baud rate.
Now save the file & upload.
Open the Serial monitor (PLUG symbol) to see some garbage message printed.This is because the IDE Serial monitor baud rate has been changed to 115200, but in code we have initiated
Serial.begin(9600);
Click on main.cpp & replace 9600 with 115200.
Save the file & upload again.
Open the Serial monitor to see the LED ON OFF message with new baud rate 115200..
In this post we shall see how PWM is implemented on ESP32 & used to fade an LED or control speed of a motor.
In Arduino or ESP8266 Nodemcu we used the analogWrite() function to achieve PWM.
But Analog Write function is not yet implemented in ESP32 Arduino version.
Instead a new Function called ledcWrite() is introduced.
As the analogWrite() function is not yet available for the ESP32 , we will need to go to lower level functions.We will also have more control and flexibility in the PWM functionality, which is good.
In this example let us fade the inbuilt LED onboard. It is mapped to GPIO2 pin.
We declare some variables to start with. GPIO2 pin is assigned to a byte variable led_pin as 2.
2 more integer variables used to store brightness & fadevalue.
Inside SETUP first thing is , we need to attach a channel ( channels available from 0 to 15) to a GPIO pin where we want the PWM signal to be generated.
Any GPIO pin can be used , but certain pins which are only INPUTS like GPIO 14,15,16 & 19 CANNOT BE ATTACHED.
GPIO OUTPUT capable pins can only be attached. The function used here is
ledcAttachpin(gpio_pin,channel)
In this example, we’ll get the signal in the led_Pin GPIO, that corresponds to GPIO 2 ( inbuilt LED). The channel that generates the signal is the ledChannel, that we assign to channel 0. There are 16 PWM channels from 0 to 15 in ESP32 & one of them is attached to a GPIO pin.
Next , PWM characteristics are then defined using function
ledSetup()
e.g ledSetup(0,12000,8);
Here the first parameter is the channel number (channel 0 is used here)
2nd parameter is the PWM Frequency ,here it is 5000 ( 5kHz) which is idle to fade an LED
3rd parameter is resolution in bits .Upto 16 bits accepted. Here we use 8 bits , so the maximum analog value is 255 ( 0 to 255 = 256)
We’ll use 8-bit resolution, which means you can control the LED brightness using a value from 0 to 255.
Finally, to control the LED brightness using PWM, you use the following function:
ledcWrite(channel, dutycycle)
This function accepts 2 arguments a channel number & an analog value (duty cycle)
Note that we use the channel that is generating the signal, and not the GPIO
Although the duty cycle is specified as a percentage, this function receives a value between 0 and another value different from 100.We can pass a value between 0 (wave always with a value of GND) and 1023 (wave always with a value of VCC for 8 bit resolution) for the duty cycle.
Inside the loop we vary the duty cycle from 0 to 255 to increase brightness of LED gradually & when it reaches vaLue 255 , we decrease it thus fading down the LED.
Now upload the code.Press & Hold the Boot button for a smooth upload.
Once code is uploaded , you can see the inbuilt blue LED fading.
In the second example let us add a potentiometer ( 10k value) to GPIO4.
One end of pot is connected to +3.3v , the other end to GND.
Center pin of pot is connected to GPIO4.
LED connected to GPIO15 is faded according to pot variation.
Inside loop() function we use the ledcWrite() function , so that according to pot variation LED brightness varies.
With the same code uploaded , we can control the speed of a motor.
Potentiometer is connected to GPIO 4 as in 2nd example.
To control a motor we need L293 driver board.As the motor used is a BO motor of 6v we need a separate power source for L293. A 6v battery is used for L293 Board.
L293 board can control 2 DC motors & it sources 500ma current.For control of each motor 2 set of control pins are provided.
IN1,IN2,EN1 for 1st motor & IN2,IN3,EN2 for second motor.In this example we use only one motor.So the first set of control pins are used.
For forward control of motor IN1 is connected to LOW , 0 , & IN2 is connected to HIGH (1) .
A built in 5v regulator is on board L293. This 5v pin can be used as HIGH & GND pin is used as LOW.
Ensure that GND pin of L293, Negative of 6v battery & GND pin of ESP32 all are made common & connected together.
EN1 is the enable pin which can also be used by PWM to control speed.If this pin is pulled High , then the motor will rotate at fixed speed.To vary speed we connect this EN1 pin to PWM pin of ESP32
, which is GPIO15 in our example.
Now you can vary the potentiometer & control the speed of motor.