avatar_elektro77

12F1822 de Adc kullanımı

Başlatan elektro77, 17 Haziran 2023, 15:07:56

elektro77

Aşağıdaki kodları yapay zeka yardımı ile yazdım fakat yapay zeka da bende problemi bulamadık.
12f1822 ile bir bataryanın seviyesini ölçmek ve bu seviyeye göre 3 ledi yakıp söndürmek istiyorum. Ama aşağıdaki kodlarda adc ölçümü alamadım. Yanlışımın nerede olduğu konusunda yardımcı olur musunuz lütfen?
Çok ara ara kod yazmaya ihtiyacım olduğu için işin içinden hemen çıkamıyorum.
Simülasyon ve kodlar ektedir.
#CONFIG  
 __config _CONFIG1, _FOSC_INTOSC & _MCLRE_OFF & _PWRTE_ON & _WDTE_OFF & _CPD_OFF
 __config _CONFIG2, _PLLEN_OFF & _LVP_OFF & _WRT_OFF
#ENDCONFIG
DEFINE ADC_BITS 10 
DEFINE ADC_CLOCK 3
DEFINE ADC_SAMPLEUS 50

DEFINE OSC 4 

OSCCON=%01101000  '%01111000=16mHZ %01101000=4 mHZ  ,  %01110000=8 mHZ  , %01111000=16mHZ ,
CM1CON0=0   'KOMPARATÖRLER İPTAL EDİLDİ
CM1CON1=0 
ANSELA=0
WPUA=%00001000
OPTION_REG=%11000110'000=1/2, 001=1/4,  010=1/8 ,  011=1/16 , 100=1/32 ,  101=1/64 ,  110=1/128 ,  111=1/256

PORTA=0
TRISA=%00000001  
ADCON0 = %00000001
ADCON1 = %10000010  ' ADC voltaj referansı VREF+ = VDD ve VREF- = FVR olarak ayarlandı
FVRCON = %10000000  ' FVR (Voltage Reference) modülünü etkinleştir ve 4.048V seç
HAM VAR WORD
'SYMBOL BUTON=porta.3 
SYMBOL LED1=porta.1    
SYMBOL LED2=porta.2  
SYMBOL LED3=porta.4   
'SYMBOL out=porta.5 

CLEAR
pause 100

BASLA:

    ADCON0 = %10000001  ' ADC dönüşümünü başlat ve AN0 girişini ölç
    WHILE ADCON0.0 = 1 : WEND  
    ADCON0=HAM
    
IF HAM>820  THEN 
LED1=1:LED2=1:LED3=1
ENDIF

IF HAM>757 AND HAM<820  THEN
LED1=0:LED2=1:LED3=1
ENDIF 

IF HAM>737 AND HAM<757  THEN 
LED1=0:LED2=0:LED3=1
ENDIF

IF HAM<737  THEN 
LED1=0:LED2=0:LED3=0
ENDIF


'    PAUSE 100  ' 100 milisaniye bekle
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"

mehmet

#1
.
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
http://www.mehmetbilgi.net.tr

elektro77

Alıntı yapılan: mehmet - 17 Haziran 2023, 15:43:36
ANSELA = %00000001
olmalı. Analog giriş seçilmemiş.
Basic bunu kendi yapıyor mu bilmiyorum?
olmadı...
"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"

mehmet

#3
.
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
http://www.mehmetbilgi.net.tr

mehmet

#4
.
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
http://www.mehmetbilgi.net.tr

elektro77

#5
Alıntı yapılan: mehmet - 17 Haziran 2023, 18:20:39İlave olarak 45. satırdan sonra "pause 20" ilave edip deneyiniz.
Satırları çok fazla değiştirdim 45. satır falan kalmadı @mehmet ve çalıştırdım galiba...Çok teşekkür ederim...
Bir çok farklı kaynaktan ve datasheet ten faydalanarak çalışan bir program oluşturdum. Tam olarak anlamaya çalışıyorum. Bir çok kopyala yapıştır olunca tüm programı kavramak zor oluyor.
Darrel Taylor ın çok faydası oldu bu konuda.
Çalışan program aşağıdadır: Batarya tasarrufu için adc yi bir kaç döngüden sonra, döngü sonunda aktif ederek okumaya çalıştım ama ne kadar doğru ve faydalı henüz tam emin değilim.
clear : pause 10
#CONFIG  
 __config _CONFIG1, _FOSC_INTOSC & _MCLRE_OFF & _PWRTE_ON & _WDTE_OFF & _CPD_OFF
 __config _CONFIG2, _PLLEN_OFF & _LVP_OFF & _WRT_OFF
#ENDCONFIG
'-------------------------------------------------------------------------------
DEFINE ADC_BITS 10 
DEFINE ADC_CLOCK 3
DEFINE ADC_SAMPLEUS 50

