Chapter 5 RGB LED

In this chapter, we will learn how to control an RGB LED.

An RGB LED has 3 LEDs integrated into one LED component. It can respectively emit Red, Green and Blue light. In order to do this, it requires 4 pins (this is also how you identify it). The long pin (1) is the common which is the Anode (+) or positive lead, the other 3 are the Cathodes (-) or negative leads. A rendering of an RGB LED and its electronic symbol are shown below. We can make RGB LED emit various colors of light and brightness by controlling the 3 Cathodes (2, 3 & 4) of the RGB LED

../../../_images/Chapter05_00.png

Red, Green, and Blue light are called 3 Primary Colors when discussing light (Note: for pigments such as paints, the 3 Primary Colors are Red, Blue and Yellow). When you combine these three Primary Colors of light with varied brightness, they can produce almost any color of visible light. Computer screens, single pixels of cell phone screens, neon lamps, etc. can all produce millions of colors due to phenomenon.

../../../_images/Chapter05_01.png

If we use a three 8 bit PWM to control the RGB LED, in theory, we can create 28*28*28=16777216 (16 million) colors through different combinations of RGB light brightness.

Next, we will use RGB LED to make a multicolored LED.

Project 5.1 RainbowLED

In this project, we will make a multicolored LED, which we can program the RGB LED to automatically change colors.

Component List

Freenove Projects Board for Raspberry Pi

Chapter01_04

Raspberry Pi

Chapter01_05

GPIO Ribbon Cable

Chapter01_06

Jumper Wire

Chapter05_02

RGBLED Module

Chapter05_03

Circuit

Schematic diagram

Chapter05_04

Hardware connection:

Chapter05_05

Note

If you have any concerns, please send an email to: support@freenove.com

Sketch

In this chapter, we will control the RGB LED with 3 PWMs.

Sketch_05_RainbowLED

First, enter where the project is located:

$ cd ~/Freenove_Kit/Pi4j/Sketches/Sketch_05_RainbowLED
../../../_images/Chapter05_06.png

Enter the command to run the code.

$ jbang RainbowLED.java
../../../_images/Chapter05_07.png

When the code is running, the RGB LED randomly emits various colors.

../../../_images/Chapter05_08.png

Press Ctr+C to exit the program.

../../../_images/Chapter05_09.png

You can open the code with Geany to view and edit it, with the following command.

$ geany RainbowLED.java

Click the icon to run the code.

../../../_images/Chapter05_10.png

If the code fails to run, please check Geany Configuration.

