Micro All Notes WithCodeSem2
Micro All Notes WithCodeSem2
Micro All Notes WithCodeSem2
Part 1
Arduino
School of Engineering
Electrical Engineering
University of Jordan
1
Unit 1
Introduction to Microcontrollers
Definition:
Examples of microcontrollers:
•Arduino Uno.
•STM32F103.
•ESP32 and ESP8266.
•Sipeed.
2
Unit 2
Microcontroller Components
3
MAIN COMPONENTS :
1. CPU:
The main processing unit inside the microcontroller. It contains the ALU and
SRAM registers and the control unit that encodes the program into control
signals to hardware.
2. Memory
I. Non-volatile, usually an EEPROM or/and flash memory, used to store
programs and some data as well as the stack (at bottom of memory).
II. Volatile, such as:
• RAM (Random Access Memory): Stores Variables
• CPU registers (FSR)
3. Interrupts: software or hardware circuit that starts a function when triggered
Sources of interrupts :
• Timers (Timer overflow interrupt, timer compare interrupt).
• I/O on digital pins at rising or falling edge or change of level.
• In Arduino there are 3 levels of interrupt priority.
Notes :
• Subroutines : a small program for a small task (works as a software
interrupt)
• When assigning variables , we can force the compiler to preserve it for
later use
• Some timers can be connected with certain I/O, for clocking purposes, and
precise timing applications.
• In Arduino : a comparator circuit is implemented, used for Brownout
detection and other user-specified functions
4
Used for sim cards where the mobile phone is the master and the sim card
is the slave
Address 0 has higher priority than address 1
Low is dominant
If: Input 1, output 0 then this means I’m not the transmitter
If: Input 1, output 1 then this means I’m the transmitter
Command → data
Ex: I want to read data from x, then I send to x that I want to read data so
x sends the data
• I2C (2 wires, data, and clock)
• USART (usually called serial port) or RS232.
• SPI (4 wires)
Has master and slave
Same device defines the master and the slave
The master doesn’t need an address
The slave needs an address
• I2S
Made because of sound
• USB:
Four wires: D+, D-, Vcc, GND
Notes :
* Analogue I/O have A-to-D converters
* D-to-A converters could be used, although Pulse Width Modulation (PWM)
could be used instead to drive DC motors.
APPLICATIONS
• Media I/O for microcontrollers:
-Camera interfaces
-Video ports: VGA , HDMI , DisplayPort
* Converters are used between different protocols
5
Notes :
• Special registers are used to store data from peripherals, it could be RAM or EEPROM
• Memory mapping: assigning address to each register in the memory.
• GoTo : a process that changes Program Counter for applications.
• Some microcontrollers have temperature sensors to control power dissipation and to
perform thermal shutdown -disconnects power supply –
• Micro Electromagnetic Sensors (MEMS), such as:
Accelerometer , Gyroscope, and compass
• Capacitive touch screens use variable capacitance.
• Hall effect: deflection of electrons in FET transistors, used for proximity sensors.
6
Figure 2 (above) : AVR block diagram
Figure 3 (Below) : Pins of Arduino Uno
7
8
Figure 4: Detailed AVR block diagram
EEPROM → External memory
o Self-programmable
o Communication protocols
o Retention time 20 years if storage is 85%
Static RAM → faster → cache memory
Power on reset
o Vcc on any device → transient → affects digital devices
o During power on → glitch (voltage changes) → so reset
o Stabilization for power
Brown out effect
o Voltage decreases (battery less)
o Before turn off
o Use the rest of voltage to save all registers (fall safe)
CRC → error detection code
9
UNIT 3
INTRODUCTION TO PROGRAMMING
We will use C/C++ programming language in the first part of this course to implement
some hardware functions. We will learn how to use most of the microcontroller
capabilities.
First, we need to select the board that we are going to use. We can do this by
navigating to Tools > Port > {Board}. The board(s) that are connected to your
computer should appear here
Second, to compile written code, click on Verify , After a few seconds, we can see
the result of the action in the console (black box in the bottom).
We can also compile & upload to board all for once by clicking Upload , results will
appear in the console, with errors -if found- will be listed here as well.
10
SERIAL COMMUNICATION :
Way of communicating:
1. Data transmission starts when voltage is low (i.e., start bit is used to initialize
communication).
2. There are certain common parameters that Rx & Tx agree to share :
I. Baud rate (rp = 1/tp) : data transmission rate (Bit/second)
II. Parity bit (odd or even)
III. Positive or negative logic
3. We sample data at the middle , to limit mis-synchronization -if occurred-
4. Stop bit is used to give time managing the data.
We need registers -to store data- and encoder -to check parity- at both Rx & Tx
11
Tx Positive/Negative logic
“1” CLK
LOW Encoder
Voltage DIVIDER
Transmit Register
Rx
Schmitt trigger
Notes:
Receive Register
1. In Arduino:
data transmission is parallel in , serial out , vice versa for receiving
2. To use serial port with microcontrollers , four important parameters are
specified:
I. Baud rate II. parity (odd/even) III. (positive/ negative) logic
IV. No. of (Data /Start/Stop) bits
3. A shift register is used transmit data
4. Pin control is used in : Tx (Amplifier) Rx (Schmidt trigger)
5. Receiver interrupt is used to trigger start of communication.
6. MAX232 interface converts from TTL (0 – 5) V to serial (-12 to 12) V and vice
versa
Problems with wires :
1. Interference : from external sources
2. Noise inside
3. Resistance of wires , with inductance and capacitance -transmission line-
4.With L & C increasing, cutoff frequency decreases , distortions occur on
signals.
12
Serial Communication:
o Chip → USB to serial
o Tx and Rx should use the same number of bits
o Common ground → to not damage the devices
o Problem in communication → ground
o When reading voltage between Rx and GND → interference
o Also, 220 volts are not constant so temperature is not constant, so there will
be variation on Vcc
o Solution → inductance between Vcc and GND
o Problems of adding an inductor: chopping, harmonics, sparks, high inductance
shock
o Power supply noise → solution: use better power supply (noise immune), or
battery-operated system (floating charge power supply) we need charge
controller and regulator
o Glitch → out of sequence
o Serial communication needs a driver to transmit more than 1000 m or 1400 m
for industrial applications
o Driver → RS485
o Interference → from devices and cables
o Ground loops → interference from ground
o Solution → read signal in differential mode
o Twisted pair → two floating wires (not grounded) → floating differential pair
o Cancel each other → decrease the effect of interference from outside but
mutual inductance increases
o In twisted pair add termination resistance = 120 Ω
o Full duplex mode → Tx and Rx are separated
o Half duplex mode → Tx and Rx are connected
When Tx → 1, Rx → 0, high impedance mode (open collector or open drain)
o L → H/m , C → F/m
1
o Speed 𝑢 =
√𝐿𝐶
1
o 𝑓𝑐𝑢𝑡−𝑜𝑓𝑓 =
2𝜋𝑙 √𝐿𝐶
o As length increases, bandwidth decreases
1
o 𝑑𝑎𝑡𝑎 𝑟𝑎𝑡𝑒 ≪
𝑡𝑟 +𝑡𝑓
o Data rate increases when tr and tf decrease
o 𝑇 ≫ (𝑡𝑟 + 𝑡𝑓 )
13
ARDUINO UNO BOARD MAIN COMPONENTS :
Notes:
1.ATMEGA16U2 converts from USB to serial
2.Voltage regulator : produces 3.3 V used for some applications: some sensors and
small LCD displays
3.ICSP -In Circuit Serial Programmer- is used to program the microcontroller
separately, and for debugging -showing registers content and Program Counter –
4.IOREF : reference voltage for A-to-D converter
Example of a program:
//Blink : makes built-in LED blink for a second
void setup() {
pinMode(LED_BUILTIN, OUTPUT); }
void loop()
{
digitalWrite(LED_BUILTIN, HIGH); // turn built-in LED on
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
delay(1000);
}
14
Serial Monitor is used to communicate with the board :
• Serial. : a defined class that enables communication with board, it has
methods like :
.begin(bode rate) : assigns Rx & Tx pin, parity, and data bits
.print(“string”)
.printline(“string”): prints the string to a new line
.available(): when received data is available
• Directives of print:
(\n) : prints new line , (\t) : prints a tab
ARDUINO I/O
D Q
Pin
Q’
PWM
Driver
Port (n) OUTPUT from
Microcontroller
Q D
Q’
0:IN
Buffer
1:OUT MUX
INPUT to
Microcontroller MUX
Control
Signal
DDR : Data Direction Register
(Latch) 0 1 2
Interrupt Registers
ISR(Interrupt vector) Data Bus
15
Schematic of a switch with debouncing circuit – 1uF capacitor-:
pin
Notes:
• More input pins require more registers
• Phases of clocks -delayed- are used to synchronize instructions
• Every interrupt has an interrupt vector : bits of data that has
information about specific pin that caused interrupt
• In switch: output is high by default -internally pulled up-
• Hardware debouncing is used when multiple instances of a
signal are happening in a short time -microseconds-
• Software debouncing can be used
• A trigger does not need debouncing – interrupt based-
• Polling needs debouncing
• A switch can be : High , Low , or High Impedance
16
TEMPRATURE SENSORS & ANALOGUE PINS:
Notes:
*Analogue pins on Arduino can used as digital
* A-to-D converters can be :
1.Flash : fast conversion -used on oscilloscopes-
2.Successive Approximation (SAR) -on Arduino-: Sampling frequency ~ 10 KHz,
uses compare counters to count on all 1024 voltage levels,
D-to-A converters
*PWM can be
used to drive
LED or Motor
1
LED:
𝟓−𝟐
For LED we need R=330Ω, 𝑹 = = 𝟑𝟎𝟎Ω
𝟎.𝟎𝟏
Speakers
o 55 W for the big speakers
o Above 55 W → burns the coil
o Max current we can get from Arduino is 20 mA
o We need a driver between the Arduino and speaker
𝟓−𝟎.𝟕
o 𝑹𝒃 = = 𝟏KΩ
𝟓𝒎
o External Vspk=12 V
o Speaker = 4Ω
𝟏𝟐−𝟎.𝟐
o 𝑰= = 𝟑𝑨
𝟒
o P = V*I = 3*12 = 36 W
𝟑
o 𝜷= = 𝟔𝟎𝟎
𝟓𝒎
o We can get β = 600 by using power transistor Darlington pair β=10*60=600
2
Opto coupler: to isolate high voltage circuits with low voltage circuits
DC Motor
o PMSM: Permanent Magnet Synchronous Motor
Like hybrid cars motors
o Encoder
o Position of rotary switch
o On rotor 11 bits
o On or off (binary)
o Holes → sensor to lights
o Gives a code
𝒅𝒊
o 𝑽𝒆𝒎𝒇 = −𝑳 ∗
𝒅𝒕
o Vemf = 370 V of DC motor
Switches and buttons
o Buttons → N/C or N/O
o For switching mode power supply, we can’t use BJT. We use MOSFET (fastest)
of IGBT
o Switch → left of right
o SPST → single pole single throw (on or off)
o SPDT → single pole double throw
o DPDT → double pole double throw (arching)
o Limit switch → button or SPDT
o Push button → damping (transient) → bouncing
o Solution → debouncing
3
o Or Schmitt trigger
To eliminate shock noise
Resistive sensor
o Works by adding pressure
o After a time, mechanical characteristics change so stops working after using it
a lot.
Capacitive sensor
o Touch sensor
o As the finger approaches the capacitive plate, there is blood in finger and a has
a certain ϵ, so the ϵ of the environment around the sensor changes.
o By reading the capacitance, when capacitance changes, we know that
someone touched the screen.
Capacitance meter
o As the current passes through the capacitor → integration
𝑄 𝐼∗𝑇
o 𝐶= =
𝑉 𝑉
4
CAPACITANCE METER :
Digital
Analog
Pseudo-code:
Make digital pin high , set t = 0
While(analogpin < V0(1-e-1)= 3.16)
{Exit}
t0 = R*C
C = t0 / R = Cx + Cerror
Cx = C - Cerror
Notes:
• RTC = Real time clock , internally preserved real time
• 32.768 KHz oscillators are used for sleep mode for CPU
5
Second method: voltage divider capacitance
Digital
Analog
Using C = Q/V
Q = Cx (Vx – V0) = V0*C0
Notes:
To get accurate result, we switch analog pin from input to output mode, then
back to input, in order to discharge internal capacitor used in A-to-D
External Note:
*To measure inductance , we make a resonance circuit,
1
where a known value of capacitance is used.
WIRED COMMUNICATION PROTOCOLS :
Rx Driver
1
TIMERS :
Microcontroller
Timer 0 8-Bits
Timer 1 16-Bits
Timer 2 8-Bits
8-Bits
Set
Reset Reset
Reset
CLK CLK CLK Generate Clock sources:
CLK • System clock
Tc • External
Up / down Overflow
Logic Count Interrupt
Notes:
Overflow interrupt : occurs when counter reaches 255 in binary -All 1- , reset
occurs afterwards
Timer duration = count * Tc , where Tc : clock period
Compare timers give interrupt when a match happens
2
INTERRUPTS :
• Level or edge(rising , falling) interrupt
• I/O interrupt , pin change interrupt
• Every interrupt has vector containing memory address of next instruction
• Reset interrupt has highest priority: it forces microcontroller’s program
counter to hold at 0
• We use reset circuit to stabilize microcontroller’s operation , & Reset
occurs when reset pin is low
• Every interrupt has registers
• Every interrupt must be initialized before it is used
• attachInterruput()is used to initialize interrupts
• ISR() is a void function -no return value-
Reset
Reset Circuit
3
// Globalinterrupt
noInterrupts() // Disable global interrupts
interrupts() // Enable global interrupts
attachInterruput(digitalPinToInterrupt(pin), ISR, mode)
digitalPinToInterrupt(interruptPin)// used instead of writing
name of the interrupt , e.g. pin 2 is used for INT0
4
Ports:
o digitalRead → reads from port D
o digitalWrite → writes on port D
o x=PORTD → reads all the 8 bits of port D
o X |= PORTD = 00000011 →
we use D2 to D7 (000000)
D0, D1 do not change (11)
o DIP → dual inline pin (through holes)
Through holes → more reliable
o Surface mount is cheaper than through hole
o Surface mount → welded at the surface but if with heating the
components may disconnect
o In surface mount we cover the surface after welding with a heat
conductive material to secure the components so they keep connected
A/D converter:
o From analog to discrete signal
o 1) Sampling
At least 2*fm to recover the signal
Discrete signal (time)
Nyquist rate → fs = 2*fm
Over sampling → fs ≥ 2*fm
2) Quantization
Discrete amplitude (voltage)
From infinity number of amplitudes to discrete number of amplitudes
5
16 levels → 4 bits
m-bits → 𝟐𝒎 levels
6
D/A converter:
o Ladder circuit:
7
FREQUENCY COUNTER
Using timers to measure frequency of a signal,
PWM
We could generate PWM signal by using timers , if an -for example- 8-bit counter
is used, then each clock period is divided into 256 counts , where a counter value
is specified to be τ == Ton
Pseudo-code:
if countervalue < τ
output = HIGH
else
output = LOW
SPI
Used for fast transmission of data , used for graphical interfaces : cameras ,
displays,
it has 4 pins : Clock , Datain , Dataout , Ground
*Variables could also be stored directly to flash memory using the following
directives:
PROGMEM or F()
8
SoftwareSerial myserial(2,3);
bool LEDVal;
char TxDta;
char RxDta;
int indx;
int LEDOut = 5;
int ButtonIn = 6;
// the setup function runs once when you press reset or power the board
void setup() {
pinMode(LEDOut, OUTPUT);
pinMode(ButtonIn, INPUT);
myserial.begin(9600);
LEDVal = false;
digitalWrite(LEDOut,LEDVal);
}
void loop() {
TxDta = 'N';
if (!digitalRead(ButtonIn)){myserial.print("A");}
while (myserial.available()) {
RxDta = (char)myserial.read();
if (RxDta=='A'){LEDVal=!LEDVal;digitalWrite(LEDOut,LEDVal);}
}
delay(200);
}
9
Capacitance Meter
float Ce; //error in reading
float Cx;
int Rext;
int DigPin=A5;
int AngPin=A0;
long Tm;
String Txt;
void setup() {
pinMode(DigPin,OUTPUT);
pinMode(AngPin,INPUT);
digitalWrite(DigPin,LOW);
Ce=0.0;
Rext=10;
Serial.begin(115200);
delay(1000);
}
void loop() {
digitalWrite(DigPin,HIGH);
Tm= micros();
while (analogRead(AngPin)<646){} //646 = 3.16 volt, ((0 to 1023)~~(0 to
5 volt))
Tm=micros()-Tm;
Cx=(float)(Tm/Rext)-Ce; //OR Cx=(1.0*Tm/Rext)-Ce;
Txt= " nF";
if (Cx>1000){Txt= " uF"; Cx=Cx/1000;}
Serial.print("Capacitance Value= "); Serial.print(Cx,2); Serial.println(Txt);
digitalWrite(DigPin,LOW); delay(2000);
}
10
Pico Farad Capacitance Meter
float Cx;
float Co;
long Vo;
int DPin = A2; //Digital pin
int AIn = A0; //Analog pin
void setup() {
pinMode(AIn,INPUT);
pinMode(DPin,OUTPUT);
digitalWrite(DPin,LOW);
Serial.begin(115200);
Co = 23.2;
Serial.println("Reading PF capacitance");
delay(1000);
}
void loop() {
Vo = 0.0;
for(int i=0;i<100;i++)
{
pinMode(AIn,INPUT);
digitalWrite(DPin,HIGH);
Vo = Vo+analogRead(AIn);
pinMode(AIn,OUTPUT); //Discharging the A/D Cap.
digitalWrite(DPin,LOW);
}
Vo = Vo/100; //Avareging 100 readings.
if(Vo>1022){Vo=1022;}
Cx = Co*Vo/(1023-Vo);
if(Cx<=0){Cx=0.0;}
Serial.println(Cx);
delay(1000);
}
11
Frequency Counter Version 1
int InPin=2;
long TL;
long TH;
float Freq;
void setup(){
Serial.begin(115200);
pinMode(InPin,INPUT);
void loop(){
while(digitalRead(InPin)==LOW){}
TL = pulseIn(InPin,LOW);
while(digitalRead(InPin)==HIGH){}
TH = pulseIn(InPin,HIGH);
Freq=(float) 1000000.0/(TL+TH);
Serial.print("Fr= ");
Serial.println(Freq,2);
delay (1000);
}
12
Frequency Counter Version 2
int InPin=2;
long To;
long Tf;
float Freq;
void setup(){
Serial.begin(115200);
pinMode(InPin,INPUT);
void loop(){
while(digitalRead(InPin)==HIGH){}
while(digitalRead(InPin)==LOW){} // while LOW dont do anything, when in
convert to high go to next line
To = micros();
while(digitalRead(InPin)==HIGH){}// while High dont do anything, when in
convert to low go to next line
Tf = micros();
Freq=(float) 500000.0/(Tf-To); // 1000000 because the time in micro seconds
Serial.print("Fr= ");
Serial.println(Freq,2);
delay (1000);
}
13
Frequency Counter Final
//D4 and D3 together, Input on D5
byte overF=0;
unsigned long freq;
double period;
void setup() {
Serial.begin(115200);
//1 Hz timer
OCR0A = 249;
TCCR0A = _BV(WGM00) | _BV(WGM01) | _BV(COM0A0); //
TCCR0B = _BV(WGM02) | _BV(CS02) | _BV(CS01); // PWM mode, input T0 pin D4
pinMode(6, OUTPUT); //AIN0
//250 Hz - timer2
OCR2A =249;
OCR2B = 125;
TCCR2A = _BV(COM2B1) | _BV(COM2B0) | _BV(WGM21) | _BV(WGM20); //output D3 in
phase, fast PWM mode
TCCR2B = _BV(WGM22) | _BV(CS22) | _BV(CS21); // set prescaler to 256 and start
the timer
pinMode(3, OUTPUT);
// counter input T1 pin D5
OCR1A = 32767; //32768 counts
TCCR1A = _BV(WGM10) | _BV(WGM11) | _BV(COM1A0); //
TCCR1B =_BV(WGM12) | _BV(WGM13) | _BV(CS12) | _BV(CS11); //input pin D5
pinMode(9, OUTPUT);
Serial.println("Frequency Counter");
}
void ReadFreq() {
//wait for high
while(digitalRead(6)){}
while(!digitalRead(6)){}
//start the count
TIFR1 = _BV(OCF1A); //reset int
OCR1A = 32767;
TCNT1=0;
overF=0;
while(digitalRead(6)){
if(TIFR1 & (1<<OCF1A)) {++overF; TIFR1 = _BV(OCF1A);} //overflow
}
//count end
freq = (unsigned long)TCNT1 + ((unsigned long)overF * 32768);
period = 1000000 / (double)freq;
if(freq == 0){period=0;}
14
}
void loop() {
ReadFreq();
Serial.print("F= "); Serial.println(freq);
// delay(1000);}
Homework
unsigned long freq = 0 , cnt = 0 , overf = 0 ;
int sampletime = 500;
void setcounter1()
{
TCCR1A = 0 ;
TCCR1B |= 0B00000111;
TIMSK1 |= 0B00000001;
}
void setup() {
// put your setup code here, to run once:
setcounter1();
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
overf = 0;
TCNT1 = 0;
TCCR1B |= 0B00000111;
delay(sampletime);
TCCR1B |= 0B00000000;
cnt = TCNT1;
Serial.print("F = ");
Serial.println((float)(cnt + overf * 65535) * 1000 / sampletime);
}
ISR(TIMER1_OVF_vect)
{
overf++;
}
15
PWM
int Vin;
int DutyCycle;
float Vout;
void setup() {
DutyCycle=0;
Serial.begin(115200);
}
void loop() {
Vin=analogRead(A1);
DutyCycle=map(Vin, 0, 1023, 0, 255);
analogWrite(3, DutyCycle);
Vout=5.0*analogRead(A0)/1023;
Serial.println(Vout,2);
16
DHT11 Temperature
// DHT Temperature & Humidity Sensor
// Unified Sensor Library Example
// Written by Tony DiCola for Adafruit Industries
// Released under an MIT license.
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
uint32_t delayMS;
void setup() {
Serial.begin(9600);
// Initialize device.
dht.begin();
Serial.println(F("DHTxx Unified Sensor Example"));
// Print temperature sensor details.
sensor_t sensor;
dht.temperature().getSensor(&sensor);
Serial.println(F("------------------------------------"));
Serial.println(F("Temperature Sensor"));
Serial.print (F("Sensor Type: ")); Serial.println(sensor.name);
Serial.print (F("Driver Ver: ")); Serial.println(sensor.version);
Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id);
17
Serial.print (F("Max Value: ")); Serial.print(sensor.max_value);
Serial.println(F("°C"));
Serial.print (F("Min Value: ")); Serial.print(sensor.min_value);
Serial.println(F("°C"));
Serial.print (F("Resolution: ")); Serial.print(sensor.resolution);
Serial.println(F("°C"));
Serial.println(F("------------------------------------"));
// Print humidity sensor details.
dht.humidity().getSensor(&sensor);
Serial.println(F("Humidity Sensor"));
Serial.print (F("Sensor Type: ")); Serial.println(sensor.name);
Serial.print (F("Driver Ver: ")); Serial.println(sensor.version);
Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id);
Serial.print (F("Max Value: ")); Serial.print(sensor.max_value);
Serial.println(F("%"));
Serial.print (F("Min Value: ")); Serial.print(sensor.min_value);
Serial.println(F("%"));
Serial.print (F("Resolution: ")); Serial.print(sensor.resolution);
Serial.println(F("%"));
Serial.println(F("------------------------------------"));
// Set delay between sensor readings based on sensor details.
delayMS = sensor.min_delay / 1000;
}
void loop() {
// Delay between measurements.
delay(delayMS);
// Get temperature event and print its value.
sensors_event_t event;
dht.temperature().getEvent(&event);
if (isnan(event.temperature)) {
Serial.println(F("Error reading temperature!"));
}
else {
Serial.print(F("Temperature: "));
Serial.print(event.temperature);
Serial.println(F("°C"));
}
// Get humidity event and print its value.
dht.humidity().getEvent(&event);
if (isnan(event.relative_humidity)) {
Serial.println(F("Error reading humidity!"));
}
else {
Serial.print(F("Humidity: "));
18
Serial.print(event.relative_humidity);
Serial.println(F("%"));
}
}
19
Part 2
Microcontroller Applications :
ESP32
20
Introduction
1
Connecting sensors , devices , appliances
to the internet , for different applications.
IP 1
IP 2
IP N
App.
MQTT protocol :
Built on top TCP & UDP , it is efficient
for sending and receiving IoT data ;
small data size.
2
In WifiScan.ino file
#include "WiFi.h" //To connect to Wi-Fi
In setup()
WiFi.mode(WIFI_STA) //Set as a station
WiFi.scanNetworks(); //Scan available
networks
WiFi.SSID(i) // Name of network
WiFi.RSSI(i) // Signal strength
WiFi.encryptionType(i)
In Weather.ino file :
#include <HTTPClient.h>
// HTTP : Hypertext transfer protocol , way
of communicating with server:
- initialize communication with server
http.begin(client, serverName)
serverName : an HTTP address of the server
- Send request:
http.GET() : Request data
http.getString(): Request
- Disconnect:
http.end()
3
- JSONVar : Class used to define JSON
objects to parse from JSON file
In WifiScanConnectWebFinal.ino file :
#include <EEPROM.h> // To operate EEPROM :
#include "WiFi.h" :
4
WiFi.softAP(Webssid, Webpassword); //define
as access point (Wi-Fi Network)
WiFi.softAPConfig(local_ip, gateway,
subnet); //set its parameters
Multi-Threading :
Running tasks on separate cores , and the
Task Manager program handles it
An OS is needed to handle different
programs , ESP32 has Embedded Linux
installed
We can manually assign Tasks to each of
the Two cores on ESP (0 or 1)
TaskHandle_t Task1; // Define Task
xTaskCreatePinnedToCore(Task Function , name
of task , stack size , NULL , priority ,
&Task1 , 0)
Programming languages are
interpreted or compiled
MicroPython is an interpreted language
(directly to machine code , not compiled )
With interpreter installed on ESP32
import network :
#To work as a station
network.WLAN(network.STA_IF) //make
device work as a station
wlan.active(True) //turn on
wlan.connect(ssid, password) //connect to
specified network
station.scan() // Scan available networks
import time :
time.sleep(seconds)
7
#Set the socket to listen for incoming
connections
server.listen(1)
WifiSimple.py
# https://docs.micropython.org/en/latest/library/network.WLAN.html
import ubinascii
ssid = 'SSID'
password = 'Password'
def format_mac_addr(addr):
mac_addr = addr.upper()
new_mac = ""
for i in range(0, len(mac_addr),2):
if (i == len(mac_addr) - 2):
new_mac = new_mac + mac_addr[i] + mac_addr[i+1]
else:
new_mac = new_mac + mac_addr[i] + mac_addr[i+1] + ":"
return new_mac
def do_connect():
import network
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('Connecting to Network...')
wlan.connect(ssid, password)
while not wlan.isconnected():
pass
8
print('network config:', wlan.ifconfig())
MacStr=wlan.config('mac')
print(MacStr)
print('MAC Address:', format_mac_addr(ubinascii.hexlify(MacStr).decode().upper()))
def ScanNet():
import network
Security=['open','WEP','WPA-PSK','WPA2-PSK','WPA/WPA2-PSK']
station = network.WLAN(network.STA_IF) # create station interface
station.active(True) # activate the interface
nets=station.scan() # (ssid, bssid, channel, RSSI, security, hidden)
net[index].decode() index(0 to 5) 0–open 1–WEP 2–WPA-PSK 3–WPA2-PSK 4–WPA/WPA2-PSK
print('No of WiFi Networks: ', len(nets))
for net in nets:
print('SSID: ',net[0].decode(),'\tBISSD:
',format_mac_addr(ubinascii.hexlify(net[1]).decode().upper()),'\tRSSI:
',str(net[3]),'dBm \tSecurity: ',Security[net[4]])
print('\n')
ScanNet()
do_connect()
Weather.py
import time
import urequests as requests
import ujson as json
import network
import esp
import gc
esp.osdebug(None)
gc.collect()
ssid = 'SSID'
password = 'PASSWORD'
city = 'Amman'
country_code = 'JO'
open_weather_map_api_key = 'f19282a3fe5af10cce5eb39f29d767e0'
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
9
while station.isconnected() == False:
pass
print('Connection successful')
print(station.ifconfig())
weather_data = requests.get(open_weather_map_url)
print(weather_data.json())
# Weather Description
description = 'Description: ' + weather_data.json().get('weather')[0].get('main')
print(description)
# Temperature
raw_temperature = weather_data.json().get('main').get('temp')-273.15
# Temperature in Celsius
temperature = 'Temperature: ' + str(raw_temperature) + '*C'
#uncomment for temperature in Fahrenheit
#temperature = 'Temperature: ' + str(raw_temperature*(9/5.0)+32) + '*F'
print(temperature)
# Pressure
pressure = 'Pressure: ' + str(weather_data.json().get('main').get('pressure')) + 'hPa'
print(pressure)
# Humidity
humidity = 'Humidity: ' + str(weather_data.json().get('main').get('humidity')) + '%'
print(humidity)
# Wind
wind = 'Wind: ' + str(weather_data.json().get('wind').get('speed')) + 'mps ' +
str(weather_data.json().get('wind').get('deg')) + '*'
print(wind)
10
HomeWork.py
import ubinascii
import machine
import network
import time
import usocket as socket
import os
from machine import Pin
def format_mac_addr(addr):
mac_addr = addr.upper()
new_mac = ""
for i in range(0, len(mac_addr),2):
if (i == len(mac_addr) - 2):
new_mac = new_mac + mac_addr[i] + mac_addr[i+1]
else:
new_mac = new_mac + mac_addr[i] + mac_addr[i+1] + ":"
return new_mac
def WiFiInitWebServer():
ScanNet()
Access_Point = network.WLAN(network.AP_IF)
Access_Point.active(True)
Access_Point.config(essid='ESP', authmode=network.AUTH_OPEN, channel=6)
Access_Point.ifconfig(('192.168.10.1', '255.255.255.0', '192.168.2.1','8.8.8.8'))
time.sleep_ms(100) # sleep for 100 milliseconds
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
# Accept incoming connections
conn, addr = server.accept()
print('Got a connection from %s' % str(addr))
request = conn.recv(1024)
if "/Root" in request:
response = handle_root()
11
elif "/SendData" in request:
response = handle_msg(request)
conn.send(response)
print("HTTP server started")
def handle_root():
HTML = "<!DOCTYPE html>\
<html>\
<style>table, th, td {border:1px solid black}</style>\
<body>\
<h1>Available WiFi Networks</h1>"
HTML +=ScanText
HTML += "<h4 style='color:blue; font-size:25px'>Select Your Network</h4>\
<p style='color:red; font-size:15px'>As: (No,Password)</p>\
<form action='/SendData'>\
<input style='font-size:30px' type='text' name='NetId' id='DtTxt'
value='1,pass'><br>\
<input style='font-size:30px' type='submit' value='Save Network'>\
</form><br>\
</body>\
</html>"
return HTML
def handle_msg(req):
req=req.decode();
req=req.split("\n")[0].split("?")
req=req[1].split(" ")[0].split("=")[1]
SSID , PWD = req.split("%2C")
inputString = SSID + "," + PWD
print(inputString)
with open('data.txt', 'w') as f:
f.write(inputString)
f.close()
return HTML
def StartWiFi():
12
PWD = inputString [2:len(inputString)-1]
f.close()
station = network.WLAN(network.STA_IF)
station.active(True)
nets=station.scan()
Security=['open','WEP','WPA-PSK','WPA2-PSK','WPA/WPA2-PSK']
k = 1
for net in nets:
print((k) ,": " , net[0].decode() , " (" + str(net[3]) , " dBm) [" ,
Security[net[4]] , "]")
k = k + 1
S = int(SSID)
SSID = nets[S-1][0].decode()
print("SSID:" , SSID)
print("Pass:" , PWD)
if not station.isconnected():
print('Connecting to Network...')
station.connect(SSID, PWD)
while not station.isconnected():
pass
print('network config:', station.ifconfig())
MacStr=station.config('mac')
print(MacStr)
print('MAC Address:',
format_mac_addr(ubinascii.hexlify(MacStr).decode().upper()))
def ScanNet():
global ScanText
ScanText="<table style='width:75%'>"
ScanText+= "<script>function myFunction(ii)
{document.getElementById('DtTxt').style.backgroundColor = 'yellow';
document.getElementById('DtTxt').value = ii+',NewPass';}</script>"
ScanText+="<tr>"
ScanText+="<th>No</th>"
ScanText+="<th>WiFi SSID</th>"
ScanText+="<th>RSSI (dBm)</th>"
ScanText+="<th>Encryption Type</th>"
ScanText+="</tr>"
Security=['open','WEP','WPA-PSK','WPA2-PSK','WPA/WPA2-PSK']
station = network.WLAN(network.STA_IF) # create station interface
station.active(True) # activate the interface
nets=station.scan() # (ssid, bssid, channel, RSSI, security, hidden)
net[index].decode() index(0 to 5) 0–open 1–WEP 2–WPA-PSK 3–WPA2-PSK 4–WPA/WPA2-PSK
i = len(nets)
print("Found " + str(i) + " WiFi networks \n")
k = 1
for net in nets:
print((k) ,": " , net[0].decode() , " (" + str(net[3]) , " dBm) [" ,
Security[net[4]] , "]")
13
ScanText+="<tr>"
ScanText+="<td><button type=\"button\" onclick=\"myFunction("+ str(k)
+")\">" + str(k) + "</button></td>";
ScanText+="<td>" + str(net[0].decode()) + "</td>"
ScanText+="<td>" + str(net[3]) + "</td>"
ScanText+="<td>" + str(Security[net[4]]) + "</td>"
time.sleep_ms(10) # sleep for 10 milliseconds
k = k + 1
ScanText+="</table>"
k = 0
P4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
if P4.value() == 0 :
WiFiInitWebServer()
else :
StartWiFi()
Weather.ino
#include <WiFi.h>
#include <HTTPClient.h>
#include <Arduino_JSON.h>
14
String countryCode = "JO";
String jsonBuffer;
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
void loop() {
// Send an HTTP GET request
if ((millis() - lastTime) > timerDelay) {
// Check WiFi connection status
if(WiFi.status()== WL_CONNECTED){
String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + city +
"," + countryCode + "&APPID=" + openWeatherMapApiKey;
//https://api.openweathermap.org/data/2.5/weather?lat=44.34&lon=10.99&appid={API
key}
jsonBuffer = httpGETRequest(serverPath.c_str());
Serial.println(jsonBuffer);
JSONVar myObject = JSON.parse(jsonBuffer);
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
payload = http.getString();
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
return payload;
}
WifiScan.ino
// https://www.upesy.com/blogs/tutorials/how-to-connect-wifi-acces-point-with-esp32
#include "WiFi.h"
16
String get_encryption_type(wifi_auth_mode_t encryptionType) {
switch (encryptionType) {
case (WIFI_AUTH_OPEN):
return "Open";
case (WIFI_AUTH_WEP):
return "WEP";
case (WIFI_AUTH_WPA_PSK):
return "WPA_PSK";
case (WIFI_AUTH_WPA2_PSK):
return "WPA2_PSK";
case (WIFI_AUTH_WPA_WPA2_PSK):
return "WPA_WPA2_PSK";
case (WIFI_AUTH_WPA2_ENTERPRISE):
return "WPA2_ENTERPRISE";
}
}
void setup(){
Serial.begin(115200);
WiFi.mode(WIFI_STA);
}
void loop() {
Serial.println("WiFi Scan Networks");
Serial.println("[*] Scanning WiFi network");
17
// Wait a bit before scanning again
delay(10000);
}
WifiScanConnect.ino
// https://www.upesy.com/blogs/tutorials/how-to-connect-wifi-acces-point-with-esp32
#include "WiFi.h"
#include <EEPROM.h>
// WIFI
String inputString;
String SSID;
String PWD;
void WiFiScan(){
int n = WiFi.scanNetworks();
18
if (n == 0) {
Serial.println("No WiFi networks found");
} else {
Serial.println((String)"Found " + n + " WiFi networks \n");
for (int i = 0; i < n; ++i) {
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(" dB) [");
Serial.print(get_encryption_type(WiFi.encryptionType(i)));
Serial.println("]");
delay(10);
}
}
Serial.println("");
SetNetParameters();
}
void SetNetParameters() {
int ii=0;
inputString="";
while (!Serial.available()) {}
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
}
int index = inputString.indexOf(',');
String SSIDStr=inputString.substring(0, index);
ii=SSIDStr.toInt();
SSID=String(WiFi.SSID(ii-1));
PWD=inputString.substring(index+1, inputString.length());
EEPROM.writeString(0, SSID);
EEPROM.commit();
EEPROM.writeString(50, PWD);
EEPROM.commit();
}
void StartWiFi(){
SSID=EEPROM.readString(0);
PWD=EEPROM.readString(50);
Serial.println("");
Serial.print("SSID: ");
Serial.print(SSID);
Serial.print(" Pass: ");
Serial.println(PWD);
delay(2000);
19
WiFi.begin(SSID.c_str(), PWD.c_str());
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi..");
}
get_network_info();
}
void get_network_info(){
if(WiFi.status() == WL_CONNECTED) {
Serial.print("Network information for ");
Serial.println(SSID);
Serial.println("\tBSSID : " + WiFi.BSSIDstr());
Serial.print("\tGateway IP : ");
Serial.println(WiFi.gatewayIP());
Serial.print("\tSubnet Mask : ");
Serial.println(WiFi.subnetMask());
Serial.println((String)"\tRSSI : " + WiFi.RSSI() + " dB");
Serial.print("\tESP32 IP : ");
Serial.println(WiFi.localIP());
Serial.print("\tCurrent MAC Address: ");
Serial.println(WiFi.macAddress());
}
}
void setup(){
Serial.begin(115200);
pinMode(buttonPin,INPUT_PULLUP);
WiFi.mode(WIFI_STA);
inputString.reserve(100);
EEPROM.begin(100);
if (digitalRead(buttonPin)==LOW) {
WiFiScan();
}
StartWiFi();
EEPROM.end();
}
void loop() {
20
WifiScanConnectWebFinal.ino
// https://www.upesy.com/blogs/tutorials/how-to-connect-wifi-acces-point-with-esp32
// https://www.w3schools.com/html/html_tables.asp
#include "WiFi.h"
#include <EEPROM.h>
#include <WebServer.h>
// WIFI
String inputString;
String SSID;
String PWD;
String ScanText;
String HTML;
void WiFiInitWebServer(){
WiFiScan();
WiFi.softAP(Webssid, Webpassword);
WiFi.softAPConfig(local_ip, gateway, subnet);
delay(100);
server.on("/", handle_root);
server.on("/SendData", handle_msg);
server.begin();
Serial.println("HTTP server started");
void handle_root() {
HTML = "<!DOCTYPE html>\
<html>\
21
<style>table, th, td {border:1px solid black}</style>\
<body>\
<h1>Available WiFi Networks</h1>";
HTML +=ScanText;
HTML += "<h4 style='color:blue; font-size:25px'>Select Your Network</h4>\
<p style='color:red; font-size:15px'>As: (No,Password)</p>\
<form action='/SendData'>\
<input style='font-size:30px' type='text' name='NetId' id='DtTxt'
value='1,pass'><br>\
<input style='font-size:30px' type='submit' value='Save Network'>\
</form><br>\
</body>\
</html>";
void handle_msg() {
Serial.println("HTTP client sends info");
if (server.hasArg("NetId") == true) {
inputString = server.arg("NetId");
Serial.print("Password Received as: ");
Serial.println(inputString);
SetNetParameters();
}
void WiFiScan(){
ScanText="<table style='width:75%'>";
ScanText+= "<script>function myFunction(ii)
{document.getElementById('DtTxt').style.backgroundColor = 'yellow';
document.getElementById('DtTxt').value = ii+',NewPass';}</script>";
ScanText+="<tr>";
ScanText+="<th>No</th>";
ScanText+="<th>WiFi SSID</th>";
ScanText+="<th>RSSI (dBm)</th>";
ScanText+="<th>Encryption Type</th>";
ScanText+="</tr>";
int n = WiFi.scanNetworks();
if (n == 0) {
Serial.println("No WiFi networks found");
} else {
Serial.println((String)"Found " + n + " WiFi networks \n");
for (int i = 0; i < n; ++i) {
Serial.print(i + 1);
ScanText+="<tr>";
ScanText+="<td><button type=\"button\" onclick=\"myFunction("+ String(i + 1)
+")\">" + String(i + 1) + "</button></td>";
Serial.print(": ");
Serial.print(WiFi.SSID(i));
ScanText+="<td>" + String(WiFi.SSID(i)) + "</td>";
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
ScanText+="<td>" + String(WiFi.RSSI(i)) + "</td>";
Serial.print(" dBm) [");
Serial.print(get_encryption_type(WiFi.encryptionType(i)));
ScanText+="<td>" + String(get_encryption_type(WiFi.encryptionType(i))) +
"</td>";
ScanText+=")</tr>";
Serial.println("]");
delay(10);
}
}
ScanText+="</table>";
Serial.println("");
}
void SetNetParameters() {
int ii=0;
int index = inputString.indexOf(',');
String SSIDStr=inputString.substring(0, index);
23
ii=SSIDStr.toInt();
SSID=String(WiFi.SSID(ii-1));
PWD=inputString.substring(index+1, inputString.length());
EEPROM.writeString(0, SSID);
EEPROM.commit();
EEPROM.writeString(50, PWD);
EEPROM.commit();
Serial.println("");
Serial.print("SSID: ");
Serial.print(SSID);
Serial.print(" Pass: ");
Serial.println(PWD);
delay(1000);
}
void StartWiFi(){
SSID=EEPROM.readString(0);
PWD=EEPROM.readString(50);
Serial.println("");
Serial.print("SSID: ");
Serial.print(SSID);
Serial.print(" Pass: ");
Serial.println(PWD);
delay(2000);
WiFi.begin(SSID.c_str(), PWD.c_str());
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi..");
}
get_network_info();
}
void get_network_info(){
if(WiFi.status() == WL_CONNECTED) {
Serial.print("Network information for ");
Serial.println(SSID);
Serial.println("\tBSSID : " + WiFi.BSSIDstr());
Serial.print("\tGateway IP : ");
Serial.println(WiFi.gatewayIP());
Serial.print("\tSubnet Mask : ");
Serial.println(WiFi.subnetMask());
Serial.println((String)"\tRSSI : " + WiFi.RSSI() + " dB");
Serial.print("\tESP32 IP : ");
Serial.println(WiFi.localIP());
Serial.print("\tCurrent MAC Address: ");
24
Serial.println(WiFi.macAddress());
}
}
void setup(){
Serial.begin(115200);
pinMode(buttonPin,INPUT_PULLUP);
WiFi.mode(WIFI_STA);
inputString.reserve(100);
EEPROM.begin(100);
if (digitalRead(buttonPin)==LOW) {
WiFiInitWebServer();
}
else
{
StartWiFi();
EEPROM.end();
}
}
void loop() {
server.handleClient();
ESPMultiCoreEx.ino
TaskHandle_t Task1;
TaskHandle_t Task2;
// LED pins
const int led1 = 2;
const int led2 = 4;
void setup() {
Serial.begin(115200);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
25
//create a task that will be executed in the Task1code() function, with priority 1
and executed on core 0
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
//create a task that will be executed in the Task2code() function, with priority 1
and executed on core 1
xTaskCreatePinnedToCore(
Task2code, /* Task function. */
"Task2", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task2, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
delay(500);
}
for(;;){
digitalWrite(led1, HIGH);
delay(1000);
digitalWrite(led1, LOW);
delay(1000);
}
}
for(;;){
digitalWrite(led2, HIGH);
delay(700);
digitalWrite(led2, LOW);
delay(700);
}
26
}
void loop() {
27