DEFINE OSC 4 
'-----------------------REGISTERS-----------------------------------------------
OSCCON  = %01101000   '%01111000=16mHZ %01101000=4 mHZ  ,  %01110000=8 mHZ  , %01111000=16mHZ , (%11110000 'PLL ENABLED,8Mhz,FSOSC<2:0>)
PORTA   = %00000000  'PORTA ALL LOW
TRISA   = %00000001  'INITIALIZE PORT DIRECTIONS
ANSELA  = %00000001  'AN0 ANALOG,AN1:AN2,AN4 DIGITAL I/O
WPUA    = %00000000    'WEAK PULLUP'S OFF
INTCON  = %00000000  'CLEAR GIE,PEIE,TMR0IE,INTE,RBIE,TMR0IF,INTF,RBIF
CM1CON0 = %00000000 'CLEAR/DISABLE COMPARATOR
CM1CON1 = %00000000 'CLEAR/DISABLE COMPARATOR
OPTION_REG = %10000000 'CLEAR ALL PULL-UPS,INTEDG,T0CS,T0SE,PSA,PS
'PIE1 = %00000000   'CLEAR ALL INTERRUPT ENABLE BITS
'PIR1 = %00000000   'CLEAR ALL INTERRUPT FLAGS
'PIE2 = %00000000   'CLEAR ALL INTERRUPT ENABLE BITS
'PIR2 = %00000000   'CLEAR ALL INTERRUPT FLAGS
'APFCON = %10000100 'ENABLE USART ON PORTA.4:5
'ADCON0 = %00000000 'CHS2:0,GO/DONE,ADOFF ; %11110000 ise 'Vref -> Vdd, Frc, Sağa yaslanık ; 
'ADCON1 = %11100000 'RIGHT JUSTIFIED,FOSC/64,VSS,VDD ;(%10001011 İSE 'ADC voltaj referansı VREF+ = VDD ve VREF- = FVR olarak ayarlandı);%10110000 'ise A/D Right Justified, FRC clock
'FVRCON = %10000010 'FVR (Voltage Reference) modülünü etkinleştir ve 4.096V seç ; (%00000000 İSE'DISABLE FIXED VOLTAGE REFERENCE )
'SRCON0 = %00000000
'SRCON1 = %00000000
'CMOUT = %00000000   'DISABLE OUTPUT REGISTER
'DACCON0 = %00000000 'CLEAR/DISABLE D/A
'DACCON1 = %00000000 'CLEAR/DISABLE D/A
'T1CON = %00000101   'PRESCALER 1/2,START TIMER 1
'T1GCON = %00000000  'NO GATE CONTROL
'T2CON = %00000110   'POSTSCALER 1/1,START,PRESCALER 16
'TMR2 = 0            'CLEAR TMR2 MODULE REGISTER
'PR2 = 255           'SET PERIOD ((((1 / 40,000,000)*4)*16 PRESCALE)*(1+255 PR2)) = 2.44 KHZ
'CCP1CON = %00000000 'PLACE CCP1 INTO DISABLE MODE
'CCPR1L = $00        'CLEAR CCP1 LOWER 8 BITS
'CCPR1H = $00        'CLEAR CCP1 UPPER 2 BITS
'--------------------------------------------------------------------------------
HAM VAR WORD
SAY VAR BYTE
'SYMBOL BUTON=porta.3 
SYMBOL LED1=porta.1    
SYMBOL LED2=porta.2  
SYMBOL LED3=porta.4   
'SYMBOL out=porta.5 

CLEAR
pause 100

'-------------------------ANA DONGU---------------------------------------------
DO:
SAY=SAY+1
IF SAY = 10 THEN 'BATARYADAN TASARRUF SAĞLAMAK İÇİN 10 SAYMADA BİR ADC OKUR
SAY=0
GOSUB ADC_OKU
GOSUB LED_YAK    'Yine bataryadan tasarruf için 10 döngüde bir ledler yakılıp söndürülür. Gerçekteki 'led parlaklık ve görünürlüğüne bakılacak
LED1=0:LED2=0:LED3=0
ENDIF

LOOP
'-------------------------------------------------------------------------------
ADC_OKU:
    ADCON1 = %10110000       ; A/D Right Justified, FRC clock
    FVRCON = %10000001       ; Enable Fixed Voltage Reference (1.024V)
    'WHILE !FVRCON.6 : WEND   ; Wait for fixed ref to be stable
    ADCIN 0, HAM             ; Read the FVR channel
    FVRCON = 0               ; Disable Fixed Voltage Reference
RETURN 
'-------------------------------------------------------------------------------  
LED_YAK:
IF HAM>820  THEN 
LED1=1:LED2=1:LED3=1
ENDIF

IF HAM>757 AND HAM<820  THEN
LED1=0:LED2=1:LED3=1
ENDIF 

IF HAM>737 AND HAM<757  THEN 
LED1=0:LED2=0:LED3=1
ENDIF

IF HAM<737  THEN 
LED1=0:LED2=0:LED3=0
ENDIF

RETURN
"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"

mehmet

#6
.
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
http://www.mehmetbilgi.net.tr

ete

FVR aktive edilmeden çalışıyor.
Dahili ref voltajını seçebilmek için önce modül aktive edilmeli
FVRCON = %10000010  bu komut FVR yi aktif ediyor ve ref voltajını 2,048V olarak ayarlıyor.
Bir alt kademe 1,024V da seçilebilir ancak çok küçük seçmek de bana göre sakıncalı. 2,048V en uygunu bana kalırsa.
Daha sonra ADCON1 registerinde ref voltajı olarak FVR seçilmeli. ADCON1 registerinin 0-1 bitleri bu seçimi yaptırıyor. Bu iki biti %11 verirseniz sistem FVR ile çalışacaktır.
Sonuçta programın başına yada başlarda bir yere;
ADCON1 = %10010011 
FVRCON = %10000010 
satırları eklenmelidir.
Bu komutları ADC okuma kısmına vermek de yanlış Bir kere verilecek register ayarıdır ve programın başlarında bir yere yerleştirilmeleri daha doğrudur.
Sonrasında 4,2V luk gerilimin ADC girişine maksimum 2,048V olarak gelmesini sağlayacak bir gerilim bölücü ayarlamak gerekiyor. Bunuda yaparsın artık.

Ete

mehmet

#8
.
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
http://www.mehmetbilgi.net.tr

elektro77

@ete Hocam:
Bataryayı şarja takınca bir yükselme eğilimine giriyor. Bu yükselme eğilimini pice algılatıp şarj göstergesi olarak ledlerin sıra ile yanıp sönmesini sağlamak istiyorum.
Bataryadaki bu yükselme eğilimini pic e nasıl bir algoritma ile algılatabiliriz? Boşta pinim olsaydı şarj çıkışından bir dirençle pic e girecektim ama yok.
"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

Batarya voltajını ölçüyorsun nasıl olsa sürekli olarak ölçtüğünü kayda al ve bir önceki ölçüm ile yeni ölçümü karşılaştır. Böylece yükselme eğilimini görebilirsin. Yükseliyor ise tabiiki. Zaten başkada bir yolu yok sanırım.
Ete

elektro77

#11
Alıntı yapılan: ete - 20 Haziran 2023, 16:03:38Batarya voltajını ölçüyorsun nasıl olsa sürekli olarak ölçtüğünü kayda al ve bir önceki ölçüm ile yeni ölçümü karşılaştır. Böylece yükselme eğilimini görebilirsin. Yükseliyor ise tabiiki. Zaten başkada bir yolu yok sanırım.
Ete
Buna örnek bir algoritma gösterebilir misiniz Hocam rica etsem. Karşılaştırma algoritması...
Yükseliyor hocam. Takribi her 5 sn de bir 0.01Volt bir yükselme var.
"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

#12
Şu anda örnek gönderecek durumda değilim. Ancak telefondan takip edebiliyorum siteyi. Bayramdan sonra yaparım.

Düşündüm de çok da zor olmasa gerek bbu işi yapmak.
ADCIN 0,HAM        'Adc kanalı oku
IF HAM=ESKI THEN RETURN  'önceki okunan ile yeni okunan aynı ise bir şeye bakmaya gerek yok geri dön 
IF HAM>ESKI THEN GOSUB ARTIS_VARA_GIT' farklı ise ve yani okunan eski okunandan büyük ise artışvar'a git

ESKI=HAM                 'Yeni okunanı eski olarak kabul et.
RETURN   'geri dön
bu şekilde olabilir sanırım.
Ete

elektro77

Alıntı yapılan: ete - 20 Haziran 2023, 20:33:03Şu anda örnek gönderecek durumda değilim. Ancak telefondan takip edebiliyorum siteyi. Bayramdan sonra yaparım.

Düşündüm de çok da zor olmasa gerek bbu işi yapmak.
ADCIN 0,HAM        'Adc kanalı oku
IF HAM=ESKI THEN RETURN  'önceki okunan ile yeni okunan aynı ise bir şeye bakmaya gerek yok geri dön 
IF HAM>ESKI THEN GOSUB ARTIS_VARA_GIT' farklı ise ve yani okunan eski okunandan büyük ise artışvar'a git

ESKI=HAM                 'Yeni okunanı eski olarak kabul et.
RETURN   'geri dön
bu şekilde olabilir sanırım.
Ete
Hocam kodlar çalıştı ama şarja takmasam bile sürekli "artış var" ve "ana program" arasında gidip geliyor. Bu döngüden çıkamıyor. Yorumunuz nedir?
"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

Üst üste yapılan iki ölçüm genellikle efak tefek artışlar veya azalışlarla yapılır. ADC ye giriş voltajı değişmese bile bir ölçüm xxx şeklinde ikincisi xxx+1 bir sonraki yine xxx bir sonraki xxx-1 şeklinde olabiliyor. Bu işe yabancılar histerisiz meselesi diyorlar. Kısaca koda bir histerisiz yani bir aralık verilmeli. Örnek olarak şunu söyleyebilirim. Artış 5 denbüyük ise artış kabul et değilse dokunma demek iyi bir fikir olabilir. Şöyle yapmak problemi çözer sanırım;

IF (HAM>ESKI-5) AND HAM<ESKI+5) THEN RETURN  '5 Birimlik+- histerisiz vermiş olduk. Gerekirse 5 yerine 2-3 birim denenebilir.

	IF HAM>ESKI THEN GOSUB ARTIS_VARA_GIT' Otomatikman bu komut histerisizden büyük artış olursa çalışacaktır.
	 

Ete

Powered by EzPortal