avatar_elektro77

Adc okuma sorunum

Başlatan elektro77, 15 Eylül 2022, 11:18:49

elektro77

Ete Hocam;
Aşağıdaki kodlarda, miline pot bağlı bir motoru önce sıfır noktasına resetleyip sonrada pottan okunan adc ye göre belirli oranlarda döndürmek istiyorum. Bunu başardım. Fakat oranlar tam 100 ve 100 ün katları olarak değişmiyor.
Sorunun ne olduğuna bakabilir misiniz lütfen?
x  VAR WORD       : x=0
sayi var word     : sayi=0
symbol motor_up   =Portc.0
symbol motor_down =portc.1
symbol up_buton   =portc.6
symbol down_buton =portc.7


lcdout $FE,1 'ekranı temizlemek
pause 200
'---------------------------------------

reset:
ADCIN 0,x
       lcdout $FE,$80,#x,"    "
              if x>10 then motor_down=1
              if X=10 then motor_down=0
              if x=10 then goto basla
       goto reset

'--------------------------------------- 

basla:
ADCIN 0,x                             ' adc okumak
lcdout $FE,$80,#x,"    "              'okunan o,pot değerini ekrana yazdırmak
LCDOUT $FE,$C0,"Yukseklik %",#sayi/100,"0  "    'yükseklik açısını ekrana yazdırmak 

'---------rampa yükseltme-----------
if up_buton=1 then
   while up_buton=1:wend 
   sayi=sayi+100
   motor_up=1
endif
if sayi>1000 then 
   sayi=1000
   motor_up=0
endif
'-------rampa indirme------------
if down_buton=1 and x>30 then
   while down_buton=1:wend 
   sayi=sayi-100
   motor_down=1
endif
if sayi<20 then 
   sayi=20
   motor_down=0
endif
 

if x=sayi then 
   motor_up=0
   motor_down=0
endif   

goto basla
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

ete

#1
Sorun aşağıdaki satırlar.

if sayi<20 then
  sayi=20
  motor_down=0
endif

Yüzer artan yada eksilen bir seride 20 nin ne işi var. Sayı küçülünce otomatikman sayı 20 oluyor ve ondan sonra 120-220 diye artıyor.

Ete

elektro77

Hocam size yazdıktan bir süre sonra o hatayı buldum.
Yeni kodlar şu şekilde ama yinede bir sorun var. Bazen sapıtıyor. özellikle alt ve üst sınırlarda sapıtıyor.
DEFINE ADC_BITS        10       'A/D çevirim sonucu kaç bit olacak
DEFINE ADC_CLOCK       3        'Clock kaynağı (3=rc)
DEFINE ADC_SAMPLEUS    100        'Örnekleme zamanı mikro saniye cinsinden.
'-------------------------------------------------------------------------------

x  VAR WORD       
sayi var word
symbol motor_up   =Portc.0
symbol motor_down =portc.1
symbol up_buton   =portc.6
symbol down_buton =portc.7

sayi=0
lcdout $FE,1 'ekranı temizlemek
pause 200
'---------------------------------------

reset:
ADCIN 0,x
       lcdout $FE,$80,#x,"    "
              if x>10 then motor_down=1
              if X=10 then motor_down=0
              if x=10 then goto basla
       goto reset

'--------------------------------------- 

basla:
ADCIN 0,x                             ' adc okumak
lcdout $FE,$80,"okunan ADC :",#x,"  "              'okunan o,pot değerini ekrana yazdırmak
lcdout $FE,$90,"sayi degeri:",#sayi,"  "
LCDOUT $FE,$C0,"Yukseklik  :%",#sayi/100,"0"    'yükseklik açısını ekrana yazdırmak 

'---------rampa yükseltme-----------

if up_buton=1 then
   while up_buton=1:wend 
   sayi=sayi+100
   motor_up=1
   endif
   if x=sayi then 
   motor_up=0
   endif
   if sayi>1000 then
   x=1000
   sayi=1000 
   motor_UP=0
   endif

