adc voltaj sorunu

Başlatan yunus417, 04 Temmuz 2020, 20:13:08

yunus417

arkadaşlar merhaba. pic16f887 ile adc sorunu yaşıyorum.proton ide kullanıyorum. yazdığım kod isiste çalışıyor. resimdeki devreye yüklüyorum adcin 0 ın ham değeri 65472 den başlıyor. oysa sadece 1 volt veriyorum. voltajı düşürüp yükseltmem farketmiyor bi türlü okutamadım. yardımcı olur musunuz

Device = 16F887
@CONFIG_REQ
@__CONFIG _CONFIG1, HS_OSC & WDT_OFF & MCLRE_ON & PWRTE_ON & DEBUG_OFF & LVP_OFF & FCMEN_OFF & IESO_OFF & BOR_SBODEN & CPD_ON & CP_ON

Xtal = 20

Declare PortB_Pullups = On 

TRISA = %11111111	    	' PORTA giriş olarak tanımla
TRISB = %11111111   	' PORTB giriş olarak tanımla
TRISC = %00000000		' PORTC nin tüm bitlerini çıkış olarak ayarla
TRISD = %00000000		' PORTD nin tüm bitlerini çıkış olarak ayarla
TRISE = %111		    ' PORTE nin tüm bitlerini giriş olarak ayarla

Declare 	LCD_DTPin = PORTD.4	
Declare 	LCD_RSPin = PORTD.2
Declare 	LCD_ENPin = PORTD.1
Declare 	LCD_Interface = 4	' 4-bit Interface
Declare 	LCD_Lines = 2         
Declare 	LCD_Type = 0

ADCON1 =%00000000     		  ' PORTA ve PORTE digital girişler aktif.
OPTION_REG = %00000000        ' PORTB PULLUP AKTİF 



Dim ham       As Word
Dim ham2 As Word
Dim ham3 As Word
'****************** Değişken ilk değerleri **********
ham=0

basla:
Cls

bas:


ADCIN 0,ham
Print At 1,1," ham=",#ham, 
DelayMS 200


GoTo basla




MB_77

#1
bu mesaj tarafımdan silinmiştir.

ete

Kod da eksiklikler var. SIrası ile şunlar;
1. Adcon1 registerine %10000000 değerini vermelisin. Böylece okma değerin sağa yaslı olarak 0-1023 aralığında olur.

2. Ansel registerine %00000001 değerini vererek kanal-0 ın analog olacağını belirlersin. Aksi taktirde TrisA registerinde 1 olarak belirtilen bu pin normal giriş pini olarak değerlendirilir.
Bütün A portunu giriş yapmışsın ama sadece 1 girişi analog kullanmışsın o yüzden Ansel registerine 1 değerini verdim. Başka analog girişler var ise onların Ansel karşılıklarıda 1 olmalıdır.

3. Adcon0 registerine %10000000 değerini vererek Fosc/32 seçeneğini ADC çevirim Clolck değeri olarak seçmiş olursunki bu değer 20Mhz OSC frekansı için doğru değer olacaktır.

4. Diğer giriş pinleri şayet analog giriş olarak kullanılmayacak ise ANSELH=0  'B portu Analog pinler iptal şeklinde değer vermelisin.

5. CM1CON0=0 'C1 Komparatör iptal ve CM2CON0=0 'C2 Komparatör iptal  değerlerini vererek komparatörleri kapatmalısın

6. Pullup ları aktive etmek için WPUB registeri ilgili bitlerine 1 değerini vermelisin. Protonda belkide bu işi  "Declare PortB_Pullups = On " komutu yapıyordur yapıyor ise WPUB registerine dokunmasan daha iyi olur.

7. Bu işlemcide ADC okumasındaki örnekleme zamanı 5us dir. Normalde bu süreyi biz basic de;
DEFINE ADC_BITS 10     ' ADCIN resolution  (Bits)
DEFINE ADC_CLOCK 2     ' ADC clock source  (Fosc/32)
DEFINE ADC_SAMPLEUS 5 ' ADC sampling time (uSec)
şeklinde üç adet define satırı ile veriyoruz. Protonda aynı satırları sanırım Declare komutu ile vermen gerekir diye düşünüyorum.

Hepsi bu kadar bu eksiklikleri ilave edersen program doğru okuma yapacaktır.

