pic16f877 ile LCD'ye bar grafik basmak.

Başlatan karamastik, 20 Mart 2008, 19:12:07

karamastik

Merhaba arkadaşlar , elimde bir cep telefonu dedektörü devresi var ; bu devreden alınan sinyal LM358 yükselteci ile yükseltiliyor.
M358'in kazancı ile oynayarak çıkıştaki voltajı 5V'a yükselttim. Amacım çıkıştaki voltaj değişimini 16f877 kullanarak LCD'de bar grafik şeklinde göstermek.
Elimdeki devrede b.groundda ;yani cep telefonu aktif değilken 5V var ; telefon iletime geçtiğinde ise bu değer yaklaşık 4V'a kadar düşüyor ve bu sinyal kare dalga şeklinde .
Daha yeni yeni pic kullanıyorum;acemiyim yani.  :(
16f877 kullanıyorum ve ADC için , bu projede sanırım ters mantık uygulamak gerekli .Niye mi ?
Çünkü, zaten devre açıkken 5V var , iletimde ise 4V'a kadar düşüyor.
Yani 5/1024= 0.004882.
Bu değer bizim resolusyonumuz olacak herhalde.
Buradaki mantık şu olur  sanırım: 0.0048828125 ->5V'a karşılık gelecek , 1023 ise -> 0V 'a  karşılık gelecek. Eğer tersi olursa , barlar artmaz azalır.
Değil mi ?
Pic Basic Pro kullanıyorum ; LCD ile sorun yok ; tanıtmaya yaptım ; en kolayı zaten o  :) .
Şimdi tek sorunum , voltaj değişimine karşı LCD'ye bar bastırmak.
Yardımlarınızı bekliyorum arkadaşlar.
Bunlar da şu ana kadar yazmış olduğum kodlar :

Alıntı Yap
TRISA=%00000001
TRISB=0
TRISE=0

@ DEVICE pic16F877
@ DEVICE pic16F877, WDT_on
@ DEVICE pic16F877, PWRT_ON
@ DEVICE pic16F877, PROTECT_OFF
@ DEVICE pic16F877, HS_OSC


DEFINE LCD_DREG       PORTB
DEFINE LCD_DBIT      0
DEFINE LCD_RSREG   PORTE
DEFINE LCD_RSBIT   1
DEFINE LCD_EREG       PORTE
DEFINE LCD_EBIT      0
DEFINE LCD_RWREG    PORTE   
DEFINE LCD_RWBIT    2
DEFINE LCD_BITS      8
DEFINE LCD_LINES   2
DEFINE LCD_COMMANDUS   1000
DEFINE LCD_DATAUS      225
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 2
DEFINE ADC_SAMPLEUS 100

ADCON1=%10001110
LOW PORTE.2

LCDOUT $FE,1
PAUSE 200

Yardımlarınızı bekliyorum  :)

ete

Mademki programın bir kısmını yazmışsın gerisinide biraz yol gösterirsem yazarsın diye düşünüyorum.

