Özel olarak MES (Manufacturing Execution System/Üretim Yürütme Sistemi) ve genel olarak IIoT (Industrial IoT) uygulamalarında çevrim süresi hesabı üretim planlaması, üretim optimizasyonu ve verimlilik hesaplama gibi bir çok alanda doğrudan veya dolayılı olarak kullanılan önemli bir kavramdır.
Bu yazımda .NET ve C# ile bir sinyalin iki ölçümü arasında geçen süreyi ölçmek için kullanabileceğimiz yapıları ele alıyorum.
Panel yazılımlarında genel olarak çevrim süresi (cycle time) bilgisinin IO kartlardan veya PLC’den gelmediği durumlarda sayaç değeleri veya input değerlerindeki değişimlere göre Environment.TickCount
kullanılarak benim virtual cycle
dediğim bir çevrim süresi hesabı yapılıyor.
Çevrim Süresi Nedir?: Kabaca, bir sinyalin değerinin iki ölçümü arasında geçen süre olarak tanımlanabilir. Sinyalin ne ifade ettiğine bağlı olarak birim çevrim süresi şeklinde bir hesaplama da yapılabilir. Örneğin, sinyalimiz makinadan gelen ve üretim adedini bize bildiren bir sinyal olsun.
T1
anında sinyal değeriC1=10
ise,T2
anında da bu değerC2=20
ise birim çevrim süresi(C2-C1)/(T2-T1)
şeklinde hesaplanabilir
Ancak, Microsoft’un dokümanlarında Environment.TickCount
ile ilgili şöyle bir bilgi söz konusu
Because the value of the TickCount property value is a 32-bit signed integer, if the system runs continuously, TickCount will increment from zero to Int32.MaxValue for approximately >24.9 days, then jump to Int32.MinValue, which is a negative number, then increment back to zero during the next 24.9 days. You can work around this issue by calling the Windows >GetTickCount function, which resets to zero after approximately 49.7 days, or by calling the GetTickCount64 function.,
Bu dokümanları özetleyecek olursak Environment.TickCount
değerinin bizim açımızdan dört problemi söz konusu;
- Environment.TickCount system timer’ın çözünürlüğü ile kısıtlı bir değer sunuyor ve çözünürlük 10-16 milisaniye seviyesinde. Bunun anlamı şu, 10-16 milisaniyeden düşük çevrim sürelerini
Environment.TickCount
ile hesaplamamız mümkün değil yani çevrim sürelerini hep 0 olarak ölçeceğiz. - Yukarıdaki bilgi notunda da belirtildiği gibi
Environment.TickCount
32-bit işaretli integer tipinde. 32-bit işaretli integer tipinin özelliği gereği sistem ayağa kalktıktan 29.7 gün spnra bu değer olası en yüksek miktarına ulaşacak ve sonrasında overflow nedeni ile negatif değerlere dönecek ve 29.7 gün daha negatif değerleri bize bilgi olarak verecek ve yaklaşık 49 gün sonra da sıfırlanacaktır. Environment.TickCount
tipinin 32-bit işaretli integer değer olması nedeni ile çevrim süresi fark hesaplarımızda aşağıdaki sorunlar oluşacaktır- +/- veya -/+ geçişlerinde çok büyük veya çok küçük değerler olarak olçülecek
- Panel yazılımının çalıştığı windows paneli örneğin eğer 35 gündür ayakta ise çevrim süresi hesaplarımız negatif değerler olacaktır. Bu durumda hesap sonucunun mutlak değeri dikkate almalıyız.
- 50 gün veya üzerinde uptime’a sahip panellerde
Environment.TickCount
değerinin sıfırlanması nedeni ile hatalı çevrim süresi hesaplanabilir.
Environment.TickCount
kullanmadan çevrim süresi hesabını aşağıdaki alternatif yöntemler ile yapmayı düşünebiliriz;
-
DateTime.Now, yani sistem saatini kullanarak iki ölçüm arasındaki zaman farkını çevrim süresi olarak hesaplayabiliriz. Ancak bu yöntemde, özellikle bazı panel donanımlarımızda, sistem saati panel ayakta iken geri kalabiliyor veya bizim kontrolümüz dışında senkronize edilebiliyor. Bu durumlar çevrim sürelerini doğru hesaplamamızı da engelleyebilir.
-
.NET içindeki Timer sınıflarını kullanabiliriz. Bu kullanımda panel yazılımında ilk çalışma anında global bir Timer nesnesi oluşturup süreyi Tick eventi içinde kendimiz takip edebiliriz. Ancak bu yöntem de çok sağlıklı bir çözüm sunmuyor, çünkü .NET içindeki Timer sınıflarının Tick event’leri işletim sistemi tarafından bazı koşullarda belirlenen interval dışında fırlatılabiliyor. Bunu engellemek için interval yerine DateTime.Now ile geçen süre farkını takip etmeyi düşünebiliriz, ancak bu durumda da ilk maddede belirttiğim sorunların farkında olmamız gerekir.
-
System.Diagnostics
altında yer alanStopwatch
sınıfını ve bu sınıfın bize sunduğuElapsedMilliseconds
değerini kullanabiliriz. Stopwatch sınıfı uygulamamızın üzerinde çalıştığı sistemin timer mekanizmasını kullanıyor. Uygulamamızın üzerinde çalıştığı sistem yüksek çözünürlüklü performance counter varsa bu değeri kullanıyor, eğer sistemde yüksek çözünürlüklü performance counter yoksa system timer’ı kullanıyor. Çevrim süresi hesaplamak için Stopwatch kullanımı bu özellikleri nedeni ile en güvenilir sonucu veren yöntem olarak düşünülebilir. Bu güvenirliğin yanısıraStopwatch
üzerindekiFrequency
değerini kullanarak çevrim süresini mikrosaniye seviyesinde de takip etmemiz mümkün olabiliyor. Bahsettiğim önceki iki mekanizma ile mikrosaniye seviyesinde çevrim süresi hesabı yapılması mümkün değil.
Stopwatch ile çevrim süresi hesabı
Aşağıdaki DcasEnvironment
static class’ı Stopwatch
nesnesini enkapsüle etmektedir. Bu class ile ilk kullanım sonrası geçen süreyi takip edebiliriz.
DİKKAT:
DcasEnvironment
class’ının static constructoru bu class’a yapılacak ilk erişim öncesinde çalışacaktır.
public static class DcasEnvironment
{
private static readonly Stopwatch _watch = new Stopwatch();
private static readonly double _microSecPerTick = 1000000D / Stopwatch.Frequency;
private static bool _isStopwatchHighRes = false;
static DcasEnvironment()
{
_isStopwatchHighRes = Stopwatch.IsHighResolution;
_watch.Start();
}
public static long ElapsedMiliseconds => ElapsedMicroseconds / 1000;
public static long ElapsedMicroseconds
{
get
{
return _isStopwatchHighRes
? (long)(_watch.ElapsedTicks * _microSecPerTick)
: _watch.ElapsedMilliseconds*1000;
}
}
public static void RestartStopatch()
{
_isStopwatchHighRes = Stopwatch.IsHighResolution;
_watch.Restart();
}
}
Aşağıdaki CycleTimer
classı ise DcasEnvironment
class’ını kullanan ve Reset
ve Update
methodları ile süre ölçümü yapmamızı sağlayan yardımcı bir class olarak kullanılabilir.
public class CycleTimer
{
private long _prevMeasuredMicroseconds = DcasEnvironment.ElapsedMicroseconds;
private long _latestMeasuredMicroseconds = DcasEnvironment.ElapsedMicroseconds;
public long ElapsedMicroseconds => _latestMeasuredMicroseconds - _prevMeasuredMicroseconds;
public double ElapsedMiliseconds => ElapsedMicroseconds / 1000D;
public void Reset()
{
_prevMeasuredMicroseconds = DcasEnvironment.ElapsedMicroseconds;
_latestMeasuredMicroseconds = DcasEnvironment.ElapsedMicroseconds;
}
public void Update()
{
(_prevMeasuredMicroseconds, _latestMeasuredMicroseconds) = (_latestMeasuredMicroseconds, DcasEnvironment.ElapsedMicroseconds);
}
}
Soru/Cevap
Soru: Ali Hocam, hassas ölçümler için
GetSystemTimePreciseAsFileTime
Win32 API’ını kullanmayı tavsiye ederlerdi. Sizce mevcut senaryoda avantajı/dezavantajı nedir?Cevap: Stopwatch’ın GetTimestamp şeklinde bir methodu var. Bu method da C# (managed code) tarafında bahsettiğiniz API’yi kullanıyor diye biliyorum. Dolayısıyla mevcut senaryoda ikisi de benim bildiğim ve anladığım kadarıyla aynı şeye denk geliyor.
Soru: RTOS (Realtime Operating System) olmayan işletim sistemlerinde high resolution stopwatch ile senkronizasyon ne derece dogru?
Cevap: Realtime OS olmayan Windows gibi sistemlerde de saha verilerinin çevrim süresinin olabildiğince doğru bir şekilde ölçülmesi ihtiyacı var. Bu nedenle doğru olmasa bile bağıl olarak iki olay arasında geçen süreyi olabildiğince yüksek çözünürlükte ölçebilmek gerekiyor.
Soru: Motorun her devrini ölçsek boyle bir çözünürlüğe ihtiyaç olur mu? Bir de bu sinyalleri loglamak konusu var, log yazma süresi o frekansa erişebiliyor mu, frekans aralıklarının ortalamasını alıp loglamak gibi işlemler nasıl yapılıyor?
Cevap: Yüksek hızdaki ölçümleri High Speed Counter (HSC) destekleyen IO kartlarımız ile yapıyoruz, yani sayma işlemi kart üzerinde yapılıyor ve yazılıma gönderiliyor. İlave olarak sampling ile belirli genişlikteki bir pencerede ortalama hesaplama, kesit alma ve kesit loglama gibi işlemler yapılıyor.Yüksek hızlı sayımlarda çevrim süresi genellikle HSC’yi yöneten ve üstünde MCU (microcontroller unit) ve gerçek zamanlı saat olan kartlar tarafından hesaplanıp MES yazılımına iletiliyor.
Soru: 1 adet HSC 128 milyarı ne kadar sürede sayar?
Cevap: Kullanılan HSC sensörüne bağlı olarak desteklenen maksimum pulse değeri değişebilir. HSC sensörlerinin diğer bir özelliği de sayma işlemini yönlü yapabiliyor olmalarıdır. Örneğin, bir motora bağlı bir HSC moturun sağ/sol dönüşlerini pozitif veya negatif değerler olarak sayabilir. Bazı üretim süreçlerinde üretilen parçanın veya yapılan işin specine göre bu dönüş yönleri doğru işlem teyidi için kullanılabilir.
Bu yazıyı beğendiyseniz Twitter’da takipçilerinizle paylaşabilir veya beni Twitter’da takip edebilirsiniz.