🧙

CAN通信で用いられるDBCフォーマットについて

に公開
2

はじめに

こんにちは!KGモーターズ株式会社でエンジニアをしている中村です。

KGモーターズは、広島を拠点に1人乗り小型 EV mibot を開発しているスタートアップです。

いよいよ量産が迫ってきております。量産の内装、完成度高いです!👇
https://x.com/yzan_travel/status/1968128542371360990

今回は私自身のドメインとは少し異なり、CAN通信関連のお話しです。

車載開発や計測器との通信で使われる CAN通信ですが、
その中で「信号がどのビットに詰められているのか」「どんな意味を持つのか」を定義するのが DBCファイル(CAN Database File) です。

このファイルがあることで、バイナリのCANフレームを「人間が読める変数・物理値」に変換できるようになります。
この記事では、DBCの基本構造と利点、フォーマット仕様の概要を整理します。

DBCファイルとは

DBCファイル は、CANメッセージとその中に含まれる各信号(Signal)の定義を記述したテキスト形式のデータベースファイルです。
(テキストファイルなのかよ、と突っ込んでしまいそうになりました)

簡単に言えば、CAN通信の辞書みたいなもので

「CAN ID 0x123 の 5bit目から16bit分が車速で、スケールは0.01 km/h単位」などのルールを決められたルールで記述していきます。

たとえば、あるメッセージが次のように定義されていたとします。

BO_ 123 VehicleStatus: 8 ECU_Main
 SG_ Speed : 0|16@1+ (0.01,0) [0|250] "km/h" Display
 SG_ BatteryVoltage : 16|16@1+ (0.1,0) [0|600] "V" Display

この例からわかることは...

  • CAN ID 123 のメッセージ(VehicleStatus)には 2 つのシグナルがある
  • Speed は 0bit から 16bit(リトルエンディアン)
  • BatteryVoltage は 16bit から始まる
  • etc...

ツールやコードジェネレータは、この定義を元に「CAN生データ ⇄ 意味のある値」の変換を行っていきます。

DBCファイルを使うと何がいいのか?

1. CANデータの意味を共有できる

これは前述の話で、DBCファイルのルールを使って共有の理解をすることができます

2. コード生成・自動解析が容易

BO_SG_ の定義を元に、自動的にシグナル変換コードを生成したり、Python でデコードしたりできます。

以下はAIに作ってもらったので、バイナリがあってるかわかりませんが...

import cantools
db = cantools.database.load_file('vehicle.dbc')
msg = db.decode_message('VehicleStatus', b'\x10\x27\xA0\x0F\x00\x00\x00\x00')
print(msg)
# {'Speed': 100.0, 'BatteryVoltage': 40.0}

このように、バイナリだけだと全くわからないものが、DBCファイルを通すと人が読める形で扱えるというのが利点です。

3. CAN通信仕様のバージョン管理ができる

DBCはテキストファイルなので、Gitでの差分管理も容易です。
「どのビットがどんな意味に変わったか」が履歴で追えるのもエンジニアにとっては嬉しい話です。

DBCフォーマット

では本題です。
DBCファイルはテキスト構造で、主に次のような構成を持っています。

VERSION ""
NS_ :
BS_:
BU_: ECU_Main Display
BO_ 123 VehicleStatus: 8 ECU_Main
 SG_ Speed : 0|16@1+ (0.01,0) [0|250] "km/h" Display
 SG_ BatteryVoltage : 16|16@1+ (0.1,0) [0|600] "V" Display
VAL_ 123 Speed 0 "STOP" 1 "RUN";
CM_ BO_ 123 "Vehicle status message";

主な構成要素のサマリー

要素 意味 備考
VERSION DBCファイルのバージョン情報 省略可
NS_ シンボルの宣言 内部シンボルリスト
BS_ ビットタイミング(形式上必須) 内容は多くの場合空
BU_ ノード定義(送信元・受信先) ECUやDisplayなど
BO_ メッセージ定義(CAN IDごと) メッセージサイズや送信ノード
SG_ シグナル定義(1つの値の構造) 開始ビット、サイズ、符号、スケールなど
VAL_ 値と文字列の対応表 例: 0="Off", 1="On"
CM_ コメント(説明文) 開発ドキュメント用途にも便利

VERSION

  • バージョン情報
  • CIで自動埋め込みにしておくと、リリース紐付けが楽。

VERSION "Vehicle DB v1.3.2 (2025-11-01)"