Önce işin hesap kısmını halledelim.
5V ta karşılık ADC den okunabilecek en yüksek değer 1023 olacaktır.
Sende kendi tabirinle ters mantık uygulanacağı için okunan Ham ADC değerini 1024 'den çıkarman gerekecek. 4 V karşılığı yaklaşık 819 civarında bir ADC değerine karşılık gelecektir. Gerçek ADC değeri ise;
1024 - 819 =205 olacaktır.
Şimdi okunan bu değerlere karşılık ekrandaki bar ların hesaplanması ve gösterilemesini biraz inceleyelim.
2x16 karekterlik LCD de ekranda bir sırada 16 karekter yer almaktadır.
O halde bizim ADC den okuyacağımız 1023 değerine karşılık 16 bar karekteri ekrana yerleştirilebilecektir. Bu durumda (1023+1)/16=64 değerini bulmuş oluruz. O halde okuduğumuz gerçek ADC değerini 64 e bölersek ekrana kaç adet bar yerleştireceğimizi bulmuş oluruz.
Aynı örneğe devam edersek 205/64 =3 adet bara tekabül etmektedir.
Şimdi gelelim bu barları nasıl yerleştireceğiz;
Ama ondan da önce bar karekterini nasıl elde edeceğiz. Bunun için LCD nin kendi karekter hafızasında yer alan 255 karekterini kullanabiliriz. Yada kendimiz bir bar karekteri oluşturabiliriz. Belkide en iyisi budur.
Aşağıdaki bar karekteleri ben oluşturdum. Birbirinden farklı karekterler.
İçlerinden yalnızca birini kullanman gerek. Dene ve beğendiğini kullan.
LCDOUT $FE, $40, $00, $0F, $0F, $0F, $0F, $0F, $0F, $0F '
LCDOUT $FE, $40, $00, $00, $1B, $1B, $1B, $1B, $00, $00 '
LCDOUT $FE, $40, $00, $00, $00, $00, $1F, $1F, $1F, $1F '
LCDOUT $FE, $40, $00, $1F, $1F, $1F, $1F, $1F, $1F, $00 '
Bunlardanbirini programın başında bir yere yerleştir. $40 değeri bu karekterin yerleştirildiği hafıza olup sıfır'ıncı karekter olarak tanımlanmıştır. Ekrana yazdırmak için yalnızca sıfır kullanılacaktır.
Gelelim bu karekterleri ekrana yazdırmaya
Önce varsayımlarımızı belirleyelim;
Değişkenlerimiz;
-Adet (byte)
- ham (word)
- I (byte) döngü değişkeni
Formüllerimiz;
Ham değeri ADC den okunan değer olacak.
Adet=(1023-ham)/64

Ekrana yazdırma;
lcdout $fe,$c0
for I=1 to ADET
lcdout ,0
next

Şayet 255 karekterini kullanmak istersen 0 (sıfır) yerine 255 yazman yeterli olacaktır.

Hepsi bu kadar.
KolayGelsin
Ete



isimli bir değişken tanımlayalım
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

karamastik

Merhaba ete(abi)  :)
Öncelikle ilginiz için çok ama çook teşekkür ederim.
Konuyu açtığımdan bu yana , sürekli sayfayı refresh yapıyorudum ve sizin mesajınızı görünce heyecandan havalara uçtum .  :)
Bu proje benim bitirme tezimin son aşaması .
Şimdi , ilk mesajımda 5V'un 4V'a kadar düştüğünü yazmıştım.Daha net sonuç alabilmek için , tekrar ölçüm yaptım ve daha doğru yapmak istedim ve tekrar gözlemledim ve gördüm ki voltaj 3.8V'a kadar düşüyor.(çok "ve" kullandım özür )
3.8V'un karşılığı da yaklaşık 778 yapıyor.
Bunu bir kenara bırakırsam, vermiş olduğunuz formulleri ve değişkenleri tanımladım .
Vermiş olduğunuz bar karakterlerinden  
LCDOUT $FE, $40, $00, $00, $1B, $1B, $1B, $1B, $00, $00  
kullandım,geri kalan kısımları da yazdım ve  0(sıfır) yerine 255 kullandım, compile yaptım hatasızca ve pic e yazdım.
Taktım , ekranda bazen 8 tane bar , pic in beslemesini çıkartıp tekrar taktığımda bazen 5 bar gösterip durdu , hiç bir değişme olmadı .
Yazdığım tüm kod şu şekilde ; umarım sizin yazdıklarınızı yanlış yazmamışımdır. :oops:
Bu arada , devredeki sinyali PIC'ın RA0'ına giriyorum değil mi , başka bir bağlantı daha olmayacak değil mi ?
Sadece devreden aldığım 5V'u 16f877'nin 2. bacağına giriyorum.

Alıntı Yap
@ DEVICE pic16F877
@ DEVICE pic16F877, WDT_on
@ DEVICE pic16F877, PWRT_ON
@ DEVICE pic16F877, PROTECT_OFF
@ DEVICE pic16F877, HS_OSC

TRISB=0
TRISE=0
PORTA=1  

LCDOUT $FE, $40, $00, $00, $1B, $1B, $1B, $1B, $00, $00  

adet var byte
ham var word
I var byte


