3. Chapter PWM

In previous chapters, we learned that a Push Button Switch has two states: Pressed (ON) and Released (OFF), and an LED has a Light ON and OFF state. Is there a middle or intermediated state? We will next learn how to create an intermediate output state to achieve a partially bright (dim) LED.

First, let us learn how to control the brightness of an LED.

3.1. Project Breathing LED

We describe this project as a Breathing Light. This means that an LED that is OFF will then turn ON gradually and then gradually turn OFF like “breathing”. Okay, so how do we control the brightness of an LED to create a Breathing Light? We will use PWM to achieve this goal.

3.1.1. Component List

  1. Raspberry Pi (with 40 GPIO) x1

  2. GPIO Extension Board & Ribbon Cable x1

  3. Breadboard x1

Jumper M/M x2

processing03_00

LED x1

processing03_01

Resistor 220Ω x1

processing03_02

3.1.2. Circuit

Schematic diagram

pr_PWM_Sc

Hardware connection. If you need any support,please feel free to contact us via:

support@freenove.com

pr_PWM_Fr

3.1.3. Sketch

3.1.3.1. Sketch BreathingLED

First, observe the result after running the sketch, and then learn about the code in detail.

  1. Use Processing to open the file Sketch_03_1_1_BreathingLED.

$ processing ~/Freenove_Kit/Processing/Sketches/Sketch_03_1_1_BreadthingLED/Sketch_03_1_1_BreadthingLED.pde
  1. Click on “RUN” to run the code.

After the program is executed, the LED in the circuit will be brightened gradually, and the color of LED pattern in Display Window will deepen gradually at the same time. The progress bar under the paten shows the percentage of completion, and clicking on the inside of window with the mouse can change the progress.

../../../_images/Breathing_Light.png

The following is program code:

 1/*****************************************************
 2 * Filename    : Sketch_03_1_1_BreathingLED
 3 * Description : Using PWM control LED brightness 
 4 * auther      : www.freenove.com
 5 * modification: 2024/09/04
 6 *****************************************************/
 7import freenove.processing.io.*;
 8
 9int ledPin = 17;    //led Pin
10int borderSize = 40;  //
11float t = 0.0;      //progress percent
12float tStep = 0.004;    // speed
13SOFTPWM p = new SOFTPWM(ledPin, 10, 100);    //Create a PWM pin,initialize the duty cycle and period
14void setup() {
15  size(640, 360);  //display window size
16  strokeWeight(4);  //stroke Weight
17}
18
19void draw() {
20  // Show static value when mouse is pressed, animate otherwise
21  if (mousePressed) {
22    int a = constrain(mouseX, borderSize, width - borderSize);
23    t = map(a, borderSize, width - borderSize, 0.0, 1.0);
24  } else {
25    t += tStep;
26    if (t > 1.0) t = 0.0;
27  }
28  p.softPwmWrite((int)(t*100)); //wirte the duty cycle according to t
29  background(255);  //A white background
30  titleAndSiteInfo();  //title and Site infomation
31
32  fill(255, 255-t*255, 255-t*255);  //cycle
33  ellipse(width/2, height/2, 100, 100);
34
35  pushMatrix();
36  translate(borderSize, height - 45);
37  int barLength = width - 2*borderSize;
38
39  barBgStyle();  //progressbar bg
40  line(0, 0, barLength, 0);    
41  line(barLength, -5, barLength, 5);
42
43  barStyle();  //progressbar 
44  line(0, -5, 0, 5);
45  line(0, 0, t*barLength, 0);
46
47  barLabelStyle();    //progressbar label
48  text("progress : "+nf(t*100,2,2),barLength/2,-25);
49  popMatrix();
50}
51
52void titleAndSiteInfo() {
53  fill(0);
54  textAlign(CENTER);    //set the text centered
55  textSize(40);        //set text size
56  text("Breathing Light", width / 2, 40);    //title
57  textSize(16);
58  text("www.freenove.com", width / 2, height - 20);    //site
59}
60void barBgStyle() {
61  stroke(220);
62  noFill();
63}
64
65void barStyle() {
66  stroke(50);
67  noFill();
68}
69
70void barLabelStyle() {
71  noStroke();
72  fill(120);
73}

First, use SOFTPWM class to create a PWM pin, which is used to control the brightness of LED. Then define a variable “t” and a variable “tStep” to control the PWM duty cycle and the rate at which “t” increases.

1float t = 0.0;      //progress percent
2float tStep = 0.004;    // speed
3SOFTPWM p = new SOFTPWM(ledPin, 10, 100);    //Create a PWM pin,initialize the duty cycle and period

In the function draw, if there is a click detected, the coordinate in X direction of the mouse will be mapped into the duty cycle “t”; Otherwise, duty cycle “t” will be increased gradually and PWM with the duty cycle will be output.

 1void draw() {
 2  // Show static value when mouse is pressed, animate otherwise
 3  if (mousePressed) {
 4    int a = constrain(mouseX, borderSize, width - borderSize);
 5    t = map(a, borderSize, width - borderSize, 0.0, 1.0);
 6  } else {
 7    t += tStep;
 8    if (t > 1.0) t = 0.0;
 9  }
10  p.softPwmWrite((int)(t*100)); //wirte the duty cycle according to t

The next code is designed to draw a circle filled with colors in different depth according to the “t” value, which is used to simulate LEDs with different brightness.

1fill(255, 255-t*255, 255-t*255);  //cycle
2ellipse(width/2, height/2, 100, 100);

The last code is designed to draw the progress bar and the percentage of the progress.

 1barBgStyle();  //progressbar bg
 2line(0, 0, barLength, 0);    
 3line(barLength, -5, barLength, 5);
 4
 5barStyle();  //progressbar 
 6line(0, -5, 0, 5);
 7line(0, 0, t*barLength, 0);
 8
 9barLabelStyle();    //progressbar label
10text("progress : "+nf(t*100,2,2),barLength/2,-25);

In processing software, you will see a tag page “SOFTPWM” in addition to the above code.

../../../_images/SOFTPWM.png

3.1.3.2. Reference

class SOFTPWM

public SOFTPWM(int iPin, int dc, int pwmRange):

Constructor, used to create a PWM pin, set the pwmRange and initial duty cycle. The minimum of pwmRange is 0.1ms. So pwmRange=100 means that the PWM duty cycle is 0.1ms*100=10ms.

public void softPwmWrite(int value)

Set PMW duty cycle.

public void softPwmStop()

Stop outputting PWM.