Micro All Notes WithCodeSem2

Download as pdf or txt
Download as pdf or txt
You are on page 1of 70

Microcontroller Applications

Part 1
Arduino

School of Engineering
Electrical Engineering

University of Jordan

1
Unit 1
Introduction to Microcontrollers

Definition:

“An integrated circuit that contains a microprocessor along


with memory and associated circuits and that controls some
or all the functions of an electronic device or system ”

Outcomes of the course:

•Understand the main concepts of Microcontrollers.


•Understand the Microcontroller I/O and Interrupts.
•Understand the C programming for Microcontrollers.
•Write C programs for Microcontrollers.
•Write Basic programs in Micro-Python for Microcontrollers.

Examples of microcontrollers:

•Arduino Uno.
•STM32F103.
•ESP32 and ESP8266.
•Sipeed.

2
Unit 2
Microcontroller Components

Figure 1 : ATMEGA328P block diagram


1 : ISR = Interrupt service routine , it handles interrupts and deliver them to CPU
2: Watchdog timer (WDT), automatically restarts microcontroller
3: Brown Out Reset.
4: ADC = Analogue to digital converter

See Figures at the end of this document.

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. I/O and Communication:


I/O (Digital and Analog)
Communication peripherals used in microcontrollers:
• 1 Wire
Floating
This is a master-slave topology

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.

PROGRAMMING LANGUAGES USED


1. Assembly language, low level but hard to read.
2. Compiled languages, such as: C/C++ languages.

*Previously, microcontrollers did not need an operating system. Recently,


RTOS – real time operating systems- are implemented such as Embedded
Linux.
*Most commercial devices that use microcontrollers have ROM instead of
EEPROM

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

Intel 8051 processors


o Core of all ARM processors
o Used for keyboards
Hermetically sealed
o Device in a container → usually metallic
o No air or dust enters
o Filled with Nitrogen so it doesn’t rust
o Usually used for military applications
o High cost
Soft reset
o Restart alone
o When not real time, we cannot change things → so restart (soft reset)
o To make initialization
1
𝑓=
2𝜋√𝐿0 𝐶0
Variable → use PLL → to control frequency

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.

We will run C/C++ code on Arduino IDE - Integrated Development Environment-

Main structure of the IDE :


1. Text editor functions (File , Edit )
2. Compiler functions (Verify & Debug , upload to board,
Tools, Help)
Components of any Arduino program:
void setup()
// Use it to initialize variables, pin modes, start using
libraries, etc.
//Runs only once.
void loop()
// This is the main function , it runs repeatedly

Getting started with Arduino :

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 :

A way of communicating to board, where USART (RS232) protocol –


Universal Synchronous Asynchronous Receiving Transmitting- is used, this
protocol was first implemented in computers
*DP9 – 9 pin – Serial port is used in computers
Tx 10101001…→ Rx
Rx  01010011… Tx Full-duplex: data transmitted both
GND ways at the same time.
Half-duplex: one way at a time
Full-Duplex communication

Figure 5 : 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

Pin Input Impedance

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:

LM35 Temperature Sensor:


Vcc Vref
A5
A4
Analogue A3
A2 A-to-D 8-Bits 0 – 1023 voltage
CLK
Pins A1
Converter 2-Bits levels
A0
Registers
Vx α Temp. Registers
Counter

LM35 outputs voltage from


4 -20V , this will be
MUX CTRL
converted in Arduino using Protection cct
A-to-D converter

analogRead(Analog pin): reads analog


map(x, 0, 1023 , 0 , 255):converts from 10 to
8 bits

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

Real A-to-D converter are used in


17ESP32, called Ladder circuit
VDC = 5 * τ / T
τ/T = Duty
cycle

*PWM can be
used to drive
LED or Motor

Pulse Width Modulation used as D-to-A in Arduino

Dht11 Temperature Sensor:


Uses 1-wire protocol (same as I2C)
<dht.h> library is used to enable communication

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

o We put fly wheeling diode for the protection of inductive loads


o To amplify the sound, we can add the signals using superposition
𝟏
∗𝑹 𝟏
o 𝑽𝒐𝒖𝒕𝟏 = 𝑽𝒔𝟏 ∗ 𝟑
𝟒 = ∗ 𝑽𝒔𝟏
∗𝑹 𝟒
𝟑
𝟏
o 𝑽𝒐𝒖𝒕(𝒕𝒐𝒕𝒂𝒍) = ∗ (𝑽𝒔𝟏 + 𝑽𝒔𝟐 + 𝑽𝒔𝟑 )
𝟒
o 𝑽𝒔𝒐𝒖𝒏𝒅 = 𝟐𝟎 ∗ √𝑻 , where T = temperature in kelvin
o 𝑽𝒔𝒐𝒖𝒏𝒅−𝒓𝒐𝒐𝒎 𝒕𝒆𝒎𝒑 = 𝟐𝟎 ∗ √𝟑𝟎𝟎 = 𝟑𝟒𝟔. 𝟒 𝒎/𝒔
o Tone → heard
o 11 KHz – 15 KHz can be heard by the human ear
o Above → ultrasound
o DTMF in cellular phones for example in answering machines

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 :