DEFINE LCD_DREG           PORTB
DEFINE LCD_DBIT          0
DEFINE LCD_RSREG       PORTE
DEFINE LCD_RSBIT        1
DEFINE LCD_EREG           PORTE
DEFINE LCD_EBIT           0
DEFINE LCD_RWREG        PORTE   
DEFINE LCD_RWBIT        2
DEFINE LCD_BITS          8
DEFINE LCD_LINES        2
DEFINE LCD_COMMANDUS   1000
DEFINE LCD_DATAUS      225
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 2
DEFINE ADC_SAMPLEUS 100
ADCON1=%10001110

LOW PORTE.2

LCDOUT $FE,1
PAUSE 200

ADCIN 0,ham
Adet=(1023-ham)/64
lcdout $fe,2
for I=1 to adet
lcdout ,255
next  

END

ete

Programda tek hata ki oda pek hata sayılmaz, kristal ayarını HS yapmışsın. Devre 4 MHz de çalışacak ve oraya XT yazman gerek.
Onun dışında önemli sayılabilecek bir şey göremedim. Zaten ekranda bar görmen devrenin çalıştığını gösteriyor. Neyin değiştiğini göreceksin pek anlamadım. Şartlar değişmemiş ise barlar da değişmeyecektir.
SOrun varsa senin devre çıkışında araman gerek.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

karamastik

Merhaba , kullandığım PIC 20 MHz ; o yüzden HS kullandım.
Cep telefonu kapalı iken , ekranda bar görülmemeli  ve cep telefonu iletimde olduğu zaman ; yani voltaj 5V'tan 3.8V'a düşüp çıktığı zaman LCD'de de barların artıp azalmasını görmeliyim.
Acaba ben mi yanlış anlattım projemi .   :oops:  
Teşekkürler.

karamastik

Üstadım acaba bağlantımda mı bir sorun var , çünkü dediğiniz gibi mantığımız doğru .
Daha önce pratik yapmak için adımı soyadımı LCD'ye bastırmıştım ve bunu yaparken LCD'nin 5. bacağı (sanırım Enable bacağı) PIC'ın 10. bacağına (RE2'ye) bağlı idi ve yazdığım program içinde (öğrendiğim kadarı ile LCD'ye yazmak için E portunun low yapılması gerekiyormuş)
LOW PORTE.2 komutunu kullandım.
Eğer alakasız şeyler söylüyorsam , cahilliğime verin lütfen; bu programda da LCD'nin E bacağı yine PIC'in 10.bacağına bağlı ve yine LOW PORTE.2 komutunu kullandım.
Kullanmış olduğum bağlantı şeması da bu şekilde :

Ayrıca 13. ve 14. bacaklar 22pF kapasitörlerle 20MHz kristale bağlı.
12. ve 31. bacaklar toprak
11. ve 32. bacaklar besleme
1. bacak 4.7k ile 5V'a ve 100 nF ile 5V'a ve toprağa bağlı.

Üstadım , bu projeye başlamadan önce , ADC' yi öğrenmek adına örnek programlara bakıyordum ; bir programda ADC işleminin öncesinde ve sonrasında bazı komutlar gördüm ; o programda ADC işleminin ekran görütüsü de aşağıdaki gibi ve bahsettiğim kodları da kırmızı içine aldım:
Aklımda olan bir şeyi daha söylemek istiyorum; acaba bar yerine I harfi yani çizgi çizgi bastıramaz mıyız ? O şekilde yapınca çözünürlüğümüz daha yüksek olmaz mı acaba ?
Ben bu şekil gösterimin adı Bar grafik diye bildiğim için mesajlarımda hep bar grafik kullandım ; acaba bu dediğimin ; yani I ild bsatırmanın adı nedir ?   :roll:

Bu komutların bizimle ilgisi var mı ?
Teşekkür ederim .  :)

karamastik

Nette , lcd bar grafik ile ilgili kodlar buldum ve uyguladım :
Alıntı Yap
@ DEVICE pic16F877
@ DEVICE pic16F877, WDT_on
@ DEVICE pic16F877, PWRT_ON
@ DEVICE pic16F877, PROTECT_OFF
@ DEVICE pic16F877, HS_OSC

