目次 — 知りたいところから読む
入力を変えて確かめる
実験パネルを開き、実行を押すとPythonを読み込みます。停止と初期値へのリセットができます。結果はこの端末内で計算します。Pythonのインストールは不要です。
下にあるローカル実行の手順は、配布ソースを再現するための任意の手順です。ブラウザ実験には不要です。
ブラウザで投影面積を試す
上のパネルで、Pythonをインストールせずに合成画像の実験を実行できます。基準・緑色タグ・暗い左半分・画面外にはみ出す形状を選び、最小明度V・ROI・mm/pixelを変更します。9プリセットには公開済みの7条件に加え、小さすぎるROIと抽出なしの条件があります。プリセットは全入力を戻します。復元用プリセットでも、明度を手動変更すればその値を使います。
入力・画面内の参照・抽出マスク・誤差画像を見比べます。赤は背景の誤検出、青は対象の見落とし。茶線は入力画像上の指定ROI境界です。結果をAに保存して一つの入力を変えると、同じ表示倍率で画像と指標を比較できます。数値表は横方向の連続画素を、0始まりのx/yと長さで記録し、間引かずに各領域を復元できます。条件共有や結果JSONの保存も使えます。
画像は元の320×240の幾何図形で、写真アップロードやカメラ入力はありません。NumPyの形状生成・測定関数は元のまま再利用します。ブラウザではOpenCVの色変換・範囲選択だけを、生成器が使う固定3色の検証済み対応表に置き換えます。RGBの背景(235,235,235)・対象(50,160,65)・暗部(20,60,25)は、OpenCV 4.6.0のuint8 HSVで(0,0,235)・(64,175,160)・(64,170,60)です。一般画像のHSV変換器ではありません。H 35–85、S 80–255は固定し、最小Vは0–255で調整します。境界値を含み、形態学処理は行いません。
タグを除くROIは(50,20,230,190)、小さいROIは(140,60,20,30)で、x/y/幅/高さの画素値です。植物に自動追従しません。尺度0.1–1.0 mm/pixelは参照平面を仮定した変換で、校正結果ではありません。尺度を変えても画像は変わりません。画面端への接触は1=はい/0=いいえで表示し、抽出なしの適合率は未定義(—)です。はみ出した形状のIoUが1でも画面外の欠落は検出できません。バイオマス・成長・ストレス・実際の葉表面積は測定しません。
元の配布物と基準結果は保持し、以下のローカル再現は任意です。ブラウザ用アダプタはOpenCVを使わずNumPyだけで動作します。実行コード・カーネル・パレットを同じフォルダへ保存し、NumPyがあればローカルでも実行できます。
CEAの計測と流れ — CO₂・養液センサーをどこに置くか
同じ表示値でも、見ている場所と時刻が違う
タンクのDOと栽培槽出口のDOに差が出た。根による酸素消費を考える前に、二つのセンサーが同じ時刻を見ているか、校正状態がそろっているか、採水中に液が変化していないかを確認したい。
根圏の基礎はEC・pH・DOの意味と水収支を分けた。本記事は、それらをどこで、どう比較するかへ進む。温湿度センサーの記事で扱った一次遅れや校正と調整の違いは再利用し、CO₂、養液、液体と空気の流れに固有の注意点を追加する。
以下の配置表と調査手順は本記事の設計案である。特定施設の実測結果、必要センサー台数、作物共通の警報値ではない。
先に観測したい差を決める
| 対象 | 比較する位置の例 | 一緒に残す情報 |
|---|---|---|
| 栽培域CO₂ | 群落付近、給気、排気または還気 | 高さ、施用・換気・扉の状態、温湿度 |
| 養液EC・pH・水温 | 混合後のタンク、栽培槽入口と出口 | 原水、投入履歴、液量、循環状態 |
| DO | タンクと根の近く、栽培槽出口 | 水温、曝気状態、プローブ方式 |
| 液体の流れ | 補給管、必要な枝管、排液管 | 流量、測定位置、バルブ状態 |
| 水位・圧力 | タンク、フィルター前後など | 水位から体積への換算、圧力基準と高さ |
| 空気の流れ | 棚の手前・奥・高さの違う位置 | 風速の向き、平均化時間、ファン状態 |
常設点は日常監視に、移動測定は分布調査に使い分ける。移動中の時間変化を区別するため、固定参照点を残す。配置が決まったら位置IDを付け、センサー交換でも測定場所の履歴が途切れないようにする。
CO₂の自動校正は、栽培条件に合うか
CO₂供給口の直近で測った値を、群落全体の代表値とはしない。供給源、給排気、人の呼気との位置関係を記録する。栽培域を調べる点と、施用設備の動作を調べる点では目的が異なる。
機器の自動校正も確認する。たとえばSensirion SCD30の2018年版フィールド校正資料は、ASCが最低濃度を400 ppmに対応付け、定期的にその濃度へ曝露される条件を必要とすると説明している。
この前提から、CO₂を継続施用する室などでは、その機能を無条件に適用できないと判断する。これは同資料に記載された方式に関する注意であり、全CO₂センサーの共通仕様ではない。選んだ機種・ファームウェアの説明に従い、基準ガスや校正済み参照器との比較を計画する。400 ppmを現在の屋外空気の保証値として入力する、という意味でもない。
CO₂計に温湿度出力があっても、筐体内部の測定が栽培域の代表値になるとは限らない。補償用の入力と、植物周囲を評価する測定を区別する。
EC・pH・DOは同じ校正液で済ませない
USGSの多項目水質計測マニュアルは、保管・保守、校正、測定と報告を一つの手順として扱う。自然水向けの資料なので、栽培の設定値や養液への適合性を直接保証するものではない。
以下はその考え方を踏まえた確認項目であり、具体的な手順と薬液は各機器の説明書に合わせる。
| 項目 | 確認内容 |
|---|---|
| EC | 導電率標準液の値と温度、想定範囲、セル定数・温度補償設定 |
| pH | 測定範囲を考慮した緩衝液、液温、電極と液絡部の状態、保管方法 |
| DO | 光学式か電気化学式か、校正条件、気圧・塩分補償、膜やキャップの状態 |
| 共通 | 調整前の差、清掃・調整後の差、標準の識別情報、実施日、安定待ち時間 |
標準液へ浸して数値を合わせる作業だけで、設置後の代表性は確認できない。気泡、付着物、液の停滞、局所的な投入直後の濃度差も調べる。
DOは方式による違いがある。YSIの測定解説では、光学式は酸素を消費しないため測定原理上の攪拌要求がなく、流れによって応答が速くなることはあると説明している。電気化学式と同じ流速条件だと決め付けず、機種の条件を確認する。光学式でも、センサー位置の液が根の周囲を代表するかという問題は残る。
採水管は過去の液を運んでくる
別置きの計測セルへ採水する場合、表示時刻と採水点の状態の時刻がずれる。説明用に、管内体積0.50 L、一定流量0.25 L/min、混合も拡散もない押し出し流れを仮定すると、輸送時間は次のようになる。
2分は管内の理想輸送時間だけであり、計測セルの混合、センサー応答、通信遅延を含まない。
流量を0.50 L/minにすると、この仮定では1分になる。実際には管やセルで混ざり、採水中に温度やガス交換が変化することもある。単にログを2分ずらせば元の状態を復元できるとは限らない。
記録には、採水点ID、管・セルの構成、流量、機器の測定時刻、受信時刻を分けて残す。複数の採水点を切り替える方式では、前の試料がどの程度残るかも確認する。
ポンプ指令、流量、水位、圧力を照合する
ポンプONは流れの測定ではない。タンクから送り出している量と各枝管へ届く量も同じ情報ではない。流量計は型式ごとの必要直管長、満管条件、測定範囲、気泡の影響を確認して設置する。
水位を体積へ変換するときはタンク形状を使う。断面積一定なら体積変化は面積×水位変化だが、底が傾斜した容器などへ一律の換算を使わない。圧力による水位測定なら、液密度や基準圧の扱いも確認する。
フィルター前後の圧力差は比較に使えるが、流量が違えば圧力差も変わりうる。同じ運転条件をそろえず「差圧が上がったから詰まり」と断定しない。測定高さ、ゲージ圧か絶対圧か、単位もそろえる。
水収支の残差で、不一致を見つける
ここではタンクだけを境界とし、タンクへ入るすべての流れを Q_{in}、出るすべての流れを Q_{out} とする。前記事の循環系全体とは境界が違うので、送りと戻りも含める。合成例では蒸発などの別項をゼロと仮定する。
流量をL/min、時間をminで入れると残差 r はLになる。次の独自例では5分間に1.0 L/minが入り、0.2 L/minが出る。予測される増加は4 Lだが、水位から求めた体積は100 Lから101 Lへ1 Lしか増えていない。残差は −3 L である。
これは未計上の流れ、流量・水位の偏り、時刻ずれ、モデルに入れていない損失などを調べる入口であり、漏水の証明ではない。
from math import isfinite
def transport_minutes(line_l, flow_l_min):
if not all(isfinite(x) for x in (line_l, flow_l_min)):
raise ValueError("finite values required")
if line_l < 0 or flow_l_min <= 0:
raise ValueError("nonnegative volume and positive flow required")
return line_l / flow_l_min
def residual_l(v0, v1, intervals):
if not all(isfinite(v) and v >= 0 for v in (v0, v1)):
raise ValueError("invalid tank volume")
if not intervals:
raise ValueError("intervals required")
predicted = 0.0
for minutes, inflow, outflow in intervals:
if not all(isfinite(x) for x in (minutes, inflow, outflow)):
raise ValueError("finite interval values required")
if minutes <= 0 or min(inflow, outflow) < 0:
raise ValueError("invalid interval")
predicted += (inflow - outflow) * minutes
return (v1 - v0) - predicted
print(f"transport: {transport_minutes(0.50, 0.25):.1f} min")
print(f"residual: {residual_l(100, 101, [(5, 1.0, 0.2)]):.1f} L")
measurement_check.py に保存し、python3 measurement_check.py で実行すると 2.0 min と -3.0 L を得る。区間内一定流量を仮定し、区間は欠測や重複なしで全期間を覆うものとする。この簡易コードは時刻列を受け取らないため、その条件を自動検証しない。
最後の体積を104 Lに変えると残差は0になる。5分の区間を同じ流量で2分と3分に分けても結果は変わらない。実測へ使うときは、欠測をゼロ流量に置き換えず、積算を無効として扱う。
仮に初期・最終体積の誤差上限を各0.5 L、二つの流量の誤差上限を各0.1 L/min、時間の誤差をゼロと置くと、5分の残差への最悪ケースの寄与は 0.5+0.5+5(0.1+0.1)=2.0 Lである。3 Lの差はこの仮定だけでは説明し切れない。これは独自の誤差上限例であり、製品精度でも統計的な信頼区間でもない。上限の根拠や未計上項を確認してから診断へ進む。
送風と換気も分けて測る
室内循環は空気を移動・混合する。換気は室外と空気を交換する。NC Stateの温室解説も両者を別に扱っている。循環ファンの定格風量を、そのまま外気交換量としてCO₂収支へ入れない。
群落付近の風速を調べるときは、プローブの向き、測定位置、平均化時間、点灯とファンの状態を記録する。棚の手前の一点で風があっても、奥まで同じとは言えない。平均だけでなく点間差や変動を残し、生育によって通り道が変わったときは測り直す。風速一値から蒸散や病害を直接推定することも避ける。
試運転で確かめる順序
- 観測の目的と境界を決め、位置ID・単位・時刻をそろえる。
- 標準または参照器との比較を行い、調整前後を保存する。
- 同じ位置への並置で機器差を調べ、位置調査と分ける。
- 操作の履歴と測定を照合し、輸送・応答・通信の遅れを区別する。
- 水収支と複数の測定量で不一致を探し、原因を一つに決め付けず確認する。
ここまでで整えるのは、制御や推定へ渡す観測の土台である。次の植物画像による推定でも、画像時刻、照明、撮影位置を同じように記録し、見かけの変化を生育量と混同しないことが必要になる。
CEAの植物画像 — 投影面積を測り、葉面積と区別する
写真の緑が増えたら、葉が増えたと言えるか
同じ植物でも、葉の向き、重なり、照明、カメラの位置が変わると、写真で見える領域が変わる。そこで最初の推定課題を、画像内で対象として抽出した領域の投影面積に限定する。葉の表面積、重量、収量やストレスを直接推定する記事ではない。
前記事の計測と流れは、場所・機器・時刻の差を分けた。画像でも同じように、撮影条件と解析条件を記録する。本記事の入力は楕円を重ねた合成図形であり、実植物の写真も学習済みモデルも使わない。失敗の原因が分かる画像で計算を確かめ、実測へ進むときの評価方法を整理する。
測る量を先に定義する
二値マスク M(u,v) が対象の画素で1、背景で0なら、画素数は N=\sum_{u,v}M(u,v) となる。等方的な縮尺を s [mm/pixel] と仮定すると、平面換算面積は次で求められる。
合成例では14,738画素、縮尺0.5 mm/pixelなので 3,684.50 mm² となる。この縮尺は説明のために与えた値で、自動検出したものではない。
| 量 | このページで測るもの | 混同しないもの |
|---|---|---|
| マスク画素数 | 抽出した画素の個数 | 輪郭で囲まれた幾何学的面積 |
| 平面換算の投影面積 | 画素数×縮尺の二乗 | 曲がった葉の実表面積 |
| 可視領域の和集合 | 上から見えている対象領域 | 重なった葉を一枚ずつ足した総面積 |
| 緑色領域 | 色条件で選んだ候補 | 葉という意味が保証された領域 |
PlantCVのサイズ解析でも、領域マスクから形状量を求め、画素寸法を使って長さ・面積を実単位へ換算する。このように領域の抽出と単位換算を分ける。本コードはPlantCVを呼び出さず、画素を直接数える。
撮影と縮尺をそろえる
測定を始める前に、カメラ位置・姿勢・焦点距離、画像サイズ、露出・ホワイトバランス、照明、植物IDと撮影時刻を記録する。自動露出や自動ホワイトバランスを使う場合も、その状態を残す。異なる設定の画像を同じ閾値で比べると、色の変化が対象面積の変化として現れうる。
既知の100 mmが画像で200画素なら、その位置での縮尺は0.5 mm/pixelとなる。基準物は測りたい平面と同じ高さに置き、カメラをできるだけ正対させる。歪みや透視の影響が無視できない場合はカメラ校正や平面の補正を行う。縦横の縮尺が異なるなら Ns_xs_y とする。
床面の基準物と、床から高く伸びた葉では、一般に画像の縮尺が同じとは限らない。平面補正も三次元の葉全体を同一平面へ変えるものではない。条件が満たせないときは、mm²を葉の物理面積として報告せず、固定撮影条件での画素数や基準平面換算値として扱う。
縮尺を0.5から0.6へ取り違えると、同じマスクでも面積は1.44倍、すなわち44%大きくなる。抽出が正しくても単位換算は誤りうる。
色の範囲で候補を抽出する
OpenCVの公式チュートリアルは、HSVへ変換して inRange で色の範囲を選ぶ方法を示す。本例もこの方式を用いるが、緑色を選べることと葉を識別できることは同じではない。
合成画像は320×240画素。8-bitのOpenCV HSVでHを35–85、Sを80–255、Vを100–255として抽出する。Hは角度をそのまま0–360で入力する形式ではない。コード内の画像配列はRGBなので COLOR_RGB2HSV を用いる。imread で読み込むBGR画像へ、その変換を無条件に流用しない。
核になる処理は次の3行である。実行に必要な画像生成・条件比較・検証は配布コードに含める。
hsv = cv2.cvtColor(rgb, cv2.COLOR_RGB2HSV)
mask = cv2.inRange(hsv, (35, 80, min_v), (85, 255, 255)) != 0
pixels = int(np.count_nonzero(mask))
本例は形態学的な穴埋めや小領域除去を行わない。後処理で見た目を整えるときも、細い葉や葉間の隙間まで変わらないか参照マスクで確認する。
同じ形で、失敗条件を比較する
参照マスクは図形生成時に定義した「画面内に見える三つの楕円の和集合」である。図形の重なりを二重に数えず、画面外に切れた部分も含めない。
赤は背景を対象とした画素、青は対象を落とした画素。緑色部分は元画像を残しており、実植物の写真ではない。
| 条件 | 抽出画素数 | 平面換算面積 [mm²] | IoU | 読み方 |
|---|---|---|---|---|
| clean:基準 | 14,738 | 3,684.50 | 1.000 | 合成参照と一致 |
| green_tag:緑色背景物 | 15,538 | 3,884.50 | 0.949 | 800画素を余分に抽出 |
| green_tag_roi:範囲を限定 | 14,738 | 3,684.50 | 1.000 | この配置では背景物を除外 |
| dim:左側を暗くする | 7,428 | 1,857.00 | 0.504 | 形が同じでも約半分を見落とす |
| dim_lower_v:V下限40 | 14,738 | 3,684.50 | 1.000 | この暗部は再び抽出できる |
| wrong_scale:縮尺0.6 | 14,738 | 5,305.68 | 1.000 | マスクは正しいが換算値は44%増 |
| clipped:画面端で切れる | 13,016 | 3,254.00 | 1.000 | 画面内参照には一致するが全体像ではない |
green_tag_roi の範囲は左上座標(50,20)、幅230、高さ190画素で固定する。合成背景物を避けるよう選んだ範囲で、実作物共通の設定ではない。対象がその外へ伸びると、正しい葉も除外してしまう。
V下限を下げる方法も万能ではない。今回は暗い対象だけが回復するが、実際には背景の暗い緑も入りうる。条件ごとに正解を見ながら閾値を合わせ、その同じ画像だけで高い精度を報告することは避ける。
面積と位置を別々に評価する
予測マスクを P、参照マスクを G とすると、IoUは重なりを和集合で割った値である。
余分な抽出と見落としが同じ画素数なら、総面積の誤差はゼロでも位置は違う。たとえば参照が [0,1,1,0]、予測が [1,1,0,0] なら、どちらも2画素だがIoUは1/3になる。
配布結果にはIoU、precision(抽出した中で正しかった割合)、recall(参照のうち抽出できた割合)を保存する。mask_area_error_percent は参照に対する画素数の誤差率で、縮尺の物理誤差を含まない。だからwrong_scaleでもこの値は0になる。参照と予測がどちらも空など、分母がゼロの場合はJSONの null とし、勝手に完全一致とは扱わない。
touches_frame は抽出マスクが画像端へ達したかを示す。clippedはtrueになる。ただし色抽出で端の部分を落とした場合や、ROIの内側で切った場合まで検出するものではない。フラグがfalseでも画像全体とROIを目視確認する。
ダウンロードして再現する
一式ZIP、Pythonコード、期待結果、README、manifestを公開する。ZIPには入力、参照、抽出マスク、誤り画像も含む。画像やマスクは同じコードで再生成できる。
検証環境はLinux x86_64、Python 3.12.3、NumPy 1.26.4、OpenCV 4.6.0。配布用の依存バージョンは固定している。他のOSやPython版での動作を保証する一覧ではない。
ZIPを展開したディレクトリで次を実行する。
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python experiment.py --self-test
.venv/bin/python experiment.py --verify expected.json --out reproduced
Windowsでは .venv/bin/python を .venv\Scripts\python.exe に置き換える。出力先 reproduced は存在しないディレクトリを指定する。既存ファイルは上書きしない。結果JSONと各条件のPNGが保存される。既定条件の生成済み出力はZIPの samples/ に入っている。
V下限を変える場合は次を実行する。
.venv/bin/python experiment.py --min-v 40 --out lower-v
dim_lower_v だけは常に40で、他の条件は指定値を使う。変更後の結果は既定の期待結果と違うため、--verify expected.json を同時に指定すれば不一致になる。これは検証の正常な失敗である。
7件のテストは既知の長方形面積、面積が同じでも位置が違う例、空マスク、7条件の関係、不正値、期待結果の改変、ROIによる見落としを確認する。元の配布パッケージに実写真の読み込み機能はない。ブラウザ用アダプタは上のパネルから利用できる。
実植物で検証するときの記録
以下は実測へ進むための評価案であり、本記事で完了した実験ではない。
- 植物ID・撮影日・照明・撮影幾何を記録し、入力画像を保存する。
- 茎や枯れた葉を含むかなど、対象領域の定義を決めて人手参照マスクを作る。
- 閾値を決める画像と評価用画像を分ける。連続撮影の近いフレームだけを別群へ分けず、植物や撮影日単位の分離も検討する。
- 明暗、背景、重なり、画面端での誤差を別々に集計し、面積とIoU、誤り画像を残す。
- 実葉面積や乾燥重量へ換算したい場合は、対応する独立した参照測定を集め、別の推定モデルとして検証する。
時系列で投影面積が変わっても、葉の姿勢変化や重なりが原因かもしれない。生育率やストレスの判定は、画像の数値が出ただけでは成立しない。まず再現可能な観測量を作り、その量が何を表しているかを参照データで確かめる。
CEAの根圏 — EC・pH・酸素と水収支を分けて読む
水位が下がったとき、何を補うのか
100 Lの養液が90 Lになった。この情報だけでは、減った10 Lが蒸散・蒸発なのか、漏れなのか、排液なのかは分からない。植物が吸収した養分量も決まらない。水量を戻す操作と、養分組成を戻す操作は別の判断である。
光環境の記事に続き、本記事では根の周囲を扱う。中心は循環養液系の基礎であり、作物別の処方や自動投薬の実装ではない。計算例はすべて合成条件である。
根圏とは根が周囲と水・養分・ガスを交換する領域を指す。養液タンクの値は管理に役立つが、根の表面、栽培槽の末端、培地内部まで同じ値とは限らない。
五つの量を一つの「養液の良さ」にまとめない
| 測る量 | 単位・意味 | 単独では決まらないもの |
|---|---|---|
| EC | mS/cmなど。液の電気の通しやすさ | 硝酸、カリウム、カルシウムなど個別の濃度 |
| pH | 水素イオン活量に関する対数量 | 目標pHまでに必要な酸・塩基の量 |
| DO(溶存酸素) | mg/L、または飽和度% | 根の表面への酸素供給速度 |
| 水温 | °C。測定した位置の温度 | 空気温度や根全体の温度分布 |
| 水量・流量 | L、L/minなど | 個々の養分の吸収量 |
この表は測定計画の整理である。値の許容範囲は作物、生育段階、栽培方式ごとに検討する。
ECは組成を復元するセンサーではない
1 mS/cm = 1,000 µS/cm = 1 dS/m。桁の取り違えを防ぐため、記録に単位を残す。ECは液温でも変わるので、実測温度と温度補償の設定・基準温度を併記し、補償済みと未補償の値を混ぜない。
ECから各塩の濃度は求められない。Oklahoma State Universityの水質検査解説も、ECとTDSでは個別の塩濃度を示せないと説明している。必要な元素の不足と、別のイオンの蓄積が同時に起きても、一つのEC値では区別できない。
EC換算型の「ppm」表示も、個々の養分を測った結果ではない。換算係数と表示方式を保存し、分析機関による濃度値と区別する。組成を確かめるには原水・養液の分析を組み合わせる。
OSUの養液管理資料は、原水の検査と、塩濃度・pH・アルカリ度・養分比率の管理を挙げている。ここから本記事では、ECの設定値へ戻ったことを「処方が元通りになった」と判断しない記録方法を採る。
pHとアルカリ度は別々に記録する
pHは現在の酸性・塩基性を表す。対数なので、二液のpHを体積で平均しても、通常は混合後のpHにならない。USGSのpH解説
アルカリ度は酸を中和する能力の指標である。同じ初期pHでもアルカリ度が違えば、同量の酸を加えたときの変化は違いうる。USGSのアルカリ度解説
したがって「pHが0.5高いから毎回同じ量を投入する」という規則は、この二量を混同する。操作を評価する記録には、原水、タンク体積、投入した物質と量、混合後の時刻を含める。具体的な投入量は、本記事の水収支だけからは計算できない。
酸素は濃度だけでなく、届く経路を見る
水中の酸素の平衡溶解量は、水温・気圧・塩分に依存する。USGS DOTABLESはこれらを入力して酸素溶解度を計算する。一般に同じ圧力・塩分なら、温かい水ほど酸素を溶かせる量は少なくなる。DOのmg/Lと飽和度%を比較するときも、同じ条件で換算されているかを確認する。
根は呼吸のために酸素を必要とする。Cornellの葉菜類向け水耕栽培ガイドは根への酸素供給と水温の関係を説明している。タンクで測ったDOが十分に見えても、根の密集部まで同じ条件とは限らない。測定場所に加え、循環・曝気の状態、栽培槽入口と出口の違いを記録する。
系全体を囲むと内部循環は外部からの補給にならない。図は完全混合や均一な酸素分布を保証するものではない。
培地を使う場合は、保水と空気の通り道も考える。タンクのDOだけで培地の通気状態は決まらない。本記事の液体一槽の計算を、培地内部へそのまま当てはめない。
水と溶質を別の帳簿で追う
ここではタンク・配管・栽培槽を含む循環系全体を境界にする。一定の時間区間で、外部からの補給を V_{in}、液としての排出を V_{out}、蒸発・植物への水移動を V_w とする。各項の単位はLである。
内部のポンプ流量はこの式へ補給として足さない。タンクだけを境界にする場合は、栽培槽への送りと戻りを別途数える。
追跡する一つの溶質について、質量を M [mg]、濃度を C=M/V [mg/L] とすると、
U は植物への移動、R は沈殿などによる液相からの正味除去である。全系で物質が消えるという意味ではない。液体の排出は水と溶質を運ぶ。蒸発による水損失と同じ扱いにはできない。連続的な排出では M_{out}=\int C_{out}(t)Q_{out}(t)dt とし、濃度変化を考慮する。
次はこの収支を確認するために設計した独自の算術例である。実際の植物の吸収速度、肥料処方、ECの予測ではない。初期状態を100 L、ある一成分10,000 mg、すなわち100 mg/Lとし、補給・沈殿はないものとする。
| 合成条件 | 最終水量 | 最終溶質量 | 最終濃度 |
|---|---|---|---|
| A:水だけ10 L減少、溶質は残る | 90 L | 10,000 mg | 111.11 mg/L |
| B:水10 Lと溶質2,000 mgが植物側へ移動 | 90 L | 8,000 mg | 88.89 mg/L |
| C:均一濃度の液を10 L排出 | 90 L | 9,000 mg | 100.00 mg/L |
同じ水位低下でも、濃度は上昇・低下・不変になりうる。Aへ対象溶質を含まない水10 Lを戻すと100 mg/Lになるが、Bでは80 mg/Lにしかならない。水位の復元は溶質量の復元ではない。
Pythonで比較を再現する
次を root_zone.py に保存し、python3 root_zone.py で実行できる。Pythonの標準機能のみを使う。
from math import isfinite
def concentration(volume_l, mass_mg):
if not (isfinite(volume_l) and isfinite(mass_mg)):
raise ValueError("finite values required")
if volume_l <= 0 or mass_mg < 0:
raise ValueError("positive volume and nonnegative mass required")
return mass_mg / volume_l
initial_v, initial_m = 100.0, 10000.0
initial_c = concentration(initial_v, initial_m)
cases = {
"A": (initial_v - 10, initial_m),
"B": (initial_v - 10, initial_m - 2000),
"C": (initial_v - 10, initial_m - 10 * initial_c),
}
for name, (volume, mass) in cases.items():
print(f"{name}: {concentration(volume, mass):.2f} mg/L")
print(f"B + water: {concentration(cases['B'][0] + 10, cases['B'][1]):.2f} mg/L")
出力は順に 111.11、88.89、100.00、80.00 mg/L となる。Bの2,000 mgを1,000 mgへ変えると、水が減った後の濃度は100 mg/Lとなる。濃度が変わらなくても、溶質は吸収されている例である。ゼロ体積や負の残量はエラーにする。
このコードはEC・pH・DOを計算しない。一成分の質量収支が合っても、多成分の化学平衡や生育応答を検証したことにはならない。
次の観測と操作を決める
以下は本記事で提案する観測の組み合わせであり、自動投入ルールではない。
| 観察 | 次に確かめるもの |
|---|---|
| EC上昇と水位低下 | 補給・排液履歴、液温と補償設定、原水・養液組成 |
| ECが一定なのに生育状態が変化 | 個別成分、根圏DO・水温、流れ、光と空気側の履歴 |
| pH調整後に再び変化 | 混合と測定時刻、原水のアルカリ度、投入履歴 |
| タンクDOと出口DOが異なる | 同期測定、センサー状態、循環と曝気、根の分布 |
最低限、時刻・場所・単位・校正記録に、水量、補給と排液の量、投入物を結び付ける。センサーの配置・校正の詳細、イオン別の栄養管理、投薬制御は次の段階で扱う。この基礎でまずできるようにするのは、見えている濃度と、系に残った物質量を分けて読むことである。

コメント
コメントの投稿にはログインが必要です
まだコメントはありません。