'-------rampa indirme------------
if down_buton=1 and x>10 then
   while down_buton=1:wend 
   sayi=sayi-100
   if sayi<1 then sayi=1 
   motor_down=1
endif
if x=sayi then 
   motor_down=0
endif   

goto basla
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

ete

Yüz'er artan eksilen bir sistemin sınırları 100 ün katları şeklinde belirlenmelidir.
Hala programında anlamsız satırlar var;
 if sayi<1 then sayi=1 gibi.
Sayı 100 den küçük ise Sayı=100 olmalı.

Ete

elektro77

#4
Hocam orayı  if sayi<1 then sayi=1 yapmazsam rampa tam sıfıra düşmüyor.
Başka bir sorun olmalı ama bulamıyorum.
Adc okuma hızı ile ilgili veya ekran yazdırma komutlarının adc okuma hızına etkisinden olabilir mi acaba.
Bu arada bu sorunlar simülasyonda oluşuyor. Gerçekte yapmıyorum devreyi Hocam. Sadece öğrenmek amaçlı.


"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

ete

Bazen dalga geçtiğini düşünüyorum.
Mesaja resim ekliyorsun çalışan bir programdan alıntı.
Programa bakıyorum bu resimdeki sonucu vermesi imkansız. Neden acaba?
Başka bir programla çalışıp buraya çalışmayacak olan kısmı koyuyorsun bunuda neden acaba diye soruyorum?

Programa bakıyorum. Ne bir LCD tanımlama komutu var. Ne bir port giriş çıkış tanımlama komutu var.
Nasıl çalışacak bu program. Hadi sadece mantığına bakayım dedim ama o resmi koyunca bunları yazmak zorunda kaldım.
Yinede verdiğin program üzerinden konuşacağım. PORTA.0 giriş pinimidir? oraya bir giriş yapmışsın.
Buton pinleri girişmidir ? belli değil tanımlama yok çünki. Nasıl oluyorda çalışıyor bu program anlamak mümkün değil.
Hepsini geçtim. Motor-Encoderi bir pot varsayıp kullanmışsın. O kullandığın bir encoder ve pot gibi çalışmaz. Çalışmayacağı için ADC den sıfırdan başka bir şeyde okuyamazsın. Ama resme bakıyorum X=10 konumunu veya X>10 konumunu görüp program oralara gelmiş nasıl acaba?
Bu konuya artık cevap yazmayacağım. Bunların mantıklı bir açıklaması vardır umarım.
Ete

elektro77

#6
Alıntı yapılan: ete - 15 Eylül 2022, 19:15:56Bazen dalga geçtiğini düşünüyorum.
Mesaja resim ekliyorsun çalışan bir programdan alıntı.
Programa bakıyorum bu resimdeki sonucu vermesi imkansız. Neden acaba?
Başka bir programla çalışıp buraya çalışmayacak olan kısmı koyuyorsun bunuda neden acaba diye soruyorum?

Programa bakıyorum. Ne bir LCD tanımlama komutu var. Ne bir port giriş çıkış tanımlama komutu var.
Nasıl çalışacak bu program. Hadi sadece mantığına bakayım dedim ama o resmi koyunca bunları yazmak zorunda kaldım.
Yinede verdiğin program üzerinden konuşacağım. PORTA.0 giriş pinimidir? oraya bir giriş yapmışsın.
Buton pinleri girişmidir ? belli değil tanımlama yok çünki. Nasıl oluyorda çalışıyor bu program anlamak mümkün değil.
Hepsini geçtim. Motor-Encoderi bir pot varsayıp kullanmışsın. O kullandığın bir encoder ve pot gibi çalışmaz. Çalışmayacağı için ADC den sıfırdan başka bir şeyde okuyamazsın. Ama resme bakıyorum X=10 konumunu veya X>10 konumunu görüp program oralara gelmiş nasıl acaba?
Bu konuya artık cevap yazmayacağım. Bunların mantıklı bir açıklaması vardır umarım.
Ete