Ete

Gadget

#3
Merhabalar Selamlar,
Arkadaşlar 16F887 ile çalışıyorum, garip bir problem yaşıyorum bir türlü çözemedim. PBP ve Microcode kullanıyorum. Sorunum ADC referans voltajı ile. Referans voltajını "internal" olarak kullanamıyorum, aslında AN2 ve AN3 pinlerini analog giriş olarak kullanamadım. İlk beş Analog girişten herhangi birisine 10K'lık Pot bağlayıp okuma yaptığımda çok kısa bir aralıkta 0-255 değeri görüyorum. Tahminim referans voltajı 0,6V tanımlanmış gibi.
Yazdığım kodlar kısacası şöyle,

   
 DEFINE OSC 20
    DEFINE HSER_RCSTA 90h
    DEFINE HSER_TXSTA 24h 
    DEFINE HSER_BAUD 115200
    DEFINE HSER_CLROERR 1
    
    DEFINE SER2_BITS 8
    DEFINE SER2_ ODD 1
    
DEFINE ADC_BITS 10     ' ADCIN resolution  (Bits)
DEFINE ADC_CLOCK 2     ' ADC clock source  (Fosc/32)
DEFINE ADC_SAMPLEUS 5 ' ADC sampling time (uSec)

OSCCON      =  %01110100

OPTION_REG  =  %00000000

INTCON      =  %00000000

CM1CON0    =  0

CM2CON0    =  0

CM2CON1    =  0

VRCON      =  %00000000  '

ADCON1      =  %00000000  '

ADCON0      =  %10000000

ANSEL      =  %00011111

ANSELH      =  %00000000


TRISA  =  %00101111      ' 
TRISB  =  %11111111      ' 
TRISC  =  %11000000      '
TRISD  =  %00000000      '
TRISE  =  %00000000      '

PORTA  =  0
PORTB  =  0
PORTC  =  0
PORTD  =  0
PORTE  =  0

PAUSE 1000

PT      VAR BYTE
PT      = 0

BASA:

    ADCON0  = %00010001
    ADCIN 4, PT
    ADCON0  = %00000000
    HSEROUT ["n10.val=",DEC PT,STR SON]

    Pause 100



GOTO BASA

END

ete

Programda eksik ve kusurlar var çalışmaması normal.
Sırası ile açıklayayım.

1. Herhangi bir Sigorta satırı yer almıyor programda. Dahili OSC ilemi çalışıyor harici OSC ilemi çalışıyor belli değil. Buna rağmen Define OSC ayarı 20 verilmiş bu standart harici OSC değeridir. Ama buun yanında OSCCON registerine, OSCCON=%01110100 değeri verilerek OSC frekansının dahili 8 Mhz olması hedeflenmiş. Burada çelişki var.

Mademki bu işlemcide dahili 8Mhz lik bir OSC var. O halde şimdilik bu işlemciyi 8Mhz lik dahili OSC ile çalıştıralım. Önce buna uygun sigorta ayarlarını ardından OSC frekansını ve OSCCON değerlerini verelim.
@ __config _CONFIG1, _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF & _DEBUG_OFF
@ __config _CONFIG2,_WRT_OFF & _BOR21V
DEFINE OSC 8
OSCCON=%01110001 'dahili osc 8Mhz e ayarlandı  %0 XXX 11 00 8MHZ=111, 4mHZ=110,
Ardından ADC ayarlarına bakalım.

2. Programda ADC için öncelikli Define komutlarını vermek gerekiyor. Bunları vermişsin. Ancak 8 Mhz OSC frekansına göre yeniden vereyim. Ayrıca ADC nin tam olarak ayarlanabilmesi için ADCON0 ve ADCON1 registerlerinide bunlara ekleyelim. ADC yi şimdilik 10 bit çalıştıralım gerekirse sonra sen 8 bite çevirirsin.
DEFINE ADC_BITS 10     ' ADCIN resolution  (Bits)
DEFINE ADC_CLOCK 2     ' ADC clock source  (Fosc/32)
DEFINE ADC_SAMPLEUS 5 ' ADC sampling time (uSec)
ADCON0=%10000000
ADCON1=%10000000

Şimdi de ADC pinlerini ayarlayalım.
Bu ayarların doğru onları geçiyorum.
Gelelim ADC okuma işine,

3. Programda kullandığın mantık doğru değil. Doğru olmayan satırlar şunlar.
    ADCON0  = %00010001
    ADCIN 4, PT
    ADCON0  = %00000000
Yarı ASM yarı Basic şeklinde bir kod şekli bu. Basic Okuma işini otomatik yaptığı için doğru komut şekli şu,
ADCIN AN_Kanal, Değişken
AN_Kanal parametresi okunadak adc kanalını ifade ediyor. AN0-AN1-AN2-AN3... şeklinde gidiyor kanal isimleri. Ancak bu parametre pin adı ile belirtilir. Yada Symbol tanımlarsın onu belirtirsin. Yazında AN2 ve AN^den ADC okumaya çalıştığını yazmışsın ama kod da AN4 kanalı yer alıyor.
Değişken okuma bit sayısına göre ayarlanmalı. 8 bit için Byte değişkeni olabileceği gibi 10 bitlik okumalar için Word değişkeni olmalı. Şimdi 10 bit okuyacağımıza göre PT değişkenini WORD cinsinden ayarlamak gerekir. PT VAR WORD şeklinde tanımlamanı değiştir.
AN2 kanalını okumak için ADCIN 2,PT  komut satırını kullanabilirsin. AN3 kanalını okumak için ise ADCIN 3,PT şeklinde kullanman yeterlidir.
Okuma işleminde ADCON0 registerini kullanman gerekmiyor. Üstelik bu registerin değerini bozmuş olacağın için sakıncalıda. Yapmak istediğini anlıyorum. ADC işlemini başlatmak istiyorsun. Bunun için ADCON.0 registerine önce 1 veriyorsun sonra okuma yapıp aynı register bitine 0 vermek istiyorsun. Basic bunu otomatik yaptığı için hiç gerek yok bunlara.

Anlatacaklarım bu kadar. Son olarak ADC işlemini nasıl 8 bit yapacaksın onuda anlatayım.
DEFINE ADC_BITS 10     ' ADCIN resolution  (Bits) satırındaki 10 sayısını 8 yapacaksın.
DEFINE ADC_BITS  8     ' ADCIN resolution  (Bits) şeklinde.
PT değişkenini BYTE cinsinden tanımlayacaksın o kadar.

Bir şey daha ekleyeyim.
Şayet bu programı 20Mhz harici (Kristal) OSC ile çalıştırmak istersen, Sİgorta ayarların aşağıdaki gibi olmalı.

@ __config _CONFIG1, _HS_OSC & _WDT_ON & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF & _DEBUG_OFF
@ __config _CONFIG2,_WRT_OFF & _BOR21V

Define OSC satırın DEEFINE OSC 20 şeklinde olmalı, OSCCON satırını kaldırmalısın bu dahili OSC ile alakalıdır.
Başkada bir değişiklik gerekmiyor. Ancak bu durumda işlemciye harici bir kristal yada rezonatör bağlaman gerekecek bunu unutma.

Ete










alisumer

hocama ek olarak  " HSEROUT ["n10.val=",DEC PT,STR SON]" kodundan anladığım kadarı ile analog veriyi nextion a gönderiyorsun bu kodu nextion kabul etmiyor başına yada sonuna üç adet hex ff koyup göndermelisin yani kodun " HSEROUT ["n10.val=",DEC PT,STR SON,$FF,$FF,$FF]" bu
Hep meraktan

alisumer

DEFINE OSC 20
    DEFINE HSER_RCSTA 90h
    DEFINE HSER_TXSTA 24h 
    DEFINE HSER_BAUD 115200
    DEFINE HSER_CLROERR 1
bu osc ve baud  değeri için spbrg değeri girmemişsin o tanımlama da gerekiyor ki yanlış hesaplamadıysam DEFINE HSER_SPBRG 9 olmalı işlemcinin bilgi kitapçığında hesaplama için formül var yanlış hatırlıyor olabilirim genede bir bak sen
Hep meraktan

Gadget

Merhabalar tekrardan teşekkürler,
Sevgili ETE ve alisumer, sırayla gideyim,
Ete hocam kusura bakmayın sigorta ayarlarını kopyala yapıştır yapmamışım, onlarda söyleydi programımda,