TRISA=%00000001
TRISB=0
TRISE=0
INCLUDE "LCDbar_INC.bas"



LCDOUT $FE, $40, $00, $1F, $1F, $1F, $1F, $1F, $1F, $00

adet var byte
ham var word
I var byte


DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 0
DEFINE LCD_RSREG PORTE
DEFINE LCD_RSBIT 1
DEFINE LCD_EREG PORTE
DEFINE LCD_EBIT 0
DEFINE LCD_RWREG PORTE
DEFINE LCD_RWBIT 2
DEFINE LCD_BITS 8
DEFINE LCD_LINES 2
DEFINE LCD_COMMANDUS 1000
DEFINE LCD_DATAUS 225
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 2
DEFINE ADC_SAMPLEUS 100

ADCON1=%10001110
LOW PORTE.2

LCDOUT $FE,1
PAUSE 200


Loop1:
   ADCIN  0, ham
   LCDOUT $FE,2,"Value = ",DEC ham,"   "
   ; syntax- BARgraph   Value, Row, Col, Width, Range, Style
   @         BARgraph  _ham,   2,   0,    16,   255,  lines
   
Goto Loop1



END

bar için gerkli olan LCDbar_INC.bas dosyasının içeriği şu şekilde :
Alıntı Yap
                                              ;                        default
BAR_width   VAR  BYTE : BAR_width = 16         ; Width of the BARgraph      16
BAR_range   VAR  WORD : BAR_range = 100        ; Range of Values (0-100)   100
BAR_row     VAR  BYTE : BAR_row = 1            ; Row location (1-4)          1
BAR_col     VAR  BYTE : BAR_col = 0            ; Column location (0-15)      0
BAR_value   VAR  WORD : BAR_value = 0          ; Current BAR value           0
BAR_style   VAR  BYTE : BAR_style = 1          ; 1=lines, 2=boxed, 3=blocks  1

; --- Temporary vars ----
BARtemp     VAR  WORD
Remainder   VAR  WORD
BARloop     VAR  BYTE
LastCharset VAR  BYTE : LastCharset = 0
Limit1      VAR  WORD

GOTO overBAR                                   ; Skip over Subroutines

ThreeBARS CON 0                                ; Identify the Custom Characters
TwoBARS   CON 1
OneBAR    CON 2

ASM
lines  = 0x10000001                            ; Define the Styles
boxed  = 0x10000002
blocks = 0x10000003
ENDASM

; --- lines Style custom chars ----
CharsetLines:
   LCDOut $FE,$40,REP $15\8                  ; Custom char 0 - 3 lines  |||
   LCDOut $FE,$48,REP $14\8                  ; Custom char 1 - 2 lines  ||
   LCDOut $FE,$50,REP $10\8                  ; Custom char 2 - 1 line   |
RETURN

; --- boxed Style custom chars ----
CharsetBoxed:
   LCDOut $FE,$40,$1F,REP $15\6,$1F          ; III
   LCDOut $FE,$48,$1C,REP $14\6,$1C          ; II
   LCDOut $FE,$50,REP $10\8                  ; I
RETURN

; --- blocks Style custom chars ----
CharsetBlocks:
   LCDOut $FE,$40,REP $1F\8
   LCDOut $FE,$48,REP $1C\8
   LCDOut $FE,$50,REP $10\8
RETURN

; ----- Show the BAR graph -----------------------------------------------------
ShowBAR:
   IF BAR_width = 0 then BARdone
   if LastCharset <> BAR_style then          ; If the Style has changed ?
       LastCharset = BAR_style
       SELECT CASE BAR_style                 ; Load the new custom chars
           CASE 1 : GOSUB CharsetLines
           CASE 2 : GOSUB CharsetBoxed
           CASE 3 : GOSUB CharsetBlocks
       END SELECT
   endif
   
@ ifdef LCD4X20    
   LOOKUP BAR_row,[$80,$80,$C0,$94,$D4],BARtemp