First method: through time constant

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

MPR121 : Capacitive touch sensor


Has 12 touch sensors , connected to capacitance meter ,
senses if any pin is touched or released , uses I2C communication

External Note:
*To measure inductance , we make a resonance circuit,
1
where a known value of capacitance is used.
WIRED COMMUNICATION PROTOCOLS :

RS485 & CAN bus


Tx

Rx Driver

Packet[Control , Data , CRC : for Parity Check]


I 2C
To use multiple devices connected on same pin
Low speed

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

The main reasons we use interrupts for are:

• To detect pin changes (e.g., rotary encoders, button presses)


• Timer interrupts - used for comparing/overflowing timers
• Communication interrupts (data transfer)
• ADC conversions (analog to digital)
• Memory ready for use

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

Variance of error = 𝜺𝟐 = 𝒎𝒆𝒂𝒏 𝒔𝒒𝒖𝒂𝒓𝒆 𝒆𝒓𝒓𝒐𝒓


𝟐
𝚫𝟐
𝜺 =
𝟏𝟐
Flash quantizer

6
D/A converter:
o Ladder circuit:

𝑽𝑯 (𝑹𝟒 //𝑹𝟑 //𝑹𝟐 )


𝑽𝒐𝒖𝒕 =
𝑹𝟏 + (𝑹𝟒 //𝑹𝟑 //𝑹𝟐 )
𝑹𝟏 < 𝑹𝟐 < 𝑹𝟑 < 𝑹𝟒
Most significant bit → least significant bit
If R = 1
R1 = R → R2 = 2*R → R3 = 4*R → R4 = 8*R
𝟏 𝟏 𝟏
𝑽𝑯 ( + + )
𝑽𝒐𝒖𝒕 = 𝟐 𝟒 𝟖
𝟏 𝟏 𝟏
𝟏+( + + )
𝟐 𝟒 𝟖

7
FREQUENCY COUNTER
Using timers to measure frequency of a signal,

pulsein()is used to measure time for one pulse


micros() count time in microseconds
*Using interrupts for counters is better for time-specific tasks

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

*analogWrite(pin , dutycycle) is used to generate PWM signal

SPI
Used for fast transmission of data , used for graphical interfaces : cameras ,
displays,
it has 4 pins : Clock , Datain , Dataout , Ground

EEPROM.write(addr, val); //write bytes


int value = EEPROM.read(address); //read bytes
*EEPROM uses
EEPROM.put(address SPI or
, value); I2C , which
// saves is used
any value forsplitting
without storingit data like -wireless network
into bytes
EEPROM.update(address , value);
username and password-, preserving it for very long time

*Variables could also be stored directly to flash memory using the following
directives:
PROGMEM or F()
8

const PROGMEM dataType variableName[] = {}; // or this one


Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));
Arduino Codes
Serial Communication
#include <SoftwareSerial.h>

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.

// REQUIRES the following Arduino libraries:


// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
// - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>

#define DHTPIN 2 // Digital pin connected to the DHT sensor


// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
// Pin 15 can work but DHT must be disconnected during program upload.

// Uncomment the type of sensor in use:


#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)

// See guide for details on sensor wiring and usage:


// https://learn.adafruit.com/dht/overview

DHT_Unified dht(DHTPIN, DHTTYPE);

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

Figure 2 : Block diagram of microcontroller with Wi-Fi

-Wi-Fi is transmitted by OFDM or spread


spectrum
-Two main internet protocols : TCP, UDP
-IP Stack : programs that are called as function
like Security protocols : generating keys from
random number , time … , etc. , choosing if
data sent by TCP or UDP protocol.
IoT

1
Connecting sensors , devices , appliances
to the internet , for different applications.
IP 1
IP 2
IP N
App.

Server Cloud LAN : Access point


WAN
Client – Server Model

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()

#include <Arduino_JSON.h> //To deal with JSON


files received from server :

3
- JSONVar : Class used to define JSON
objects to parse from JSON file

In WifiScanConnectWebFinal.ino file :
#include <EEPROM.h> // To operate EEPROM :

EEPROM.begin(100); //start operating and


setting 100 addresses in memory
EEPROM.end();
EEPROM.writeString(0 , SSID); // Write a
string starting at address 50
EEPROM.readString(50); // read string
starting from address 50
EEPROM.commit(); //Force EEPROM to write
#include <WebServer.h> //Used to initialize a
server :
-set an IP address for this server;
specifying gateway and subnet
-define port of webserver (80 for HTTP)
server.on("/", handle_root) // opens
homepage of server
server.on("/SendData", handle_msg);
//Receive messages from client (sending on
server)
server.send(200, "text/html", HTML); //save
html file on server

