プロローグ
wiringPiのハードウェアPWMpwmWriteを使ってデューティー比を変えることでLEDの明るさを変えてみる実験。
pwmWriteの使い方は公式のドキュメントが割と詳しかったので公式の記述に沿ってやってみた。
回路
PWM専用ピンを使うシンプルLチカ回路。
GPIO18 → 330Ω抵抗 → LED(アノード→カソード) → GND
ソースコード
1024のレンジ(デフォルト値)で約1kHzでだんだん明るくなって暗くなるを繰り返す。
終了したらLEDが付きっぱなしになるのが気になったので、消灯するようにしてみた。
led_pwm_dimmer.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <wiringPi.h>
#define LED_PIN_BCM 18
#define BASE_CLOCK_HZ 19200000 // 基準クロック19.2MHz
volatile sig_atomic_t g_running = 1;
void handleSigint(int sig)
{
(void)sig;
g_running = 0;
}
int calcClockDivisor(int targetFreqHz, int range)
{
int divisor = BASE_CLOCK_HZ / (targetFreqHz * range);
if (divisor < 1) divisor = 1; // 1未満は指定不可
return divisor;
}
int main(void)
{
if (wiringPiSetupPinType(WPI_PIN_BCM) == -1) {
printf("setup wiringPi failed.\n");
return EXIT_FAILURE;
}
// Ctrl+Cをハンドラで捕まえる
struct sigaction sa;
sa.sa_handler = handleSigint;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
pinMode(LED_PIN_BCM, PWM_OUTPUT);
pwmSetMode(PWM_MODE_MS);
int range = 1024;
int divisor = calcClockDivisor(1000, range); // 1kHz
pwmSetRange(range);
pwmSetClock(divisor);
while(g_running) {
// だんだん明るく
for (int duty = 0; duty <= 1024; duty += 8) {
pwmWrite(LED_PIN_BCM, duty);
delay(10);
}
// だんだん暗く
for (int duty = 1024; duty >= 0; duty -= 8) {
pwmWrite(LED_PIN_BCM, duty);
delay(10);
}
}
// LED消灯
pwmWrite(LED_PIN_BCM, 0);
return EXIT_SUCCESS;
}
実行
pwmWrite は /devmem にアクセスするため実行には sudo が必要。
gcc ./led_pwm_dimmer.c -o led_pwm_dimmer -lwiringPi
sudo ./led_pwm_dimmer
エピローグ
ソフトウェアPWMでフルカラーRGBLEDを光らせるというのもやって見たけれど、ほぼSunFounderのコードのままな上、動画も撮り忘れたので割愛。