Hocam ne haddime sizinle dalga geçmek. Size olan saygımı görebilseydiniz bütün fikirleriniz bir anda değişirdi. Bu algınızı biran önce kırmalısınız artık. Başka sitelerde benim yazılarımı okuyup bu algıya kapılmıyorsunuzdur umarım. Oralarda bambaşkayım. Arada sırada sert yönümü gösterip her zaman  Aptal olduğumu  düşünmelerine izin vermiyorum oralarda. Ama size saygım sonsuz. Dövseniz gık çıkarmam. Azarlayıcı sert sözlerine kızıp alınmadığım tek insan sizsiniz. Bunu böyle bilesiniz.
İkincisi; Asıl ben sizin neden anlayamadığınızı anlamakta çok zorlanıyor ve şaşıyorum. Programın tamamını buraya koyup yer kaplasın istemedim. Ben sizin programa şöyle bir gözatip anlayabildiğinizi veya sadece programı simule edebileceğiniz bir aracınızın olduğunu düşünerek tanımlamaları koymuyordum. Ama haklısınız ADC sorusu sorup ADC tanımlamalarıni koymamam ahmaklıktı. Ayrıca artık giriş çıkış nasıl ayarlanır, sigorta ayarları nasıl yapılır, register lara nasıl değer atanır vs. Birçok şeyi sormadan yapabilecek kadar öğrendim. Tabi siz öğrendiğimi bilmiyorsunuz. Bu nedenle hala o eski elektro77 algınızla bakıyorsunuz? Fark ediyorsanız, sizin değiminizle, programın birkaç satırını yazıp burada geri kalanını sormuyorum artık. Bitmiş ve çalışan programlar ve simülasyonlar koyup çok küçük sorunlarımı soruyorum.
Üçüncüsü program çalışıyor ve o bir encoder olamaz çünkü ayarlarında pot değerini Kohm cinsinden ayarlayabiliyorsunuz ve adc yi de çalıştırıyor. Proteusunuzun son versiyon olduğunu biliyorum ve bu servo electromechanical kütüphanesinde 10. sırada var.  Kimden ne öğreneceğimiz bazen şaşırtıyor değil mi? :)
Çalışan ama küçük sorunları olan program ve dosyalar ektedir.
Saygılarımla Hocam


"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

elektro77

Hocam yazdığım programda önereceğiniz değişiklikler nelerdir? Önerilerinizle geliştireceğim.
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

ete

Tek önerim SAYI isimli değişkenin 1 den küçük olması durumunda SAYI=1 dedğin yere aşağıdaki satırı yazman olur.
IF SAYI>1000 THEN SAYI=0
dikkat et değiştireceğin satır;
if down_buton=1 and x>10 then
	   while down_buton=1:wend 
	   sayi=sayi-100
	   if sayi<1 then sayi=1 
	   motor_down=1
	endif
kod dizisi içinde bulunuyor.
Şimdi IF SAYI>1000.. ne anlama geliyor onu açıklayayım isteren.
Down_Buton basıldıkça sayı değerinden 100 eksiltiyor. Tuşa bastıkça sayı 200 olacak sonra 100 sonra sıfır ve en sonunda sıfırın altına geçip 65435 sayısına eşitlenecek. Yani SAYI=65435 olacak bu sayı 1000 den büyükmüdür? elbette büyüktür ve bu değeri sayı değişkeninden sürekli çıkartma yapıldığı için ulaşmıştır. Bir yerde eksi konuma düşmüş oldu. O zaman sayının sıfırlanması gerekecek. İşte bu noktada IF SAYI>1000 then SAYI=0 diyerek durumu kurtarmış oluyoruz. Senin sayılarını bozan bu satır ve bu şekilde sorun düzelmiş olacak.

Ete

elektro77

#9
Ben o sayıyı x i hesapladığım gibi hesaplamıştım. Yani 1024 değeri üzerinden. Doğru ya, hatam bu imiş. Çok teşekkür ederim.
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

