-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
48b442a
commit d66881e
Showing
21 changed files
with
403 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,15 @@ | ||
# Summary | ||
|
||
- [Introduction](./index.md) | ||
- [ESP32 Family](./esp32-family.md) | ||
- [ESP32 Family](./esp32-intro/esp32-family.md) | ||
- [Pinout Diagram](./esp32-intro/pinout.md) | ||
- [Dev Environment](./dev-env.md) | ||
- [Quick Start](./quick-start.md) | ||
- [Async and Embassy](./embassy.md) | ||
- [Pinout Diagram](./pinout.md) | ||
<!-- - [Dimming LED](./dimming-led/index.md) --> | ||
- [Core Concepts](./core-concepts/index.md) | ||
- [Voltage Divider](./core-concepts/voltage-divider.md) | ||
- [ADC](./core-concepts/adc.md) | ||
- [PWM](./core-concepts/pwm/index.md) | ||
- [no_std, no_main in Rust](./core-concepts/no-std-main.md) | ||
- [Dimming LED](./dimming-led/index.md) | ||
- [LED PWM Controller](./core-concepts/pwm/led-pwm-controller.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# ADC (Analog to Digital Converter) | ||
|
||
An Analog-to-Digital Converter (ADC) is a device used to convert analog signals (continuous signals like sound, light, or temperature) into digital signals (discrete values, typically represented as 1s and 0s). This conversion is necessary for digital systems like microcontrollers (e.g., Raspberry Pi, Arduino) to interact with the real world. For example, sensors that measure temperature or sound produce analog signals, which need to be converted into digital format for processing by digital devices. | ||
|
||
<img style="display: block; margin: auto;" alt="ADC" src="./images/adc.jpg"/> | ||
|
||
## ADC Resolution | ||
The resolution of an ADC refers to how precisely the ADC can measure an analog signal. It is expressed in bits, and the higher the resolution, the more precise the measurements. | ||
|
||
- 8-bit ADC produces digital values between 0 and 255. | ||
- 10-bit ADC produces digital values between 0 and 1023. | ||
- 12-bit ADC produces digital values between 0 and 4095. | ||
|
||
The resolution of the ADC can be expressed as the following formula: | ||
\\[ | ||
\text{Resolution} = \frac{\text{Vref}}{2^{\text{bits}} - 1} | ||
\\] | ||
|
||
## ESP32 | ||
The ESP32 has 12-bit Analogue to Digital Converter (ADC). So, it provides values ranging from 0 to 4095 (4096 possible values) | ||
|
||
\\[ | ||
\text{Resolution} = \frac{3.3V}{2^{12} - 1} = \frac{3.3V}{4095} \approx 0.000805 \text{V} \approx 0.8 \text{mV} | ||
\\] | ||
|
||
## Pins | ||
//TODO: details of ESP32 ADC Pins | ||
|
||
## ADC Value and LDR Resistance in a Voltage Divider | ||
In a voltage divider with an LDR and a fixed resistor, the output voltage \\( V_{\text{out}} \\) is given by: | ||
|
||
\\[ | ||
V_{\text{out}} = V_{\text{in}} \times \frac{R_{\text{LDR}}}{R_{\text{LDR}} + R_{\text{fixed}}} | ||
\\] | ||
|
||
It is same formula as explained in the previous chapter, just replaced the \\({R_2}\\) with \\({R_{\text{LDR}}}\\) and \\({R_1}\\) with \\({R_{\text{fixed}}}\\) | ||
|
||
- **Bright light** (low LDR resistance): \\( V_{\text{out}} \\) decreases, resulting in a lower ADC value. | ||
- **Dim light** (high LDR resistance): \\( V_{\text{out}} \\) increases, leading to a higher ADC value. | ||
|
||
## Example ADC value calculation: | ||
|
||
**Bright light**: | ||
|
||
Let's say the Resistence value of LDR is \\(1k\Omega\\) in the bright light (and we have \\(10k\Omega\\) fixed resistor). | ||
|
||
\\[ | ||
V_{\text{out}} = 3.3V \times \frac{1k\Omega}{1k\Omega + 10k\Omega} \approx 0.3V | ||
\\] | ||
|
||
The ADC value is calculated as: | ||
\\[ | ||
\text{ADC value} = \left( \frac{V_{\text{out}}}{V_{\text{ref}}} \right) \times (2^{12} - 1) \approx \left( \frac{0.3}{3.3} \right) \times 4095 \approx 372 | ||
\\] | ||
|
||
**Darkness**: | ||
|
||
Let's say the Resistence value of LDR is \\(140k\Omega \\) in very low light. | ||
|
||
\\[ | ||
V_{\text{out}} = 3.3V \times \frac{140k\Omega}{140k\Omega + 10k\Omega} \approx 3.08V | ||
\\] | ||
|
||
The ADC value is calculated as: | ||
\\[ | ||
\text{ADC value} = \left( \frac{V_{\text{out}}}{V_{\text{ref}}} \right) \times (2^{12} - 1) \approx \left( \frac{3.08}{3.3} \right) \times 4095 = 3822 | ||
\\] | ||
|
||
### **Converting ADC value back to voltage**: | ||
|
||
Now, if we want to convert the ADC value back to the input voltage, we can multiply the ADC value by the resolution (0.8mV). | ||
|
||
For example, let's take an ADC value of 3822: | ||
|
||
\\[ | ||
\text{Voltage} = 3822 \times 0.8mV = 3057.6mV \approx 3.06V | ||
\\] | ||
|
||
|
||
## Reference | ||
- [What is Analog to Digital Converter & Its Working](https://www.elprocus.com/analog-to-digital-converter/) | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Core concepts | ||
|
||
This section primarily covers theoretical concepts. Feel free to skip it and dive into the exercises instead. As you work through the exercises related to each concept, we'll link back to the theory. This approach may help you understand the material better by showing you exactly where and why these concepts are needed in practice. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# No Standard and Main in Rust | ||
|
||
If you haven't read "The Embedded Rust Book" yet, I highly recommend you to check it out. | ||
[https://docs.rust-embedded.org/book/intro/index.html](https://docs.rust-embedded.org/book/intro/index.html) | ||
|
||
## #![no_std] | ||
The `#![no_std]` attribute disables the use of the standard library (std). This is necessary most of the times for embedded systems development, where the environment typically lacks many of the resources (like an operating system, file system, or heap allocation) that the standard library assumes are available. | ||
|
||
**Related Resources:** | ||
- [Rust official doc](https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute) | ||
- [The Embedded Rust Book](https://docs.rust-embedded.org/book/intro/no-std.html) | ||
- [Writing an OS in Rust Book](https://os.phil-opp.com/freestanding-rust-binary/#the-no-std-attribute) | ||
|
||
## #![no_main] | ||
The `#![no_main]` attribute is to indicate that the program won't use the standard entry point (fn main). Instead, it provides a custom entry point, usually required when working with embedded systems where the runtime environment is minimal or non-existent. | ||
|
||
**Related Resources:** | ||
- [Rust official doc](https://doc.rust-lang.org/reference/crates-and-source-files.html?highlight=no_main#the-no_main-attribute) | ||
- [Writing an OS in Rust Book](https://os.phil-opp.com/freestanding-rust-binary/#overwriting-the-entry-point) | ||
|
||
|
||
## Panic Handler | ||
A panic handler is a function in Rust that defines what happens when your program encounters a panic. In environments without the standard library (when using no_std attribute), you need to create this function yourself using the #[panic_handler] attribute. This function must follow a specific format and can only appear once in your program. It provides details about the error, such as where it happened and why. By setting up a panic handler, you can choose how to respond to errors, like logging them for later review or stopping the program completely. | ||
|
||
You don't have to define your own panic handler function; you can use existing crates such as panic_halt or panic_probe instead. | ||
|
||
For example, we used the panic_halt crate to halt execution when a panic occurs. | ||
```rust | ||
use panic_halt as _; | ||
``` | ||
The program will stop and remain in this infinite loop whenever a panic occurs. | ||
|
||
In fact, the [panic_halt crate's code](https://github.com/korken89/panic-halt/blob/master/src/lib.rs) implements a simple panic handler, which looks like this: | ||
```rust | ||
use core::panic::PanicInfo; | ||
use core::sync::atomic::{self, Ordering}; | ||
|
||
#[inline(never)] | ||
#[panic_handler] | ||
fn panic(_info: &PanicInfo) -> ! { | ||
loop { | ||
atomic::compiler_fence(Ordering::SeqCst); | ||
} | ||
} | ||
``` | ||
|
||
**Related Resources:** | ||
- [Rust official doc](https://doc.rust-lang.org/nomicon/panic-handler.html) | ||
- [The Embedded Rust Book](https://docs.rust-embedded.org/book/start/panicking.html) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
|
||
# Pulse Width Modulation (PWM) | ||
|
||
In this section, we will explore what is PWM and why we need it. | ||
|
||
## Digital vs Analog | ||
In a digital circuit, signals are either high (such as 5V or 3.3V) or low (0V), with no in-between values. These two distinct states make digital signals ideal for computers and digital devices, as they're easy to store, read, and transmit without losing accuracy. | ||
|
||
Analog signals, however, can vary continuously within a range, allowing for any value between a High and Low voltage. This smooth variation is valuable for applications requiring fine control, such as adjusting audio volume or light brightness. | ||
|
||
Devices like servo motors and LEDs(for dimming effect) often need gradual, precise control over voltage, which analog signals provide through their continuous range. | ||
|
||
Microcontrollers use PWM to bridge this gap. | ||
|
||
## What is PWM? | ||
PWM stands for **Pulse Width Modulation**, creates an analog-like signal by rapidly pulsing a digital signal on and off. The average output voltage, controlled by adjusting the pulse's high duration or "duty cycle," can simulate a continuous analog level. | ||
|
||
<img style="display: block; margin: auto;" alt="LED PWM" src="../images/led-pwm.jpg" /> | ||
|
||
|
||
The **duty cycle** of the signal determines how long it stays on compared to how long it stays off. | ||
|
||
- **Duty Cycle**: | ||
The percentage of time the signal is on during one cycle. | ||
- For example: | ||
- 100% duty cycle means the signal is always on. | ||
- 50% duty cycle means the signal is on half the time and off half the time. | ||
- 0% duty cycle means the signal is always off. | ||
<img style="display: block; margin: auto;" alt="Duty Cycle" src="../images/pwm-duty-cycle.png" /> | ||
<span style="text-align: center;display: block; margin: auto; font-size: 12px;">Image Credit: Wikipedia</span> | ||
|
||
## Period and Frequency | ||
Period is the total time for one on-off cycle to complete. | ||
|
||
The frequency of a PWM signal is the number of cycles it completes in one second, measured in Hertz (Hz). Frequency is the inverse of the period: | ||
|
||
\\[ | ||
\text{Frequency (Hz)} = \\frac{1}{\text{Period (s)}} | ||
\\] | ||
|
||
So if the period is 1 second, then the frequency will be 1HZ. | ||
|
||
\\[ | ||
1 \text{Hz} = \\frac{1 \text{ cycle}}{1 \text{ second}} = \\frac{1}{1 \text{ s}} | ||
\\] | ||
|
||
For example, if the period is 20ms(0.02s), the frequency will be 50Hz. | ||
|
||
\\[ | ||
\text{Frequency} = \\frac{1}{20 \text{ ms}} = \\frac{1}{0.02 \text{ s}} = 50 \text{ Hz} | ||
\\] | ||
|
||
|
||
|
||
**Calculating Cycle count from Frequency per second** | ||
|
||
The Formula to calculate cycle count: | ||
\\[ | ||
\text{Cycle Count} = \text{Frequency (Hz)} \\times \text{Total Time (seconds)} | ||
\\] | ||
|
||
If a PWM signal has a frequency of 50Hz, it means it completes 50 cycles in one second. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# LED PWM Controller |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
$ 1 0.000005 10.20027730826997 63 10 62 5e-11 | ||
v 240 400 240 80 0 0 40 3.3 0 0 0.5 | ||
w 240 80 368 80 0 | ||
r 368 80 368 240 0 10000 | ||
w 240 400 368 400 0 | ||
O 368 240 432 240 1 0 | ||
x 378 144 393 147 4 12 R1 | ||
x 377 305 392 308 4 12 R2 | ||
x 199 219 227 222 4 14 3.3V | ||
x 209 201 223 204 4 10 Vin | ||
x 424 227 444 230 4 10 Vout | ||
374 368 240 368 400 0 0.0001 Light\sBrightness |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
$ 1 0.000005 10.20027730826997 63 10 62 5e-11 | ||
v 240 400 240 80 0 0 40 3.3 0 0 0.5 | ||
w 240 80 368 80 0 | ||
r 368 80 368 240 0 10000 | ||
w 240 400 368 400 0 | ||
O 368 240 432 240 1 0 | ||
x 378 144 393 147 4 12 R1 | ||
x 377 305 392 308 4 12 R2 | ||
r 368 400 368 240 0 10000 | ||
x 199 219 227 222 4 14 3.3V | ||
x 209 201 223 204 4 10 Vin | ||
x 424 227 444 230 4 10 Vout |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Voltage Divider | ||
|
||
A **voltage divider** is a simple circuit that reduces an input voltage \\( V_{in} \\) to a lower output voltage \\( V_{out} \\) using two series resistors. The resistor connected to the input voltage \\( V_{in} \\) is called \\( R_{1} \\), and the other resistor is \\( R_{2} \\). The output voltage \\( V_{out} \\) is taken from the junction between \\( R_{1} \\) and \\( R_{2} \\), producing a fraction of \\( V_{in} \\). | ||
|
||
## Circuit | ||
|
||
<img style="display: block; margin: auto;" alt="Voltage Divider" src="./images/voltage-divider.png"/> | ||
|
||
The output voltage (V<sub>out</sub>) is calculated using this formula: | ||
|
||
\\[ | ||
V_{out} = V_{in} \times \frac{R_2}{R_1 + R_2} | ||
\\] | ||
|
||
### Example Calculation for \\( V_{out} \\) | ||
|
||
Given: | ||
- \\( V_{in} = 3.3V \\) | ||
- \\( R_1 = 10 k\Omega \\) | ||
- \\( R_2 = 10 k\Omega \\) | ||
|
||
Substitute the values: | ||
|
||
\\[ | ||
V_{out} = 3.3V \times \frac{10 k\Omega}{10 k\Omega + 10 k\Omega} = 3.3V \times \frac{10}{20} = 3.3V \times 0.5 = 1.65V | ||
\\] | ||
|
||
|
||
The output voltage \\( V_{out} \\) is 1.65V. | ||
|
||
|
||
```rust,editable | ||
fn main() { | ||
// You can edit the code | ||
// You can modify values and run the code | ||
let vin: f64 = 3.3; | ||
let r1: f64 = 10000.0; | ||
let r2: f64 = 10000.0; | ||
let vout = vin * (r2 / (r1 + r2)); | ||
println!("The output voltage Vout is: {:.2} V", vout); | ||
} | ||
``` | ||
|
||
## Use cases | ||
|
||
Voltage dividers are used in applications like potentiometers, where the resistance changes as the knob is rotated, adjusting the output voltage. They are also used to measure resistive sensors such as light sensors and thermistors, where a known voltage is applied, and the microcontroller reads the voltage at the center node to determine sensor values like temperature. | ||
|
||
|
||
## Simulator | ||
|
||
I used the website [https://www.falstad.com/circuit/e-voltdivide.html](https://www.falstad.com/circuit/e-voltdivide.html) to create this diagram. It's a great tool for drawing circuits. You can download the file I created, [`voltage-divider.circuitjs.txt`](./voltage-divider.circuitjs.txt), and import it to experiment with the circuit. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# LED PWM | ||
|
||
The ESP32 has LED PWM Controller(LEDC) that generates PWM signals for controlling LEDs(example, dimming effect). However, its functionality isn't limited to LEDs;you can use it for other applications as well. If you are not familiar with PWM(Pulse Width Modulation), i recommend you to check the PWM section [here](../core-concepts/pwm.md). | ||
|
||
The LEDC includes 16 independent PWM generators and supports a maximum PWM duty cycle resolution of 20 bits. The 16 PWM channels further classified into two types: 8 high speed channel and 8 low speed channels. | ||
|
||
The PWM controller can automatically increase or decrease the duty cycle gradually, allowing for smooth fades without using the processor. For more details, refer to page 390 of the [ESP32 Technical Reference Manual](https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf#ledpwm). | ||
|
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.