The following is program code:

  1///usr/bin/env jbang "$0" "$@" ; exit $?
  2
  3//DEPS org.slf4j:slf4j-api:2.0.12
  4//DEPS org.slf4j:slf4j-simple:2.0.12
  5//DEPS com.pi4j:pi4j-core:2.6.0
  6//DEPS com.pi4j:pi4j-plugin-raspberrypi:2.6.0
  7//DEPS com.pi4j:pi4j-plugin-gpiod:2.6.0
  8
  9import com.pi4j.Pi4J;  
 10import com.pi4j.context.Context;  
 11import com.pi4j.io.gpio.digital.DigitalOutput;  
 12import com.pi4j.util.Console;
 13import java.util.HashMap;  
 14import java.util.Map;  
 15import java.util.Random; 
 16
 17class PWMController implements Runnable {  
 18    private DigitalOutput pwm;  
 19	private int pwmFrequency;
 20	private double pwmDutyCycle;
 21    private boolean running = true;  
 22	private long period;  
 23	private long highTime;  
 24	private long lowTime;  
 25	
 26    public PWMController(DigitalOutput pwm) {  
 27        this.pwm = pwm;  
 28		this.pwmFrequency = 1000;
 29		this.pwmDutyCycle = 0.5;
 30		this.period = (int) (1000000 / pwmFrequency);  
 31		this.highTime = (int) (period * pwmDutyCycle);  
 32		this.lowTime = (int) (period - highTime);  
 33    }  
 34  
 35    @Override  
 36    public void run() {  
 37        while (running) {  
 38            if(highTime!=0){
 39				pwm.high();  
 40				delayUs(highTime); 
 41			}			
 42			if(lowTime!=0){
 43				pwm.low();  
 44				delayUs(lowTime);  
 45			} 		
 46        }  
 47    }  
 48  
 49	public void setPwmFrequency(int frequency) {  
 50        if(frequency!=0){
 51			this.pwmFrequency = frequency;
 52			this.period = (int) (1000000 / pwmFrequency);  
 53			this.highTime = (int) (period * pwmDutyCycle);  
 54			this.lowTime = (int) (period - highTime); 
 55		}
 56		else{
 57			this.pwmFrequency = 0;
 58			this.period = (int) (1000);  
 59			this.highTime = (int) (0);  
 60			this.lowTime = (int) (period - highTime); 
 61		}
 62    }  
 63	
 64	public void setPwmDutyCycle(double dutyCycle) {  
 65        this.pwmDutyCycle = dutyCycle;
 66		this.highTime = (int) (period * pwmDutyCycle);  
 67		this.lowTime = (int) (period - highTime); 
 68    } 
 69
 70    private void delayUs(long us) {  
 71        long startTime = System.nanoTime();  
 72        long endTime = startTime + (us * 1000);  
 73        while (System.nanoTime() < endTime) {  
 74        }  
 75    }  
 76  
 77    public void requestStop() {  
 78        running = false;  
 79    }  
 80}
 81
 82public class RainbowLED {  
 83    private static final Context pi4j = Pi4J.newAutoContext();  
 84    private static final Map<Integer, PWMController> pwmControllers = new HashMap<>();  
 85	
 86	public static void setPwmConfig(int pin) throws Exception {  
 87        DigitalOutput led = pi4j.dout().create(pin);  
 88        PWMController pwmController = new PWMController(led);  
 89        Thread pwmThread = new Thread(pwmController, "PWM LED Controller " + pin);  
 90        pwmControllers.put(pin, pwmController);  
 91        pwmThread.start();  
 92        Runtime.getRuntime().addShutdownHook(new Thread(() -> {  
 93            pwmController.requestStop();  
 94            try {  
 95                pwmThread.join();  
 96            } catch (InterruptedException e) {  
 97                Thread.currentThread().interrupt();  
 98            }  
 99        }));  
100    } 
101	
102	public static void ledSetup(int[] pins) {  
103        for (int pin : pins) {  
104            try {  
105                setPwmConfig(pin);  
106            } catch (Exception e) {  
107                e.printStackTrace();  
108            }  
109        }  
110    } 
111	
112	public static void setLedColor(int[] pins, int r, int g, int b) {  
113        if (pins.length >= 3) {  
114            PWMController red = pwmControllers.get(pins[0]);  
115            PWMController green = pwmControllers.get(pins[1]);  
116            PWMController blue = pwmControllers.get(pins[2]);  
117            if (red != null) red.setPwmDutyCycle((double) r / 100.0);  
118            if (green != null) green.setPwmDutyCycle((double) g / 100.0);  
119            if (blue != null) blue.setPwmDutyCycle((double) b / 100.0);  
120        }  
121    } 
122	
123    public static void main(String[] args) throws Exception {  
124		final var console = new Console();
125		int[] LED_PINS = {13, 6, 5}; 
126		Random random = new Random();	
127		
128        try {  
129			ledSetup(LED_PINS);
130			while (true) {  
131				int red = random.nextInt(101);  
132				int green = random.nextInt(101);  
133				int blue = random.nextInt(101);  
134				console.println("R:%d  G:%d, B:%d", red, green, blue);
135				setLedColor(LED_PINS, red, green, blue);
136				Thread.sleep(500);
137			}  
138        }  
139		finally {  
140            for (PWMController controller : pwmControllers.values()) {  
141                controller.requestStop();  
142            }  
143            pi4j.shutdown();  
144        }  
145    }  
146}

Import Pi4j library, context management, digital output interface, HashMap class and Map interface, and random function library.

1import com.pi4j.Pi4J;  
2import com.pi4j.context.Context;  
3import com.pi4j.io.gpio.digital.DigitalOutput;  
4import com.pi4j.util.Console;
5import java.util.HashMap;  
6import java.util.Map;  
7import java.util.Random; 

Initialize the pins corresponding to the RGB lights and print a stack trace if an exception occurs.

1	public static void ledSetup(int[] pins) {  
2        for (int pin : pins) {  
3            try {  
4                setPwmConfig(pin);  
5            } catch (Exception e) {  
6                e.printStackTrace();  
7            }  
8        }  
9    } 

Configure the RGB colored lights and adjust the brightness of the LED by adjusting the duty cycle of PWM.

 1	public static void setLedColor(int[] pins, int r, int g, int b) {  
 2        if (pins.length >= 3) {  
 3            PWMController red = pwmControllers.get(pins[0]);  
 4            PWMController green = pwmControllers.get(pins[1]);  
 5            PWMController blue = pwmControllers.get(pins[2]);  
 6            if (red != null) red.setPwmDutyCycle((double) r / 100.0);  
 7            if (green != null) green.setPwmDutyCycle((double) g / 100.0);  
 8            if (blue != null) blue.setPwmDutyCycle((double) b / 100.0);  
 9        }  
10    } 

Create a console instance, define an array of GPIO pins for LED connections, and create a random number generator instance.

1final var console = new Console();
2int[] LED_PINS = {13, 6, 5}; 
3Random random = new Random();	

Initialize the array of GPIO pins connected to the LEDs, generate 3 new random numbers every 500 milliseconds as brightness values for the RGB lights, and print prompt messages on the console.

 1        try {  
 2			ledSetup(LED_PINS);
 3			while (true) {  
 4				int red = random.nextInt(101);  
 5				int green = random.nextInt(101);  
 6				int blue = random.nextInt(101);  
 7				console.println("R:%d  G:%d, B:%d", red, green, blue);
 8				setLedColor(LED_PINS, red, green, blue);
 9				Thread.sleep(500);
10			}  
11        }  

At the end of the program, stop all PWM controllers and close the Pi4J context.

1		finally {  
2            for (PWMController controller : pwmControllers.values()) {  
3                controller.requestStop();  
4            }  
5            pi4j.shutdown();  
6        }