elektro77

#10
Yine olmadı Hocam. Sayı düzeldi ama motor 0 a indikten sonra yukarı hareket etmiyor.
if sayi>1000 then
   x=1000
   sayi=1000 
   motor_UP=0
   endif
Kod dizini içinde bulunan yukarıdaki başka bir kod dizini verdiğiniz düzeltmeyi engelliyor.
Ayrıca yazılımda 10 bit değeri ile word değeri arasında matematiksel bir uyuşmazlık oluyor. Bunu yapmanın başka bir yolu var ama kodlar çok uzayacak. Sadece 2 dizi kodla  farklı bir yolu daha var ama onda da farklı sorunlar olacak.
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

ete

Motor döndükçe pot dan akunan değer birer birer artar yada eksilirse senin kod çalışır.
Ama bak bakalım öylemi oluyor. Birdefa o pot hiç sıfıra ulaşamıyor en küçük değeri 1 de kalıyor.
İlk başlarken 511 (default değer) başlıyor.Artırmaya başladığında artışlar lineer olmuyor.
Önce bu işe çare bulman gerekir. Çaresi pot dan okunan değer için aralık kullanman başak çare yok gibi. Bu gerçek pot dan okumada da böyle olur belki bu kadar atlamalı gitmez ama birer birer artarak da gitmeyebilir.
Gerçi amacınıda net anlayabilmiş değilim. Sanki ;
- Başlangıçta ADC değeri 10'a gelsin istiyorsun.
- SOnra Up butonuna absınca %10 yükseklikle birlikte sayı değerin 100 oluyor ve adc den aokunan değerde 100 oluncaya kadar motor dönsün istiyorsun gibi geliyor bana.
Sonra tekrar butona basıp Sayı=200 yapıyorsun ve yine ADC dene okunan değeri 200 oluncaya kadar motoru çeviriyorsun.
Ama ADC den okunan değerler hiç bir zaman net 100 veya net 200 veya net 10 olamıyor maalesef.
Bunu denemen gerekirdi.

Ete

ete

Ekdeki dosyaları bir incele çalıştır bak bakalım.

Programı burada da vereceğim
#config
 __Config _HS_OSC  &  _WDT_OFF &_PWRTE_OFF &_BODEN_ON &_CP_ON &_CPD_OFF &_LVP_OFF 
#ENDCONFIG
'------------------
define OSC 8

ADCON1=%10001110

CMCON=7               'komparatör pinleri iptal hepsi giriş çıkış yapıldı.
'ADCON1=7              'ADC KANALLARI DİJİTAL YAPILDI - ADC İPTAL
OPTION_REG.7=1        'portB deki dahili PULL-UP lar iptal edildi.
 TRISA=%00000001      
 TRISB=%00000000      'Portb nin tamamı çıkış olarak ayarlandı
 TRISC=%11000000      'portc deki bazı pinler giriş olarak ayarlandı
 PORTA=0
 PORTB=0
 PORTC=0
'-------------------
DEFINE LCD_DREG		PORTB	
DEFINE LCD_DBIT		4		
DEFINE LCD_RSREG	PORTB	
DEFINE LCD_RSBIT	2	
DEFINE LCD_EREG		PORTB	
DEFINE LCD_EBIT		3		
DEFINE LCD_BITS		4	
DEFINE LCD_LINES	4
DEFINE LCD_COMMANDUS   2000     'Command delay time in us 
DEFINE LCD_DATAUS      50       'Data delay time in us
 '-------------------------------------------------------------------------------
DEFINE ADC_BITS        10       'A/D çevirim sonucu kaç bit olacak
DEFINE ADC_CLOCK       3        'Clock kaynağı (3=rc)
DEFINE ADC_SAMPLEUS    100        'Örnekleme zamanı mikro saniye cinsinden.
'-------------------------------------------------------------------------------

HAM  VAR WORD       
SAYI var word
W    VAR BYTE
symbol motor_up   =Portc.0
symbol motor_down =portc.1
symbol up_buton   =portc.6
symbol down_buton =portc.7

