PWM調光器 - DMX512対応・調光カーブ設計
STM32 BluePill で作る 12bit PWM調光器 - DMX512対応6ch調光カーブ設計
はじめに
舞台照明やLED制御で使われるDMX512プロトコルを受信し、滑らかな調光を実現するPWMコントローラーを STM32F103C8T6 (BluePill) で作成しました。
本記事では、12bit PWM調光における8種類の調光カーブとフェード速度制御の実装について解説します。
主な特徴
- DMX512受信(6チャンネル)
- 12bit PWM(4000カウント)
- 8種類の調光カーブ選択
- 4段階フェードスピード
- DIPスイッチでアドレス設定(9bit: 0-511)
- SSD1306 OLED表示
調光カーブの必要性
なぜリニアではダメなのか?
人間の目は対数的な明るさ感覚を持っています。DMX値を単純にリニアでPWM出力すると:
- 低域(暗い部分): 急に明るくなる感覚
- 高域(明るい部分): 変化が見えにくい
これを補正するために、ガンマカーブやS字カーブを適用します。
8種類の調光カーブ
本プロジェクトでは、4種類のベーステーブル × 2種類の乗数で8パターンの調光カーブを提供します。
カーブ一覧
| 設定値 | テーブル | 乗数 | 特徴 | 用途 |
|---|---|---|---|---|
| 0 | Dim0 | ×4 | リニア(低域持ち上げ) | 汎用・初期値 |
| 1 | Dim1 | ×4 | ガンマ補正1(暗部滑らか) | LED照明 |
| 2 | Dim2 | ×4 | ガンマ補正2(中間強調) | ステージ照明 |
| 3 | Dim5 | ×4 | 急カーブ(S字型) | 演出効果用 |
| 4 | Dim0 | ×3 | リニア(出力75%) | 省電力モード |
| 5 | Dim1 | ×3 | ガンマ補正1(出力75%) | 省電力LED |
| 6 | Dim2 | ×3 | ガンマ補正2(出力75%) | 省電力ステージ |
| 7 | Dim5 | ×3 | 急カーブ(出力75%) | 演出効果・省電力 |
全カーブ比較グラフ
グラフの見方:
- X軸: DMX入力値(0-255)
- Y軸: PWM出力値(0-4000)
- 実線: ×3乗数(最大3600)
- 破線: ×4乗数(最大4800、PWM_P=4000でクリップ)
- 灰色点線: PWM_P=4000(12bit上限)
低域拡大グラフ
暗部の立ち上がり特性を比較すると:
- Dim0/1/2(青・オレンジ・緑): 低域から明るく立ち上がる
- Dim5(赤): S字カーブで低域がゆっくり立ち上がる
Dim5のS字カーブは人間の目の感覚に最も近く、自然な調光感を実現します。
実装コード
config_compat.h での設定
//-----------------------------------------------------------------------------
// 調光カーブ選択(12bitモード用)
//-----------------------------------------------------------------------------
// 0 = Dim0×4 リニア(デフォルト)
// 1 = Dim1×4 ガンマ補正1(暗部滑らか)
// 2 = Dim2×4 ガンマ補正2(中間強調)
// 3 = Dim5×4 急カーブ(明部圧縮)
// 4 = Dim0×3 リニア(出力75%)
// 5 = Dim1×3 ガンマ補正1(出力75%)
// 6 = Dim2×3 ガンマ補正2(出力75%)
// 7 = Dim5×3 急カーブ(出力75%)
//-----------------------------------------------------------------------------
#define DIM_TABLE_SELECT 0 // ★ 調光カーブ(0-7)
Dimテーブル定義(main.c)
// リニア(低域持ち上げ)
const int Dim0[]={
0, 4, 8, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36,
38, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96,
...
932,936,940,944,948,952,956,960,964,968,972,976,980,984,988,1200};
// S字カーブ(指数/対数型)
const int Dim5[]={
0x000,0x001,0x002,0x003,0x004,0x005,0x006,0x007,0x008,0x009,0x00A,0x00B,
...
0xC97,0xCCB,0xD00,0xD35,0xD6C,0xDA3,0xDDB,0xE14,0xE4E,0xE89,0xEC5,0xF02,0xF3F,0xF5E,0xF7E,0xFFF};
テーブル選択ロジック
// Sw2d の値に応じてテーブルと乗数を選択
switch(Sw2d & 0x07) {
case 0: pwm = Dim0[dmx_value] * 4; break; // Dim0×4
case 1: pwm = Dim1[dmx_value] * 4; break; // Dim1×4
case 2: pwm = Dim2[dmx_value] * 4; break; // Dim2×4
case 3: pwm = Dim5[dmx_value] * 4; break; // Dim5×4
case 4: pwm = Dim0[dmx_value] * 3; break; // Dim0×3
case 5: pwm = Dim1[dmx_value] * 3; break; // Dim1×3
case 6: pwm = Dim2[dmx_value] * 3; break; // Dim2×3
case 7: pwm = Dim5[dmx_value] * 3; break; // Dim5×3
}
フェードスピード制御
DMX値が変化したとき、即座にPWM出力を変えるとチラつきが発生します。これを防ぐため、フェード(徐変)処理を実装しています。
4段階フェードスピード
| 設定値 | 速度 | 0→255フェード時間 | 用途 |
|---|---|---|---|
| 0 | 即座 | 0秒(瞬時切替) | デバッグ・テスト |
| 1 | 2倍速 | 約3秒 | 素早い演出 |
| 2 | 1倍速 | 約6秒 | 標準的な調光 |
| 3 | スロー | 約20秒 | ゆっくりした演出 |
config_compat.h での設定
//-----------------------------------------------------------------------------
// フェードスピード設定(12bitモード用)
//-----------------------------------------------------------------------------
// 0 = 即座(フェードなし) → 0秒(瞬時切替)
// 1 = 2倍速(速い) → 約3秒(0→255フェード時)
// 2 = 1倍速(普通) → 約6秒(0→255フェード時)
// 3 = スロー(遅い) → 約20秒(0→255フェード時)
//-----------------------------------------------------------------------------
#define FADE_SPEED 1 // ★ フェードスピード(0-3)
フェード実装のポイント
メインループは非常に高速(マイクロ秒単位)で回るため、毎回フェード処理を実行すると一瞬で完了してしまいます。
解決策:ループカウンタで呼び出し頻度を制限
// フェード速度に応じたループ回数設定
int fade_limit;
switch(Sw3d) {
case 0: fade_limit = 1; break; // 毎回実行(即座)
case 1: fade_limit = 100; break; // 100回に1回(2倍速)
case 2: fade_limit = 200; break; // 200回に1回(1倍速)
case 3: fade_limit = 400; break; // 400回に1回(スロー)
}
// カウンタがlimitに達したらフェード実行
if(++fade_counter >= fade_limit) {
fade_counter = 0;
inc_dec(); // フェード処理
}
DIPスイッチ設定
10個のDIPスイッチ(S1~S10)で各種設定を行います。
12bitモードと16bitモードでスイッチの役割が異なります。
ファームウェアのコンパイル時に ENABLE_LOG_CURVE マクロで切り替えます。
モード比較(12bit vs 16bit)
| 項目 | 12bitモード | 16bitモード |
|---|---|---|
| マクロ | ENABLE_LOG_CURVE=0 |
ENABLE_LOG_CURVE=1 |
| PWM分解能 | 4,000段階(約12bit) | 65,535段階(16bit) |
| 調光カーブ | Dim0/1/2/5テーブル | 2乗LOGカーブ |
| S1-S4の機能 | カット値設定 | 下駄上げ(細かい) |
| S5-S6の機能 | 調光カーブ選択 | 下駄上げ(大きい) |
| S7-S9の機能 | フェード速度 | LCD/フェード方式 |
| 用途 | 汎用LED調光 | 暗部の滑らかさ重視 |
12bitモード(ENABLE_LOG_CURVE=0)
DIPスイッチ機能一覧
┌─────────────────────────────────────────────────────────────┐
│ 12bitモード DIPスイッチ配置 │
├─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┤
│ S1 │ S2 │ S3 │ S4 │ S5 │ S6 │ S7 │ S8 │ S9 │ S10 │
├─────┴─────┴─────┴─────┼─────┴─────┴─────┼─────┴─────┼─────┤
│ カット値 (×4) │ 調光カーブ │フェード速度│手動 │
│ 0-60 │ 0-7 │ 0-3 │ON/OFF│
└───────────────────────┴────────────────┴───────────┴─────┘
| スイッチ | 機能 | 設定値 | 説明 |
|---|---|---|---|
| S1-S4 | カット値 | 0-60 | DMXノイズカット(4飛び) |
| S5-S7 | 調光カーブ | 0-7 | Dim0~Dim7 選択 |
| S8-S9 | フェード速度 | 0-3 | 即座/速/普通/遅い |
| S10 | マニュアル | ON/OFF | ON=全ch 255出力 |
カット値の設定(S1-S4)
用途: DMX入力のノイズ除去。指定値以下のDMXは消灯扱い。
| S4 | S3 | S2 | S1 | カット値 | 動作 |
|---|---|---|---|---|---|
| OFF | OFF | OFF | OFF | 0 | DMX=0のみ消灯 |
| OFF | OFF | OFF | ON | 4 | DMX 1~4 も消灯 |
| OFF | OFF | ON | OFF | 8 | DMX 1~8 も消灯 |
| OFF | ON | OFF | OFF | 16 | DMX 1~16 も消灯 |
| ON | ON | ON | ON | 60 | DMX 1~60 も消灯 |
計算式: カット値 = (S1×1 + S2×2 + S3×4 + S4×8) × 4
調光カーブの選択(S5-S7)
| S7 | S6 | S5 | 値 | カーブ | 特徴 |
|---|---|---|---|---|---|
| OFF | OFF | OFF | 0 | Dim0×4 | リニア(標準) |
| OFF | OFF | ON | 1 | Dim1×4 | 暗部滑らか |
| OFF | ON | OFF | 2 | Dim2×4 | 中間強調 |
| OFF | ON | ON | 3 | Dim5×4 | S字カーブ |
| ON | OFF | OFF | 4 | Dim0×3 | リニア75% |
| ON | OFF | ON | 5 | Dim1×3 | 暗部滑らか75% |
| ON | ON | OFF | 6 | Dim2×3 | 中間強調75% |
| ON | ON | ON | 7 | Dim5×1 | ゲイン対応★推奨 |
フェード速度の設定(S8-S9)
| S9 | S8 | 値 | 速度名 | 0→255時間 |
|---|---|---|---|---|
| OFF | OFF | 0 | 即座 | 0秒 |
| OFF | ON | 1 | 速い | 約3秒 |
| ON | OFF | 2 | 普通 | 約6秒 |
| ON | ON | 3 | 遅い | 約20秒 |
config_compat.h での設定
// 12bitモード有効化
#define ENABLE_LOG_CURVE 0 // 0=12bitモード
// DIPパラメータモード有効化(★推奨)
#define DMX_PATCH_MODE 1 // パッチモード使用
#define DIP_PARAM_MODE 1 // S1-S9でパラメータ変更可能
16bitモード(ENABLE_LOG_CURVE=1)
DIPスイッチ機能一覧
┌─────────────────────────────────────────────────────────────┐
│ 16bitモード DIPスイッチ配置 │
├─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┤
│ S1 │ S2 │ S3 │ S4 │ S5 │ S6 │ S7 │ S8 │ S9 │ S10 │
├─────┴─────┴─────┴─────┴─────┼─────┼─────┼─────┼─────┼─────┤
│ 下駄上げ(×2刻み) │+1024│LCD │Fade │LCD │手動 │
│ 0-62 │ │16bit│方式 │全表示│ │
└─────────────────────────────┴─────┴─────┴─────┴─────┴─────┘
| スイッチ | 機能 | 設定値 | 説明 |
|---|---|---|---|
| S1-S5 | 下駄上げ(小) | 0-62 | PWM底上げ(2刻み) |
| S6 | 下駄上げ(大) | +1024 | 大きめの底上げ |
| S7 | LCD 16bit表示 | ON/OFF | ON=16進表示なし |
| S8 | フェード方式 | ON/OFF | OFF=Hybrid, ON=Current |
| S9 | LCD全表示 | ON/OFF | ON=全変化を表示 |
| S10 | マニュアル | ON/OFF | ON=全ch MAX |
下駄上げ(LOG_offset)とは?
用途: DMX=1でも十分な明るさを確保するための底上げ値。
16bitモードでは暗部の分解能が高いため、最小出力が暗すぎる場合に使用。
┌────────────────────────────────────────────────┐
│ 下駄上げなし (LOG_offset=0) │
│ DMX: 0 ──┬── 1 ── 2 ── 3 ──...── 255 │
│ PWM: 0 │ 8 16 24 63487 │
│ │ ↑ かなり暗い │
├────────────────────────────────────────────────┤
│ 下駄上げあり (LOG_offset=1024) │
│ DMX: 0 ──┬── 1 ──── 2 ──── 3 ──...── 255 │
│ PWM: 0 │ 1032 1040 1048 64511 │
│ │ ↑ 十分な明るさ │
└────────────────────────────────────────────────┘
下駄上げ値の設定(S1-S6)
| S6 | S5 | S4 | S3 | S2 | S1 | 下駄上げ値 |
|---|---|---|---|---|---|---|
| OFF | OFF | OFF | OFF | OFF | OFF | 0 |
| OFF | OFF | OFF | OFF | OFF | ON | 2 |
| OFF | OFF | OFF | OFF | ON | OFF | 4 |
| OFF | ON | ON | ON | ON | ON | 62 |
| ON | OFF | OFF | OFF | OFF | OFF | 1024 |
| ON | ON | ON | ON | ON | ON | 1086 |
計算式: LOG_offset = (S1×1 + S2×2 + S3×4 + S4×8 + S5×16) × 2 + S6×1024
フェード方式の選択(S8)
| S8 | 方式 | 特徴 |
|---|---|---|
| OFF | Hybrid(8段階) | 高速追従、暗部で細かく |
| ON | Current(7段階) | 従来方式、安定動作 |
config_compat.h での設定
// 16bitモード有効化
#define ENABLE_LOG_CURVE 1 // 1=16bitモード
// DMXアドレスはマクロで固定
#define DMX_START_ADDRESS 1 // 開始アドレス
モード選択の早見表
| 用途 | 推奨モード | 設定 |
|---|---|---|
| 汎用LED照明 | 12bit | ENABLE_LOG_CURVE=0 |
| 舞台照明(暗部重視) | 16bit | ENABLE_LOG_CURVE=1 |
| DIPでカーブ変更したい | 12bit + パラメータ | DIP_PARAM_MODE=1 |
| DIPで下駄上げ調整 | 16bit | デフォルト |
| DMXアドレスをDIPで設定 | 12bit | DIP_ADDRESS_MODE=1 |
マクロ組み合わせ一覧
| ENABLE_LOG_CURVE | DMX_PATCH_MODE | DIP_ADDRESS_MODE | DIP_PARAM_MODE | S1-S9の機能 |
|---|---|---|---|---|
| 0 | 0 | 0 | - | 未使用(マクロ固定) |
| 0 | 0 | 1 | - | DMXアドレス(9bit) |
| 0 | 1 | 0 | 0 | 未使用(パッチプリセット) |
| 0 | 1 | 0 | 1 | カット/カーブ/速度 ★推奨 |
| 1 | - | - | - | 下駄上げ/LCD/Fade方式 |
ハードウェア構成
使用マイコン
- STM32F103C8T6 (BluePill)
- 72MHz動作
PWM出力
- TIM1: CH1-CH4(4ch)
- TIM4: CH1-CH2(2ch)
- 周波数: 約4.2kHz(72MHz / 17 / 4000)
表示
- SSD1306 OLED 128x64
- I2C接続
- 180度反転表示対応
まとめ
STM32 BluePillを使った12bit PWM調光器を作成しました。
ポイント
- 8種類の調光カーブで用途に応じた調光特性を選択可能
- **S字カーブ(Dim5)**が人間の目に最も自然な調光感
- フェード速度制御でチラつきのない滑らかな調光
- マクロ設定で簡単にパラメータ変更可能
今後の課題
- 16bitモード対応(PWM_P=65535)
- RDM(リモートデバイス管理)対応
- 複数台連携機能
追加機能実装方針
103AC10(AC位相制御版)の調整パラメータを参考に、DC PWM調光器向けにキャリブレーション機能を追加します。
処理フロー設計
┌─────────────────────────────────────────────────────────────────┐
│ PWM出力処理フロー │
└─────────────────────────────────────────────────────────────────┘
DMX受信値 (0-255)
│
▼
┌─────────────────┐
│ ① デッドバンド │ ← 微小変化を無視(チラつき防止)
│ DEAD_BAND │ 例: ±2以内の変化は無視
└─────────────────┘
│
▼
┌─────────────────┐
│ ② 立ち上がり遅延 │ ← 変化開始を遅らせる(演出効果)
│ START_DELAY │ 例: 100ms遅延後にフェード開始
└─────────────────┘
│
▼
┌─────────────────┐
│ ③ 下限カット │ ← ノイズフロア除去
│ LOW_CUT │ 例: DMX 0-5 → 0扱い
└─────────────────┘
│
▼
┌─────────────────┐
│ ④ フェード処理 │ ← 徐変(既存実装)
│ FADE_SPEED │ 例: 0-3段階
└─────────────────┘
│
▼
┌─────────────────┐
│ ⑤ 調光カーブ適用 │ ← Dimテーブル変換(既存実装)
│ DIM_TABLE │ 例: Dim0/1/2/5 × 3/4
└─────────────────┘
│
▼
┌─────────────────┐
│ ⑥ オフセット加算 │ ← 下駄を履かせる(103AC10互換)
│ PWM_OFFSET │ 例: +50 でベース出力追加
└─────────────────┘
│
▼
┌─────────────────┐
│ ⑦ ゲイン調整 │ ← 出力レベル調整(103AC10互換)
│ PWM_GAIN │ 例: 256=等倍, 200=78%
└─────────────────┘
│
▼
┌─────────────────┐
│ ⑧ 下限閾値カット │ ← 完全消灯保証
│ PWM_MIN_CUT │ 例: PWM<30は0にする
└─────────────────┘
│
▼
┌─────────────────┐
│ ⑨ 上限リミット │ ← LED保護、消費電力制限
│ PWM_MAX │ 例: 最大3000(75%)
└─────────────────┘
│
▼
PWM出力 (0-4000)
config_compat.h パラメータ追加
//=============================================================================
// PWMキャリブレーション設定(103AC10互換パラメータ)
//=============================================================================
//-----------------------------------------------------------------------------
// ① デッドバンド: 微小変化を無視(チラつき防止)
//-----------------------------------------------------------------------------
// 前回値との差がこの値以下なら変化を無視
// 0 = デッドバンドなし
// 2 = ±2以内の変化を無視(推奨)
// 5 = ±5以内の変化を無視
//-----------------------------------------------------------------------------
#define DEAD_BAND 2 // ★ デッドバンド(0-10)
//-----------------------------------------------------------------------------
// ② 立ち上がり遅延: 変化開始を遅らせる
//-----------------------------------------------------------------------------
// DMX値が変化してからフェード開始までの遅延
// 0 = 遅延なし(即座にフェード開始)
// 1 = 100ms遅延
// 2 = 200ms遅延
// 3 = 500ms遅延
//-----------------------------------------------------------------------------
#define START_DELAY 0 // ★ 立ち上がり遅延(0-3)
//-----------------------------------------------------------------------------
// ③ 下限カット(DMXレベル): ノイズフロア除去
//-----------------------------------------------------------------------------
// DMX値がこの値以下の場合、0として扱う
// 0 = カットなし(DMX=0のみ消灯)
// 3 = DMX 0-3 を消灯扱い(推奨)
// 5 = DMX 0-5 を消灯扱い
//-----------------------------------------------------------------------------
#define LOW_CUT_DMX 3 // ★ 下限カット閾値(0-20)
//-----------------------------------------------------------------------------
// ⑥ PWMオフセット(下駄): ベース出力を上げる
//-----------------------------------------------------------------------------
// カーブ適用後のPWM値に加算する固定値
// 0 = オフセットなし
// 50 = 最低でもPWM=50から開始(DMX>0時)
// 100 = LED初期点灯の応答性改善
// ※103AC10のPWM_OFFSETと同等機能
//-----------------------------------------------------------------------------
#define PWM_OFFSET 0 // ★ オフセット(0-200)
//-----------------------------------------------------------------------------
// ⑦ PWMゲイン: 出力レベル調整
//-----------------------------------------------------------------------------
// 256 = 等倍(デフォルト)
// 200 = 約78%出力(省電力)
// 300 = 約117%出力(明るめ)
// 計算: 出力 = (カーブ出力 × PWM_GAIN) >> 8
// ※103AC10のPWM_GAINと同等機能
//-----------------------------------------------------------------------------
#define PWM_GAIN 256 // ★ ゲイン(200-300)
//-----------------------------------------------------------------------------
// ⑧ 下限閾値カット(PWMレベル): 完全消灯保証
//-----------------------------------------------------------------------------
// PWM値がこの値未満の場合、0にする
// 0 = カットなし
// 30 = PWM<30は0出力(完全消灯保証)
// ※103AC10のPWM_MIN_THRESHOLDと同等機能
//-----------------------------------------------------------------------------
#define PWM_MIN_CUT 30 // ★ 下限閾値(0-100)
//-----------------------------------------------------------------------------
// ⑨ 上限リミット: 最大出力制限
//-----------------------------------------------------------------------------
// PWM出力の最大値を制限
// 4000 = 制限なし(12bitフル)
// 3000 = 最大75%出力
// 2000 = 最大50%出力
//-----------------------------------------------------------------------------
#define PWM_MAX_LIMIT 4000 // ★ 上限リミット(0-4000)
実装コード例
//==============================================================================
// apply_calibration() - PWMキャリブレーション適用
// 調光カーブ適用後に呼び出し、オフセット/ゲイン/リミットを適用
//==============================================================================
uint16_t apply_calibration(uint16_t pwm_value, uint8_t dmx_value) {
int32_t result = pwm_value;
// ⑥ オフセット加算(DMX>0の場合のみ)
if(dmx_value > LOW_CUT_DMX && PWM_OFFSET > 0) {
result += PWM_OFFSET;
}
// ⑦ ゲイン調整
result = (result * PWM_GAIN) >> 8;
// ⑧ 下限閾値カット(完全消灯保証)
if(result < PWM_MIN_CUT) {
result = 0;
}
// ⑨ 上限リミット
if(result > PWM_MAX_LIMIT) {
result = PWM_MAX_LIMIT;
}
return (uint16_t)result;
}
//==============================================================================
// apply_dead_band() - デッドバンド適用
// DMX受信時に呼び出し、微小変化を無視
//==============================================================================
uint8_t apply_dead_band(uint8_t current, uint8_t new_value) {
int diff = (int)new_value - (int)current;
if(diff < 0) diff = -diff; // 絶対値
if(diff <= DEAD_BAND) {
return current; // 変化なし
}
return new_value;
}
//==============================================================================
// apply_low_cut() - 下限カット適用
// DMX値がLOW_CUT_DMX以下なら0を返す
//==============================================================================
uint8_t apply_low_cut(uint8_t dmx_value) {
if(dmx_value <= LOW_CUT_DMX) {
return 0;
}
return dmx_value;
}
調整の考え方
1. オフセット vs プリヒート
| パラメータ | 適用位置 | 用途 |
|---|---|---|
PWM_OFFSET |
カーブ後、ゲイン前 | 下駄を履かせる(低域持ち上げ) |
| プリヒート | 最終出力直前 | 最小出力保証(完全消灯回避) |
使い分け:
- 白熱電球のフィラメント予熱 →
PWM_OFFSET - LED応答性改善 →
PWM_OFFSET - 完全消灯を避けたい → プリヒート
2. ゲイン調整の計算
出力PWM = (カーブPWM + オフセット) × ゲイン / 256
例: カーブ出力=2000, オフセット=50, ゲイン=200
出力 = (2000 + 50) × 200 / 256 = 1601
3. 下限カットの2段階
DMX入力 → [LOW_CUT_DMX] → フェード → カーブ → [PWM_MIN_CUT] → 出力
① LOW_CUT_DMX: DMXレベルでカット(ノイズ除去)
② PWM_MIN_CUT: PWMレベルでカット(完全消灯保証)
103AC10 vs 103c6pwm6 パラメータ対応表
| 103AC10(AC位相制御) | 103c6pwm6(DC PWM) | 説明 |
|---|---|---|
PWM_OFFSET |
PWM_OFFSET |
オフセット補正 |
PWM_GAIN |
PWM_GAIN |
ゲイン調整(256=等倍) |
PWM_MIN_THRESHOLD |
PWM_MIN_CUT |
最小点弧閾値 |
CURVE_DEFAULT |
DIM_TABLE_SELECT |
調光カーブ選択 |
Fspeed |
FADE_SPEED |
フェード速度 |
| - | LOW_CUT_DMX |
DMXレベル下限カット |
| - | PWM_MAX_LIMIT |
上限リミット |
| - | DEAD_BAND |
デッドバンド |
| - | START_DELAY |
立ち上がり遅延 |
推奨設定例
汎用LED調光
#define DEAD_BAND 2
#define START_DELAY 0
#define LOW_CUT_DMX 3
#define PWM_OFFSET 0
#define PWM_GAIN 256
#define PWM_MIN_CUT 30
#define PWM_MAX_LIMIT 4000
白熱電球(プリヒート付き)
#define DEAD_BAND 2
#define START_DELAY 0
#define LOW_CUT_DMX 3
#define PWM_OFFSET 100 // フィラメント予熱
#define PWM_GAIN 256
#define PWM_MIN_CUT 30
#define PWM_MAX_LIMIT 4000
省電力モード(75%出力)
#define DEAD_BAND 2
#define START_DELAY 0
#define LOW_CUT_DMX 3
#define PWM_OFFSET 0
#define PWM_GAIN 200 // 78%ゲイン
#define PWM_MIN_CUT 30
#define PWM_MAX_LIMIT 3000 // 75%リミット
追加機能詳細
1. 立ち上がり遅延(Start Delay)
DMX値が変化してから実際にフェードを開始するまでの遅延時間を設定します。複数の調光器を使用する際、意図的にずらした演出が可能になります。
//-----------------------------------------------------------------------------
// 立ち上がり遅延設定
//-----------------------------------------------------------------------------
// 0 = 遅延なし(即座にフェード開始)
// 1 = 100ms遅延
// 2 = 200ms遅延
// 3 = 500ms遅延
//-----------------------------------------------------------------------------
#define START_DELAY 0 // ★ 立ち上がり遅延(0-3)
// 遅延カウンタ(チャンネルごと)
uint16_t delay_counter[6] = {0};
uint8_t delay_target[6] = {0}; // 遅延後に適用する目標値
// 遅延処理
void apply_start_delay(uint8_t ch, uint8_t new_value) {
if(START_DELAY == 0) {
target[ch] = new_value; // 即座に適用
} else {
delay_target[ch] = new_value;
delay_counter[ch] = START_DELAY * 100; // 遅延開始
}
}
// メインループで呼び出し
void process_delay(void) {
for(int ch = 0; ch < 6; ch++) {
if(delay_counter[ch] > 0) {
delay_counter[ch]--;
if(delay_counter[ch] == 0) {
target[ch] = delay_target[ch]; // 遅延完了、適用
}
}
}
}
2. 下限カット(Low Cut / Noise Floor)
DMX値が設定値以下の場合、PWM出力を0にします。ノイズや微小な入力を無視し、完全な消灯を保証します。
//-----------------------------------------------------------------------------
// 下限カット設定
//-----------------------------------------------------------------------------
// DMX値がこの値以下の場合、PWM出力を0にする
// 0 = カットなし(DMX=0のみ消灯)
// 5 = DMX 0-5 を消灯扱い
// 10 = DMX 0-10 を消灯扱い
//-----------------------------------------------------------------------------
#define LOW_CUT_THRESHOLD 3 // ★ 下限カット閾値(0-20推奨)
// 適用処理
uint8_t apply_low_cut(uint8_t dmx_value) {
if(dmx_value <= LOW_CUT_THRESHOLD) {
return 0;
}
return dmx_value;
}
3. プリヒート(Preheat / Minimum Level)
完全消灯ではなく、最小限の出力を維持します。白熱電球のフィラメント予熱や、LEDの応答性向上に使用します。
//-----------------------------------------------------------------------------
// プリヒート設定
//-----------------------------------------------------------------------------
// DMX=0でも最小限のPWM出力を維持
// 0 = プリヒートなし(完全消灯可)
// 10 = 最小PWM=10(約0.25%)
// 50 = 最小PWM=50(約1.25%)
//-----------------------------------------------------------------------------
#define PREHEAT_LEVEL 0 // ★ プリヒートレベル(0-100推奨)
// 適用処理
uint16_t apply_preheat(uint16_t pwm_value) {
if(pwm_value == 0) {
return 0; // DMX=0なら完全消灯
}
if(pwm_value < PREHEAT_LEVEL) {
return PREHEAT_LEVEL;
}
return pwm_value;
}
4. 上限リミット(Maximum Limit)
PWM出力の上限を制限します。LED保護や消費電力制限に使用します。
//-----------------------------------------------------------------------------
// 上限リミット設定
//-----------------------------------------------------------------------------
// PWM出力の最大値を制限
// 4000 = 制限なし(12bitフル)
// 3000 = 最大75%出力
// 2000 = 最大50%出力
//-----------------------------------------------------------------------------
#define MAX_PWM_LIMIT 4000 // ★ 上限リミット(0-4000)
// 適用処理
uint16_t apply_max_limit(uint16_t pwm_value) {
if(pwm_value > MAX_PWM_LIMIT) {
return MAX_PWM_LIMIT;
}
return pwm_value;
}
5. デッドバンド(Dead Band)
小さな変化を無視し、チラつきを防止します。
//-----------------------------------------------------------------------------
// デッドバンド設定
//-----------------------------------------------------------------------------
// 前回値との差がこの値以下なら変化を無視
// 0 = デッドバンドなし
// 2 = ±2以内の変化を無視
// 5 = ±5以内の変化を無視
//-----------------------------------------------------------------------------
#define DEAD_BAND 2 // ★ デッドバンド(0-10推奨)
// 適用処理
uint8_t apply_dead_band(uint8_t current, uint8_t new_value) {
int diff = (int)new_value - (int)current;
if(diff < 0) diff = -diff; // 絶対値
if(diff <= DEAD_BAND) {
return current; // 変化なし
}
return new_value;
}
統合処理フロー
DMX受信値
↓
┌─────────────────┐
│ デッドバンド適用 │ ← 微小変化を無視
└─────────────────┘
↓
┌─────────────────┐
│ 立ち上がり遅延 │ ← 変化開始を遅らせる
└─────────────────┘
↓
┌─────────────────┐
│ 下限カット │ ← ノイズフロア除去
└─────────────────┘
↓
┌─────────────────┐
│ フェード処理 │ ← 徐変
└─────────────────┘
↓
┌─────────────────┐
│ 調光カーブ適用 │ ← Dimテーブル変換
└─────────────────┘
↓
┌─────────────────┐
│ プリヒート適用 │ ← 最小出力保証
└─────────────────┘
↓
┌─────────────────┐
│ 上限リミット │ ← 最大出力制限
└─────────────────┘
↓
PWM出力
config_compat.h への追加提案
//=============================================================================
// 追加調光パラメータ(12bitモード用)
//=============================================================================
// 立ち上がり遅延: 0=なし, 1=100ms, 2=200ms, 3=500ms
#define START_DELAY 0
// 下限カット: この値以下は0として扱う(0-20推奨)
#define LOW_CUT_THRESHOLD 3
// プリヒート: DMX>0時の最小PWM出力(0-100推奨)
#define PREHEAT_LEVEL 0
// 上限リミット: PWM出力の最大値(0-4000)
#define MAX_PWM_LIMIT 4000
// デッドバンド: この差以内の変化は無視(0-10推奨)
#define DEAD_BAND 2
12bit パラメータ入力と出力カーブの詳細解説
本セクションでは、DMX入力値(0-255)に対するPWM出力値(0-4000)の変換処理と、各パラメータが出力に与える影響を図解します。
処理フロー概要図
┌─────────────────────────────────────────────────────────────────────────────┐
│ 12bit PWM出力カーブ 処理フロー │
└─────────────────────────────────────────────────────────────────────────────┘
DMX入力 (0-255)
│
│ 例: DMX = 128 (中間値)
▼
┌─────────────────────────────────────────┐
│ ① Dimテーブル変換 │
│ Dim0/Dim1/Dim2/Dim5 から選択 │
│ 例: Dim0[128] = 512 │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ ② 乗数適用 │
│ ×3 または ×4 │
│ 例: 512 × 4 = 2048 │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ ③ クリッピング │
│ PWM_P (4000) を超える場合は4000 │
│ 例: 2048 → 2048 (そのまま) │
└─────────────────────────────────────────┘
│
▼
PWM出力 (0-4000) → デューティ比: 2048/4000 = 51.2%
各Dimテーブルのカーブ特性
出力カーブ特性図
PWM出力
4000 ┬─────────────────────────────────────────────────────┐
│ **** │ ← ×4乗数時 (Dim5)
│ ***** │
│ *** │
│ *** │
3000 ┤ ** │
│ ** ******* ────→ ×4乗数時 (Dim0/1/2)
│ ** ***** │
│ ** **** │
│ * *** │
2000 ┤ * *** │
│ ** * │
│ * * │
│ ** │
│ * │
1000 ┤ ** │
│ ** │
│ ** │
│ ** │
│ ** │
0 ┼─**──────────────────────────────────────────────────
0 32 64 96 128 160 192 224 255
DMX入力値
───── Dim0 (リニア) ・・・・・ Dim5 (S字カーブ)
───── Dim1 (ガンマ補正1) ─ ─ ─ PWM_P上限 (4000)
───── Dim2 (ガンマ補正2)
パラメータ設定と結果の対応表
以下は主要なDMX入力値に対する各カーブの理論出力値です。
【表1】Dimテーブル基準値(乗数適用前)
| DMX入力 | Dim0 | Dim1 | Dim2 | Dim5 | 備考 |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 消灯 |
| 1 | 4 | 2 | 2 | 1 | 最低点灯 |
| 5 | 16 | 12 | 12 | 5 | 低域 |
| 10 | 26 | 20 | 20 | 10 | 低域 |
| 16 | 38 | 52 | 34 | 20 | 低域 |
| 32 | 100 | 116 | 96 | 50 | 約12.5% |
| 64 | 228 | 244 | 224 | 130 | 25% |
| 96 | 356 | 372 | 352 | 265 | 37.5% |
| 128 | 512 | 500 | 512 | 496 | 50% (中間) |
| 160 | 640 | 640 | 640 | 853 | 62.5% |
| 192 | 768 | 768 | 768 | 1540 | 75% |
| 224 | 896 | 896 | 896 | 2649 | 87.5% |
| 255 | 1200 | 1200 | 1200 | 4095 | 最大 |
【表2】×4乗数適用後のPWM出力(設定0-3)
| DMX入力 | 設定0 Dim0×4 |
設定1 Dim1×4 |
設定2 Dim2×4 |
設定3 Dim5×4 |
PWM最大 |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 4000 |
| 1 | 16 | 8 | 8 | 4 | 4000 |
| 5 | 64 | 48 | 48 | 20 | 4000 |
| 10 | 104 | 80 | 80 | 40 | 4000 |
| 16 | 152 | 208 | 136 | 80 | 4000 |
| 32 | 400 | 464 | 384 | 200 | 4000 |
| 64 | 912 | 976 | 896 | 520 | 4000 |
| 96 | 1424 | 1488 | 1408 | 1060 | 4000 |
| 128 | 2048 | 2000 | 2048 | 1984 | 4000 |
| 160 | 2560 | 2560 | 2560 | 3412 | 4000 |
| 192 | 3072 | 3072 | 3072 | 4000 | 4000 |
| 224 | 3584 | 3584 | 3584 | 4000 | 4000 |
| 255 | 4000 | 4000 | 4000 | 4000 | 4000 |
※太字は PWM_P (4000) でクリップされた値
【表3】×3乗数適用後のPWM出力(設定4-7)
| DMX入力 | 設定4 Dim0×3 |
設定5 Dim1×3 |
設定6 Dim2×3 |
設定7 Dim5×3 |
PWM最大 |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 3600 |
| 1 | 12 | 6 | 6 | 3 | 3600 |
| 5 | 48 | 36 | 36 | 15 | 3600 |
| 10 | 78 | 60 | 60 | 30 | 3600 |
| 16 | 114 | 156 | 102 | 60 | 3600 |
| 32 | 300 | 348 | 288 | 150 | 3600 |
| 64 | 684 | 732 | 672 | 390 | 3600 |
| 96 | 1068 | 1116 | 1056 | 795 | 3600 |
| 128 | 1536 | 1500 | 1536 | 1488 | 3600 |
| 160 | 1920 | 1920 | 1920 | 2559 | 3600 |
| 192 | 2304 | 2304 | 2304 | 3600 | 3600 |
| 224 | 2688 | 2688 | 2688 | 3600 | 3600 |
| 255 | 3600 | 3600 | 3600 | 3600 | 3600 |
キャリブレーションパラメータの影響
config_compat.h で設定するパラメータが出力に与える影響を示します。
キャリブレーション処理フロー
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
DMX入力: 128 → Dimテーブル変換 → 512 × 4 = 2048
│
┌──────────────────────┘
▼
PWM_OFFSET (+50) → 2048 + 50 = 2098
│
▼
PWM_GAIN (256) → 2098 × 256 / 256 = 2098 (等倍)
PWM_GAIN (200) → 2098 × 200 / 256 = 1639 (78%)
│
▼
PWM_MIN_CUT (30) → 2098 > 30 → パス
│
▼
PWM_MAX_LIMIT (4000) → 2098 < 4000 → パス
│
▼
最終出力: 2098
測定値記録用スプレッドシート
実機テストでパラメータの効果を確認するためのテンプレートです。
【シート1】基本カーブ測定(設定0: Dim0×4)
測定条件:
- config_compat.h設定:
DIM_TABLE_SELECT = 0 - キャリブレーション: OFF (OFFSET=0, GAIN=256, MIN_CUT=0)
- 測定日: _______________
- 測定者: _______________
| DMX入力 | 理論PWM | 実測PWM | 実測電圧(V) | 実測輝度 | 備考 |
|---|---|---|---|---|---|
| 0 | 0 | 消灯確認 | |||
| 1 | 16 | 最低点灯 | |||
| 2 | 32 | ||||
| 3 | 48 | ||||
| 5 | 64 | 低域特性 | |||
| 8 | 88 | ||||
| 10 | 104 | ||||
| 16 | 152 | ||||
| 24 | 256 | 約10% | |||
| 32 | 400 | 約12.5% | |||
| 48 | 656 | ||||
| 64 | 912 | 25% | |||
| 96 | 1424 | 約35% | |||
| 128 | 2048 | 50%中間 | |||
| 160 | 2560 | 約65% | |||
| 192 | 3072 | 75% | |||
| 224 | 3584 | 約90% | |||
| 240 | 3840 | 約95% | |||
| 255 | 4000 | 最大 |
【シート2】S字カーブ測定(設定3: Dim5×4)
測定条件:
- config_compat.h設定:
DIM_TABLE_SELECT = 3 - キャリブレーション: OFF
- 測定日: _______________
- 測定者: _______________
| DMX入力 | 理論PWM | 実測PWM | 実測電圧(V) | 実測輝度 | 備考 |
|---|---|---|---|---|---|
| 0 | 0 | 消灯確認 | |||
| 1 | 4 | 最低点灯 | |||
| 2 | 8 | ||||
| 3 | 12 | ||||
| 5 | 20 | 低域特性 | |||
| 8 | 36 | ||||
| 10 | 40 | ||||
| 16 | 80 | ||||
| 24 | 148 | ||||
| 32 | 200 | 低い立ち上がり | |||
| 48 | 344 | ||||
| 64 | 520 | カーブ開始 | |||
| 96 | 1060 | 急上昇開始 | |||
| 128 | 1984 | 50%付近 | |||
| 160 | 3412 | 急上昇 | |||
| 192 | 4000 | クリップ | |||
| 224 | 4000 | クリップ | |||
| 240 | 4000 | クリップ | |||
| 255 | 4000 | 最大 |
【シート3】キャリブレーション効果測定
測定条件:
- 固定DMX入力: 128
- 測定日: _______________
| パラメータ設定 | 理論PWM | 実測PWM | 実測電圧(V) | 備考 |
|---|---|---|---|---|
| 基準 (OFFSET=0, GAIN=256) | 2048 | ベースライン | ||
| OFFSET=50 | 2098 | +50加算 | ||
| OFFSET=100 | 2148 | +100加算 | ||
| GAIN=200 (78%) | 1600 | 出力低下 | ||
| GAIN=300 (117%) | 2400 | 出力増加 | ||
| MIN_CUT=30 (DMX=5) | 0 | DMX=5で消灯確認 | ||
| MAX_LIMIT=3000 | 2048 | DMX=255で3000確認 |
【シート4】低域特性詳細測定
目的: DMX 0-32 の立ち上がり特性を詳細に測定
測定条件:
- config_compat.h設定:
DIM_TABLE_SELECT = ___ - 測定日: _______________
| DMX入力 | 設定0 | 設定1 | 設定2 | 設定3 | 実測輝度差 |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | |
| 1 | 16 | 8 | 8 | 4 | |
| 2 | 32 | 16 | 16 | 8 | |
| 3 | 48 | 32 | 32 | 12 | |
| 4 | 56 | 40 | 40 | 16 | |
| 5 | 64 | 48 | 48 | 20 | |
| 6 | 72 | 56 | 56 | 24 | |
| 7 | 80 | 64 | 64 | 28 | |
| 8 | 88 | 80 | 72 | 32 | |
| 10 | 104 | 96 | 80 | 40 | |
| 12 | 116 | 112 | 88 | 48 | |
| 16 | 152 | 208 | 136 | 80 | |
| 20 | 224 | 272 | 192 | 112 | |
| 24 | 256 | 336 | 256 | 148 | |
| 28 | 352 | 400 | 320 | 180 | |
| 32 | 400 | 464 | 384 | 200 |
測定手順
-
準備
- config_compat.h でパラメータを設定
- プロジェクトをビルド・書き込み
- DMXテスタまたはDMXコンソールを接続
-
測定
- 各DMX値を順番に入力
- オシロスコープでPWM出力を測定(または電圧計で平均電圧)
- 輝度は照度計または目視で評価(1-10スケール)
-
記録
- 各シートに測定値を記入
- 理論値との差異が大きい場合は備考に記載
-
分析
- 理論値と実測値の差異を確認
- 必要に応じてキャリブレーションパラメータを調整
測定用CSVファイル
ノートブックを実行すると、以下のCSVファイルが生成されます(Excel/Googleスプレッドシートで開いて記入可能):
| ファイル名 | 内容 |
|---|---|
measurement_sheet_all_curves.csv |
全カーブ測定(19ポイント) |
measurement_sheet_low_0-32.csv |
低域詳細測定(33ポイント) |
measurement_sheet_calibration.csv |
キャリブレーション効果測定 |
キャリブレーションパラメータ効果グラフ
各パラメータがPWM出力カーブに与える影響を可視化したグラフです。
基本パラメータ効果
| パネル | パラメータ | 効果 |
|---|---|---|
| ① | PWM_OFFSET | ベース出力を上げる(下駄を履かせる)。低域でPWM出力が底上げされる |
| ② | PWM_GAIN | 出力レベル調整(78%〜117%)。全体のカーブ傾きが変わる |
| ③ | PWM_MIN_CUT | 完全消灯保証。低PWM値を0にカット(チラつき防止) |
| ④ | PWM_MAX_LIMIT | 上限リミット(LED保護・省電力)。最大出力を制限 |
追加パラメータ効果
| パネル | パラメータ | 効果 |
|---|---|---|
| ⑤ | LOW_CUT_DMX | DMXノイズフロア除去。DMX 0〜N を消灯扱い |
| ⑥ | DEAD_BAND | 微小変化を無視(チラつき防止)。DMX値±2以内の変化は無視 |
| ⑦ | 複合効果 | OFFSET + GAIN の組み合わせ例。用途に応じた設定パターン |
| ⑧ | 処理フロー | DMX=128の処理フロー可視化。各ステップでの値変化 |
グラフの見方
- ①のインセット図: 低域(DMX 0-32)でOFFSETの効果が顕著
- ③のインセット図: MIN_CUTにより消灯範囲が広がる
- ⑥のデッドバンド効果: 赤線(デッドバンドあり)は微小変化時に値が維持される
- ⑧の棒グラフ: DMX入力から最終出力までの各ステージの値を可視化
参考資料
関連ファイル:



