ADC hızlımı çalışıyor ?

Başlatan onurinci, 01 Temmuz 2017, 00:06:44

onurinci

hocam aynı devreyi yıllar önce 16F877 ile yapmıştım güzelde çalışmıştı,16F88 uyarladım yine çalıştı fakat ekranın sol üst köşesindeki rakamlar hiç stabil değil ,örnek 38 göstersin ,ararada 39 kırpışıp duruyor F88' adc'sinde okuma hızı gibi bir farkmı var acaba ?

' PICBASIC PRO program to measure voltage (0-5VDC)
' and display on LCD with 2 decimal places. A
' 60 segment bargraph is also displayed using
' custom LCD characters.

' This program uses the */ operator to scale the
' ADC result from 0-1023 to 0-500.  The */ performs
' a divide by 256 automatically, allowing math which
' would normally exceed the limit of a word variable.

@ DEVICE pic16F88, WDT_OFF, PWRT_ON, PROTECT_OFF, LVP_OFF, BOD_OFF, MCLR_OFF, FCMEN_OFF
@ DEVICE pic16F88, IESO_OFF, CCPMX_OFF, DEBUG_OFF, WRT_OFF, CPD_OFF, INTRC_OSC_NOCLKOUT
DEFINE OSC 4
OSCCON= %01101110       ' 4 MHz internal Clock

TRISA= %11111111 : PORTA= 0   ' Set PORTA to all input
ADCON1= %10000010  ' Set PORTA analog and right justify result
TRISB= %00000000 : PORTB= 0   ' Set PORTB to all Output
CMCON= 7

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 ADC_BITS     10    ' Set number of bits in result
Define ADC_CLOCK    3     ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50    ' Set sampling time in uS





' Declare variables
adval  VAR WORD ' Create adval to store result
fullbars VAR BYTE ' Number of full bars at left of graph
barval VAR BYTE ' Value passed to bargraph routine
partbar VAR BYTE ' ASCII code for partial bar character
pad VAR BYTE ' Number of spaces to pad to the right of graph


       
        Pause 500        ' Wait .5 second
       
' Load the custom characters to LCD CGRAM. The blank at $0 makes the graphing math work faster.
       
    LCDOut $FE,64,REP $0\8 ' Load blank character (ascii $0)
    LCDOut $0,REP $10\6,$0 ' Load | character (ascii $1)
    LCDOut $0,REP $14\6,$0 ' Load || character (ascii $2)
    LCDOut $0,REP $15\6,$0 ' Load ||| character (ascii $3)
   
    LCDOut $FE, 1 ' Clear the display


mainloop: ADCIN 0, adval ' Read channel 0 to adval (0-1023)


adval = (adval */ 512)>>2 ' equates to: (adval * 500)/1024

        LCDOut $FE,2,DEC (adval/100), DEC2 adval," =PF Tuning C" ' Display the decimal value      "Load Cap= PF "
       
        barval = (adval/9)+1 ' Scale 0-500 to 60 segment bargraph (1-56)
       
        GoSub bargraph ' Update bargraph with new barval
       
       
   IF adval >500 And adval <512 THEN
  LCDOUT $FE,$C0," High Limits    "
  PAUSE 500 : PORTB.0=1
ENDIF

   IF adval >011 And adval <499 THEN
;  LCDOUT $FE,$C0," High Limits    "
  PORTB.0=0
ENDIF
 

    IF adval >000 And adval <010 THEN
   
  LCDOUT $FE,$C0," Low   Limits   "
   PAUSE 500 : PORTB.0=1
ENDIF
 
        GoTo mainloop        ' Do it forever


bargraph:

  fullbars = (barval MIN 60)/3 ' Calculate number of full bars (|||).
 
' partbar holds the ascii code for the partial bar character: $0=" ", $1="|", or $2="||"

  partbar = (barval MIN 60) // 3 ' Calculate ascii code for partial bar character
 
  pad = 19 - fullbars ' Number of spaces to fill display width.
 
LCDOut $fe,$c0, REP $3\fullbars, partbar, REP " "\pad ' Display the bar on second line

Return

        End

dnaci

Örnekleme zamanı için 50 değeri verilmiş. Adc ölçümü için pic içindeki kondansatörün şarj süresini bu değer belirliyor. Bu değeri 100 yapıp denermisiniz.