NS_ (new symbols)

  • DBC内で使用するシンボル群の宣言
  • 多くの場合、定型の羅列で問題なく、中身を編集することはあまりない

NS_ :
  CM_
  BA_DEF_
  BA_
  VAL_
  SIG_VALTYPE_
  BO_TX_BU_
  VAL_TABLE_
  SIG_GROUP_
;

BS_ (bit timing)

  • ビットタイミング
  • 何も書かないのが一般的らしく、消すとエラーになることがある(らしい)

BS_:

BU_(nodes)

  • ネットワーク上のノード(ECUやツール)を列挙する
  • 送信者/受信者として参照されるため、先にここへ全ノードを登録
BU_: NODE1 NODE2 NODE3

BO_(message)

  • CANメッセージの定義。続けてSG_で中のシグナルを定義
  • message_id はDBC内で一意である必要がある
  • またmessage_size はバイト単位(最大8:Classical CAN、CAN FDはツール依存)

BO_ 288 VehicleStatus: 8 ECU_Main

SG_(signal)

  • 値(信号)の位置・型・スケーリングを定義
  • 開始ビット定義はエンディアンで解釈が異なる
    • byte_orderが0ならBig Endian, 1ならLittle Endian
  • 浮動小数そのものを送りたいときは後述の SIG_VALTYPE_ を併用。
  • 受信者(receiver)はノード名を指定
  • @byte_order0: Big (Motorola), 1: Little (Intel)
  • 物理値は raw * factor + offset

BO_ 288 VehicleStatus: 8 ECU_Main
 SG_ Speed        : 0|16@1+ (0.01,0) [0|300] "km/h" Display
 SG_ BattVoltage  : 16|16@1+ (0.1,0)  [0|600] "V"    Display

ここはテンプレート化すると以下のようになります。
{}に値が入ります。

SG_ {signal_name} : {start_bit}|{size}@{byte_order}{value_type} ({factor}, {offset}) [{min}|{max}] {unit} {receiver}

VAL_(値→文字列の変換テーブル)

  • Signalや環境変数の状態名を定義
  • GUIやログで人間が読みやすくなる

VAL_ 288 GearPos 0 "P" 1 "R" 2 "N" 3 "D" ;
VAL_ Move_Stop 1 "On" 0 "Off" ;

CM_(コメント)

  • DBC内オブジェクトに説明文を付与
  • 仕様の背景/注意点をここに残すと設計レビューが楽になる(かも)

CM_ "Vehicle project DB for 2026 SOP";
CM_ BO_ 288 "Vehicle status message (main loop @10ms)";
CM_ SG_ 288 Speed "Wheel-based speed (filtered)";

BA_(属性の付与)

  • 個々のオブジェクトに属性値を割当(初期値など)

BA_ "CycleMs" BO_ 288 10 ;
BA_ "SafetyLevel" SG_ 288 Speed "ASIL-B" ;
BA_ "Owner" BO_ 288 "Taro.Yamada" ;

最後に

と自分の記録に近い内容となりましたが、KGモーターズでは現在も一緒に働くエンジニアを募集しています!

特に車の制御や組み込みに興味のある方を強く募集しています!
興味がありましたらお気軽にご連絡ください!

https://herp.careers/v1/kgmotors/m1Nj-CQ52U_w

GitHubで編集を提案
KGモーターズ Tech Blog

Discussion

poissonpoisson

とても勉強になりました。いい記事をありがとうございます。
私の経験としては、DBCファイルはVector Infomatik社のツール「CANdb++」で見るのがメインでした。差分確認したいときにテキストエディタやWinMergeで見ることはあれど、各要素の数値の意味を正確には理解していませんでした。なのでこのまとめで「こう読めばいいのか!」「分解能はここで決めてたんだ!」と新しい気付きが得られました。Vector社のライセンスがなくてもDBCファイルの構造さえわかれば、その意味を視覚的に理解できるような内製ツールが作れそうですね。

Sota NakamuraSota Nakamura

コメントありがとうございます!
ソフトウェア開発チームではこの辺りは完全に内製になっていて(改めてDevOps環境を記事にしたいと思ってはいるのですが...)、
CAN定義をJsonやYamlで書きつつGitで管理し、CIでDBCファイルを生成、結合テストを回すなどの仕組みを入れて人手をなるべく排除しています。

そのためvectorライセンスは特になしでDBCを使ったり変えたりする必要があるためフォーマットの理解が重要になっております...笑

また疎通の確認も製品は使わず自分たちでテストコードの中にCAN送受信のプログラムを書いてなるべく自動化できるように開発してきます!