@ else
   LOOKUP BAR_row,[$80,$80,$C0,$90,$D0],BARtemp
@ endif    
   LCDOUT $FE, BARtemp + BAR_col             ; Move cursor to start of the BAR
   BARtemp = BAR_value * BAR_width           ; calc the char position
   BARtemp = DIV32 BAR_range
   Remainder = R2

   For BARloop = 0 to BAR_width -1
       SELECT CASE BARtemp
           CASE IS > BARloop
               LCDOUT ThreeBARS              ; send 3 bars    |||
           CASE IS < BARloop
               LCDOUT " "                    ; clear to end of BARwidth
           CASE IS = BARloop
               Limit1 = BAR_range * 6
               Limit1 = DIV32 10
               if Remainder >= Limit1 then
                   LCDOUT TwoBARS            ; send 2 bars    ||
               else
                   Limit1 = BAR_range * 3
                   Limit1 = DIV32 10
                   if Remainder >= Limit1 then    ; 30%
                       LCDOUT OneBAR         ; send 1 bar     |
                   else
                       LCDOUT " "            ; no bars
                   endif                
               endif
       END SELECT
   NEXT BARloop
BARdone:
RETURN

ASM
; --- The main macro for creating BARgraphs ------------------------------------
BARgraph  macro  Value, Row, Col, Width, Range, Style
   MOVE?CW    Range, _BAR_range              ; Range MUST be a constant
   MOVE?WW    Value, _BAR_value              ; Value MUST be a WORD variable
   if (Row < 5)                              ; Row is a constant
       MOVE?CB    Row,   _BAR_row
   else                                      ; Row is a variable
       MOVE?BB    Row,   _BAR_row          
   endif
   if (Col < 16)                             ; Is Col a constant ?
       MOVE?CB    Col,   _BAR_col
   else                                      ; NO, it's a variable
       MOVE?BB    Col,   _BAR_col                                    
   endif
   if (Width <= 40)
       MOVE?CB    Width, _BAR_width
   else
       MOVE?BB    Width, _BAR_width
   endif
   if ((Style >= lines) & (Style <= blocks)) ; Is Style a valid constant ?
       MOVE?CB    Style, _BAR_style
   else                                      ; NO, treat it like a variable
       MOVE?BB    Style, _BAR_style
   endif
   L?CALL   _ShowBAR
   endm
   
ENDASM

overBAR:

Bu şekilde yaptığım zaman Value'nun yani ( ham değerinin ) değiştini görüyorum ama değişim çook çookk hızlı ; o kadar hızlı ki karakterlerin ekrana basılmasıyla sönmesi bir oluyor.
Cep telefonu kapalı iken barlar değişmiyor , telefon aktif iken barlar değişiyor ama çok hızlı olduğu için hiç bir şey anlayamıyorum

Sonuçta çalışan kodda şu şekilde bir çıktı elde ediliyor :

ama benim LCD'de hem "Value" yazısı sürekli değişiyor hem de barlar çok hızlı yanıp sönüyor ve bir şey anlaşılmıyor.
Unutmadan buradaki sadece örnek ;yani üst satırda yazan value değeri benim için önemli değil , benim sadece bu şekilde bar bastırmam gerek.

ipek

karamastik gsm telefonda uyarı alıyorum dediğini algıladım bunu nereden alıyorsun şemada devre çıkışı dediğin A0 portu analog tanımlanmış
uyarı aldıgın noktaya devreni unut şase ile çıkış diye tanımladığın noktaya dijital ölçü aleti ile bak gsm telefon aktif olduğu zaman 0....5 volt arasında bir gerilim varmı eğer sharper comparator gibi yani mutlat 0volt ve 5 volt arasında (bir nevi schimith trigger) gibi davranıyor ise barlar araları okumayıp 0 volt'ta bar yok 5 volt'ta full bar olacaktır bu noktayı kontrol edin yada önerim devrenizi bitirene kadar analog porta sadece gerilimi istediğiniz gibi ayarlayabileceginiz bir potansiyometre bağlayın...
not ...>Gsm telefonlar QAM modulasyon ile çalışırlar mikrofona ses yüklemezseniz rf çıkışı okunamayacak kadar azalır..

