Akıllı Üretim

IoT Sensörler ve MQTT ile Makine Duruş Takibi

Eski ya da yeni her makinede duruşları takip edin: pens tipi akım sensörlü bir ESP32 çalışma ve duruş durumlarını MQTT üzerinden yayınlar, bir Python kaydedici de her duruşu süresi ve nedeniyle kaydeder.

Motor kablosunda pens tipi akım sensörü, çalışma ve duruş durumlarını MQTT ile yayınlayan bir ESP32 ve bir duruş kaydıyla makine duruş takibi illüstrasyonu
Bunu kendi MQTT broker’ınızda çalıştırınFree planla özel, yönetilen bir MQTT broker alın ve hazır kod örnekleriyle başlayın.
Ücretsiz deneyin Kod örnekleri Kart gerekmez

Makine duruş takibi yeni bir kontrolör veya pahalı bir MES gerektirmez. Bu eğitimde bir makinenin motor kablosuna bir akım sensörü takacak, bir ESP32 ile çalışma ve duruş durumlarını MQTT üzerinden yayınlayacak ve her duruşu başlangıcı, bitişi, süresi ve nedeniyle kaydeden bir Python kaydedici çalıştıracaksınız. Bu yaklaşım veri portu olmayan eski makinelerde de çalışır; tam da manuel kayıtların en az güvenilir olduğu yerlerde.

Sensör Tabanlı Duruş Takibi Neden İşe Yarar?

Kâğıt kayıtlar ve operatör terminalleri, insanların duruşları kaydetmeyi hatırlamasına bağlıdır. Uzun arızalar genellikle kaydedilir; forklift için on dakikalık bekleme veya hızlı bir takım değişimi ise çoğu zaman kaydedilmez. Sonuç, sistematik olarak fazla iyimser bir duruş tablosudur.

Bir akım sensörü hafıza sorununu ortadan kaldırır. Bir motor, makine çalışırken akım çeker, çalışmadığında ise çok az akım çeker; böylece durum, kumanda panosunun mantığına herhangi bir kablo bağlamadan otomatik olarak algılanabilir. Operatörün tek görevi bir neden eklemektir ve bu bile doğru anda istenebilir.

Her Makine İçin Donanım

Parça Amaç Notlar
ESP32 geliştirme kartı Sensörü okur, Wi-Fi üzerinden yayınlar Yaygın ESP32 kartlarının hepsi çalışır
Açılabilir (split-core) akım trafosu (örneğin akım çıkışlı SCT-013 tipi) Devreyi kesmeden motor akımını ölçer Kablonun tamamına değil, tek bir iletkene takın
Yük (burden) direnci CT akımını gerilime dönüştürür Beklenen akım aralığına göre boyutlandırın
İki direnç ve bir kondansatör Sinyali besleme geriliminin ortasına kaydırır ESP32 ADC'si negatif gerilimleri okuyamaz
5 V besleme ve muhafaza Güç ve koruma Mümkünse panonun dışında tutun

Önce güvenlik: şebeke iletkenlerinin yakınına herhangi bir şey kurmak, yerel mevzuata uygun olarak yetkin bir elektrikçi tarafından yapılmalıdır. Açılabilir bir CT müdahalesizdir, ancak pano doğaçlama yapılacak bir yer değildir. Ayrıntılı kablolama ESP32 SCT-013 akım sensörü rehberinde ele alınmıştır.

Adım 1: Çalışma ve Duruş Yayınlayan ESP32 Yazılımı

Bu sketch sensörü 200 ms boyunca örnekler, RMS değerini hesaplar, kısa düşüşlerin sahte duruşlar oluşturmaması için histerezis ve bir debounce süresi uygular ve her değişimde retained bir durum mesajı yayınlar. Ayrıca ölçülen akımı her 30 saniyede bir yayınlar; bu da daha sonra eşikleri ayarlamanıza yardımcı olur. PubSubClient kütüphanesini kullanır.

#include <WiFi.h>
#include <PubSubClient.h>

const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* MQTT_HOST = "broker.connectmq.com";
const int   MQTT_PORT = 1883;
const char* CLIENT_ID = "press04-ct-m6j2";
const char* TOPIC_STATE   = "connectmq/demo/m6j2/plant1/stamping/press04/state";
const char* TOPIC_CURRENT = "connectmq/demo/m6j2/plant1/stamping/press04/current";

