c# da hasas zamanlama sorunu

Başlatan cemilkendir, 07 Nisan 2012, 23:24:46

cemilkendir

selam arkadaşlar
c# ile bir proje yapıyorum kısaca izah edersek projeyi şu şekilde
saniyede bir seri porttan gelen dataların ortalamasını kullanıcının girdiği zaman boyunca alıp txt dosyaya yazdırmak bu işlemleri yapıyorum güzel bir şekilde
şimdi sorun şu ben zamanı timerlar ile saydırıyorum örneğin kullanıcı 10Sn de bir kayıt yapsın dedi ozaman timer 10 defa ticklediği zaman kayıt işlemini yapıyorum ancak datalarda periyodik bir şekilde kayma gerçekleşiyor şöyleki aşağıdaki datalar 10 snde bir kayıt olacak şekilde ayarlandı ama sizinde gördüğünüz gibi belli bir kayıttan sonra 1sn kayıyor

bu bilgilerin ışığında bana tam olarak nasıl 1sn lik periyodlarla sayma yapabileceğim konusunda yardımcı olacak bir fikir bir öneri bekliyorum sizlerden

15:40:38 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:40:48 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:40:58 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:41:08 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:41:18 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:41:28 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:41:38 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:41:49 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:41:59 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:42:09 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:42:19 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:42:29 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:42:39 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:42:49 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:43:00 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:43:10 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:43:20 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:43:30 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:43:40 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:43:50 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:44:00 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
15:44:11 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
17:06:27 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
17:06:37 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
17:06:48 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
17:06:58 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
17:07:08 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
17:07:18 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
17:07:28 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
17:07:38 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
17:07:48 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh
17:07:58 27-03-12 | Ort: 10,4 °C, Min: 10,4 °C, Max: 10,4 °C | Ort: 64,5 rh, Min: 64,5 rh, Max: 64,5 rh


teşekkürler...

kralsam

Timer saydırdığın döngüde bir döngü fazla yada eksik saydırıyor olabilirmisin?
örn: 10 döngü için for(int i=0;i<10;i++) yerine for(int i=0;i<=10;i++) gibi..

Yaygın yapılan yanlışlar. Basit ama gözden kaçabiliyor.

cemilkendir

yok orada bir sorun yok verdiğim datalarda mesela 8 defa tam 10 sn bir kayıt almış ama 9. kayıttan sonra 1sn atmış yani her kaydı 1 sn ileriye atmıyor belli bir kayıttan sonra 1 sn ileriye atıyor

EMG81

Kaymasının sebebi kralsam ın dediği gibi de olabilir de bence sorun seri port işlemi yaptığından oluyor. Yani an geliyor ki, atıyorum 4.85 sn de seri port işleme başlıyor ve işini 5.2 de bitiyor. bak 1 sn kaydı işte.

Bence saniyeyi sürekli oku(sn de 100 kere ). Kullanıcının belirlediği rakamlara böl. Mesela 10 sn de 1 işlem yapmak istiyorsun. 0,10,20,30,40 ve 50 de işlemini yap. Böylece timer ın RTC gibi çalışmasını beklememiş olursun. Böylelikle hata oluşması daha da aza indirgenmiş olur.

kralsam

Birde periyot verildiğinde uygun bir şekilde timerın initial değerini değiştirip dene. Bu sayede işlemci gereksiz yere o metoda girmeyecek ve diğer işlemlerle ilgilenmiş olacak. Bu kullanım daha doğru olur sanırım.
O da olmazsa sistem saatini alıp timer ile değilde direk saat üzerinde işlem yapabilirsin.

cemilkendir

#5
Alıntı yapılan: EMG81 - 07 Nisan 2012, 23:53:47
Kaymasının sebebi kralsam ın dediği gibi de olabilir de bence sorun seri port işlemi yaptığından oluyor. Yani an geliyor ki, atıyorum 4.85 sn de seri port işleme başlıyor ve işini 5.2 de bitiyor. bak 1 sn kaydı işte.

Bence saniyeyi sürekli oku(sn de 100 kere ). Kullanıcının belirlediği rakamlara böl. Mesela 10 sn de 1 işlem yapmak istiyorsun. 0,10,20,30,40 ve 50 de işlemini yap. Böylece timer ın RTC gibi çalışmasını beklememiş olursun. Böylelikle hata oluşması daha da aza indirgenmiş olur.

bunu denedim timerı 10ms de bir çalışacak şekilde kurdum öyle yapınca sonuç daha iyi oldu tabi ama bu seferde 8 datada değilde 80 datada kayma olmaya başladı
birde kullanıcı istediği değeri girebilir sn cinsinden yani 123 sn de yazabilir 33 sn de

seri porttan gelen datayı datarecived fonksiyonu ile otomatik okutuyorum
Alıntı yapılan: kralsam - 07 Nisan 2012, 23:55:47
Birde periyot verildiğinde uygun bir şekilde timerın initial değerini değiştirip dene. Bu sayede işlemci gereksiz yere o metoda girmeyecek ve diğer işlemlerle ilgilenmiş olacak. Bu kullanım daha doğru olur sanırım.
O da olmazsa sistem saatini alıp timer ile değilde direk saat üzerinde işlem yapabilirsin.
bunu tam anlamadım biraz daha ayrıntı verirmisin

EMG81

