Progress Log: Serial.printlnの使い方ガイド¶
Task Description¶
Serial.println(およびSerial.print)の使い方をKurikintonsプロジェクトの文脈で整理しました。
以下の観点から調査・整理しました。
Serial.printlnとSerial.printの違い- 基本的な型と出力方法
- Fマクロによるメモリ最適化
kurikintonsでの実践的な使用例ArduinoJsonとの連携
Outcome¶
Serial.printlnの包括的な使用ガイドを作成しました。
Serial.print vs Serial.println¶
違い:
Serial.print()- 改行なしSerial.println()- 改行付き(\nを自動追加)
Serial.print("Detection:");
Serial.print(95);
Serial.println(); // 改行
// 出力: Detection:95
出力可能な基本型¶
// 文字列
Serial.println("Hello, World!"); // 文字列リテラル
Serial.println("Detection complete");
// 数値型
Serial.println(123); // 整数
Serial.println(45.67); // 浮動小数点数
Serial.println((byte)255); // バイト値
// 真偽値
Serial.println(true); // "1"
Serial.println(false); // "0"
// 変数
int value = 100;
float temp = 25.35;
Serial.println(value);
Serial.println(temp);
char配列とStringオブジェクト¶
// char配列(C文字列)
char str[] = "Detection";
Serial.println(str);
// Stringオブジェクト
String myString = "ArduinoJson";
Serial.println(myString);
数値の基数指定¶
// 16進数
Serial.println(0xFF, HEX); // FF
// 2進数
Serial.println(255, BIN); // 11111111
// 8進数
Serial.println(255, OCT); // 377
// 10進数(デフォルト)
Serial.println(255, DEC); // 255
Serial.println(255); // 255
Fマクロ - メモリ最適化¶
問題: 文字列リテラルはデフォルトでRAMに格納される
// ❌ 問題:RAMを消費
Serial.println("Detection complete");
Serial.println("Sensor initialized");
Serial.println("Error occurred");
解決: Fマクロを使ってフラッシュメモリに格納
// ✅ 推奨:RAMを節約
Serial.println(F("Detection complete"));
Serial.println(F("Sensor initialized"));
Serial.println(F("Error occurred"));
メモリ削減効果:
- 固定メッセージ3つ(各30バイト程度): 90バイトのRAM節約
- ESP32は限られたRAMしかないため、制御メッセージはすべてFマクロを使用すべき
Kurikintonsでの実践例¶
1. 検出イベントのログ出力¶
// イベント発生時の通知(Fマクロ使用)
if (detection.detected) {
Serial.println(F("=== Detection Event ==="));
// 検出値の出力(動的なので Fマクロ不要)
Serial.print(F("signal1: "));
Serial.println(detection.signal1);
Serial.print(F("signal2: "));
Serial.println(detection.signal2);
Serial.print(F("temperature: "));
Serial.println(temperature);
}
2. JSONL形式での出力¶
StaticJsonDocument<256> doc;
doc["signal1"] = 95;
doc["signal2"] = 87;
doc["signal3"] = 92;
doc["adc"] = 2048;
doc["temp"] = 25.35;
doc["pressure"] = 1013.25;
doc["humidity"] = 45.67;
doc["uptime_ms"] = 123456;
doc["duration_us"] = 1234567890;
// JSON全体をシリアル出力(JSONL形式)
serializeJson(doc, Serial);
Serial.println(); // 改行で1行を完成
シリアル出力:
{"signal1":95,"signal2":87,"signal3":92,"adc":2048,"temp":25.35,"pressure":1013.25,"humidity":45.67,"uptime_ms":123456,"duration_us":1234567890}
3. センサー初期化ログ¶
void setup() {
Serial.begin(115200);
delay(3000);
// Fマクロで制御メッセージを出力
Serial.println(F("Kurikintons System Starting..."));
// センサー初期化
if (bme280_init()) {
Serial.println(F("BME280 initialized"));
} else {
Serial.println(F("BME280 initialization failed"));
}
cosmic_detector_init();
Serial.println(F("Cosmic detector initialized"));
Serial.println(F("System ready"));
}
4. デバッグ出力パターン¶
// 値と説明を組み合わせた出力
Serial.print(F("Free heap: "));
Serial.print(ESP.getFreeHeap());
Serial.println(F(" bytes"));
// 複数の値を1行で出力
Serial.print(F("Signal: "));
Serial.print(signal1);
Serial.print(F(", "));
Serial.print(signal2);
Serial.print(F(", "));
Serial.println(signal3);
// 結果: Signal: 95, 87, 92
Serial.print/println vs ArduinoJson¶
Single値の出力:
Serial.println(value); // 単純で直感的
複合データ(JSON)の出力:
// JSON全体をまとめて出力
serializeJson(doc, Serial);
Serial.println(); // 改行で1行完成
// 結果: {"signal1":95,"signal2":87,...}
推奨パターン:
- 制御メッセージ →
Serial.println(F("...")) - センサー値 →
Serial.print()とSerial.println() - 検出データ(複合) →
serializeJson(doc, Serial)+Serial.println()
メモリ使用量のチェック¶
void print_memory_info() {
// Fマクロでメモリ情報を出力
Serial.print(F("Free heap: "));
Serial.print(ESP.getFreeHeap());
Serial.println(F(" bytes"));
Serial.print(F("Largest free block: "));
Serial.print(ESP.getMaxAllocHeap());
Serial.println(F(" bytes"));
Serial.print(F("Flash size: "));
Serial.print(ESP.getFlashChipSize() / 1024);
Serial.println(F(" KB"));
}
ボーレート設定¶
// 115200 bps はKurikintons標準
Serial.begin(115200); // JSONL出力に推奨
転送時間の目安(115200 bps = 9600 バイト/秒):
- 60バイト(スペース区切り): 約6ms
- 150バイト(JSONL): 約16ms
Learnings¶
- Fマクロは必須: 固定メッセージにはF()を使ってRAMを節約
- print vs println: 用途に応じて使い分ける(改行の有無)
- JSON出力との組み合わせ:
serializeJson(doc, Serial)+Serial.println()で効率的 - メモリ制約を意識: ESP32のRAMは限られているため、ストリーミング出力が有効
- デバッグとデータ出力の分離: 制御メッセージ(Fマクロ)と検出データ(JSON)を分ける
Next Steps¶
- Kurikintonsでの統合:
- 既存の
Serial.printlnをFマクロに置き換え - JSONL形式の検出データ出力へ移行
-
ログレベル機能の実装(デバッグ/本番)
-
パフォーマンス測定:
- JSONL形式でのシリアル出力速度テスト
- メモリ使用量の実測定
-
バッファオーバーフロー確認
-
ドキュメント統合:
- ArduinoJsonガイドとの組み合わせ例
- JSON形式ガイドとの統合