const int   CT_PIN = 34;
const float AMPS_PER_ADC_RMS = 0.0488;  // bir pens ampermetreyle kalibre edin
const float RUN_ON_AMPS  = 3.0;          // bunun üstü -> çalışıyor
const float RUN_OFF_AMPS = 2.0;          // bunun altı -> durdu
const unsigned long DEBOUNCE_MS = 5000;  // durum bu kadar süre devam etmeli

WiFiClient net;
PubSubClient mqtt(net);
bool running = false;
unsigned long candidateSince = 0;
unsigned long lastCurrentPub = 0;

float readAmpsRms() {
  const int samples = 2000;
  long sum = 0;
  long sumSq = 0;
  unsigned long start = millis();
  int n = 0;
  while (millis() - start < 200 && n < samples) {
    int v = analogRead(CT_PIN);
    sum += v;
    sumSq += (long)v * v;
    n++;
  }
  float mean = (float)sum / n;
  float variance = (float)sumSq / n - mean * mean;
  return sqrt(max(variance, 0.0f)) * AMPS_PER_ADC_RMS;
}

void publishState(float amps) {
  char payload[96];
  snprintf(payload, sizeof(payload), "{\"state\":\"%s\",\"amps\":%.2f}", running ? "RUNNING" : "STOPPED", amps);
  mqtt.publish(TOPIC_STATE, payload, true);  // retained
}

