TinyMLで植物の健康状態を診断:実践ガイド
必要な部品と用品
| 部品 | 数量 | 備考 |
|---|---|---|
| Arduino Nano 33 BLE Sense | 1 | |
| Digilentステッピングモーター | 1 | |
| Theremino DRV8825ステッピングモータードライバー | 1 |
必要な工具と機械
- 3Dプリンター(汎用)
- ハンダごて(汎用)
使用アプリとオンラインサービス
- Microsoft VS Code
- Arduino IDE
- Edge Impulse Studio
このプロジェクトについて
前提
人間と同じように、植物も病気になります。皮膚感染で発疹ができるように、植物の葉もカビや病原体によって黄変や斑点が現れます。機械学習の力を活用して色をスキャンし、葉の色が正常でないときに検出できるモデルを訓練できます。
ハードウェア
このプロジェクトの頭脳はArduino Nano 33 BLE Senseです。選んだ理由はいくつかあります。まず、9DoF IMU、APDS-9960(色、ジェスチャー、近接、明るさ)、マイクロフォン、温度/湿度/気圧センサーコンボなど、強力な内蔵センサーが豊富に搭載されています。ボードを植物の葉の周りを動かして測定するため、2つのステッピングモーターとDRV8825ドライバーボードを2つ使用します。


TinyMLのセットアップ
このプロジェクトでは、Edge Impulseに登録されているArduino Nano 33 BLE Senseの内蔵センサー(加速度計とマイクロフォンのみ)では対応できないため、シリアルデーモンの代わりにデータフォワーダーを使用します。まず新しいプロジェクトを作成し名前を付けます。次に、Node.jsとNPMをインストールし、npm install -g edge-impulse-cliを実行してEdge Impulse CLIをインストールします。パスが通っていない場合は環境変数PATHにインストールパスを追加してください。次にedge-impulse-data-forwarderを実行して動作確認し、Ctrl+Cで終了します。

色の読み取り
APDS-9960は赤外線を表面に照射し、物質に吸収されなかった波長を読み取ることで色を検出します。センサーと通信するには、Arduino APDS9960ライブラリをインストールするのが最適です。いくつかの便利な関数にアクセスできます。コードでは、APDS-9960を初期化してからloop関数に入ります。そこでは色データが利用可能になるまで待機します。読み取り可能になると、APDS.readColor()で色を読み取り、表面との近接度も取得します。各RGB成分は0〜2^16-1の数値から、その値を総和で割った比率に変換されます。
スキャンリグ
葉の色をスキャンするため、リグを2軸で動かして、オンボードのAPDS-9960の下に葉の様々な位置を通過させます。各軸はリードスクリューを時計回りまたは反時計回りに回転させ、ブロックをどちらかの方向に移動させます。システム全体はFusion 360で設計しました。以下は設計レンダリングです:



X軸がY軸の上に乗る構造で、上部ブロックが両軸で移動可能です。Y軸にはステッピングモーターの重量を支える追加のVホイールがあります。パーツは約45%インフィルのPLAでプリントしました。

データ収集
システム起動時、ステッピングモーターは位置を把握していないため、リミットスイッチに当たるまでステップごとに原点へ移動してホーミングを行います。次にAPDS-9960を初期化します。境界ボックスを2つの2要素配列(対角の角)で定義します。この2地点間でランダムな点を選び、その間の色を読み取りながらステッピングモーターをその位置まで動かします。
色情報の処理と送信
色はAPDS.readColor()で読み取ります。総和を計算した後、パーセンテージを算出し、Serial.printf()でUSB経由で送信します。値はカンマ区切り、各読み取りは改行文字で区切られます。データフォワーダープログラムで受信すると、指定されたラベル(健全または不健全)としてEdge Impulseクラウドプロジェクトに訓練データとして送信されます。


モデルの訓練
全訓練データを収集後、健全な葉と不健全な葉を区別するモデルを作ります。3軸時系列、スペクトル分析ブロック、Kerasブロックで構成されるインパルスを使用しました。以下のスクリーンショットは、データから特徴を生成する方法を示しています:


テスト
新しいテストデータ(不健全な葉)を収集してモデルをテストしました。モデルの精度は約63%で、テスト特徴を通すとほとんどの場合正しく分類できました。

訓練データを増やし、学習速度を落とすことで精度を向上できます。
コード
leafReader.ino (C/C++)
#include#include #include #include "pinDefs.h" int r, g, b, c, p; float sum; AccelStepper xStepper(AccelStepper::DRIVER, STEPPER_1_STEP, STEPPER_1_DIR); AccelStepper yStepper(AccelStepper::DRIVER, STEPPER_2_STEP, STEPPER_2_DIR); MultiStepper steppers; // 境界ボックス内でランダムな位置を選択 const long boundingBox[2][2] = { {0, 0}, {40, 40} }; void setup() { Serial.begin(115200); while(!Serial); if(!APDS.begin()) { Serial.println("Could not init APDS9960"); while(1); } pinMode(X_AXIS_HOMING_SW, INPUT_PULLUP); pinMode(Y_AXIS_HOMING_SW, INPUT_PULLUP); xStepper.setPinsInverted(X_AXIS_DIR); yStepper.setPinsInverted(Y_AXIS_DIR); xStepper.setMaxSpeed(150); yStepper.setMaxSpeed(150); steppers.addStepper(xStepper); steppers.addStepper(yStepper); homeMotors(); } void loop() { long randomPos[2]; randomPos[0] = random(boundingBox[0][0], boundingBox[1][0]) * STEPS_PER_MM; randomPos[1] = random(boundingBox[0][1], boundingBox[1][1]) * STEPS_PER_MM; steppers.moveTo(randomPos); while(steppers.run()) { if(!APDS.colorAvailable() || !APDS.proximityAvailable()) {} else { APDS.readColor(r, g, b, c); sum = r + g + b; p = APDS.readProximity(); if(!p && c > 10 && sum >= 0) { float rr = r / sum, gr = g / sum, br = b / sum; Serial.printf("%1.3f,%1.3f,%1.3f\n", rr, gr, br); } } } } void homeMotors() { // X軸ホーミング while(digitalRead(X_AXIS_HOMING_SW)) xStepper.move(-1); // Y軸ホーミング while(digitalRead(Y_AXIS_HOMING_SW)) yStepper.move(-1); xStepper.setCurrentPosition(0); yStepper.setCurrentPosition(0); }
pinDefs.h (C/C++)
#define STEPPER_1_STEP 2 #define STEPPER_1_DIR 3 #define STEPPER_2_STEP 4 #define STEPPER_2_DIR 5 #define X_AXIS_HOMING_SW 6 #define Y_AXIS_HOMING_SW 7 // true if inverted #define X_AXIS_DIR false #define Y_AXIS_DIR false #define MICROSTEPS 1 #define STEPS_PER_MM 160 * MICROSTEPS
カスタムパーツとエンクロージャ
3Dプリント用パーツ
CADファイル:thingiverse.com
回路図

製造プロセス
- K30 CO2センサで室内空気質をリアルタイム監視する
- 1SheeldとArduinoで盲ろう者のコミュニケーションを支援する
- スマート貯金箱を作ろう:Arduino Nanoでコインアクセプターを制御
- ArduinoでBluetooth経由でLEDを制御 – シンプルDIYガイド
- DFRobot静電容量式指紋センサーをArduino/ESP8266で使う – 登録・認証・削除の完全ガイド
- Arduino MegaとNextion HMIで作る高機能ウェザーステーション
- Arduinoベースのヌンチャク操作6自由度ロボットアームキット
- Arduino Nanoとジョイスティックで2軸ステッピングモーターを制御:Visuinoで簡単プログラミング
- Arduino UNOとEthernetシールドで太陽放射を測定する自作ピラノメーター
- コンパクトなArduinoレーダーシステム – HC-SR04超音波センサー & 1.8インチST7735ディスプレイ搭載
- Arduinoで楽器演奏:音階生成のステップバイステップガイド