karamastik

İlginiz için teşekkür ederim.
Babamın sağlık sorunu sebebiyle bu hafta projemle ilgilenemeyeceğim, okuldan da projeye arama vermek için izin aldım.
Tekrar teşekkür ederim, görüşmek üzere ...

karamastik

Tekrar merhaba herkese,
bana halââ yardım etmek isterseniz , yardımlarınızı bekliyorum.
En son kodumu şu şekilde düzenledim

Alıntı Yap
@ DEVICE pic16F877
@ DEVICE pic16F877, WDT_on
@ DEVICE pic16F877, PWRT_ON
@ DEVICE pic16F877, PROTECT_OFF
@ DEVICE pic16F877, HS_OSC

TRISB=0
TRISE=0
PORTA=1

LCDOUT $FE, $40, $00, $00, $1B, $1B, $1B, $1B, $00, $00

adet var byte
ham var word
I var byte
toplam var WORD

DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 0
DEFINE LCD_RSREG PORTE
DEFINE LCD_RSBIT 1
DEFINE LCD_EREG PORTE
DEFINE LCD_EBIT 0
DEFINE LCD_RWREG PORTE
DEFINE LCD_RWBIT 2
DEFINE LCD_BITS 8
DEFINE LCD_LINES 2
DEFINE LCD_COMMANDUS 1000
DEFINE LCD_DATAUS 225
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 2
DEFINE ADC_SAMPLEUS 100
ADCON1=%10001110

LOW PORTE.2

LCDOUT $FE,1
PAUSE 200

FOR I=1 to 50
ADCIN 0,ham
TOPLAM=TOPLAM+HAM
PAUSE 5
next
HAM=TOPLAM/50
Adet=(1023-ham)/64
lcdout $fe,2,"ham=",dec4 HAM," adet=",#adet," "
lcdout $fe,$c0
for I=1 to ADET
lcdout ,0
next


END

Bu kodla LCD'de ilk satırda ham değeri ( 0-1023) ve bar sayısı ( adet ) nı görebiliyorum ; ama ADC analog değeri okumuyor.Yani sadece PIC'i resetlediğim zaman kafasına göre ekranda 1023 için adet = 0 ve ya 0 için adet = 15 olarak gözüküyor.Bu işlemi ben manuel olarak yaptırmış oluyorum sanırım.

Daha önce uyguladığım kod , analog değeri okuyabiliyordu,yani PIC'ın PORTA0'ına trimpod ile girip , direnci değiştirdiğimde değişen değeri görebiliyordum,daha önce denediğim kod aşağıda :

Alıntı Yap
@ DEVICE pic16F877
@ DEVICE pic16F877, WDT_on
@ DEVICE pic16F877, PWRT_ON
@ DEVICE pic16F877, PROTECT_OFF
@ DEVICE pic16F877, HS_OSC

TRISA=%00000001
TRISB=0
TRISE=0
INCLUDE "LCDbar_INC.bas"



LCDOUT $FE, $40, $00, $1F, $1F, $1F, $1F, $1F, $1F, $00

adet var byte
ham var word
I var byte


DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 0
DEFINE LCD_RSREG PORTE
DEFINE LCD_RSBIT 1
DEFINE LCD_EREG PORTE
DEFINE LCD_EBIT 0
DEFINE LCD_RWREG PORTE
DEFINE LCD_RWBIT 2
DEFINE LCD_BITS 8
DEFINE LCD_LINES 2
DEFINE LCD_COMMANDUS 1000
DEFINE LCD_DATAUS 225
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 2
DEFINE ADC_SAMPLEUS 100

ADCON1=%10001110
LOW PORTE.2

LCDOUT $FE,1
PAUSE 200


Loop1:
ADCIN 0, ham
LCDOUT $FE,2,"Value = ",DEC ham," "
; syntax- BARgraph Value, Row, Col, Width, Range, Style
@ BARgraph _ham, 2, 0, 16, 255, lines

Goto Loop1



END
Sanırım bu iki kodu düzenleyip birleştirebilirsem , sonuca ulaşabileceğim.