📂

【Arduino IDE】プログラムのフォルダー分け

に公開

プログラムをフォルダーに分けて整頓したい

Arduinoを使った開発、元へ電子工作は、随分と可能性の幅が広いものです。小規模なものはLEDの点灯やボタン入力などといったものがあるでしょう。やや規模が大きくなると、様々に周辺機器を使いだします。“センサー”で環境を測ってみたり、“モーター”のようなアクチュエーターで物を動かしてみたり、“画面”に文字や図柄を映し出したり、Wi-Fiなどの“通信機”でデータを送受信したり、SDカードのような“ストレージ”にデータを保存してみたりと、枚挙に遑ありません。

しかし規模が大きくなれば、それだけプログラムも煩雑に膨張してゆくものです。殊にArduino IDEで使う言語はC/C++ですから、他の現代的な言語よりも見通しよく管理したいものです。

本題

https://github.com/amenaruya/arduino-structured-sketch-with-directories

GitHubに載せた例の通り、「モジュール」という単位でプログラムを分けました。単なる例のため、文字列を返却するだけの取るに足らないものです。

  1. Module1

https://github.com/amenaruya/arduino-structured-sketch-with-directories/blob/main/Modules/M1/Module1.cpp

  1. Module2

https://github.com/amenaruya/arduino-structured-sketch-with-directories/blob/main/Modules/M2/Module2.cpp

一応どのような構造になっているのか示しておきます。

階層構造
> tree /F
Folder PATH listing for volume OS
Volume serial number is ____-____
C:.
   folder.ino
   ModulesMap.hpp
   
└───Modules
    ├───M1
       Module1.cpp
       Module1.hpp
       
    └───M2
            Module2.cpp
            Module2.hpp

この様にフォルダーを使って分類することで、乱雑に全て臚列しておくよりも整理整頓されることが期待できます。

少し規模が大きくなった場合の例

私物で恐縮乍ら、少し複雑で規模も大きくなってしまったスケッチの様子を紹介します。出来上がるのは、温湿度計と時計を組み合わせただけのものです。

> tree /F
フォルダー パスの一覧:  ボリューム OS
ボリューム シリアル番号は ____-____ です
C:.
  ModulesMap.hpp
  ThermohygrometerWatchRtosLvgl.ino
  THWRL_ThreadErpc.ino
  THWRL_ThreadHih.ino
  THWRL_ThreadRtc.ino
  UsingQueueTypeAliases.hpp

└─Modules
  Publics.hpp

    ├─eRPC
  ├─Queue
      MutexStaticQueue.hpp
      MutexStaticQueue.ipp

  └─WiFi
          ApiClient.cpp
          ApiClient.hpp
          SsidAndPassword.hpp

    ├─GUI
      LvglArduinoAbstractLayer.hpp
      LvglArduinoAbstractLayer.ipp
      WatchApp.cpp
      WatchApp.hpp

    └─peripherals
        ├─HIH6130
      HIH6130.cpp
      HIH6130.hpp

        └─RTC
                RtcTimer.cpp
                RtcTimer.hpp

フォルダー分けの弊害

注意すべきは、上述した通りプログラムをフォルダーに分けてしまうと、明確に弊害がある点です。

フォルダーの中が見えない
フォルダーに分けたファイルが見えない

Arduino IDEでは、所謂「直下」にあるファイルしか表示されません。ここではfolder.inoModulesMap.hppしか表示されていない樣が見て取れるでしょう。

これ自体は、VSCodeのような他のIDEを使えば良い話です。寧ろ、元来そうしているという人もあるでしょう。こればかりは、Arduino IDEの根本的な使いづらさだろうと思います。

問題なのは、表示されていないプログラムは認識されていないため、基本的にはコンパイルにも含まれずエラーになることです。せめてコンパイルと書き込みくらいは間違いなくできてほしいものです。

弊害への対応

コンパイルに含めるためには、直接ファイルを指定する必要があります。私は整理の意味で、includeだけのファイルを作りました。

https://github.com/amenaruya/arduino-structured-sketch-with-directories/blob/main/ModulesMap.hpp

しかしこの記述では孰れ「二重インクルード」を起こすため、広い目で見れば不適切です。

今回はあまりにも取るに足らないことしか書かれていないため奇跡的に無事なだけであり、.c.cppのようなソースファイルには通常「インクルードガードを付けない」ことが起因してか、「二重インクルード」になります。

そもそもソースファイルをインクルードしていること自体おかしいのですが、コンパイルするためこのようになってしまいました。回避する方法もあるのでしょうが、私はそこまで辿り着けませんでした。

依てより複雑な構造になってしまった場合には、次のように配慮します。

配慮の鬼󠄁
#ifndef __MODULES_MAP_HPP__
#define __MODULES_MAP_HPP__

/* publics */
#ifndef __PUBLICS_HPP__ // インクルードガード
#include "Modules/Publics.hpp"
#endif // __PUBLICS_HPP__

/* eRPC */

/* Queue */
#ifndef __MUTEX_STATIC_QUEUE_H__ // インクルードガード
#include "Modules/eRPC/Queue/MutexStaticQueue.hpp"
// #include "Modules/eRPC/Queue/MutexStaticQueue.ipp"
#endif // __MUTEX_STATIC_QUEUE_H__

/* Wi-Fi */
#ifndef __API_CLIENT_HPP__ // インクルードガード
#include "Modules/eRPC/WiFi/ApiClient.hpp"
#include "Modules/eRPC/WiFi/ApiClient.cpp"
#endif // __API_CLIENT_HPP__

/* GUI */

#ifndef __LVGL_ARDUINO_ABSTRACT_LAYER_HPP__ // インクルードガード
#include "Modules/GUI/LvglArduinoAbstractLayer.hpp"
// #include "Modules/GUI/LvglArduinoAbstractLayer.ipp"
#endif // __LVGL_ARDUINO_ABSTRACT_LAYER_HPP__

#ifndef __WATCH_APP_HPP__ // インクルードガード
#include "Modules/GUI/WatchApp.hpp"
#include "Modules/GUI/WatchApp.cpp"
#endif // __WATCH_APP_HPP__

/* peripherals */

/* HIH6130 */
#ifndef __HIH6130_HPP__ // インクルードガード
#include "Modules/peripherals/HIH6130/HIH6130.hpp"
#include "Modules/peripherals/HIH6130/HIH6130.cpp"
#endif // __HIH6130_HPP__

/* RTC */
#ifndef __RTC_TIMER__ // インクルードガード
#include "Modules/peripherals/RTC/RtcTimer.hpp"
#include "Modules/peripherals/RTC/RtcTimer.cpp"
#endif // __RTC_TIMER__

#endif // __MODULES_MAP_HPP__

このようになることを踏まえると、予めファイル一つ使って対応した方がよいでしょう。

上に触れた二重インクルード以外にも、「フォルダー分けしなければこんなこと不要だった」と感じる配慮を幾つも要します。畢竟、「不便」な側面もあるというのが素直な所感でした。単に整頓したいからと手を出すよりも、本当に煩雑になってしまった場合のみ頼むべき手法であろうと考えます。

Discussion