60 sn den yukarı işlemler yapıcaksan dk yı da işleme almalısın. Sistemini tam olarak anlamadım. Tam olarak ne yapıyor, ne ediyorsun kafamda canlandıramadım ama sn de 100 kere belirlenen bir zamanı bekleyen timer ın hata yapma oranı 0 a yakındır.(olağan üstü birşeyler olması lazım) Benim dediğim gibi de hata yaptığını düşünüyorsan sanırım farklı şeylerden bahsediyoruz.

kralsam

#7
Öncelikle "interval" yazacakken initial yazmışım onu düzelteyim.

Başlamışken de biraz açayım.  t diye bir Timer nesnesi tanımladığımızı düşün.
int periyot = 0;
Timer t;
.
.
periyot = ...; //saniye..
.
t = new Timer();
t.Interval = p*1000;
t.Enabled = True;
...
gibi..

Seri porttan pic ile RTC kullanarak analog saat uygulaması yapmıştım. Belki fikir verebilir.
http://www.mafgom.com/c-ile-analog-saat-pic16f877a-ve-pcf8583-rtc-kullanarak/

@Düzenleme:
Sistem saati içinde ilk şu linki gördüm.

http://blog.burakkutbay.com/sistem-saatini-alma-c-sharp-console-uygulamasi.html/

muhittin_kaplan

zor bir yöntem. hem seri port hem timer.
ben olsam nasıl yazardım
seri porttan gelen bilgiyi devamlı kayderdim ama sistem zamanınıda kayıt alanlarına ekleyerek.
yani datarecived olayında hem seri portdan gelen bilgileri hemde sistem zamanını (hatta systemtick i bile olabilir yada time interval ve date interval) kaydederdim.

cemilkendir

Alıntı yapılan: muhittin_kaplan - 08 Nisan 2012, 00:29:05
zor bir yöntem. hem seri port hem timer.
ben olsam nasıl yazardım
seri porttan gelen bilgiyi devamlı kayderdim ama sistem zamanınıda kayıt alanlarına ekleyerek.
yani datarecived olayında hem seri portdan gelen bilgileri hemde sistem zamanını (hatta systemtick i bile olabilir yada time interval ve date interval) kaydederdim.

bu şekildede yapmaya çalıştım sonuçda data gönderen sistem 1sn lik peryodlarla data gönderiyor. bende dedimki 10snde bir kayıt alacaksam eğer ,10 tane data gelince verileri saatle birlikde dosyaya yaz, ancak sonradan korktum dedim ya cihazın saati tam doğru değilse, geri yada ileri kalıyorsa . yani bilgisayarın saati daha güvenilir gelmişti ,ama olmadı beceremedim  :(


cemilkendir

ben aslında c# programcısı değilim yani pc için hiç program yazmamıştım
bilgisayar aynı anda oluşan threadları (kesmeleri) yada kesme içinde kesmeleri işleyemiyormu
program,datarecived içerisindi iken , timer olayı gerçekleşince aynı anda ona bakamıyormu

muhittin_kaplan

dediğim yöntemle fark etmez.
yapacağın şudur.
gelen dataları nezaman geldiğiyle beraber kaydedeceksin.
sonrasında kullanıcı hangi zaman aralığını istediyse -zaman aralığına bakıp- onları getireceksin. sonrası hesap kitap ortalama vs. (kayıt için text değilde sql çalışabilen bir sistem yaparsan iyi olur. XML ve dataset ile güzel olur yada access, sqlserver)

muhittin_kaplan

Alıntı yapılan: cemilkendir - 08 Nisan 2012, 00:43:14
ben aslında c# programcısı değilim yani pc için hiç program yazmamıştım
bilgisayar aynı anda oluşan threadları (kesmeleri) yada kesme içinde kesmeleri işleyemiyormu
program,datarecived içerisindi iken , timer olayı gerçekleşince aynı anda ona bakamıyormu
bakar, multitread ı araştır. zaten seri porttan aldığın bilgiyi işleyebilmek için crosstread hatasını bertaraf etmen gerek.  ama bence gerek yok

cemilkendir

Alıntı yapılan: EMG81 - 07 Nisan 2012, 23:53:47
Kaymasının sebebi kralsam ın dediği gibi de olabilir de bence sorun seri port işlemi yaptığından oluyor. Yani an geliyor ki, atıyorum 4.85 sn de seri port işleme başlıyor ve işini 5.2 de bitiyor. bak 1 sn kaydı işte.

Bence saniyeyi sürekli oku(sn de 100 kere ). Kullanıcının belirlediği rakamlara böl. Mesela 10 sn de 1 işlem yapmak istiyorsun. 0,10,20,30,40 ve 50 de işlemini yap. Böylece timer ın RTC gibi çalışmasını beklememiş olursun. Böylelikle hata oluşması daha da aza indirgenmiş olur.
sanırım hata burada oluşuyor datarecivedda ki kodlar biraz uzun sanırsam ve birde readline(); kullanıyorum datanın tamamının gelmesini bekliyorum budas yaklaşık 20ms sürüyor

programı güncelleyip takrar yazıcam arkadaşlar sağolun

kralsam

Alıntı yapılan: cemilkendir - 08 Nisan 2012, 00:51:29
sanırım hata burada oluşuyor datarecivedda ki kodlar biraz uzun sanırsam ve birde readline(); kullanıyorum datanın tamamının gelmesini bekliyorum budas yaklaşık 20ms sürüyor

programı güncelleyip takrar yazıcam arkadaşlar sağolun

Yanlış yapıyormuşsun. Seriport kısmında sadece veri yada arkadaşın dediği gibi zaman+veri alman lazım. O kısımda başka işlem ile meşgul etme CPU yu.