0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

4pin RGB LED アノード コモン・カソード コモン どちらでも 同じに扱う

Posted at

RGB LED

今回 扱うLEDは、NeoPixel(WS2812他)等のマイコン内蔵フルカラーLEDではありません。
(下の写真のような)Red、Green、Blue 各色のピンと共通ピンの合計4ピンあるRGBLEDです。

800px-RGB_LED.jpg

アノード(+)コモン と、カソード(-)コモンの2タイプがあります。

anode-common.png cathord-common.jpg

一番足の長いピンが共通ピンですが、R・G・Bピンの並びは、RGBLEDの製品により異なる場合があるので、データシートで確認します。

R・G・B のそれぞれのピンに電流制限抵抗を入れる必要があります。RGBLED製品の諸元をもとに必要な抵抗値を計算で求められますが、3.3V〜5Vで駆動する場合は 500Ω〜1KΩ 程度の抵抗を使えばほぼ問題ありません。

点灯させる論理のおさらい

これまでの説明の通り、R・G・B の各色は独立していることが分かります。

※折りたたんであります。「LEDを点灯させる論理」を確認したい方は、次の「ここに表示」をクリックしてください。

ここに表示

On/Off制御(デジタル制御)

各色を光る消すで制御すると、次の8色の発光パターンが作れます。
(下表で、1:光る0:消すを表す)

R G B
0 0 0 (全消灯)
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

これを実現するには、

  • アノードコモン の場合

    • 1:光る V-(GND)に接続
    • 0:消す V+(VDD)に接続
       
  • カソードコモン の場合

    • 1:光る V+(VDD)に接続
    • 0:消す V-(GND)に接続
       

と、なります。
アノードコモンとカソードコモンでは、逆の理論になっています。
(カソードコモンの方が、電気の流れと論理が一致していて、分かり易い気がします)

タイトルでいう「同じに扱う」にはなっていませんが、反転するだけです。

整数の01で表すなら、カソードコモンを基準に01に決定した値をiとすると、アノードコモンの場合の値は、(1-i)です。
Boolean変数xなら、(Not x)で、言語により(!x)かも知れません。