SAYI=0
lcdout $FE,1 'ekranı temizlemek
pause 200
'---------------------------------------

reset:
      GOSUB ADC_BAK
      GOSUB EKRAN
      if HAM>1 then motor_down=1
      WHILE HAM>1
        GOSUB ADC_BAK
        GOSUB EKRAN
        IF HAM=1 THEN 
          MOTOR_DOWN=0
          GOTO BASLA
        ENDIF  
      WEND  
      MOTOR_DOWN=0
	'--------------------------------------- 
	 
	basla:
	GOSUB ADC_BAK  
    IF HAM>10 THEN 
       MOTOR_DOWN=1:PAUSEUS 1:MOTOR_DOWN=0
       GOTO BASLA
    ENDIF                             ' adc okumak
    GOSUB EKRAN
BASLA_BIR:	 
	'---------rampa yükseltme-----------
	 
	if up_buton=1 then
	   PORTC.2=1
	   sayi=sayi+100
	   IF SAYI>1000 THEN SAYI=1000
       GOSUB EKRAN
	   GOSUB ADC_BAK
	   motor_up=1
       while HAM<SAYI 'AND HAM<SAYI         
        GOSUB ADC_BAK
        IF HAM=SAYI THEN 
          MOTOR_UP=0:GOTO CIK1
        ENDIF  
       wend 
CIK1:   MOTOR_UP=0
       GOSUB EKRAN	
       WHILE UP_BUTON=1:WEND   
     endif
     PORTC.2=0     
	 
	'-------rampa indirme------------
	if down_buton=1 and HAM>10 then
	   PORTC.3=1
	   SAYI=SAYI-100
	   if sayi>1000 then sayi=0 
       GOSUB EKRAN
	   GOSUB ADC_BAK
	   MOTOR_DOWN=1:MOTOR_UP=0
       while HAM>SAYI 
	     GOSUB ADC_BAK
	     GOSUB EKRAN 
	     IF HAM=1 AND SAYI=0 THEN CIK2
	   WEND
	   
CIK2:motor_down=0
     PORTC.3=0             
     GOSUB EKRAN  
     WHILE DOWN_BUTON=1:WEND          	   
	endif 
	
	GOTO BASLA_BIR

    ADC_BAK:
            ADCIN 0,HAM
            RETURN
  EKRAN:
'        lcdout $FE,$80,DEC3 HAM,"    "
	    lcdout $FE,$80,"okunan ADC :",DEC3 HAM,"  "              'okunan o,pot değerini ekrana yazdırmak
	    lcdout $FE,$94,"sayi degeri:",DEC3 sayi,"  "
	    LCDOUT $FE,$C0,"Yukseklik  :%",#sayi/100,"0"    'yükseklik açısını ekrana yazdırmak         
        RETURN            

Ete

elektro77

#13
Ete Hocam simülasyon kusursuz çalışıyor.Sonunda yaptınız yine yapacağınızı. Çok teşekkürler.
Bende Proteus 8.13 versiyonu olduğu için devreyi açamadım. Kodlarınızı kendi devrem üzerinde çalıştırdım. Bu nedenle anlamadığım bir iki şey oldu;
Aşağıda yazdığınız kodlarda Portc.2 ve portc.3 ü kullanmışsınız. O pinlerin lojik seviyesine göre bir şeyler gözlemlediniz herhalde. Benim devremde bu pinler kullanılmamıştı. Ama yazılımınız benim devremde çalıştı.
CIK1:   MOTOR_UP=0
       GOSUB EKRAN	
       WHILE UP_BUTON=1:WEND   
     endif
     PORTC.2=0     
	 
	'-------rampa indirme------------
	if down_buton=1 and HAM>10 then
	   PORTC.3=1
	   SAYI=SAYI-100
	   if sayi>1000 then sayi=0 
       GOSUB EKRAN
	   GOSUB ADC_BAK
	   MOTOR_DOWN=1:MOTOR_UP=0
       while HAM>SAYI 
	     GOSUB ADC_BAK
	     GOSUB EKRAN 
	     IF HAM=1 AND SAYI=0 THEN CIK2
	   WEND
	   
