Dikey Tarım Otomasyonu: API aracılığıyla Robotik Kontrol
Milano'nun eteklerinde Cavenago di Brianza'da terk edilmiş bir endüstriyel depo. İçeride, 9.000 metre mavi-kırmızı LED ışıklar altında marul, fesleğen ve rokanın yetiştiği dikey raflardan oluşan kareler güneşi hiç görmeden. 21 derecede sabit sıcaklık, %70 nem, 1.200 ppm'de CO2. Her bitki Kişiselleştirilmiş bir ışık tarifi vardır, her yetiştirme hattı API aracılığıyla merkezi bir sistemle iletişim kurar, her robot gerçek zamanlı olarak nereye gideceğini biliyor. Bu Gezegen Çiftlikleriİtalyan dikey çiftliği 2025 yılında otomatik kapalı alan tarımı için dünya referanslarından biri haline geldi.
Dikey tarım artık bir laboratuvar deneyi değil. 2025 yılında küresel pazarın değeri 9,62 milyar dolar 2033 yılına kadar 39,2 milyar olacağı tahmin ediliyor (CAGR %19,3). Yeni nesil dikey çiftlikler, %95 daha az su saygı geleneksel tarıma geçerek, iklim ne olursa olsun tüm yıl boyunca üretim yapıyorlar, pestisitleri ortadan kaldırıyorlar ve açık alana göre 100 kata kadar daha yüksek metrekare başına verim elde edin. Fakat bu sonuçlar bunlar ancak endüstriyel düzeyde yazılım ve robotik altyapı ile mümkündür.
Bu makalede dikey bir çiftliğin tüm yazılım mimarisini oluşturuyoruz: çevresel sensörlerden FastAPI ile REST API tasarımından robotlar için ROS2 entegrasyonuna kadar Python'daki PID denetleyicisine, dijital ikizden takviyeli öğrenmeye dayalı optimizasyon hattına kadar. Çalışan kod, üretimde test edilen mimariler, İtalyan ekosisteminden gerçek sayılar.
Bu Makalede Neler Öğreneceksiniz?
- Dikey çiftlikler için eksiksiz yazılım mimarisi: sensörler, kontrolörler, SCADA, bulut, yapay zeka
- LED spektrum yönetimi: PAR, DLI, marul, fesleğen ve çilek için ışık tarifleri
- Sıcaklık, CO2, nem ve sulama için Python'da PID denetleyici uygulaması
- Mahsul tarifi yönetimi ve aktüatör kontrolü için FastAPI ile REST API tasarımı
- Otomatik robot ekimi, ekimi ve hasadı için ROS2 entegrasyonu
- Çiftliğin dijital ikizi: bitki büyüme simülasyonu ve yerleşim planı optimizasyonu
- Işık tariflerinin optimizasyonu için pekiştirmeli öğrenme
- IoT Altyapısı: Modbus RTU, MQTT, OPC-UA, endüstriyel ağ geçitleri
- Ekonomik analiz: CAPEX, OPEX, başabaş noktası ve açık hava çiftçiliğiyle karşılaştırma
- Örnek olay: Planet Farms ve Agricola Moderna, önde gelen İtalyan dikey çiftlikleri
FoodTech Serisi - Tüm Makaleler
| # | Öğe | Seviye | Durum |
|---|---|---|---|
| 1 | Python ve MQTT ile Hassas Tarım için IoT Pipeline | Gelişmiş | Yayınlandı |
| 2 | Mahsul İzleme için ML Edge: Tarlalarda Bilgisayarlı Görme | Gelişmiş | Yayınlandı |
| 3 | Uydu API ve Bitki Örtüsü Endeksleri: Python ve Sentinel-2 ile NDVI | Orta seviye | Yayınlandı |
| 4 | Gıdada Blockchain izlenebilirliği: Tarladan süpermarkete | Orta seviye | Yayınlandı |
| 5 | Gıda Endüstrisinde Kalite Kontrol için Bilgisayarlı Görme | Gelişmiş | Yayınlandı |
| 6 | FSMA ve Dijital Uyumluluk: Düzenleyici Süreçlerin Otomasyonu | Orta seviye | Yayınlandı |
| 7 | Dikey Tarım Otomasyonu: API Üzerinden Robotik Kontrol (şu anda buradasınız) | Gelişmiş | Akım |
| 8 | Prophet ve LightGBM ile Gıda Perakendesinde Talep Tahmini | Orta seviye | Yakında gelecek |
| 9 | Çiftlik Zekası Kontrol Paneli: Grafana ile Gerçek Zamanlı Analiz | Orta seviye | Yakında gelecek |
| 10 | Tedarik Zinciri Gıda Optimizasyonu: Atıkların Azaltılması için ML | Orta seviye | Yakında gelecek |
2025'te Dikey Tarım Pazarı: Büyüme ve Teknolojik Etkenler
Dikey tarım, 2023-2024'te bazı büyük oyuncuların katılımıyla bir konsolidasyon aşamasından geçti Bu yük altında iflas ilan eden Kuzey Amerika şirketleri (AeroFarms, AppHarvest, Bowery Farming) çok yüksek CAPEX ve patlayan enerji maliyetleri. Ancak pazar durmadı: yeniden yapılandırıldı geliştirenleri ödüllendiren Darwinci bir seçimle daha verimli modeller etrafında ölçeklendirmeden önce sağlam birim ekonomisi.
2025'te rakamlar artan olgunluğun öyküsünü anlatıyor: Küresel pazar buna değer 9,62 milyar dolar 2033 yılına kadar ise 39,2 milyara ulaşacak. Başka bir tahmin (Maximize Market Research) 39,7 milyar tahminle 2025'te 8 milyara ulaşacağını öngörüyor. 2032'de %25,7'lik bir Bileşik Büyüme Oranı. Tahminlerdeki farklılıklar, neyin oluşturulduğunu sınıflandırmanın zorluğunu yansıtıyor. tam olarak "dikey tarım" (yalnızca iç mekanda istiflenmiş tepsiler mi? aynı zamanda gelişmiş seralar mı?), ancak trend ve kesindir. Bağlantılı tarımsal robotik pazarı 2025 yılında 10,23 milyar değerinde olacak. 2030 yılına kadar büyüme 28,2 milyara ulaşacak.
Dikey Tarım ve Geleneksel Tarım: Performans Karşılaştırması
| Parametre | Açık Havada Tarım | Sera | Dikey Çiftlik |
|---|---|---|---|
| Su tüketimi (göreceli) | %100 | %30-40 | %5-10 |
| m² başına verim (marul) | ~2 kg/m²/yıl | ~15 kg/m²/yıl | ~150-200 kg/m²/yıl |
| Üretim döngüsü/yıl | 1-3 | 4-8 | 12-18 |
| Pestisitler | Yüksek gereklilik | Azaltılmış | Sıfır |
| İklim bağımlılığı | Toplam | Kısmi | Hiçbiri |
| Arazi kullanımı (arazi) | 1x | 1x | 0,01-0,05x |
| Enerji gerekli | Düşük | Ortalama | Yüksek (LED + HVAC) |
| Üretim maliyeti (marul) | 0,5-1$/kg | 1,5-3$/kg | 4-8$/kg |
2025 yılında büyümenin dört itici gücü var: Birincisi, yüksek verimli LED'lerin maliyetinin düşmesi Son on yılda %70 oranında artış göstererek aydınlatma yatırım harcamalarını çok daha erişilebilir hale getirdik. İkincisi, ben Yapay zeka tabanlı kontrol sistemleri, 3-4 yıla kadar düşünülemez enerji optimizasyonlarına olanak tanır önce. Üçüncüsü, yerel, taze ve pestisit içermeyen ürünlere olan talep sürekli artıyor. özellikle kentsel alanlarda. Dördüncüsü, ekim, dikim ve hasat için robotik modüller artık sadece laboratuvar fiyatlarında değil, endüstriyel fiyatlarla da mevcutlar.
Dikey Çiftlik için Yazılım Mimarisi: Komple Yığın
Modern bir dikey çiftlik aslında siber-fiziksel bir sistemdir: her fiziksel karar (açma) bir LED, bir vananın açılması, bir robotun hareket ettirilmesi) ve bir yazılım hesaplamasının sonucu. Mimarlık kontrol için gerçek zamanlı, mahsul güvenliği için güvenilir ve aşağıdakiler için ölçeklenebilir olmalıdır: yüzlerce ekim alanını yönetin.
Uçtan Uca Mimari Yığın
+-----------------------------------------------------------------------+
| LAYER 1: FIELD DEVICES |
| [Sensori Temp/RH] [CO2 Sensor] [PAR Meter] [Nutrient EC/pH] |
| [Flow Sensor] [Camera RGB-D] [Weight Sensor] [RFID Tray] |
| | | | | |
| +------------------+-------------+--------------+ |
| Modbus RTU / RS-485 / I2C / SPI |
+-----------------------------------------------------------------------+
|
+-----------------------------------------------------------------------+
| LAYER 2: EDGE CONTROLLER |
| [PLC Siemens S7-1500 / Beckhoff CX / Raspberry] |
| - Loop PID per temperatura, CO2, umidita |
| - Scheduling ricette luminose (LED driver DMX/PWM) |
| - Gestione irrigazione NFT/DWC cicli |
| - Buffer locale offline-tolerant |
| - OPC-UA Server / MQTT Publisher |
+-----------------------------------------------------------------------+
|
+-----------------------------------------------------------------------+
| LAYER 3: SCADA / MES |
| [Ignition SCADA / custom Python SCADA] |
| - Supervisione multi-zona real-time |
| - Storicizzazione time-series (InfluxDB/TimescaleDB) |
| - Allarmi e notifiche (temperatura, EC, pH out-of-range) |
| - Ricette colturali e scheduling batch |
+-----------------------------------------------------------------------+
|
+-----------------------------------------------------------------------+
| LAYER 4: CLOUD PLATFORM |
| [FastAPI Backend] [Message Broker MQTT/Kafka] [PostgreSQL] |
| - REST API per integrazione ERP/WMS/retail |
| - Gestione ricette, batch, inventory, ordini |
| - Autenticazione OAuth2, RBAC, audit log |
+-----------------------------------------------------------------------+
|
+-----------------------------------------------------------------------+
| LAYER 5: AI / ANALYTICS |
| [ML Pipeline] [Digital Twin] [Computer Vision] [RL Optimizer] |
| - Ottimizzazione ricette luminose (RL) |
| - Previsione resa e time-to-harvest |
| - Rilevamento anomalie (sensori + visione) |
| - Simulazione crescita (digital twin) |
+-----------------------------------------------------------------------+
Endüstriyel PLC (Siemens S7, Beckhoff) ile tek kartlı bilgisayar (Raspberry Pi 4, BeagleBone) gereken güvenilirlik düzeyine bağlıdır. Yüksek mahsüllü ticari çiftlikler için değer, donanım yedekliliği ve doğru seçim ile IEC 61131-3 sertifikalı bir PLC. Prototipler için ve deneysel çiftlikler, gömülü donanım üzerinde bir Python çözümü ve geliştirilmesi daha esnek ve daha hızlı.
Çevresel Kontrol Sistemleri: LED, HVAC, CO2 ve Sulama
Çevresel kontrol, dikey bir çiftliğin operasyonel kalbidir. Dört parametre hakimdir: ışık spektrumu ve yoğunluğu, hava sıcaklığı, CO2 konsantrasyonu ve besin çözeltisinin bileşimi. Her biri özel bir kontrol döngüsü gerektirir.
LED Spektrum Yönetimi: PAR, DLI ve Işık Tarifleri
Bitkiler görünür ışığın tamamını eşit şekilde kullanmazlar. Fotosentetik olarak aktif aralık itibaren gider 400 ila 700 nm (PAR - Fotosentetik Aktif Radyasyon). İçeride Bu aralıkta mavi (400-500 nm), yaprak morfolojisini ve bileşiklerin sentezini düzenler. aromatikler; kırmızı (600-700 nm) fotosentezin ana sürücüsüdür; uzak kırmızı (700-800 nm) Fitokrom sistemi aracılığıyla çiçeklenme ve bitki geometrisini etkiler.
DLI (Günlük Işık İntegrali), bir bitkinin aldığı toplam PAR foton miktarını ölçer 24 saat içinde mol/m²/gün cinsinden ifade edilir. Ve tariflerin boyutlandırılmasında en önemli ölçü parlak. 2025 yılında Nature Scientific Reports'ta yayınlanan araştırma, optimize edilmiş LED'lerin dikey tarım için ürettikleri %32 daha fazla verim spektrumlarla karşılaştırıldığında standart, marul ve fesleğende daha fazla taze ağırlık ile.
Ana Mahsuller için Işık Parametreleri
| Kültür | PPFD (μmol/m²/s) | DLI Hedefi (mol/m²/gün) | Optimum Spektrum | Fotoperiyod |
|---|---|---|---|---|
| Marul (yaprak) | 150-250 | 15.00-18.00 | R:B = 4:1, +kırmızı ötesi %5 | 16-18 saat ışık |
| Marul (kafa) | 200-300 | 17-22 | R:B = 3:1, UV 380 nm %2 | 16 saat ışık |
| Reyhan | 200-300 | 14.00-17.00 | R:B = 3:1, mavi %20-25 | 16 saat ışık |
| Ispanak | 150-200 | 12-17 | R:B = 4:1 | 14-16 saat ışık |
| Çilek (bitkisel) | 200-300 | 15.00-20.00 | R:B = 3:1 | 16 saat ışık |
| Çilek (çiçekli) | 300-400 | 20-25 | R:B:FR = 3:1:0,5 | 12 saat ışık |
| Mikro yeşillikler | 100-200 | 8-12 | Tam spektrumlu beyaz | 16 saat ışık |
| Aromatik otlar | 200-250 | 14-16 | Mavi %15, R baskın | 16 saat ışık |
LED yönetim denetleyicisi bu tarifleri LED sürücülerine PWM sinyallerine çevirmelidir. Her yetiştirme alanının farklı bir tarifi olabilir ve tarif yıl içinde değişebilir. yetiştirme döngüsü (örneğin fesleğenin aromasını yoğunlaştırmak için son 48 saatte daha fazla mavi). Tam bir PID denetleyicisinin Python uygulaması:
"""
Vertical Farm Environmental Controller
Controller PID per gestione LED, CO2, temperatura e irrigazione
"""
import time
import asyncio
import logging
from dataclasses import dataclass, field
from typing import Optional
from enum import Enum
logger = logging.getLogger(__name__)
class CropStage(Enum):
GERMINATION = "germination"
SEEDLING = "seedling"
VEGETATIVE = "vegetative"
MATURATION = "maturation"
HARVEST_READY = "harvest_ready"
@dataclass
class LightRecipe:
"""Ricetta luminosa per una coltura in un determinato stadio"""
crop_name: str
stage: CropStage
ppfd_target: float # µmol/m²/s
dli_target: float # mol/m²/giorno
photoperiod_hours: float # ore di luce al giorno
spectrum_red_pct: float # % canale rosso (620-700nm)
spectrum_blue_pct: float # % canale blu (400-500nm)
spectrum_white_pct: float # % LED bianco full-spectrum
spectrum_farred_pct: float # % far-red (700-800nm)
spectrum_uv_pct: float = 0.0
def validate(self) -> bool:
total = (self.spectrum_red_pct + self.spectrum_blue_pct +
self.spectrum_white_pct + self.spectrum_farred_pct +
self.spectrum_uv_pct)
return abs(total - 100.0) < 0.1
def ppfd_from_dli(self) -> float:
"""Calcola PPFD target dalle ore di fotoperiodo e DLI"""
photoperiod_seconds = self.photoperiod_hours * 3600
return (self.dli_target * 1_000_000) / photoperiod_seconds
@dataclass
class PIDController:
"""
Controller PID generico per parametri ambientali.
Usa anti-windup per prevenire integrator saturation.
"""
kp: float
ki: float
kd: float
setpoint: float
output_min: float = 0.0
output_max: float = 100.0
_integral: float = field(default=0.0, init=False)
_last_error: float = field(default=0.0, init=False)
_last_time: float = field(default_factory=time.time, init=False)
def compute(self, measured_value: float) -> float:
current_time = time.time()
dt = current_time - self._last_time
if dt <= 0:
return self._last_output if hasattr(self, '_last_output') else 0.0
error = self.setpoint - measured_value
# Proporzionale
p_term = self.kp * error
# Integrale con anti-windup (clamping)
self._integral += error * dt
i_term = self.ki * self._integral
# Clamp integrale per prevenire windup
i_max = (self.output_max - self.output_min) / self.ki if self.ki != 0 else 1000
self._integral = max(-i_max, min(i_max, self._integral))
i_term = self.ki * self._integral
# Derivativo
d_term = self.kd * (error - self._last_error) / dt if dt > 0 else 0.0
output = p_term + i_term + d_term
output = max(self.output_min, min(self.output_max, output))
self._last_error = error
self._last_time = current_time
self._last_output = output
return output
class EnvironmentalController:
"""
Controller principale per una zona di coltivazione.
Gestisce temperatura, CO2, umidita e irrigazione via PID.
"""
def __init__(self, zone_id: str, recipe: LightRecipe):
self.zone_id = zone_id
self.recipe = recipe
# PID temperatura: setpoint 21°C, banda ±1°C
self.temp_pid = PIDController(
kp=2.0, ki=0.5, kd=0.1,
setpoint=21.0,
output_min=-100.0, # raffreddamento
output_max=100.0 # riscaldamento
)
# PID CO2: setpoint 1200 ppm per crescita accelerata
self.co2_pid = PIDController(
kp=0.5, ki=0.1, kd=0.05,
setpoint=1200.0,
output_min=0.0,
output_max=100.0 # % apertura valvola CO2
)
# PID umidita relativa: setpoint 70%
self.humidity_pid = PIDController(
kp=1.5, ki=0.3, kd=0.05,
setpoint=70.0,
output_min=0.0,
output_max=100.0
)
def compute_led_pwm(self, current_hour: float) -> dict:
"""
Calcola duty cycle PWM per ogni canale LED
in base all'ora del giorno e alla ricetta.
"""
# Determina se siamo nel fotoperiodo attivo
# Fotoperiodo: ore 6:00 - (6 + photoperiod_hours)
start_hour = 6.0
end_hour = start_hour + self.recipe.photoperiod_hours
if not (start_hour <= current_hour < end_hour):
return {
'red': 0.0, 'blue': 0.0,
'white': 0.0, 'farred': 0.0, 'uv': 0.0
}
# Calcola intensità normalizzata (0-1) dal PPFD target
# Assumendo che 100% PWM = 600 µmol/m²/s
max_ppfd = 600.0
intensity = min(self.recipe.ppfd_target / max_ppfd, 1.0)
return {
'red': round(intensity * self.recipe.spectrum_red_pct / 100, 4),
'blue': round(intensity * self.recipe.spectrum_blue_pct / 100, 4),
'white': round(intensity * self.recipe.spectrum_white_pct / 100, 4),
'farred': round(intensity * self.recipe.spectrum_farred_pct / 100, 4),
'uv': round(intensity * self.recipe.spectrum_uv_pct / 100, 4),
}
async def control_loop(self, sensor_reader, actuator_writer, interval: float = 30.0):
"""
Loop di controllo asincrono: legge sensori, calcola PID, scrive attuatori.
Frequenza default: ogni 30 secondi.
"""
logger.info(f"Avvio loop controllo zona {self.zone_id}")
while True:
try:
# Leggi sensori
sensors = await sensor_reader.read_zone(self.zone_id)
# Calcola output PID
temp_output = self.temp_pid.compute(sensors['temperature'])
co2_output = self.co2_pid.compute(sensors['co2_ppm'])
humidity_output = self.humidity_pid.compute(sensors['humidity_rh'])
# Calcola PWM LED
from datetime import datetime
current_hour = datetime.now().hour + datetime.now().minute / 60.0
led_pwm = self.compute_led_pwm(current_hour)
# Scrivi attuatori
await actuator_writer.set_hvac(self.zone_id, temp_output, humidity_output)
await actuator_writer.set_co2_valve(self.zone_id, co2_output)
await actuator_writer.set_led_channels(self.zone_id, led_pwm)
logger.debug(
f"Zona {self.zone_id} | "
f"T={sensors['temperature']:.1f}°C (PID:{temp_output:.1f}%) | "
f"CO2={sensors['co2_ppm']:.0f}ppm (valve:{co2_output:.1f}%) | "
f"RH={sensors['humidity_rh']:.1f}% | "
f"LED R:{led_pwm['red']:.2f} B:{led_pwm['blue']:.2f}"
)
except Exception as e:
logger.error(f"Errore loop controllo zona {self.zone_id}: {e}")
await asyncio.sleep(interval)
# --- Ricette standard per colture comuni ---
LETTUCE_VEGETATIVE = LightRecipe(
crop_name="Lattuga Lollo",
stage=CropStage.VEGETATIVE,
ppfd_target=200.0,
dli_target=17.0,
photoperiod_hours=16.0,
spectrum_red_pct=65.0,
spectrum_blue_pct=20.0,
spectrum_white_pct=10.0,
spectrum_farred_pct=5.0,
spectrum_uv_pct=0.0,
)
BASIL_VEGETATIVE = LightRecipe(
crop_name="Basilico Genovese",
stage=CropStage.VEGETATIVE,
ppfd_target=250.0,
dli_target=15.0,
photoperiod_hours=16.0,
spectrum_red_pct=60.0,
spectrum_blue_pct=25.0, # blue elevato per aromi
spectrum_white_pct=10.0,
spectrum_farred_pct=5.0,
spectrum_uv_pct=0.0,
)
STRAWBERRY_FLOWERING = LightRecipe(
crop_name="Fragola Elsanta",
stage=CropStage.MATURATION,
ppfd_target=350.0,
dli_target=22.0,
photoperiod_hours=12.0, # fotoperiodo corto per fioritura
spectrum_red_pct=55.0,
spectrum_blue_pct=20.0,
spectrum_white_pct=20.0,
spectrum_farred_pct=5.0,
spectrum_uv_pct=0.0,
)
Sulama Sistemleri: NFT, DWC ve Aeroponics
Dikey çiftliklerdeki üç baskın hidrofonik teknolojinin kontrol mimarileri vardır farklıdır ve her birinin izlenmesi ve düzenlenmesi gereken kendi kritik parametreleri vardır.
Topraksız Sistemlerin Karşılaştırılması
| Sistem | İdeal mahsuller | Kritik Parametreler | Karmaşıklık Kontrolü | Su Tüketimi |
|---|---|---|---|---|
| NFT'ler (Besin Film Tekniği) | Marullar, otlar | Akış hızı, kanal eğimi, EC, pH | Ortalama | Minimum (devridaim) |
| DWC (Derin Su Kültürü) | Marul, ıspanak | Oksijenasyon (DO), EC, pH, sıcaklık | Düşük | Bas |
| Aeroponik | Çilek, kökler, otlar | Nebulizasyon döngüsü, basınç, EC, pH | Yüksek | Minimum (%90 vs toprak) |
| Yüzeyler (hindistancevizi/taşyünü) | Domates, biber | Döngü sulama, EC, pH, drenaj | Ortalama | Ilıman |
"""
Irrigation Controller per sistema NFT
Gestione pompe, monitoraggio EC/pH, dosaggio nutrienti
"""
import asyncio
from dataclasses import dataclass
from typing import Optional
import logging
logger = logging.getLogger(__name__)
NUTRIENT_TARGETS = {
"lettuce": {"ec_ms_cm": 1.6, "ph": 6.0, "temp_c": 20.0},
"basil": {"ec_ms_cm": 1.8, "ph": 6.0, "temp_c": 21.0},
"spinach": {"ec_ms_cm": 2.0, "ph": 6.2, "temp_c": 20.0},
"strawberry": {"ec_ms_cm": 2.2, "ph": 5.8, "temp_c": 18.0},
"herbs": {"ec_ms_cm": 1.4, "ph": 6.0, "temp_c": 21.0},
}
@dataclass
class NFTController:
zone_id: str
crop_type: str
flow_rate_lpm: float = 1.5 # litri/minuto per canale
channel_slope_pct: float = 2.0 # pendenza canale in %
def get_targets(self) -> dict:
return NUTRIENT_TARGETS.get(self.crop_type, NUTRIENT_TARGETS["lettuce"])
async def check_and_adjust(self, ec_sensor: float, ph_sensor: float,
ec_doser, ph_doser) -> dict:
targets = self.get_targets()
actions = {}
# Controllo EC
ec_delta = targets["ec_ms_cm"] - ec_sensor
if abs(ec_delta) > 0.2:
if ec_delta > 0:
# EC troppo bassa: aggiungi concentrato nutrienti
dose_ml = ec_delta * 50 # ml di concentrato A+B
await ec_doser.dose(zone=self.zone_id, ml=dose_ml, solution="AB")
actions["ec_dosing"] = f"+{dose_ml:.1f}ml AB"
else:
# EC troppo alta: diluisci con acqua RO
await ec_doser.dose_water(zone=self.zone_id, ml=abs(ec_delta) * 100)
actions["ec_dilution"] = f"+{abs(ec_delta)*100:.0f}ml H2O"
# Controllo pH
ph_delta = targets["ph"] - ph_sensor
if abs(ph_delta) > 0.3:
if ph_delta > 0:
# pH troppo basso: aggiungi pH-up (KOH)
dose_ml = abs(ph_delta) * 10
await ph_doser.dose(zone=self.zone_id, ml=dose_ml, solution="ph_up")
actions["ph_adjust"] = f"pH-up +{dose_ml:.1f}ml"
else:
# pH troppo alto: aggiungi pH-down (H3PO4)
dose_ml = abs(ph_delta) * 10
await ph_doser.dose(zone=self.zone_id, ml=dose_ml, solution="ph_down")
actions["ph_adjust"] = f"pH-down +{dose_ml:.1f}ml"
logger.info(
f"NFT zona {self.zone_id} | "
f"EC: {ec_sensor:.2f} (target {targets['ec_ms_cm']:.2f}) | "
f"pH: {ph_sensor:.2f} (target {targets['ph']:.2f}) | "
f"Azioni: {actions}"
)
return actions
Robotik ve Otomasyon: Dikey Çiftlikte ROS2
Robotik, 2025'te dikey tarımda en dönüştürücü faktör olacak. Manuel operasyonlar tohumlama (tepsilere ekim), dikim (fidelerin saksılara dikilmesi) daha yoğundur. son raflar), hasat ve paketleme. Bir işçi yaklaşık 500-700 bitkiyi nakledebilir şimdilik; ekim robotu saatte 2.000-3.000 bitki ile daha düşük hata oranıyla çalışır %1'de. Günde 30.000 tepsi marulla (Agnadello'daki Agricola Moderna örneğinde olduğu gibi), Robotik bir tercih değil, zorunluluktur.
ROS2 (Robot İşletim Sistemi 2), robot programlama için fiili standart haline geldi kapalı bir ortamda. ROS1 ile karşılaştırıldığında yerel gerçek zamanlı destek (DDS ara katman yazılımı) sunar, Geliştirilmiş güvenlik mimarisi, yerel çoklu robot desteği ve yönetilen yaşam döngüsü düğümleri. Düğüm ve konu yapısı planlama mantığının net bir şekilde ayrılmasını sağlar hareket, motor kontrolü, yapay görme ve sistemle arayüz çiftlik yönetimi.
"""
ROS2 Node per Harvesting Robot in Vertical Farm
Gestisce pianificazione percorso, prelievo e deposito vassoi
"""
import rclpy
from rclpy.node import Node
from rclpy.action import ActionServer
from geometry_msgs.msg import Pose, PoseStamped
from std_msgs.msg import String, Bool
from sensor_msgs.msg import Image
import json
import asyncio
# Messaggi custom per la farm (definiti in farm_interfaces package)
# from farm_interfaces.msg import TrayInfo, HarvestStatus
# from farm_interfaces.action import HarvestTray
# from farm_interfaces.srv import GetZoneLayout
class HarvestingRobotNode(Node):
"""
Nodo ROS2 per robot di raccolta in vertical farm.
Si interfaccia con:
- Sistema SCADA per ricevere job di raccolta
- Controller braccio robotico (MoveIt2)
- Sistema conveyor per deposito vassoi
- Computer vision per verifica maturita
"""
def __init__(self):
super().__init__('harvesting_robot_node')
# Publisher stato robot
self.status_pub = self.create_publisher(
String, '/farm/robot/harvest/status', 10
)
# Subscriber per job di raccolta da SCADA
self.job_sub = self.create_subscription(
String, '/farm/scada/harvest_jobs',
self.on_harvest_job, 10
)
# Subscriber per immagine camera end-effector
self.camera_sub = self.create_subscription(
Image, '/robot/camera/raw',
self.on_camera_frame, 10
)
# Client per servizio layout zona
# self.layout_client = self.create_client(GetZoneLayout, '/farm/zone/layout')
self.current_job: dict = {}
self.is_busy = False
self.get_logger().info('HarvestingRobotNode avviato')
def on_harvest_job(self, msg: String):
"""Riceve job di raccolta dallo SCADA"""
if self.is_busy:
self.get_logger().warn('Robot occupato, job ignorato')
return
try:
job = json.loads(msg.data)
self.get_logger().info(
f"Job ricevuto: zona={job['zone_id']}, "
f"tray={job['tray_id']}, "
f"crop={job['crop_type']}"
)
self.current_job = job
self.is_busy = True
# Avvia sequenza raccolta in thread separato
self.executor.create_task(self.execute_harvest(job))
except (json.JSONDecodeError, KeyError) as e:
self.get_logger().error(f"Job malformato: {e}")
async def execute_harvest(self, job: dict) -> bool:
"""
Sequenza completa raccolta:
1. Naviga verso zona target
2. Verifica maturita con visione artificiale
3. Preleva vassoio con braccio robotico
4. Trasporta a conveyor di uscita
5. Aggiorna SCADA
"""
try:
# Step 1: Navigazione
self.publish_status("NAVIGATING", job)
success = await self.navigate_to_zone(job['zone_id'], job['shelf_row'])
if not success:
self.publish_status("NAV_FAILED", job)
return False
# Step 2: Verifica maturita (computer vision)
maturity_score = await self.check_crop_maturity(job['tray_id'])
if maturity_score < 0.85:
self.get_logger().warn(
f"Vassoio {job['tray_id']}: maturita {maturity_score:.2f} "
f"sotto soglia 0.85, raccolta posticipata"
)
self.publish_status("MATURITY_INSUFFICIENT", job)
self.is_busy = False
return False
# Step 3: Raccolta
self.publish_status("HARVESTING", job)
await self.pick_tray(job['tray_id'], job['shelf_position'])
# Step 4: Deposito su conveyor
self.publish_status("DELIVERING", job)
await self.deliver_to_conveyor(job['destination_line'])
# Step 5: Completamento
self.publish_status("COMPLETED", job)
self.is_busy = False
return True
except Exception as e:
self.get_logger().error(f"Errore harvest job {job.get('tray_id')}: {e}")
self.publish_status("ERROR", job)
self.is_busy = False
return False
def publish_status(self, status: str, job: dict):
msg = String()
msg.data = json.dumps({
"robot_id": self.get_name(),
"status": status,
"tray_id": job.get("tray_id"),
"zone_id": job.get("zone_id"),
"timestamp": self.get_clock().now().to_msg().sec
})
self.status_pub.publish(msg)
async def navigate_to_zone(self, zone_id: str, shelf_row: int) -> bool:
"""Naviga AGV verso la zona target (stub - usa Nav2 in produzione)"""
self.get_logger().info(f"Navigazione verso zona {zone_id} fila {shelf_row}")
await asyncio.sleep(2.0) # simulazione movimento
return True
async def check_crop_maturity(self, tray_id: str) -> float:
"""Analisi visione artificiale per valutazione maturita (stub)"""
# In produzione: inferenza YOLO/custom model su immagine camera
await asyncio.sleep(0.5)
return 0.92 # score maturita 0-1
async def pick_tray(self, tray_id: str, position: dict) -> bool:
"""Controllo braccio robotico per prelievo vassoio via MoveIt2 (stub)"""
await asyncio.sleep(1.5)
return True
async def deliver_to_conveyor(self, destination_line: str) -> bool:
"""Deposita vassoio su conveyor di uscita (stub)"""
await asyncio.sleep(1.0)
return True
def on_camera_frame(self, msg: Image):
"""Callback per frame camera (elaborato async su richiesta)"""
pass
def main(args=None):
rclpy.init(args=args)
node = HarvestingRobotNode()
try:
rclpy.spin(node)
except KeyboardInterrupt:
pass
finally:
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Dikey Çiftlik için API Tasarımı: FastAPI REST Arka Uç
API katmanı, çiftliğin fiziksel kontrol sistemi ile yönetim sistemi arasındaki entegrasyon noktasıdır. dış dünya: kurumsal ERP, müşteri portalı, operatör mobil uygulaması, WMS sistemi dağıtım deposu. Bu bağlamda kötü tasarlanmış bir API tutarsızlıklara yol açar mahsul tariflerinde planlama hataları ve potansiyel mahsul kaybı. İyi bir tane API ise tam tersine tüm alt sistemleri koordine eden sinir sistemidir.
"""
FastAPI Backend per Gestione Vertical Farm
Endpoints: ricette colturali, zone, batch produzione, attuatori, sensori
"""
from fastapi import FastAPI, HTTPException, Depends, BackgroundTasks, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel, Field, validator
from typing import Optional, List
from datetime import datetime, date
from enum import Enum
import uuid
app = FastAPI(
title="Vertical Farm Control API",
description="API per gestione vertical farm: ricette, zone, robot, sensori",
version="2.1.0"
)
security = HTTPBearer()
# ============================================================
# MODELLI PYDANTIC
# ============================================================
class CropTypeEnum(str, Enum):
LETTUCE = "lettuce"
BASIL = "basil"
SPINACH = "spinach"
STRAWBERRY = "strawberry"
MICROGREENS = "microgreens"
HERBS = "herbs"
class GrowingSystemEnum(str, Enum):
NFT = "nft"
DWC = "dwc"
AEROPONICS = "aeroponics"
SUBSTRATE = "substrate"
class LightRecipeCreate(BaseModel):
name: str = Field(..., min_length=3, max_length=100)
crop_type: CropTypeEnum
growth_stage: str
ppfd_target: float = Field(..., ge=50, le=800)
dli_target: float = Field(..., ge=5, le=40)
photoperiod_hours: float = Field(..., ge=8, le=24)
spectrum_red_pct: float = Field(..., ge=0, le=100)
spectrum_blue_pct: float = Field(..., ge=0, le=100)
spectrum_white_pct: float = Field(..., ge=0, le=100)
spectrum_farred_pct: float = Field(default=0.0, ge=0, le=20)
spectrum_uv_pct: float = Field(default=0.0, ge=0, le=10)
notes: Optional[str] = None
@validator('spectrum_blue_pct')
def validate_spectrum_sum(cls, v, values):
total = (values.get('spectrum_red_pct', 0) + v +
values.get('spectrum_white_pct', 0))
# Tolleranza +/- 5% per arrotondamenti
if total > 105:
raise ValueError(f"Somma canali spettro {total}% supera 100%")
return v
class BatchCreate(BaseModel):
zone_id: str
recipe_id: str
crop_type: CropTypeEnum
growing_system: GrowingSystemEnum
seeding_date: date
expected_harvest_date: date
tray_count: int = Field(..., ge=1, le=10000)
seeds_per_tray: int = Field(default=50, ge=1, le=500)
client_order_id: Optional[str] = None
@validator('expected_harvest_date')
def harvest_after_seeding(cls, v, values):
seeding = values.get('seeding_date')
if seeding and v <= seeding:
raise ValueError("La data di raccolta deve essere successiva alla semina")
return v
class SensorReading(BaseModel):
zone_id: str
timestamp: datetime
temperature_c: float
humidity_rh: float
co2_ppm: float
ppfd_umol: Optional[float] = None
ec_ms_cm: Optional[float] = None
ph: Optional[float] = None
water_temp_c: Optional[float] = None
class ActuatorCommand(BaseModel):
zone_id: str
command_type: str # "led_update", "co2_valve", "pump_speed", "hvac"
parameters: dict
priority: int = Field(default=5, ge=1, le=10) # 10 = emergenza
# ============================================================
# ROUTES: RICETTE COLTURALI
# ============================================================
@app.post("/api/v1/recipes", status_code=status.HTTP_201_CREATED)
async def create_recipe(
recipe: LightRecipeCreate,
credentials: HTTPAuthorizationCredentials = Depends(security)
):
"""
Crea una nuova ricetta colturale nel sistema.
Le ricette definiscono parametri luminosi, ambientali e irrigazione.
"""
recipe_id = str(uuid.uuid4())
# In produzione: salvataggio su PostgreSQL
return {
"recipe_id": recipe_id,
"name": recipe.name,
"crop_type": recipe.crop_type,
"ppfd_target": recipe.ppfd_target,
"dli_target": recipe.dli_target,
"created_at": datetime.utcnow().isoformat(),
"status": "active"
}
@app.get("/api/v1/recipes/{recipe_id}")
async def get_recipe(recipe_id: str):
"""Recupera ricetta colturale per ID"""
# Stub - in produzione: query PostgreSQL
return {
"recipe_id": recipe_id,
"name": "Lattuga Lollo Rossa - Vegetativo",
"crop_type": "lettuce",
"ppfd_target": 200.0,
"dli_target": 17.0,
"photoperiod_hours": 16.0,
"spectrum": {"red": 65, "blue": 20, "white": 10, "farred": 5},
"env_targets": {"temp_c": 21.0, "humidity_rh": 70.0, "co2_ppm": 1200},
"nutrient_targets": {"ec_ms_cm": 1.6, "ph": 6.0}
}
@app.get("/api/v1/recipes")
async def list_recipes(
crop_type: Optional[CropTypeEnum] = None,
active_only: bool = True,
limit: int = Field(default=50, le=200)
):
"""Lista ricette con filtro per tipo coltura"""
return {
"recipes": [],
"total": 0,
"filters": {"crop_type": crop_type, "active_only": active_only}
}
# ============================================================
# ROUTES: BATCH PRODUZIONE
# ============================================================
@app.post("/api/v1/batches", status_code=status.HTTP_201_CREATED)
async def create_batch(
batch: BatchCreate,
background_tasks: BackgroundTasks,
credentials: HTTPAuthorizationCredentials = Depends(security)
):
"""
Avvia un nuovo batch di produzione.
Associa zona, ricetta, dati di seeding e target harvest.
Background: programma scheduling LED e irrigazione su SCADA.
"""
batch_id = str(uuid.uuid4())
background_tasks.add_task(schedule_batch_on_scada, batch_id, batch)
return {
"batch_id": batch_id,
"zone_id": batch.zone_id,
"crop_type": batch.crop_type,
"seeding_date": batch.seeding_date.isoformat(),
"expected_harvest_date": batch.expected_harvest_date.isoformat(),
"tray_count": batch.tray_count,
"status": "scheduled"
}
async def schedule_batch_on_scada(batch_id: str, batch: BatchCreate):
"""Task background: invia configurazione a SCADA per scheduling"""
# In produzione: chiamata API verso SCADA (Ignition, custom Python SCADA)
pass
# ============================================================
# ROUTES: SENSORI E TELEMETRIA
# ============================================================
@app.post("/api/v1/telemetry")
async def ingest_sensor_data(reading: SensorReading):
"""
Endpoint per ingestion dati sensori da edge controller.
Validazione, allarmi e storicizzazione su InfluxDB/TimescaleDB.
"""
alerts = []
# Allarmi temperatura
if reading.temperature_c > 28.0:
alerts.append({"type": "HIGH_TEMP", "value": reading.temperature_c, "threshold": 28.0})
elif reading.temperature_c < 16.0:
alerts.append({"type": "LOW_TEMP", "value": reading.temperature_c, "threshold": 16.0})
# Allarmi CO2
if reading.co2_ppm > 2000:
alerts.append({"type": "HIGH_CO2", "value": reading.co2_ppm, "threshold": 2000})
# Allarmi pH
if reading.ph is not None and (reading.ph < 5.0 or reading.ph > 7.5):
alerts.append({"type": "PH_OUT_OF_RANGE", "value": reading.ph})
# In produzione: write batch su InfluxDB e publish alert su Kafka/MQTT
return {
"status": "accepted",
"zone_id": reading.zone_id,
"timestamp": reading.timestamp.isoformat(),
"alerts": alerts,
"alert_count": len(alerts)
}
@app.get("/api/v1/zones/{zone_id}/current")
async def get_zone_current_state(zone_id: str):
"""Stato ambientale corrente di una zona (last value da InfluxDB)"""
# Stub
return {
"zone_id": zone_id,
"timestamp": datetime.utcnow().isoformat(),
"sensors": {
"temperature_c": 21.3,
"humidity_rh": 69.8,
"co2_ppm": 1185,
"ppfd_umol": 198.5,
"ec_ms_cm": 1.62,
"ph": 6.05
},
"actuators": {
"led_pwm": {"red": 0.617, "blue": 0.192, "white": 0.098, "farred": 0.049},
"co2_valve_pct": 12.5,
"hvac_cooling_pct": 35.0,
"pump_active": True
},
"active_batch_id": "b-2025-001-lollo",
"days_since_seeding": 18
}
# ============================================================
# ROUTES: CONTROLLO ATTUATORI
# ============================================================
@app.post("/api/v1/actuators/command")
async def send_actuator_command(
command: ActuatorCommand,
credentials: HTTPAuthorizationCredentials = Depends(security)
):
"""
Invia comando manuale a un attuatore di zona.
Usato per override manuali, manutenzione e test.
Richiede autenticazione e viene loggato per audit.
"""
allowed_commands = {"led_update", "co2_valve", "pump_speed", "hvac", "emergency_stop"}
if command.command_type not in allowed_commands:
raise HTTPException(
status_code=400,
detail=f"Tipo comando non valido: {command.command_type}"
)
command_id = str(uuid.uuid4())
# In produzione: publish su MQTT/OPC-UA verso edge controller
return {
"command_id": command_id,
"zone_id": command.zone_id,
"command_type": command.command_type,
"parameters": command.parameters,
"status": "sent",
"sent_at": datetime.utcnow().isoformat()
}
Farm Digital Twin: Simülasyon ve Optimizasyon
Dikey bir çiftliğin dijital ikizi ve davranışı kopyalayan bir hesaplama modeli Çiftlik fiziği tahmine dayalı simülasyonlara izin verecek kadar doğru. Evet değil Bu görsel bir 3 boyutlu kopya değil (bu bir "görselleştirme"), matematiksel bir model Çevresel parametrelerin mevcut durumu göz önüne alındığında bitki büyümesini öngören ve hasat zamanı.
Kontrollü ortamlarda en çok kullanılan bitki büyüme modelleri şu yaklaşıma dayanmaktadır: radyasyon kullanım verimliliği (RUE): biriken biyokütle orantılıdır yakalanan ışık (PAR) ve sıcaklığa, CO2'ye bağlı olan dönüşüm verimliliği, su ve besin varlığı. Başlangıçta sistemler için geliştirilen bu modeller Açık alanlardaki verim tahminlerinin (örn. DSSAT, APSIM) çevreye göre uyarlanması deneysel olarak kalibre edilmiş parametrelerle iç mekan.
"""
Digital Twin - Modello di Crescita Vegetale per Vertical Farm
Basato su Radiation Use Efficiency (RUE) + effetti temperatura/CO2
"""
import numpy as np
from dataclasses import dataclass, field
from typing import List, Optional
from datetime import datetime, timedelta
@dataclass
class PlantGrowthModel:
"""
Modello semplificato di crescita per lattuga in sistema idroponico.
Parametri calibrati su dati sperimentali per Lactuca sativa.
"""
# Parametri biologici della coltura
rue_base: float = 1.8 # g biomassa / MJ PAR intercettato
temp_base: float = 5.0 # temperatura base (°C) - sotto non cresce
temp_opt: float = 22.0 # temperatura ottimale
temp_max: float = 32.0 # temperatura max sopravvivenza
co2_base_ppm: float = 400.0 # CO2 ambient reference
co2_enhancement: float = 0.002 # incremento RUE per ppm CO2 extra
# Stato corrente della pianta
fresh_weight_g: float = 0.5 # peso fresco iniziale (semenzale 5g DW)
dry_weight_g: float = 0.05 # peso secco iniziale
leaf_area_cm2: float = 5.0 # area fogliare iniziale
days_since_seeding: int = 0
# Target harvest
target_fresh_weight_g: float = 150.0 # lattuga da 150g
water_content: float = 0.95 # % acqua rispetto al peso fresco
def temperature_factor(self, temp: float) -> float:
"""
Fattore temperatura (0-1) usando funzione beta.
temp_opt da il massimo rendimento (1.0).
"""
if temp <= self.temp_base or temp >= self.temp_max:
return 0.0
if temp <= self.temp_opt:
return (temp - self.temp_base) / (self.temp_opt - self.temp_base)
else:
return (self.temp_max - temp) / (self.temp_max - self.temp_opt)
def co2_factor(self, co2_ppm: float) -> float:
"""Fattore arricchimento CO2 (1.0 ad ambient, >1 con arricchimento)"""
extra_co2 = max(0, co2_ppm - self.co2_base_ppm)
return 1.0 + (self.co2_enhancement * extra_co2)
def par_intercepted_mj(self, ppfd: float, leaf_area_cm2: float,
photoperiod_h: float) -> float:
"""
Calcola PAR intercettata dalla pianta in MJ/giorno.
ppfd: µmol/m²/s -> conversione a W/m² (1 W/m² ≈ 4.6 µmol/m²/s per LED)
"""
ppfd_wm2 = ppfd / 4.6
par_w = ppfd_wm2 * (leaf_area_cm2 / 10000) # in m²
par_mj_day = par_w * photoperiod_h * 3600 / 1e6
return par_mj_day
def simulate_day(self, temp: float, co2_ppm: float,
ppfd: float, photoperiod_h: float) -> dict:
"""
Simula un giorno di crescita e aggiorna lo stato della pianta.
Restituisce delta giornaliero e stato aggiornato.
"""
# Fattori ambientali
tf = self.temperature_factor(temp)
cf = self.co2_factor(co2_ppm)
par_intercepted = self.par_intercepted_mj(ppfd, self.leaf_area_cm2, photoperiod_h)
# Crescita biomassa secca (RUE model)
delta_dw = self.rue_base * par_intercepted * tf * cf
delta_fw = delta_dw / (1 - self.water_content)
self.dry_weight_g += delta_dw
self.fresh_weight_g += delta_fw
# Aggiornamento area fogliare (SLA - specific leaf area)
sla_cm2_per_g = 350 # cm²/g DW per lattuga
self.leaf_area_cm2 = self.dry_weight_g * sla_cm2_per_g
self.days_since_seeding += 1
# Check harvest readiness
harvest_ready = self.fresh_weight_g >= self.target_fresh_weight_g
return {
"day": self.days_since_seeding,
"fresh_weight_g": round(self.fresh_weight_g, 2),
"dry_weight_g": round(self.dry_weight_g, 3),
"leaf_area_cm2": round(self.leaf_area_cm2, 1),
"delta_fw_g": round(delta_fw, 3),
"temp_factor": round(tf, 3),
"co2_factor": round(cf, 3),
"par_intercepted_mj": round(par_intercepted, 6),
"harvest_ready": harvest_ready,
}
def simulate_full_cycle(self, daily_conditions: List[dict]) -> dict:
"""
Simula l'intero ciclo colturale con condizioni giornaliere variabili.
Restituisce proiezione completa e giorno stimato di raccolta.
"""
days_log = []
harvest_day = None
for day_idx, cond in enumerate(daily_conditions):
day_state = self.simulate_day(
temp=cond.get('temp', 21.0),
co2_ppm=cond.get('co2_ppm', 1200),
ppfd=cond.get('ppfd', 200),
photoperiod_h=cond.get('photoperiod_h', 16)
)
days_log.append(day_state)
if day_state['harvest_ready'] and harvest_day is None:
harvest_day = day_idx + 1
return {
"days_simulated": len(days_log),
"final_fresh_weight_g": self.fresh_weight_g,
"estimated_harvest_day": harvest_day,
"daily_log": days_log,
"achieved_target": self.fresh_weight_g >= self.target_fresh_weight_g
}
# Esempio utilizzo digital twin
def predict_harvest_date(recipe: dict, seeding_date: datetime) -> datetime:
"""
Usa il digital twin per predire la data di raccolta
dato una ricetta ambientale costante.
"""
model = PlantGrowthModel()
# Condizioni giornaliere dalla ricetta (costanti per semplicità)
daily_conditions = [{
'temp': recipe.get('temp_c', 21.0),
'co2_ppm': recipe.get('co2_ppm', 1200),
'ppfd': recipe.get('ppfd_target', 200),
'photoperiod_h': recipe.get('photoperiod_hours', 16)
}] * 40 # massimo 40 giorni di simulazione
result = model.simulate_full_cycle(daily_conditions)
harvest_day = result.get('estimated_harvest_day', 35)
return seeding_date + timedelta(days=harvest_day)
Optimizasyon için Yapay Zeka: Parlak Tarifler için Takviyeli Öğrenim
Dijital ikiz, basit tahminden daha güçlü bir şeyi mümkün kılıyor: tarif optimizasyonu Takviyeli öğrenme (RL) yoluyla. Temsilci RL dijital ikizle etkileşime girer (gerçek çiftlikle değil), binlerce kombinasyon kombinasyonunu keşfeder ışık parametrelerini bulun ve tüketimi en aza indirirken verimi en üst düzeye çıkaran yapılandırmaları bulun enerjik. Simülasyonda en uygun tarif bulunduğunda, tek seferde doğrulanır. ölçekli dağıtımdan önce gerçek çiftliğin pilot alanı.
Bu yaklaşım dedi simden gerçeğe aktarımve araştırmanın sınırı AI dikey çiftçiliğinde. Simülasyon ve gerçeklik arasındaki boşluk (simülasyondan gerçeğe geçiş) bir Çiftlikten toplanan gerçek veriler üzerinde büyüme modelinin sürekli kalibrasyonu.
"""
Reinforcement Learning per Ottimizzazione Ricette Luminose
Usa Gymnasium + custom environment basato sul PlantGrowthModel
"""
import gymnasium as gym
import numpy as np
from gymnasium import spaces
from typing import Tuple, Optional
class VerticalFarmEnv(gym.Env):
"""
Ambiente Gymnasium per ottimizzazione ricette luminose.
Observation space: stato ambientale corrente + stato pianta
Action space: aggiustamenti parametri LED (continuo)
Reward: crescita giornaliera / consumo energetico
"""
metadata = {'render_modes': ['human']}
def __init__(self, crop_type: str = "lettuce", episode_days: int = 30):
super().__init__()
self.crop_type = crop_type
self.episode_days = episode_days
self.current_day = 0
# Action space: [delta_ppfd, delta_red_ratio, delta_blue_ratio, delta_photoperiod]
# Valori normalizzati in [-1, 1], scalati internamente
self.action_space = spaces.Box(
low=np.array([-1.0, -1.0, -1.0, -1.0], dtype=np.float32),
high=np.array([1.0, 1.0, 1.0, 1.0], dtype=np.float32)
)
# Observation space: [ppfd, red_ratio, blue_ratio, photoperiod,
# fresh_weight, leaf_area, days, temp, co2]
self.observation_space = spaces.Box(
low=np.array([50, 0, 0, 8, 0, 0, 0, 15, 400], dtype=np.float32),
high=np.array([800, 1, 1, 24, 500, 5000, 45, 30, 2000], dtype=np.float32)
)
# Stato corrente
self.ppfd = 200.0
self.red_ratio = 0.65
self.blue_ratio = 0.20
self.photoperiod = 16.0
self.plant_model = None
def reset(self, seed: Optional[int] = None, **kwargs) -> Tuple[np.ndarray, dict]:
super().reset(seed=seed)
self.current_day = 0
self.ppfd = 200.0
self.red_ratio = 0.65
self.blue_ratio = 0.20
self.photoperiod = 16.0
from digital_twin import PlantGrowthModel # import locale
self.plant_model = PlantGrowthModel()
return self._get_obs(), {}
def step(self, action: np.ndarray) -> Tuple[np.ndarray, float, bool, bool, dict]:
# Applica azione con scaling
self.ppfd = np.clip(self.ppfd + action[0] * 50, 50, 800)
self.red_ratio = np.clip(self.red_ratio + action[1] * 0.1, 0.3, 0.8)
self.blue_ratio = np.clip(self.blue_ratio + action[2] * 0.05, 0.1, 0.35)
self.photoperiod = np.clip(self.photoperiod + action[3] * 1.0, 10, 22)
# Simula giorno con nuove condizioni
day_result = self.plant_model.simulate_day(
temp=21.0, co2_ppm=1200,
ppfd=self.ppfd, photoperiod_h=self.photoperiod
)
# Calcola consumo energetico (kWh/giorno per m² crescita)
energy_kwh = (self.ppfd / 4.6) * (self.photoperiod / 1000) # semplificato
# Reward: crescita / energia (massimizza efficienza)
growth = day_result['delta_fw_g']
reward = growth / max(energy_kwh, 0.001) * 0.01
# Penalita per harvest_ready raggiunto troppo tardi
if self.current_day > 35 and not day_result['harvest_ready']:
reward -= 5.0
# Bonus per harvest_ready raggiunto nei tempi
if day_result['harvest_ready'] and self.current_day <= 28:
reward += 20.0
self.current_day += 1
done = day_result['harvest_ready'] or self.current_day >= self.episode_days
return self._get_obs(), reward, done, False, day_result
def _get_obs(self) -> np.ndarray:
pm = self.plant_model
return np.array([
self.ppfd, self.red_ratio, self.blue_ratio, self.photoperiod,
pm.fresh_weight_g if pm else 0.5,
pm.leaf_area_cm2 if pm else 5.0,
self.current_day, 21.0, 1200.0
], dtype=np.float32)
# Training con Stable-Baselines3
# from stable_baselines3 import PPO
# env = VerticalFarmEnv(crop_type="lettuce")
# model = PPO("MlpPolicy", env, verbose=1, learning_rate=3e-4)
# model.learn(total_timesteps=500_000)
# model.save("optimized_lettuce_recipe_v1")
Endüstriyel IoT Altyapısı: Modbus, MQTT, OPC-UA
Dikey çiftlikler bir dizi endüstriyel protokol kullanır: Modbus RTU/TCP eski sensörler ve aktüatörlerle (termohigrometreler, CO2 ölçüm cihazları, kontrolörler) iletişim LED), Siemens/Beckhoff PLC'ler ve SCADA sistemleriyle iletişim için OPC-UA, buluta veri gönderme. Seçim satıcının donanımına, gecikme süresine bağlıdır gerekli ve güvenlik düzeyi.
Dikey Tarımda IoT Protokolleri: Karşılaştırma
| Protokol | Katmanlar | Gecikme | Emniyet | Tipik Kullanım Durumu |
|---|---|---|---|---|
| Modbus RTU | Saha-PLC | 10-100ms | Yok (eski) | EC/pH sensörleri, LED sürücüleri |
| Modbus TCP | PLC-SCADA | 5-50ms | İsteğe bağlı TLS | PLC veri toplama |
| OPC-UA | PLC-SCADA-Bulut | 1-50ms | X.509, imza, şifreleme | Endüstri 4.0 standartları |
| MQTT | Kenar Bulutu | 10-500ms | TLS + kimlik doğrulama | Buluta telemetri |
| REST/HTTP | Bulut-Bulut | 50-500ms | HTTPS, OAuth2 | ERP entegrasyon API'si |
"""
Bridge Modbus -> MQTT per vertical farm
Legge sensori via Modbus RTU e pubblica su MQTT broker
"""
import asyncio
import json
import time
import logging
from pymodbus.client import AsyncModbusSerialClient
import paho.mqtt.client as mqtt
logger = logging.getLogger(__name__)
# Mappa registri Modbus per sensore combo Temp/RH/CO2 (esempio Vaisala HMP60)
MODBUS_REGISTER_MAP = {
"temperature": {"address": 0x0000, "count": 1, "scale": 0.1, "unit": "°C"},
"humidity": {"address": 0x0001, "count": 1, "scale": 0.1, "unit": "%RH"},
"co2_ppm": {"address": 0x0002, "count": 1, "scale": 1.0, "unit": "ppm"},
"ec_ms_cm": {"address": 0x0010, "count": 1, "scale": 0.01, "unit": "mS/cm"},
"ph": {"address": 0x0011, "count": 1, "scale": 0.01, "unit": "pH"},
}
class ModbusMQTTBridge:
def __init__(self, zone_id: str, modbus_port: str,
modbus_address: int, mqtt_broker: str, mqtt_port: int = 1883):
self.zone_id = zone_id
self.modbus_client = AsyncModbusSerialClient(
port=modbus_port, baudrate=9600, timeout=3
)
self.mqtt_client = mqtt.Client(client_id=f"bridge-{zone_id}")
self.mqtt_broker = mqtt_broker
self.mqtt_port = mqtt_port
self.mqtt_topic = f"farm/zones/{zone_id}/telemetry"
async def connect(self):
await self.modbus_client.connect()
self.mqtt_client.connect(self.mqtt_broker, self.mqtt_port, keepalive=60)
self.mqtt_client.loop_start()
logger.info(f"Bridge avviato per zona {self.zone_id}")
async def read_all_sensors(self, device_id: int = 1) -> dict:
readings = {"zone_id": self.zone_id, "timestamp": time.time()}
for sensor_name, reg in MODBUS_REGISTER_MAP.items():
try:
result = await self.modbus_client.read_holding_registers(
address=reg["address"],
count=reg["count"],
slave=device_id
)
if not result.isError():
raw_value = result.registers[0]
readings[sensor_name] = round(raw_value * reg["scale"], 3)
else:
logger.warning(f"Errore lettura {sensor_name} zona {self.zone_id}")
readings[sensor_name] = None
except Exception as e:
logger.error(f"Eccezione Modbus {sensor_name}: {e}")
readings[sensor_name] = None
return readings
async def publish_loop(self, interval_sec: float = 30.0):
while True:
readings = await self.read_all_sensors()
payload = json.dumps(readings)
result = self.mqtt_client.publish(
topic=self.mqtt_topic,
payload=payload,
qos=1
)
if result.rc == mqtt.MQTT_ERR_SUCCESS:
logger.debug(f"Pubblicato su {self.mqtt_topic}: {payload[:80]}...")
else:
logger.error(f"Errore publish MQTT: rc={result.rc}")
await asyncio.sleep(interval_sec)
Dikey Tarım Ekonomisi: CAPEX, OPEX ve Başabaş
Dikey tarım ekonomik olarak sürdürülebilir midir? 2025'teki cevap: Bağlı olmak. Bu, mahsule bağlıdır (otlar ve mikro yeşillikler maruldan çok daha karlıdır), ölçek (ölçek ekonomisi 5.000 m²'nin üzerinde görünür), konum (maliyet yerel enerji ve işçilik maliyetleri çok önemlidir) ve satış kanalıyla (doğrudan satışlar) Premium fiyatlarla B2C ve GDO emtiaları).
Ekonomik Analiz: Çiftlik 1.000 m² Net Ekim
| Ses | Değer | Notlar |
|---|---|---|
| CAPEX (ilk yatırım) | ||
| Yapı ve sistem | 800.000 € | Depo yenileme |
| NFT rafları ve kanalları | 300.000 € | Topraksız sistemler |
| LED aydınlatma | 600.000 € | 600W/m² verimlilik 2,8 µmol/J |
| HVAC ve iklim | 250.000 € | Soğutma + nem alma |
| CO2 sistemi | 50.000 € | Depolama + dağıtım |
| Otomasyon ve robotik | 400.000 € | Ekme makinesi, fide dikme makinesi, biçerdöver |
| Yazılım ve entegrasyon | 150.000 € | SCADA, API, dijital ikiz |
| Toplam Yatırım Harcamaları | 2.550.000 € | ~2.550€/m² |
| YILLIK OPEX | ||
| Elektrik | 420.000 € | %35 OPEX - ana kritik enerji |
| Çalışma (10 operatör) | €350.000 | %27 işletme giderleri |
| Tohumlar ve substrat | 80.000 € | %6 işletme gideri |
| Besinler ve CO2 | 60.000 € | %5 İşletme Giderleri |
| Bakım | 90.000 € | %7 OPEX |
| Paketleme ve lojistik | 120.000€ | %9 İşletme Giderleri |
| Diğer (sigorta vb.) | 80.000 € | %6 işletme gideri |
| Toplam İşletme Giderleri | 1.200.000 € | €1.200/m²/yıl |
| GELİRLER | ||
| Marul üretimi (18 döngü x 25kg/m²) | 450 kg/m²/yıl | Toplam 450.000 kg |
| Premium GDO satış fiyatı | €3,5/kg | vs 0,8-1,2 € açık havada |
| Brüt gelirler | 1.575.000 € | |
| FAVÖK | €375.000 | %23,8 marj |
| CAPEX amortismanı (10 yıl) | 255.000 € | |
| Vergi öncesi net kâr | 120.000€ | %7,6 marj |
| Başabaş (yıl) | ~8-10 yıl | Bitkilerle birlikte: 4-5 yıl |
Dikey Tarımda Enerji Sorunu
Dikey tarımın enerjisi ve varoluşsal zorluğu. 2025'te mevcut olan en verimli LED'ler yaklaşık olarak ulaşıyorlar 3,0-3,5 µmol/J fotonik verimlilik. Bir üretmek 16 saatlik fotoperiyot ile 17 mol/m²/günlük DLI, yaklaşık 280 Wh/m²/gün gerektirir; 102 kWh/m²/yıl sadece aydınlatma için. 1.000 m² alanlı ve uygun maliyetli 0,15 €/kWh enerji (İtalya endüstriyel tarifesi 2025), LED faturası halihazırda 153.000 €/yıldır. HVAC (tipik olarak LED enerjisinin %60-70'i), CO2, pompalar, otomasyon ekleyin; istediğinizi elde edersiniz kolayca 420.000 €/yıl seviyesinde. Düşük maliyetli yenilenebilir enerjiye erişimi olanlar (örneğin tarımsal %100 yenilenebilir enerjiye sahip modern) veya kurulu fotovoltaik önemli bir kısmı kapsıyor ihtiyaçların tamamı değil.
Dikey tarım her enerji fiyatında sürdürülebilir değil. Enerji ile 0,25 €/kWh'nin üzerinde (2022-2023 gibi kriz dönemlerinde olası senaryo), birçok ekonomik model çökerler. Bahis şu ki, LED verimliliği gelişmeye devam ediyor ve yenilenebilir enerji maliyeti giderek azalıyor.
Örnek Olay: Gezegen Çiftlikleri ve Modern Tarım - İtalyan Modeli
İtalya, Avrupa'nın en gelişmiş dikey tarım projelerinden ikisine ev sahipliği yapıyor. Milano'nun hinterlandında yerleşik. Yolları farklı ama tamamlayıcıdır ve temsil eder. Avrupa dikey çiftçiliğinde ölçeklenebilirlik ve karlılık sorununa iki yaklaşım.
Gezegen Çiftlikleri - Cavenago di Brianza
2018 yılında Luca Travaglini ve Massimiliano Loschi tarafından kurulan Planet Farms, Cavenago'nun (MB) eski sanayi bölgesindeki ilk fabrika. Orijinal bitki 9.000 m² ve 2024 yılında Avrupa'nın en büyüklerinden biri haline geldi 20.000 m² büyüme yüzeyi. Kasım 2023'te Planet Farms bir tur topladı 500 milyon dolarlık değerlemeyle 40 milyon dolarlık, sektörde Avrupa'nın en büyüklerinden biri. 2025'te Swiss Life Asset Managers ile ortaklık, €200 milyonlarca Avrupa çapında geniş ölçekte dikey çiftlikler geliştirmek.
Siemens ile teknolojik ortaklık otomasyonun kalbinde yer alıyor: kontrol sistemleri endüstriyel Siemens S7-1500 çevresel döngüleri yönetirken, platform da Mindsphere (şimdiki adı Siemens Industrial Copilot) verileri topluyor ve analiz ediyor. Ürün amiral gemisi ürünleri "Yaşayan Otlar"dır - aromatik bitkiler hala tepsilerde satılmaktadır. kök, maruldan daha yüksek marjlı premium segment.
Modern Tarım - Agnadello (CR)
Agricola Moderna, 2018 yılında Pierluigi Giuliani ve Benjamin Franchetti tarafından Milano'da kuruldu. yeni fabrika Eylül 2024'te açıldı 11.000 m² reklam Agnadello (Cremona), Intesa Sanpaolo'dan 10 milyon Euro'luk bir krediyle finanse edildi. Bitki üretir Günde 30.000 torba salata, güçlendirilmiş Ar-Ge ekibi tarafından geliştirilen dahili yapay zeka ile %100 yenilenebilir kaynaklardan tarifleri optimize edin.
Agricola Moderna'nın teknolojik farklılaşması ve hiperspektral görüntüleme sistemi (SPECIM ile ortaklık) bitkilerin beslenme durumunu değerlendirmenizi sağlar Semptomlar insan gözüyle görülmeden önce. Yeniden yapılandırma için RGB-D kameralar Kanopinin 3D'si, binlerce ölçüm noktasına sahip çevresel sensörler ve algoritmalar Dahili olarak geliştirilen bilgisayarlı görüntü sistemleri, tescilli teknoloji yığınını oluşturur.
Karşılaştırma Gezegen Çiftlikleri ve Modern Agricola
| Parametre | Gezegen Çiftlikleri | Modern Tarım |
|---|---|---|
| Yüzey | 20.000 m² | 11.000 m² |
| Üretim/gün | N.D. (otlar odağı) | 30.000 salata poşeti |
| Finansman | 40 milyon $ yuvarlak + 200 milyon € ortak girişim | 10 Milyon € Intesa Sanpaolo |
| PLC/Otomasyon | Siemens S7-1500 | Beckhoff + özel |
| Yapay Zeka Platformu | Siemens Endüstriyel Yardımcı Pilot | Şirket içi geliştirme |
| Bilgisayarla Görme | RGB standartları | Hiperspektral (Numune) |
| Enerji | Kısmen yenilenebilir | %100 yenilenebilir |
| Hedef pazar | Premium perakende GDO + Birleşik Krallık genişlemesi | İtalyan büyük ölçekli perakende ticareti (IV aralığı) |
Sektörün Zorlukları, Sınırlamaları ve Gerçekleri
Dikey tarımla ilgili dürüst bir makale, yalnızca faydaları değil, gerçek zorlukları da içermelidir. Sektör, 2022-2024'te iflaslarla birlikte büyük bir hayal kırıklığı yaşadı milyarlarca dolarlık yatırımı yakan sansasyonel olanlar. Neden önemli olduğunu anlamak Sürdürülebilir sistemler inşa etmek.
Dikey Tarımın Gerçek Zorlukları
- Enerji maliyeti: Ve bir numaralı katil. Dikey çiftlik operatörlerinin %60'ı Büyük ölçüde elektrik maliyetlerinden dolayı henüz karlı değil. Enerji olmadan düşük maliyetli yenilenebilir ekonomik model yalnızca birinci sınıf mahsuller için geçerlidir.
- Sınırlı ürün çeşitleri: Dikey tarım aşağıdakiler için mükemmeldir: yapraklı yeşillikler (marul, ıspanak), aromatik bitkiler ve mikro yeşillikler. Domates, biber için salatalıkların enerji verimi henüz rekabetçi değildir. Tahıllar, baklagiller ve kökler teknik ve ekonomik açıdan ulaşılmaz.
- Yüksek CAPEX: Profesyonel bir kurulumun maliyeti 2.000-4.000 Euro'dur m² ekim başına. Marulun başabaş noktası 8-10 yıldır; birçok yatırımcı için çok fazla. Sadece şifalı bitkiler ve mikro yeşillikler 4-5 yıl içinde başabaş noktasına ulaşır.
- LED tedarik zinciri bağımlılığı: Yüksek kaliteli LED çipleri birkaç tedarikçi (Epistar, Lumileds, Osram) tarafından üretilmektedir. Tedarik zincirinde bozulma hem başlangıçtaki CAPEX'i hem de bakımı etkiler.
- Gerçek ve algılanan sürdürülebilirlik: Su tasarrufu (%95) gerçektir. Ancak karbon ayak izi büyük ölçüde enerji karışımına bağlıdır. Güçlü bir dikey çiftlik Kömürün karbon ayak izi açık havada tarıma göre daha kötü. Yalnızca yenilenebilir kaynaklarla denge açıkça pozitif hale gelir.
- Teknik ölçeklenebilirlik: 500 m²'lik pilot çiftlikten 20.000 m² ticari alan basit bir çarpım değildir. Kontrol sistemleri, mahsul yönetimi, dahili lojistik ve robotik sistemler gerektirir Her ölçek atlamasında derinlemesine yeniden tasarım.
Üretimde Dağıtım: Konteynerizasyon ve İzleme
Dikey bir çiftliğin yazılım bileşenleri, gerçek zamanlı PID denetleyicisinden (çalışan) doğrudan PLC'den veya bir Raspberry Pi'den (konteynersiz) FastAPI arka ucuna ve AI boru hatları (Docker konteynerlerinde rahatça yaşamak). Tipik bulut altyapısı şirket içi kenar katmanını bulut kontrol düzlemiyle birleştirir.
# docker-compose.yml per stack vertical farm (dev/staging)
version: '3.9'
services:
# API principale
farm-api:
build: ./farm-api
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://farm:farm@postgres:5432/farmdb
- MQTT_BROKER=emqx
- INFLUXDB_URL=http://influxdb:8086
- REDIS_URL=redis://redis:6379
depends_on:
- postgres
- influxdb
- emqx
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
# MQTT Broker
emqx:
image: emqx/emqx:5.8
ports:
- "1883:1883" # MQTT
- "8883:8883" # MQTT TLS
- "18083:18083" # Dashboard
environment:
- EMQX_NODE__COOKIE=farm-secret-cookie
volumes:
- emqx_data:/opt/emqx/data
# Time-series database per dati sensori
influxdb:
image: influxdb:2.7
ports:
- "8086:8086"
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=admin
- DOCKER_INFLUXDB_INIT_PASSWORD=farmpass123
- DOCKER_INFLUXDB_INIT_ORG=verticalfarm
- DOCKER_INFLUXDB_INIT_BUCKET=sensors
volumes:
- influxdb_data:/var/lib/influxdb2
# PostgreSQL per dati applicativi (ricette, batch, inventory)
postgres:
image: postgres:16-alpine
environment:
- POSTGRES_DB=farmdb
- POSTGRES_USER=farm
- POSTGRES_PASSWORD=farm
volumes:
- postgres_data:/var/lib/postgresql/data
# Redis per cache e job queue
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
# Grafana per dashboard real-time
grafana:
image: grafana/grafana:11.0.0
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
depends_on:
- influxdb
# Worker ML per digital twin e ottimizzazione
ml-worker:
build: ./ml-worker
environment:
- INFLUXDB_URL=http://influxdb:8086
- REDIS_URL=redis://redis:6379
- MODEL_PATH=/models
volumes:
- ml_models:/models
volumes:
emqx_data:
influxdb_data:
postgres_data:
grafana_data:
ml_models:
Dikey Tarımda Trendler ve Yenilikler 2025-2026
Sektör üç cephede hızla gelişiyor: enerji verimliliği, mahsuller ve daha derin yapay zeka entegrasyonu. İşte en önemli trendler.
Dikey Tarımda Temel Yenilikler 2025
| Yenilik | Darbe | Ticari Durum |
|---|---|---|
| LED verimliliği 4,0+ µmol/J | -20-25% aydınlatma enerjisi maliyeti | Mevcut (LG, Signify) |
| Hiperspektral görüntüleme | Bitki stresinin erken teşhisi, optimizasyonu | Erken benimseme (Specim + Agricola M.) |
| Dinamik tarifler için RL | Aynı enerjiyle +%15-25 verim | Gelişmiş arama / erken üretim |
| Yüksek hızlı ekim robotu | 3.000+ tohumlama/saat ile 700 manuel ekim | Ticari (Bol, 80 Dönüm) |
| Mantar/mantar yetiştiriciliği | Mahsul karışımı çeşitlendirmesi, yüksek karlılık | Ticari büyüme |
| Veri merkezi atık ısısı olarak dikey çiftlik | HVAC azaltımı için ısı geri kazanımı | Pilot (Finlandiya, Almanya) |
| BESS ile fotovoltaik entegrasyon | -Optimum senaryolarda %40-60 enerji maliyeti | Büyüyor |
Özellikle ilginç bir ortaya çıkan trend, dikey tarımın tarımla entegrasyonudur. Veri merkezleri: Sunucular, azaltmak için geri kazanılabilen atık ısı üretir. Soğuk aylarda seraları ısıtmanın maliyeti. Enerjinin olduğu Finlandiya'da pahalı olmasına rağmen birçok pilot proje bu simbiyozu test ediyor. Atık ısı 40-60°C sıcaklıktadır ve kışlık seralarda yetiştirme sıcaklıklarının korunması için idealdir ek enerji tüketimi olmadan.
Sonuçlar: Bir Yazılım Mühendisliği Projesi Olarak Dikey Tarım
Modern bir dikey çiftlik ve her şeyden önce bir yazılım sistemi. Donanım (LED'ler, sensörler, robot, raflar) gereklidir ancak yeterli değildir: dönüştüren yazılım düzeyidir Optimize edilmiş bir gıda fabrikasında ışıklı bir depo. PID denetleyicileri yönetir bilimsel olarak kalibre edilmiş tariflere göre çevre; REST API'leri çiftliği birbirine bağlar ticari ekosisteme; ROS2 robotları koordine eder; dijital ikiz simülasyonlara izin veriyor tahmine dayalı; Takviyeli öğrenme, tasarlananlardan daha iyi tarifler bulur ziraat uzmanları tarafından manuel olarak.
2025'te 9,6 milyar olan dikey tarım pazarı 2033'te 39 milyara çıkacak. otomatik olarak garanti edilir: sektörün sorunu çözme becerisine bağlıdır enerji tasarrufu sağlamak ve ekonomik olarak üretilebilecek ürün yelpazesini genişletmek sürdürülebilir. Planet Farms ve Agricola Moderna ile İtalya doğru konumda özellikle PNRR ve teşviklerden sonra bu geçişin kahramanı olmak Teknolojik CAPEX'in maliyetini azaltan 5.0 geçişi.
Bu sektöre girmek isteyen geliştirici için en çok talep edilen beceriler şunlardır: Otomasyon ve ML için Python, endüstriyel arka uç için FastAPI, robotik için ROS2, Endüstriyel protokoller için MQTT/Modbus/OPC-UA, zaman serileri için InfluxDB ve temel bilgiler Optimize edilecek parametreleri anlamak için bitki fizyolojisinin. Nasıl olduğunu bilmene gerek yok bahçecilik, ancak bitkilerin neden belirli dalga boylarında daha fazla büyüdüğünü anlamak iyi bir kontrol sistemi ile mükemmel bir kontrol sistemi arasındaki farkı yaratır.
Daha Fazla Bilgi Edinecek Araçlar ve Kaynaklar
- Pymodbus - Modbus RTU/TCP için Python kütüphanesi, PLC'ler ve sensörlerle iletişim için idealdir
- Paho-MQTT - Aracılarla entegrasyon için MQTT Python istemcisi (EMQX, HiveMQ, Mosquitto)
- ROS2 Mütevazı / Cazip - Robotik çerçeve, docs.ros.org adresindeki resmi belgeler
- FastAPI - Python eşzamansız arka uç, endüstriyel kontrol API'leri için mükemmel
- AkışDB 2.x - Sensör analizi için Flux sorgulama dili içeren zaman serisi veritabanı
- Kararlı Temel Çizgiler3 - Tarif optimizasyonu için RL uygulamaları (PPO, SAC, TD3)
- Spor salonu - Dijital ikiz ortamlar için kullanılan RL ortamları için standart
- Ateşleme SCADA'sı - Uygun fiyatlı OEM lisanslı endüstriyel SCADA platformu
- Dikey Çiftlik Günlük - Dikey sektöre ilişkin ana haber kaynağı
- USDA CEA Yönergeleri - Kontrollü çevre tarımı için referans parametreler
Serinin Sonraki Bölümü: Gıda Perakendesinde Talep Tahmini
8. Maddede tam tersi sorunu ele alıyoruz: Ürünlere olan talebin nasıl tahmin edileceği Üretim siparişlerini optimize etmek (dikey çiftliklerden de) ve gıda miktarını azaltmak için atık. Mevsimsellik ve trendler için Prophet by Meta'yı, kalıplar için LightGBM'yi kullanacağız gelişmiş tablolar ve özelliklerle eksiksiz bir tahmin hattı oluşturacağız İtalyan gıda perakendeciliğine özel mühendislik (hava durumu etkileri, tatiller, promosyonlar).
Şununla devam edin: Prophet ve LightGBM ile Gıda Perakendesinde Talep Tahmini
Diğer Serilerdeki İlgili Makaleler
- IoT Boru Hattı Serisi: Hassas Tarım için IoT Boru Hattı - Dış mekan sensör izleme için MQTT, InfluxDB, Grafana
- MLOps Serisi: Üretimdeki Yapay Zeka Modelleri için MLOps - Nasıl dağıtılır RL tarif optimizasyon modeli üretimde
- Bilgisayarlı Görme Serisi: Kalite Kontrol CV'si - Teknikler Mahsulün olgunluğunu ve kalitesini değerlendirmek için yapay görüş
- Veri ve Yapay Zeka İş Serisi: Üretimde Yapay Zeka - Tahmine Dayalı Bakım ve Dijital İkiz, dikey tarıma uygulanabilir ikiz mimariler







