Skip to content

Commit

Permalink
pwm simulation
Browse files Browse the repository at this point in the history
  • Loading branch information
ImplFerris committed Dec 24, 2024
1 parent 985b498 commit efedc23
Show file tree
Hide file tree
Showing 3 changed files with 469 additions and 2 deletions.
174 changes: 172 additions & 2 deletions src/core-concepts/pwm/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,75 @@

# Pulse Width Modulation (PWM)

<style>

.slider-container {
margin: 20px 0;
}

label {
margin-right: 10px;
}

.led-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
position: relative;
}

.led-body {
width: 30px;
height: 40px;
background: radial-gradient(circle at center, #ff5555, #cc0000);
border-radius: 50% 50% 0 0;
border: 2px solid #990000;
position: relative;
box-shadow: 0 0 10px rgba(255, 85, 85, 0.8);
}

.led-body::after {
content: '';
position: absolute;
top: 5px;
left: 7px;
width: 16px;
height: 16px;
background: rgba(255, 255, 255, 0.4);
border-radius: 50%;
}

.led-pin {
width: 2px;
height: 40px;
background-color: #333;
position: relative;
}

.anode {
height: 50px; /* Longer pin for the anode */
margin-right: 15px;
background-color: #666;
}

.cathode {
height: 40px; /* Shorter pin for the cathode */
margin-left: 15px;
background-color: #333;
position: absolute;
margin-top: 45px;
}

canvas {
border: 1px solid #ccc;
display: block;
margin: 10px auto;
}
#pwmCanvas {
background-color: #fefefe;
</style>

In this section, we will explore what is PWM and why we need it.

## Digital vs Analog
Expand Down Expand Up @@ -29,10 +98,34 @@ The percentage of time the signal is on during one cycle.
<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>


## PWM Simulation

Here is the interactive simulation. Use the sliders to adjust the duty cycle and frequency, and watch how the pulse width and LED brightness change.


<canvas id="pwmCanvas" width="800" height="200"></canvas>
<div class="led-container">
<div class="led-body" id="ledBody"></div>
<div class="led-pin anode"></div>
<div class="led-pin cathode"></div>
</div>

<div class="slider-container">
<label for="dutyCycle">Duty Cycle (%): </label>
<input type="range" id="dutyCycle" min="0" max="100" value="50">
<span id="dutyCycleValue">50</span>%
</div>
<div class="slider-container">
<label for="frequency">Frequency (Hz): </label>
<input type="range" id="frequency" min="1" max="50" value="10">
<!-- <span id="frequencyValue">x</span> Hz -->
</div>

## 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:
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. So, a higher frequency means a shorter period, resulting in faster switching between HIGH and LOW states.

\\[
\text{Frequency (Hz)} = \\frac{1}{\text{Period (s)}}
Expand All @@ -51,7 +144,6 @@ For example, if the period is 20ms(0.02s), the frequency will be 50Hz.
\\]



**Calculating Cycle count from Frequency per second**

The Formula to calculate cycle count:
Expand All @@ -60,3 +152,81 @@ The Formula to calculate cycle count:
\\]

If a PWM signal has a frequency of 50Hz, it means it completes 50 cycles in one second.

<script>
const pwmCanvas = document.getElementById('pwmCanvas');
const pwmCtx = pwmCanvas.getContext('2d');

const dutyCycleSlider = document.getElementById('dutyCycle');
const dutyCycleValue = document.getElementById('dutyCycleValue');
const frequencySlider = document.getElementById('frequency');
const frequencyValue = document.getElementById('frequencyValue');
const ledBody = document.getElementById('ledBody');

let dutyCycle = 50; // Initial duty cycle in percentage
let frequency = 10; // Initial frequency in Hz

function drawPWM() {
pwmCtx.clearRect(0, 0, pwmCanvas.width, pwmCanvas.height);

const period = 1000 / frequency; // Period in ms
const onTime = period * (dutyCycle / 100); // On time in ms
const offTime = period - onTime; // Off time in ms

const totalWidth = pwmCanvas.width;
const cycles = frequency; // Number of cycles to display
const cycleWidth = totalWidth / cycles;

pwmCtx.strokeStyle = 'black';
pwmCtx.lineWidth = 2;
pwmCtx.beginPath();

let x = 0;

if (dutyCycle === 100) {
pwmCtx.moveTo(0, 50);
pwmCtx.lineTo(pwmCanvas.width, 50);
} else if (dutyCycle === 0) {
pwmCtx.moveTo(0, 150);
pwmCtx.lineTo(pwmCanvas.width, 150);
} else {
for (let i = 0; i < cycles; i++) {
const highWidth = (onTime / period) * cycleWidth;
const lowWidth = (offTime / period) * cycleWidth;

pwmCtx.moveTo(x, 50);
pwmCtx.lineTo(x + highWidth, 50);
pwmCtx.lineTo(x + highWidth, 150);
pwmCtx.lineTo(x + highWidth + lowWidth, 150);
pwmCtx.lineTo(x + highWidth + lowWidth, 50);

x += cycleWidth;
}
}
pwmCtx.stroke();
}

function updateLED() {
const brightness = dutyCycle / 100;

ledBody.style.background = `radial-gradient(circle at center, rgba(255, 85, 85, ${brightness}), #cc0000)`;
}

function update() {
dutyCycle = parseInt(dutyCycleSlider.value, 10);
frequency = parseInt(frequencySlider.value, 10);

dutyCycleValue.textContent = dutyCycle;
// frequencyValue.textContent = frequency;

drawPWM();
updateLED();
}

dutyCycleSlider.addEventListener('input', update);
frequencySlider.addEventListener('input', update);

// Initial draw
drawPWM();
updateLED();
</script>
8 changes: 8 additions & 0 deletions src/core-concepts/pwm/led-pwm-controller.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,13 @@ The ESP32 has LED PWM Controller(LEDC) that generates PWM signals for controllin

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.

<div class="alert-box alert-box-info">
<span class="icon"><i class="fa fa-info"></i></span>
<div class="alert-content">
<b class="alert-title">High vs Low Speed channels</b>
<p>High-speed channels use hardware to automatically adjust the PWM duty cycle in a glitch-free manner, ensuring smooth operation. In contrast, low-speed channels rely on software to manually adjust the duty cycle.</p>
</div>
</div>

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

Loading

0 comments on commit efedc23

Please sign in to comment.