#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

We could add functions as libraries


5
In WifiSimple.py file :

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

#To work as an access point


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'))

Other libraries and functions


from machine import Pin :
6
ex.
p0 = Pin(0, Pin.OUT)
p0.value(0)

import time :
time.sleep(seconds)

#To initialize an HTTP server


We use usocket

import usocket as socket :


server = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)

#Set an IP address and port for server


server.bind(('192.168.10.1', 80))

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())

#set your unique OpenWeatherMap.org URL


open_weather_map_url = 'http://api.openweathermap.org/data/2.5/weather?q=' + city +
',' + country_code + '&APPID=' + open_weather_map_api_key

weather_data = requests.get(open_weather_map_url)
print(weather_data.json())

# Location (City and Country code)


location = 'Location: ' + weather_data.json().get('name') + ' - ' +
weather_data.json().get('sys').get('country')
print(location)

# 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)

# Bind the socket to an IP address and port


server.bind(('192.168.10.1', 80))

# Set the socket to listen for incoming connections


server.listen(1)

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()

HTML = "<!DOCTYPE html>\


<html>\
<body>\
<h4 style='color:blue'>Network Selected</h4>\
</body>\
</html>"

return HTML

def StartWiFi():

with open('data.txt', 'r') as f:


inputString = f.read()
SSID = inputString[0]

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>

const char* ssid = "FiberHome.-2.4G";


const char* password = "jam123456";

// Your Domain name with URL path or IP address with path


String openWeatherMapApiKey = "d100fb5ad1c5460d2e66b4a62ce90781";

// Replace with your country code and city


String city = "Amman";

14
String countryCode = "JO";

unsigned long lastTime = 0;


// Set timer to 10 seconds (10000)
unsigned long timerDelay = 10000;

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());

Serial.println("Timer set to 10 seconds (timerDelay variable), it will take 10


seconds before publishing the first reading.");
}

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);

// JSON.typeof(jsonVar) can be used to get the type of the var


if (JSON.typeof(myObject) == "undefined") {
Serial.println("Parsing input failed!");
return;
}

Serial.print("JSON object = ");


Serial.println(myObject);
Serial.print("Temperature: ");
Serial.println(myObject["main"]["temp"]);
15
Serial.print("Pressure: ");
Serial.println(myObject["main"]["pressure"]);
Serial.print("Humidity: ");
Serial.println(myObject["main"]["humidity"]);
Serial.print("Wind Speed: ");
Serial.println(myObject["wind"]["speed"]);
}
else {
Serial.println("WiFi Disconnected");
}
lastTime = millis();
}
}

String httpGETRequest(const char* serverName) {


WiFiClient client;
HTTPClient http;

// Your Domain name with URL path or IP address with path


http.begin(client, serverName);

// Send HTTP POST request


int httpResponseCode = http.GET();

String payload = "{}";

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");

// WiFi.scanNetworks will return the number of networks found


int n = WiFi.scanNetworks();
Serial.println("[*] Scan done");
if (n == 0) {
Serial.println("[-] No WiFi networks found");
} else {
Serial.println((String)"[+] " + n + " WiFi networks found\n");
for (int i = 0; i < n; ++i) {
// Print SSID, RSSI and WiFi Encryption for each network found
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("");

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;

const int buttonPin = 4;

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 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>

/* Put your SSID & Password */


const char* Webssid = "ESPWeb"; // Enter SSID here
const char* Webpassword = ""; //Enter Password here

/* Put IP Address details */


IPAddress local_ip(192,168,100,1);
IPAddress gateway(192,168,100,1);
IPAddress subnet(255,255,255,0);
WebServer server(80);

// WIFI
String inputString;
String SSID;
String PWD;
String ScanText;
String HTML;

const int buttonPin = 4;

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>";

server.send(200, "text/html", 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();
}

HTML = "<!DOCTYPE html>\


<html>\
<body>\
<h4 style='color:blue'>Network Selected</h4>\
</body>\
</html>";

server.send(200, "text/html", HTML);


}

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):
22
return "WPA2_ENTERPRISE";
}
}

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);
}

//Task1code: blinks an LED every 1000 ms


void Task1code( void * pvParameters ){
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());

for(;;){
digitalWrite(led1, HIGH);
delay(1000);
digitalWrite(led1, LOW);
delay(1000);
}
}

//Task2code: blinks an LED every 700 ms


void Task2code( void * pvParameters ){
Serial.print("Task2 running on core ");
Serial.println(xPortGetCoreID());

for(;;){
digitalWrite(led2, HIGH);
delay(700);
digitalWrite(led2, LOW);
delay(700);
}
26
}

void loop() {

27

You might also like