@  __CONFIG    _CONFIG1, _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_ON & _CP_ON & _MCLRE_ON & _PWRTE_OFF & _WDT_OFF & _HS_OSC
@  __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V

    Include "modedefs.bas"

OSCCON satırınıda kapatacaktım notmalde kapalı, oralarda birşeyler denerken unutmuşum.

Sayın alisumer, nextion'da problemim yok, programda byte tanımlamalarında şu ekli, 3 adet $FF yazmaya üşendim

SON     VAR BYTE[3]
SON[0]  = $FF
SON[1]  = $FF
SON[2]  = $FF

HSEROUT ["n10.val=",DEC PT,STR SON]

Yazdıklarınızı tekrardan programımda düzeltip deniyorum, teşekkürler



alisumer

#8
sanırım problemin hala çözülmedi yeni sorunlar bulalım ff komutlarını hex formatında göndermeyi dene , 2 analog okumaya bölme oranı "100 ns" ye  tanımlamışsın ama çok hızlı o örnekleme  hızını uygun frekansa göre tekrar ayarla 20 mhz için adcon0 :b'0110 0000 (3,2 us) mesela bilgi kitapçığında bi tablo olması lazım ilgili registerlerin resmini atayım sana hatta ,tüm bu okumaları düzgün yapsan bile spbrg değeri hala girilmemiş bu da seri haberleşmenin yanlış veriler göndermesine yol açar hız tutarsızlığ ayrıca ASM de analog okuma sonrası adcon0 go-done bitini kontrol ederiz okuma bitmişmi diye bitmiş ise değişkene atama yaparız protonda nasıl otomatikmi bilmiyorum o kontrol ama biraz zaman tanıman iyi olur genede okuma emri sonrasında pic e

Hep meraktan

Gadget

Merhabalar Tekrardan,
Atölyeye gidecek pek vaktim olmadı bu aralar anca deneyebildim, ADC okuma ve LCD ye seri porttan yazdırma ile ilgili bir problemim kalmadı demek isterdim ama, şimdi daha ilginç bir problemim var. Daha önceleride başıma geldi ama AN2 ve AN3 pinlerini dışarıdan referans voltaj girişi olarak kullanmıştım.
Şimdi öncelikle ADCON1 registerinde bulunan VCFG1 ve VCFG0 bitlerini VSS ve VDD olarak ayarladığımda AN3 ve AN2 bacaklarında sabit 5 volt görüyorum. Pic i değiştirdim yine olmadı.
Fakat VCFG1 ve VCFG0 bitlerini -Vref pin ve +Vref pin seçtiğimde ADC okuma yapabiliyorum, sadece Analog voltaj sabit olmasına rağmen yaklaşık 5-6 değer oynama yapıyor sürekli.
Güç aldığım yer LM2596.   
Aynı program düzenini 18F4550 de kullandığımda problem yaşamıyorum.

Gadget

ADC okumada yaşadığım değer değişimi sorununu çözdüm, direk 5V güç kaynağı kullandım. Normalde 24 Volttan LM2596 yardımı ile 5 Volt'a gerilimi düşürüyordum.

alisumer

problemi çözdüğüne sevindim konuyu uzatmak istemem ama rc kumanda çalışmalarımdan çıkardığım birkaç sonucu paylaşmak isterim ADC bacaklarından boşta iken voltaj okumak normaldir bozuk olduğu anlamına gelmez devreyi bir pot yada direnç ile çalıştırdığınızda okuma yaptığını görürsünüz,çok pürüzsüz okuma yapmak istediğinizde ortalama almak çok işe yarar(ETE  taktiği) örneğin bir servo sürerken istenmeyen titreşimleri engeller ki bu titreşimler adc nin iyi okumadığından kaynaklı değildir devre üzerindeki parazitleri dahi okuduğundan kaynaklanıyor olabilir sonuçta 0-5 volt arasını 1024 parçaya bölüp okuyor ki (0,0048828125 v ) ediyor buda devreye üflesen havadaki nem miktarının değişiminden ham değerin değişmesine yol açacak kadar çok hassasiyet demek ek bilgi olarak basicte 8 bit 10 bit okuma seçeneği olması adcnin 8 bit okuduğu anlamına gelmiyor o gene 10 bit okuma yapıyor basic uygun değere çekmek için yazılımsal 8 bit e çeviriyor değeri başarılar
Hep meraktan

Powered by EzPortal