ete

#2
Pic işlemcilerde örnekleme zamanı 4 us ile 20 us arasında değişmektedir. Bu ise bahsettiğiniz görsel effekti yaratmaktan uzak bir süre anlamına gelir. Genelleme yaparsak adc okuması hızlıdır. Diğer taraftan okuma hızlılığının yanı sıra yeterli örnekleme zamanı vermezseniz de ADC okuması benzer hızlı değişim özelliğini gösterebilir. Daha iyi anlamak için sistemi yavaşlattığımızı düşünelim. Önce ADC sistemi nasıl çalışıyor ona bakalım. İçeride bir kondansatör var. Bu kondansatör örnekleme zamanı kadar şarj ediliyor. Sonra ADC pinine bağlı elemanlar üzerinden deşarj ediliyor. Bu esnada deşarj süreside ölçülüyor ve bu süre ADC nin digital karşılığı  olarak bize veriliyor.
Diyelimki örnekleme zaman (şarj süresi 20us ve biz sadece 10us şarj ettik. Bu durumda doğru okuma yapılamayacağını anlamanız gerekir. Zira kondansatör tam şarj edilmemiş ise boşalmasıda çabuk olacaktır. Sonuçta doğru adc değeri alamayacaksınız demektir.
Bu nedenle her işlemcinin data sheet'ine bakıp "acquistation time" değerini  DEFINE ADC_SAMPLEUS xx tanımlamasında xx yerine yazmak gerekir. Küsüratları tama, tamamlamak en doğrusu olur. Kimisinde 4,7us gibi bir değer verilir bunu 5us olarak kullanmak gerekir.
Bu süreyi fazla fazla kullanmak az kullanmaktan daha iyidir.  20us olan bir değeri 100us olarak kullanmak zorun yaratmaz ama 10us olarak kullanmak sorun yaratabilir.
Unutmayın ADC okuması hiç bir zaman çok stabil şekilde çalışmaz. Yani aynı noktada 10 defa üst üste yaptığınız okumaların tamamı aynı değeri vermeyebilir. Bu nedenle bazı düzeltme tekniklerine başvurmak gerekebilir. Bunları sıralayacak olursak;
1. Ortalama Almak: üst üste en azından 20-30 okuma yapılmalı sonra bunlar toplanarak okuma sayısına bölünmelidir.
10 bitlik ADC okumalarında  maksimum 63 okumayı toplayabilir ve sonra ortalamasını alabilirsiniz. Ben genellikle 30-40 civarı okuma yapıp ortalama alıyorum.
2. Diğer bir yöntem hem ortalama alıp hemde sıralama algoritması kullanmak. Bu sistemde ortalaması alınmış okumaları toplamda 20-30 adede çıkartıp her birini bir dizi değişkenine yerleştirerek sonra küçükten büyüğe doğru bunları sıralamak ve işin karekterine göre ya ortadan belirli adedi alıp tekrar ortalamasını almak yada ortadan tek bir değer almak gibi yöntemler gerçekten çok stabil sonuçlar vermektedir.
3. Benim uyguladığım bir sistem de farklı bir mantık da kullanıyorum. ADC okuması yapıp ortalamasını aldıktan sonra üst üste 3 defa aynı okumayı yapmadan yeni okumayı okunmuş değer olarak kullanmıyorum. Buda bana stabil sonuçlar veriyor.
Bu biraz karmaşık yöntem örnekle açıklamak daha iyi olur sanırım.
1. ADC den 980 okuduk diyelim.
2. Bir sonraki okuma 981 ise öncekini değiştirmiyorum
3. Bir sonraki okuma yine 980 ise tekrar okuyorum bir sonraki yine 980 ise birdaha okuyorum ve yeni okuma 980 ise bu okunan yeni değerdir diyorum. Kısaca her okunan değer en azından üst üste 3 defa okunmalı bunu 2 defa ya da indirebilirsiniz.

Ete


onurinci

hocam mükemmelsiniz çok ayrıntılı ve izah edici olmuş....

@Dnaci teşekkür ederim..

dnaci

Önemli değil onurinci. Ete hocam sağolsun durumu çok ayrıntılı anlatmış.

Powered by EzPortal