void connectMqtt() {
  while (!mqtt.connected()) {
    if (mqtt.connect(CLIENT_ID, TOPIC_STATE, 1, true, "{\"state\":\"OFFLINE\"}")) {
      publishState(0);
    } else {
      delay(2000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  analogReadResolution(12);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  connectMqtt();
}

void loop() {
  if (!mqtt.connected()) connectMqtt();
  mqtt.loop();

  float amps = readAmpsRms();
  bool candidate = running ? (amps > RUN_OFF_AMPS) : (amps > RUN_ON_AMPS);

  if (candidate != running) {
    if (candidateSince == 0) candidateSince = millis();
    if (millis() - candidateSince >= DEBOUNCE_MS) {
      running = candidate;
      candidateSince = 0;
      publishState(amps);
    }
  } else {
    candidateSince = 0;
  }

  if (millis() - lastCurrentPub > 30000) {
    char buf[32];
    snprintf(buf, sizeof(buf), "{\"amps\":%.2f}", amps);
    mqtt.publish(TOPIC_CURRENT, buf);
    lastCurrentPub = millis();
  }
}

Last Will mesajı, ESP32 gücünü veya Wi-Fi bağlantısını kaybederse makineyi OFFLINE olarak işaretler; böylece kaydedici ölü bir sensörü asla duran bir makineyle karıştırmaz. Çıktıyı şu komutla kontrol edin:

mosquitto_sub -h broker.connectmq.com -p 1883 -i dt-viewer-m6j2 -t "connectmq/demo/m6j2/plant1/+/+/state" -v

Adım 2: Eşikleri Seçmek

Durumlara güvenmeden önce current topic'ini bir gün boyunca izleyin. Genellikle üç bant görürsünüz: makine kapalıyken sıfıra yakın, enerjili ama boşta iken (hidrolik pompa, soğutma sıvısı, iş mili durmuş) daha düşük bir bant ve çalışırken daha yüksek bir bant. RUN_ON_AMPS değerini boşta bandının rahatça üzerinde, RUN_OFF_AMPS değerini ise biraz altında ayarlayın; böylece aradaki fark histerezis sağlar. Boşta ve çalışma bantları örtüşüyorsa sensörü makinenin ana beslemesi yerine yalnızca üretim sırasında çalışan bir motora, örneğin ana iş miline veya pres tahrikine taşıyın.

Adım 3: Her Duruş Olayını Python ile Kaydedin

Kaydedici tüm makinelere abone olur, bir makine durduğunda bir duruş kaydı açar, makine yeniden çalıştığında kapatır ve SQLite'ta saklar. Nedenler, bir operatör tableti veya buton kutusu tarafından yayınlanan ayrı bir reason topic'i üzerinden gelir ve o makinenin en son açık veya yeni kapanmış olayına eklenir.

import json
import sqlite3
import time

import paho.mqtt.client as mqtt

PREFIX = "connectmq/demo/m6j2/plant1"
db = sqlite3.connect("downtime.db", check_same_thread=False)
db.execute("""CREATE TABLE IF NOT EXISTS downtime (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    machine TEXT, started REAL, ended REAL, seconds REAL, reason TEXT)""")
db.commit()

current_state = {}


def on_connect(client, userdata, flags, reason_code, properties):
    client.subscribe([(f"{PREFIX}/+/+/state", 1), (f"{PREFIX}/+/+/reason", 1)])


def on_message(client, userdata, msg):
    parts = msg.topic.split("/")
    machine, kind = parts[-2], parts[-1]
    data = json.loads(msg.payload)
    now = time.time()

    if kind == "state":
        new, old = data["state"], current_state.get(machine)
        current_state[machine] = new
        if msg.retain or new == old:
            return  # retained tekrarları ve yinelemeleri yok say
        if new in ("STOPPED", "OFFLINE") and old == "RUNNING":
            db.execute("INSERT INTO downtime (machine, started, reason) VALUES (?, ?, ?)",
                       (machine, now, "OFFLINE" if new == "OFFLINE" else None))
        elif new == "RUNNING":
            db.execute("""UPDATE downtime SET ended = ?, seconds = ? - started
                          WHERE machine = ? AND ended IS NULL""", (now, now, machine))
        db.commit()
        print(machine, old, "->", new)

    elif kind == "reason":
        db.execute("""UPDATE downtime SET reason = ? WHERE id = (
                        SELECT id FROM downtime WHERE machine = ?
                        ORDER BY started DESC LIMIT 1)""", (data["code"], machine))
        db.commit()
        print(machine, "reason", data["code"])


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="downtime-logger-m6j2")
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.connectmq.com", 1883, keepalive=30)
client.loop_forever()

Bir operatörün neden girişini simüle edin:

mosquitto_pub -h broker.connectmq.com -p 1883 -i tablet-m6j2 -t "connectmq/demo/m6j2/plant1/stamping/press04/reason" -m '{"code":"MAT-WAIT"}'

Kaydedicinin zaman damgasını mesajı aldığı anda eklediğine dikkat edin. Dakikalarla ölçülen duruşlar için bu yeterlidir; saniye düzeyinde doğruluğa ihtiyacınız varsa, saatini NTP ile senkronize ettikten sonra ESP32'den bir zaman damgası ekleyin.

Adım 4: Kaydı Kararlara Dönüştürün

Birkaç haftalık veri biriktiğinde, bir avuç sorgu soruların çoğunu yanıtlar:

sqlite3 downtime.db "SELECT machine, reason, COUNT(*) AS stops, ROUND(SUM(seconds)/60,1) AS minutes FROM downtime WHERE ended IS NOT NULL GROUP BY machine, reason ORDER BY minutes DESC LIMIT 15;"

Sonucu şu sırayla kullanın:

  1. En büyük kayıpları bulmak için nedenleri toplam dakikaya göre sıralayın.

  2. Çoğu zaman ucuz çözümleri olan sık ve kısa duruşları bulmak için adede göre sıralayın.

  3. Açıklanmamış olaylara (reason NULL) bakın ve operatörlerin neden bir neden girmediğini sorun; genellikle sorun neden listesindedir.

  4. Arıza nedenleri için MTBF ve MTTR hesaplama yazısında anlatıldığı gibi arızalar arası ortalama süreyi ve ortalama onarım süresini hesaplayın.

  5. Çalışma süresini gerçek zamanlı OEE izleme için kullanılabilirlik hesabına aktarın.

  6. adımın kalitesi neden listesinin kendisine bağlıdır. Çok uzun, çok belirsiz veya nedenler yerine departmanlara göre düzenlenmiş bir liste kullanılamaz veri üretir; bu nedenle devreye almadan önce duruş nedeni kodlarını tasarlamak yazısını okuyun.

Tek Makineden Tüm Atölyeye Ölçeklenmek

İlk sensör konsepti kanıtlar; değer ise her önemli makine raporlamaya başladığında ortaya çıkar. Birkaç uygulama yaygınlaştırmayı sorunsuz hale getirir:

  1. Topic ağacını standartlaştırın. plant/area/machine/state kalıbını her yerde koruyun; böylece makineler eklendiğinde kaydedici ve panolarda değişiklik gerekmez.
  2. Her ESP32'ye benzersiz bir client ID ve kendi kimlik bilgilerini verin. ConnectMQ'da client ID'ler verilen kimlik bilgilerine bağlıdır; dolayısıyla aynı ID'ye sahip kopyalanmış bir yazılım imajı, başka bir sensörü sessizce çevrimdışı bırakamaz.
  3. Eşikleri makine başına kaydedin. RUN_ON_AMPS ve RUN_OFF_AMPS değerlerini, sensörün takıldığı iletkenle birlikte bir tabloda veya yapılandırma dosyasında saklayın; böylece yedek bir sensör aynı şekilde kurulabilir.
  4. Wi-Fi kapsamasını planlayın. Metal makineler ve panolar sinyalleri engeller. Muhafazayı monte etmeden önce her kurulum noktasında sinyal gücünü test edin.
  5. Sensör sağlığını izleyin. Uzun süredir OFFLINE olan makineler için günlük bir kontrol, verilerde boşluk bırakmadan önce bozulan güç kaynaklarını yakalar.
  6. Darboğazla başlayın. Darboğaz makinedeki duruş tüm hatta mal olur; bu yüzden önce onu donatın ve sonuçları orada gösterin.

Üretim Kurulumu

Herkese açık broker test için idealdir, ancak oraya yayınlanan her şey başkaları tarafından okunabilir. Gerçek bir kurulum için ConnectMQ üzerinde özel bir broker oluşturun ve ESP32 sketch'inde size verilen kullanıcı adı, parola ve client ID ile 8883 portunda WiFiClientSecure kullanımına geçin. Bir yönetilen MQTT broker, tesis ekibini broker yönetiminden uzak tutar ve bir bulut MQTT broker olduğu için bakım müdürü duruşları herhangi bir sahadan görebilir. Portalın cihaz görünümü hangi sensörlerin bağlı olduğunu gösterir ve eşik uyarı kuralları bir makine OFFLINE bildirdiğinde sizi haberdar edebilir. Daha geniş yol haritası için akıllı üretim rehberine bakın.

ConnectMQ ile Başlayın

Kredi kartı olmadan Serverless planında app.connectmq.com adresinde ücretsiz bir broker oluşturun, ESP32'ye kimlik bilgilerinizle yazılım yükleyin ve bu hafta gerçek duruşları kaydetmeye başlayın.

Sık Sorulan Sorular

Bir akım sensörü bana makinenin neden durduğunu söyleyebilir mi?

Hayır. Makinenin durduğunu ve ne kadar süre durduğunu güvenilir şekilde algılar. Neden bir operatör girişinden, makinenin alarm kodlarından veya her ikisinin birleşiminden gelir.

Sensörü hangi iletkene takmalıyım?

Yalnızca üretim sırasında çalışan bir motorun, örneğin iş milinin veya ana tahrikin tek bir faz iletkenine. Kablonun tamamına takmak manyetik alanı sıfırlar ve sıfıra yakın bir değer okunur.

Kısa duraklamaların duruş olarak sayılmasını nasıl önlerim?

Yazılımdaki debounce süresini ve raporlamada bir minimum süre filtresini kullanın. Çok kısa duruşlar, performans kaybı altında mikro duruşlar olarak analiz edilmeye daha uygundur.

Bu, zaten PLC'si olan makinelerde çalışır mı?

Evet, ancak PLC zaten bir çalışma sinyali sunuyorsa onu bir gateway üzerinden okumak daha fazla ayrıntı verir. Akım sensörü, erişilebilir kontrolleri olmayan makineler için en hızlı yoldur.

İlgili yazılar

OEE vs TEEP vs OOE: Hangi Metriği Kullanmalısınız?

OEE, OOE ve TEEP aynı performans ve kalite faktörlerini paylaşır, ancak farklı zaman tabanlarına göre ölçer. Bu karşılaştırma tek bir örnek üzerinden ilerliyor ve her metriğin ihtiyaç duyduğu MQTT sinyallerini listeliyor.

6 dk okuma

Tüm yazılar →

Özel MQTT broker’ınız birkaç tık uzağınızda

Hesabınızı oluşturun, broker kimlik bilgilerinizi alın ve ilk cihazınızı bağlayın — kurulacak, yamalanacak ya da ölçeklendirilecek sunucu yok.