ArduinoにおけるdigitalWrite()がこれに当たります。R・G・B のそれぞれのピンに対して実行します。

  • カソードコモンの場合
    digitalWrite(pin#, i) or digitalWrite(pin#, x)
     
  • アノードコモンの場合
    digitalWrite(pin#, 1 - i) or digitalWrite(pin#, !x)

ただし、最初からdigitalWrite(pin#, 0)がOn、digitalWrite(pin#, 1)がOffを意味する負論理のマイコンが存在します。今回の記事を負論理のマイコンに適用する場合は、さらにNotが必要になります。ややこしい・・・

PWM制御(アナログ制御)

他方、各R・G・BのOn・Off制御ではなく、各R・G・Bを16階調や256階調で制御することで、4096色($16^3$)や1677万色($256^3$)の発光パターンを作れます。

これは、各R・G・Bに印加する電圧を変化させることで実現します。この方法としては、PWM(Pulse Width Modulation)電圧変換が一般的です。

PWM電圧変換とは、一定電圧(VDD)の入力からパルス列のオンとオフの一定周期を作り(周期を周波数で示すことが多い)、オンの時間幅(デューティ比)を変化させ、出力電圧を制御することです。出力電圧はデューティ比に該当する平均化された大きさとなります。
例えば、デューティ比を50%とすれば、VDDの半分の電圧を出力することができます。

デューティ比の指定方法は、使用するマイコンと使用する言語によって異なりますが、どんなマイコンでもPWM制御は持っていますし、デューティ比も変えられます。
PWMの周波数は、数百Hzで十分です。高性能のマイコンなら数KHzでも可

例えば、関数PWM(0〜1023)でデューティ比が指定できると仮定すると、256階調とするなら、$\bigl(\frac{1023}{255}\bigr)$≒4倍した値を引数に渡せばよいことになります。

スカイブルーという色のRGB値が(R:135, G:206, B:235)だとすると、以下の擬似コードになります。

Red.PWM(135 * 1023 / 255)
Green.PWM(206 * 1023 / 255)
Blue.PWM(235 * 1023 / 255)

ただし、これは、カソードコモン での場合です。
アノードコモン の場合は、反転論理ですから、値を反転する必要があります。
PWM関数の引数でカソードコモンでの値をiとするなら、アノードコモン の場合は、(1023-i)となります。

アノードコモンの場合
Red.PWM(1023 - 135 * 1023 / 255)
Green.PWM(1023 - 206 * 1023 / 255)
Blue.PWM(1023 - 235 * 1023 / 255)

今回は検証用に WOKWI版 Raspbery Pi Pico & Micropython を使いますが、どんなマイコンであれ、使える言語に差があっても、考え方はどれも同じです。

rgbled2.png

Picoは、どのGPIOピンでもPWMを使用できますが、全部で8チャネルしかありません。
GPIO0〜15とGPIO16以降でチャネルが重複しているので、PWMで使用するGPIOピンを選ぶときは注意が必要です。

参考サイト
https://www.denshi.club/parts/2021/07/raspberry-pi-pico-18-pwm.html

実際に試す

上の写真のように、カソードコモンとアノードコモンのRGBLEDを、Raspbery Pi Picoに接続します。

On/Off制御

アノードコモンとカソードコモンの差を吸収するために、クラス化しました。インスタンス生成時に、コモンタイプを指定します。

from machine import Pin
import utime

class RGBLED:
    def __init__(self, red_pin, green_pin, blue_pin, anode_common=False):
        self.red = Pin(red_pin, Pin.OUT)
        self.green = Pin(green_pin, Pin.OUT)
        self.blue = Pin(blue_pin, Pin.OUT)
        self.anode_common = anode_common

    def rgb(self, r, g, b):
        if self.anode_common:
            r = 1 - r
            g = 1 - g
            b = 1 - b
        self.red.value(r)
        self.green.value(g)
        self.blue.value(b)

a_led = RGBLED(28, 27, 26, anode_common=True) #アノードコモン
c_led = RGBLED(3, 2, 1)                       #カソードコモン

Illumination = [
    (0, 0, 1), #青
    (0, 1, 0), #緑
    (0, 1, 1), #水
    (1, 0, 0), #赤
    (1, 0, 1), #紫
    (1, 1, 0), #黄
    (1, 1, 1), #白
    (0, 0, 0)  #全消灯
]
while True:
    for r, g, b in Illumination:
        a_led.rgb(r, g, b)
        c_led.rgb(r, g, b)
        utime.sleep(1)

タネを明かすと、これが、タイトルに書いた『同じに扱う』ということでした。
下のURLをクリックすると、WOKWI シミュレータが開きます。 rgbled4.pngをクリックすると、コードを実行してRGBLEDが光る様子を見られます。

PWM制御

こちらも、アノードコモンとカソードコモンの差を吸収するために、クラス化しました。
MicroPythonでは、PWMのでデューティ比を0〜65535で指定するため、256階調にするために、$\bigl(\frac{65535}{255}\bigr)$≒256倍します。

from machine import Pin, PWM
import utime

class RGBLED:
    def __init__(self, red_pin, green_pin, blue_pin, anode_common=False):
        self.red = PWM(Pin(red_pin), freq=200)
        self.green = PWM(Pin(green_pin), freq=200)
        self.blue = PWM(Pin(blue_pin), freq=200)
        self.anode_common = anode_common

    def pwm(self, r, g, b):
        r = int(r * 65535 / 255)
        g = int(g * 65535 / 255)
        b = int(b * 65535 / 255)
        if self.anode_common:
            r = 65535 - r
            g = 65535 - g
            b = 65535 - b
        self.red.duty_u16(r)
        self.green.duty_u16(g)
        self.blue.duty_u16(b)

a_led = RGBLED(28, 27, 26, anode_common=True) #アノードコモン
c_led = RGBLED(3, 2, 1)                       #カソードコモン

Illumination = [
    (64, 154, 227),
    (128, 0, 128),
    (50, 150, 50),
    (255, 30, 30),
    (0, 128, 255),
    (99, 199, 0),
    (128, 128, 128),
    (255, 100, 0)
]
while True:
    for r, g, b in Illumination:
        a_led.pwm(r, g, b)
        c_led.pwm(r, g, b)
        utime.sleep(1)

下のURLをクリックすると、WOKWI シミュレータが開きます。

実は、MicroPythonのPWMには 論理反転する引数invertがはじめから用意されており、これを使うと、自力で論理反転する処理が不要になります。
この場合は、以下のコードとなります。

from machine import Pin, PWM
import utime

class RGBLED:
    def __init__(self, red_pin, green_pin, blue_pin, anode_common=False):
        self.red = PWM(Pin(red_pin), freq=200, invert=anode_common)
        self.green = PWM(Pin(green_pin), freq=200, invert=anode_common)
        self.blue = PWM(Pin(blue_pin), freq=200, invert=anode_common)
        self.anode_common = anode_common

    def pwm(self, r, g, b):
        r = int(r * 65535 / 255)
        g = int(g * 65535 / 255)
        b = int(b * 65535 / 255)
        self.red.duty_u16(r)
        self.green.duty_u16(g)
        self.blue.duty_u16(b)

a_led = RGBLED(28, 27, 26, anode_common=True) #アノードコモン
c_led = RGBLED(3, 2, 1)                       #カソードコモン

Illumination = [
    (64, 154, 227),
    (128, 0, 128),
    (50, 150, 50),
    (255, 30, 30),
    (0, 128, 255),
    (99, 199, 0),
    (128, 128, 128),
    (255, 100, 0)
]
while True:
    for r, g, b in Illumination:
        a_led.pwm(r, g, b)
        c_led.pwm(r, g, b)
        utime.sleep(1)

下のURLをクリックすると、WOKWI シミュレータが開きます。

まとめ

自分が持っていないコモンタイプの制作例を真似するときは、“反転”するだけで使えるようになりました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?