CIK2:motor_down=0
     PORTC.3=0             
     GOSUB EKRAN  
     WHILE DOWN_BUTON=1:WEND          	   
	endif 
	
	GOTO BASLA_BIR

Bende aşağıdaki gibi çok kısa bir yol buldum. Hem reset kodlarından kurtuldum hemde birkaç satırla aynı şeyi yaptım. Fakat motor sürekli  aşağı-yukarı hareket etme eğiliminde.   Gerçekte bu sorun çıkarabilir tabi ki. Belki çok turlu pot ile çalışa da bilir. Denemek gerekli. Ama bu kodlarda bir kenarda dursun. Bir nevi mekanik PI kontrol gibi bir şey oldu.Pot yerine denge sensörü konulsa bir şeyi dengede tutabilir. Belki başka bir şeye temel teşkil edebilir.
basla:                                              
ADCIN 0,x                                           ' adc okumak
gosub ekran  

if x!=sayi and x>sayi then 
motor_down=1
else 
motor_down=0
endif

if x!=sayi and x<sayi then 
motor_up=1
else 
motor_up=0
endif                           

'---------rampa yükseltme-----------

if up_buton=1 then
   while up_buton=1:wend 
   sayi=sayi+100
   endif

''-------rampa indirme------------
if down_buton=1 and sayi>0 then
   while down_buton=1 : wend
   sayi=sayi-100
endif


goto basla
ekran:
lcdout $FE,$80,"okunan ADC :",#x,"  "           'okunan o,pot değerini ekrana yazdırmak
lcdout $FE,$90,"sayi degeri:",#sayi,"  "
LCDOUT $FE,$C0,"Yukseklik  :%",#sayi/10,"  "   'yükseklik açısını ekrana yazdırmak
return
Birde Hocam bir şey daha sorabilir miyim?
OSC frekansına göre en hızlı adc örneklemesi almak için registerleri nasıl ayarlamalıyız?  Çünkü simülasyondaki servonun ayarlarından devirini 600 yapınca program adc yi zamanında okuyamıyor. 16f87x lerde ADCON0 registeri tam olarak ne işe yarıyor? Nasıl ayarlanıyor? Bu registerle ilgili bir kaç ayarlama ve kod denemesi yaptım ama pek birşey anladığımı söyleyemem.
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

ete

Denemelerimde programınbazı yerlerde takılı kaldığını ve tuş kabul etmediğini gördüm. Anladımki döngülerin özellikle while wend döngülerinde adc okuma değerine bağlı olarak takılıp kalıyor idi.
Bende deöngülere girişte PORTC.x pinini set edip çıkışta reset yaparak nerede takıldığını anlamaya çalışıp o pinler saysedinde takılma noktalarını buldum ve gereken düzeltmeyi yaptım. Onları kaldırabilirsin koddan artık gerekli değiller.

Bu işlemci için acquisition time 19,72us verilmiş. Bu bir ADC okumasında gerekli olan okuma zamanıdır ve minimum değerdir. Bundan daha küçük verilmemesi gerekir. Bu data sheet de yazıyor.
Dolayısıyla ;
DEFINE ADC_BITS 10     ' ADCIN resolution  (Bits)
DEFINE ADC_CLOCK 5     ' ADC clock source  (Fosc/16)
DEFINE ADC_SAMPLEUS 11 ' ADC sampling time (uSec)
komutlarında ADC sampling time 20us yapılmalıdır.
BU sana uzun gelmemeli aslında çok çok küçük bir değerdir.

Yazdığın ilave kodlar tamamen motoru kontrol etmekten uzak görünüyor. Bir limit kontrolü olmayınca doğal olarak alıp başını gider.

Ete

Powered by EzPortal