Ynt: adc deki değeri 10 bit lik array e ekleme

Başlatan xcyqp09k2, 22 Haziran 2015, 04:43:56

xcyqp09k2

arkadaşlar adin0 komutuyla aldığım 1024 lük dğeri nasıl 10 bitlik x[10] arrayına eklerim ?

şöyle yaptım ama proton hata veriyor.

Dim y As Byte
Dim x[10] As Byte 
                                                        
ANSEL.4 = 0
ANSEL.5 = 0                                
BASLA:                          

y = ADIn 0

x[10] = Dec y 
                   
SerOut PORTC.1, 16468, ["XYZ", Str x\10]


mesaj birleştirme:: 22 Haziran 2015, 19:00:24


tamam arkadaşlar sanırım hallettim. şöyle bişey yaptım. ama fikri olan varsa paylaşsın lütfen. amacım Pic16F684 ler ile adc ölçümü yapıp serout ile gönderip serin ile almak ve pwm üretmek. pwm üretirken de hpwm veya pwm komutlarını kullanmadım. datasheeti detaylı okuyarak pr2 timer2 registerlerini girerek pwm ürettim. CCPR1L , CCP1CON.5 ve CCP1CON.4 registerleri pwm nin duty değerini tutuyor.

proteusta güzel bir pwm elde ettim yarın sabah boardda da denerim.




VERİCİ:

Device = 16F684                         
Xtal 20                                
Include "MODEDEFS.bas"                   
                            
Declare Adin_Res 10
Declare Adin_Tad FRC
Declare Adin_Stime 200
                                   
TRISA=0                       
TRISC=0 

TRISA.0 = 1
TRISA.3 = 1
TRISC.1 = 0

PORTA=0                             
PORTC=0
                              
PR2 = 0xFF 

ADCON0.7 = 0
ADCON0.6 = 0
ADCON0.5 = 0
ADCON0.4 = 0
ADCON0.3 = 0
ADCON0.2 = 0
ADCON0.0 = 1

ANSEL.0 = 1

ADCON1.5 = 1
ADCON1.4 = 1

Dim y As Word
                                
Dim x[10] As Byte                               
                                 
ANSEL.4 = 0
ANSEL.5 = 0                                
BASLA:                          

y = (ADIn 0)/64

x.0 = y.0
x.1 = y.1
x.2 = y.2
x.3 = y.3
x.4 = y.4
x.5 = y.5
x.6 = y.6
x.7 = y.7
x.8 = y.8
x.9 = y.9
                   
SerOut PORTC.1, 16468, ["XYZ", Str x\10]
                                
GoTo BASLA                         


ALICI:

Device = 16F684                         
Xtal 20                                
Include "MODEDEFS.bas"                   
                                                                                                  
Declare CCP1_Pin PORTC.5

TRISA=0                       
TRISC=0
TRISA.3 = 1                                     
TRISC.1 = 1                       
TRISC.5 = 0 

PR2 = 0xFF

T2CON.6 = 0
T2CON.5 = 0
T2CON.4 = 0
T2CON.3 = 0
T2CON.2 = 1
T2CON.1 = 0
T2CON.0 = 1
                                    
PORTA=0                             
PORTC=0                              

CCP1CON.7 = 0
CCP1CON.6 = 0
CCP1CON.3 = 1
CCP1CON.2 = 1
CCP1CON.1 = 0
CCP1CON.0 = 0

Dim x[10] As Byte                                                             
                                 
ANSEL.4 = 0
ANSEL.5 = 0
                                
BASLA:                          
SerIn PORTC.1, 16468, [Wait("XYZ"), Str x\10]

CCPR1L.7 = x.9
CCPR1L.6 = x.8
CCPR1L.5 = x.7
CCPR1L.4 = x.6
CCPR1L.3 = x.5
CCPR1L.2 = x.4
CCPR1L.1 = x.3
CCPR1L.0 = x.2
CCP1CON.5 = x.1
CCP1CON.4 = x.0                  
                                 
GoTo BASLA                         



Maxim

direk word olarak gönderip alamıyormuyuz datayı?
array kullanmadaki amaç nedir?

ete

Yapılmak istenilen ile yapılanlar arasında fark var. Dizi kullanılıp okunan adc değerleri 10 elemanlı bir diziye verilmek istenmiş ama yalnıcza tek okuma yapılıp X[0] elemanına okunan değer yüklenmiş. Ama karşı tarafa bu bilgi dizi şeklinde yollanmış. Tabiiki yollanırken ilk bilgi adc değeri sonraki 9 bilgi ise sıfır olarak yollanmış. Bu durumda ne gereği var dizi kullanmanın.
Üstelik alıcı tarafında da dizi olarak alınan bilginin yalnızca X(0) elemanı değerlendirilip bundan PWM sinyali elde edilmeye çalışılmış.

Diğer bir hata da Byte cinsinden olan X değişkeni sanki 10 bitlik bir değişkenmiş gibi x.8, x.9 gibi bitleri işleme sokulmuş. X değişkeninin yalnızca X.7 şeklinde biti vardır X.8 diye bir şey yoktur. Buradan anladığım kadarı ile bit ile dizi olayı bir birine girmiş. Elemanın bitleri dizi gibi değerlendirilmiş sanki.

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

xcyqp09k2

#3
peki bunu nasıl yapabilirm ? adc ile aldığım bilgiyi bir diziye aktarmak istiyorum. sonra dizi karakterlerini sırasıyla göndermek istiyorum? bunu yapmaya çalıştım.

@Maxim maksat array kullanımı. array ile yapmak istiyorum.   

@ete  tek okuma derken? amacım bir defa okuma yapıp 1024 bitlik adc değerinin binary değerini dğerlenndirip (%1010111010) her bir sayısını(bir ve sıfırlar) bir dizi elemanına aktarmak. mesela şöyle...

(1024)10 = (0000010000000000)2
(450)10 = (0000000111000010)2
(256)10 = (0000000100000000)2




burada 1024 gibi bir ölçüm değerini binray olarak ele alacağız. binary nin de sağdan  ilk 10 elemanını bir array dizisine ekleyeceğiz. daha sonra da göndereceğiz.. umarım yapmaya çalıştığım şeyi anlatabilmişimdir ...  :)

ete

Anladığım kadarı ile ADC kanalından tek bir okuma yapacaksın. Örnekle devam etmek gerekirse diyelimki 1020 okudun.
Bu binary olarak  ADC=%1111111100 şeklinde bir sayı oluyor. Sonra bunun her bir bitini  bir dizi değişkenine vereceksin ve sonra onu karşıya yollayacaksın. Yollama aşamasına kadar her şey mantıklı. Ne amaçla bunu yapıyorsun onu sormadım daha. Ama yollama işine gelince bana mantıklı gelmiyor. Zira tek bir bit karşıya yollanmaz. Daha açık ifade ile;
1111111100 şeklindeki bitleri sırası ile X(10) dizisine şöyle yerleştirdiğimizi düşünelim.
X(0)=0 , X(1)=0 , X(2)=1 , X(3)=1 , X(4)=1 , X(5)=1 , X(6)=1 , X(7)=1 , X(8)=1 , X(9)=1
Bunu karşıya yollarken word olarak yollarsan zaten bit bit aktarılır ve karşıda bu tekrra 10 bitlik değişken haline getirilir.

Serout ....[ADC ] diye yollarsan veya 2 byte halinde ADC.byte1,ADC.byte0 şeklinde yollarsan otomatikman karşıya bütün bitleri yollamış olursun.
Amacının ne olduğunu anlamadan bu işe bir anlam vermem çok zor o nedenle işin nasıl yapılacağını sana anlatayım bari,
Öncsinde DIM VAR X[10] BIT
DIM INDEX VAR BYTE
DIM Y VAR WORD
şeklinde değişkenleri tanımlıyorsun.
Sonra ,
y = ADIn 0
FOR INDEX=0 to 9
  X[INDEX]=GETBIT Y,INDEX
NEXT
şeklinde bir döngü kurarsan okunan ADC (Y) nin bitleri otomatikman X dizisine yerleştirilmiş olacaktır.
Gerisini artık ne yapmak istersen ona göre yaparsın.

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

xcyqp09k2

@ete teşekkürler hocam  8) açıklama ve ilgi alaka için.  bir projede adc okuyup uart ile gönderip almaya ve karşı tarafta da bu değerden pwm üretmeye çalışıyordum. 16F684 de uart yok. adc ve pwm özellikleri var.serin serout komutlarını kullandım fakat başarılı olamadım. kısmen başarılı oldum diyebiliriz. yukarda yazdığım kodlar proteus8.1 de çalışıyor. 1024 de % 100  ve 512 de % 50 pwm elde ediyorum yani herşey OK. yalnız boarda yükleyince kodları çalışmıyorlar bir türlü. 16f684 de uart olmamasından kaynaklanıyor diye düşündüm ve 10 bitlik veriyi tek tek göndermeye çalıştım. onu da şurdan yola çıkarak düşündüm. daha önceki bir projemde portları değişkenlere eşitleyip (yine aynı pic ile ) serin serout la karşıya değişkenleri göndermiştim. e haliyle portlar ya 1 oluyor ya da 0. yani ben karşıya 1010 gönderiyordum. 4 kanallıydı. o proje de aynı pic ile olduğundan ve yine serout komutu kullandığımdan demek ki uart olmayınca proton yardımıyla da sadece 1 ve 0 gibi bilgiler gönderilebiliyor diye düşündüm. bilmiyorum ne kadar mantıklı ne kadar doğru .. aşağıya da o eski projemi ekliyeyim.

4 kanal alıcı verici 16F684 20 mhz

VERİCİ:

Device = 16F684                      
Config FCMEN_OFF, IESO_OFF, BOD_OFF, CPD_OFF, CP_OFF, MCLRE_OFF, PWRTE_OFF, WDT_OFF,  
Xtal 20                                
                                               
Include "modedefs.bas"               
All_Digital True                     
                                                                         
TRISA=%001111                        
TRISC=%000001                          

PORTA=0                             
PORTC=0                              

Dim x As PORTA.0                      
Dim y As PORTA.1                      
Dim z As PORTA.2                     
Dim t As PORTC.0                      
                                                             
BASLA:                         

SerOut PORTC.1,396,["vvvooter",x,y,z,t]                                      
                                   
GoTo BASLA     



ALICI:

Device = 16F684     
Config FCMEN_OFF, IESO_OFF, BOD_OFF, CPD_OFF, CP_OFF, MCLRE_OFF, PWRTE_OFF, WDT_OFF, 
Xtal 20                                                 
                            
Include "modedefs.bas"               
All_Digital True                    
                                                                          
TRISA=%000000                        
TRISC=%000010                    

PORTA=0                              
PORTC=0                              

Dim x As PORTA.0                     
Dim y As PORTA.1                      
Dim z As PORTA.2                      
Dim t As PORTC.0                      
                                
BASLA:                          

SerIn PORTC.1, 396, [Wait ("vvvooter"),x,y,z,t]

x = PORTA.0                                   
y = PORTA.1
z = PORTA.2
t = PORTC.0                                  
                                   
GoTo BASLA                         

ete

Haberleşme stamdartında yollanan bilginin komutlarda byte yada word olarak yazılmasına rağmen aslında bit bazında yollandığı herkes tarafından bilinir. Yani karşı tarafa 48 rakamını gönder dediğimiz zaman bu aslında 48 in binary karşılığı olan %00110000 sayısının 0-0-0-0-1-1-0-0 şeklinde gönderileceğini gösterir. Bu nedenle senin yapmaya çalıştığın şey aslında sağ el ile sol kulağı tutmaktan başka bir şey değil.
Eski projende de VERI=PORTA & %00000111 : VERI.3=PORTC.0 demiş olsan ve peşinden

SerOut PORTC.1,396,["vvvooter",VERI] demiş olsan aynı sonucu elde edecektin. Üstelik daha az komut ve daha kısa sürede bu işi yapabilecek idin.

Yeni projende, Yapman gereken şu bana kalırsa, Öncelikle Alıcı tarafında çalışacak PWM frekansını belirlemen gerekiyor.
Verdiğin değerlere bakılırsa 4,9 Khz lik bir sinyal yada belkide 5KHz lik bir sinyal oluşturmaya çalışıyorsun. Ancak Duty değerlerin yanlış.
Diyelimki 5KHz lik bir sinyal oluşturacaksın. Bu senin frekansındır. Duty değerini başlangıçta sıfır da verebilirsin %50 de verebilirsin. Biz %50 vermeye çalışalım. Şimdi 20 Mhz de 5Khz lik bir sinyalin parametrelerine bakalım. PR2=249 olması gerekiyor. T2CON=%00000101 olması gerekiyor. Bu frekansta Duty değeri maksimum 1000 (%100 duty için ) ve min. 0 olabiliyor. %50 duty için verilecek değer ise 500 olacaktır.
Verici tarafında ADC okuması Duty değerini belirleyeceğine göre oradan okuyacağın 0-1023 arasındaki bilgiyi 0-1000 aralığına indirgememiz gerekecek. Bunun için okunan ADC değerinin maksimum değeri 1023 olacağına göre 1000/1023=0,977517 gibi bir sabit çarpan değeri bulunur. Hesabı kolaylaştırmak açısından bu değeri 256 ile çarparsak 250,24 gibi bir değer elde ederiz. Burada
y = (ADIn 0) : Y=(Y*/2503)/10 şeklinde bir formül uygularsak maksimum ADC değeri karşılığında Y=1000 olarak hesaplayabiliriz.
Şimdi bunu karşıya 2 byte olarak yollamak gerekiyor.
SerOut PORTC.1, 16468, ["XYZ", Y.HIGHBYTE , Y.LOWBYTE] şeklinde karıya yollayabilirsin.
Verici tarafındaki işimiz bitti. ADC dene okunan değer Duty değerine çevrilip 10 bit olarak karşıya yollanmış oluyor.
Şimdi alıcı tarafını organize edelim.
Programın baş tarafına önce;
PR2=249
T2CON=%00000101
CCP1CON=%00001100
GOSUB PWM_VER
değerlerini verdikten sonra önce PWM_VER isimli alt programı ayarlamak gerekecek burada gelen Duty değerine uygun PWM sinyalini oluşturmak için düzenleme yapılacaktır.
Programın alt kısımlarına şu alt programı ilave etmen gerekiyor.
PWM_VER :
X=DUTY
CCP1CON.4=X.0
CCP1CON.5=X.1
CCPR1L=X>>2
RETURN

Burada dikkat edilecek husus şu, X ve DUTY değişkenleri ikiside WORD cinsiden olmalıdır.
Bunları yaptıktan sonra şimdi bilgi alma işine bakalım.

SerIn PORTC.1, 16468, [Wait("XYZ"), DUTY.HIGHBYTE , DUTY.LOWBYTE]

şeklinde alacağız bilgiyi
Hemen altına IF DUTY>0 then GOSUB PWM_VER
şeklinde bir komut kullanarak gelen DUTY değerine göre PWM sinyalini CCP1 pininden çıkartmış olacaksın.
Hepsi bu kadar. Bu şekilde dizilerle falan uğraşmadan istediğini elde etmiş olursun.
Takıldığın yerde yeniden sorarsın.
Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

xcyqp09k2

@ete  tekrardan teşekkürler hocam ilgi alaka için. benim piclerde sorun var. basit bir program yazdım ve sonuç çalıştırmadılar. yeni picler gelince denerim buraya yazarım. proje proteusta çalışıyor çünkü.

bu arada PR2 ve diğer registerler le pwm ayarlamayı son zamanlarda hallettim gibi hocam. Daha da bakacağım. yalnız bir byte word yapılarını öğenmem hakim olmam lazım galiba. ver gönderme işlemleri yaparken x.lowbyte x high byte  ların MSB LSB(most significant bit , least significant bit) yapılarını iyice oturtmam gerek. onun dışında şu 1 sene boyunca baya yol katettim. sizin ve sitenin emeği çok büyük  :) geçen yaz başladım. hatta okul zamanını saymassak toplam 5 ay ciddi ilgilenmişimdir. şimdi sıra avr lerde  8)

OG

#8
Byte 8 bitin yerleştiği yani 8 bit derinlikli değer.

1 bit derinlikli değer;
1 Bit = x
x, 2 konum alabilir, 0 veya 1.
O zaman
1 bit = 0
veya
1 bit = 1

2 bit derinlikli değer;
2 Bit = xy

x ve y, 2 konum alabilir, 0 veya 1.
O zaman 2 bit derinlikli değer şu varyasyonları alabilir

x y
0 0
0 1
1 0
1 1

Burada x ve y aynı güçte değildir. Yani x in 1 olması ile y nin 1 olması 2 bit derinlikli sayıya aynı güçte etki etmez.

Bizim onluk sayı sisteminde de aynı yapı geçerlidir,
zq
15

z = 1 , q =5 .
q , z'den büyük görünüyor ama z nin ağırlığı daha fazla.
z'deki 1 bileşen sayının toplamına on değer etki ediyor, q'daki 1 bileşen sayıya bir değer etki ediyor.

O zaman z daha yuksek degerlikli rakam, q ise daha düşük degerlikli rakam.

Üstteki örnek 2 haneli, 5 haneli olsa idi mesela

abcdef
18459

a, diğer hepsinden daha yüksek değerlikli, f ise hepsinden daha düşük değerlikli.
Burada
a'ya MSD (Most Significant Digit)
f'ya LSD (Least Significant Digit)

denir.

Bu onlu sistem sayısı idi. 2 li sisteme dönersek Digit => Bit olacaktır. Cünkü sayı haneleri bitler ile gösterilmektedir.

8 derinlikli İkili Sayı sistemine dönersek;
Alacağı tüm varyasyonlar şu ikisinin arasındadır

00000000
.
.
11111111

En soldaki bit MSB (değer katkısı en fazla olan)
En sağdaki bit LSB (değer katkısı en az olan)

00000000
.
.
11111111

Bu değerlerin ilki
00000000 = sıfır deger içerir.

Sonu
11111111 = iki yuz elli beş deger içerir.

İşte bu 8 derinlikli ikili sayı yüküne Byte Yükü denir. 0 ila 255 arasındaki bir yuke sahip olabilir.

Bunun iki katı yani 16 derinlikli sayı yükü olsaydı alacağı varyasyonlar

0000000000000000
.
.
1111111111111111

olurdu.
Yine
0000000000000000 = sıfır deger içerir.
1111111111111111 = altmış beş bin beş yüz otuz beş  deger içerir.

Buna da Word Yükü denir. 0 ila 65535 arasındaki bir yuke sahip olabilir.

------
Sinyal aktarımlarında değeri içeren bilgide genellikle BYTE yuku (yani 8 bit) paketleri kullanılır. WORD yukunu veya daha büyük yuk değerlerini taşımamız gerektiğinde bunu BYTE parçalarına ayırırız.

Şöyle bir word yukumuz (16 bit) olsun
abcdefghijklmnop

Bunu ortadan ikiye bölersek
abcdefgh
ijklmnop

olarak 8 er bitlik 2 yük elde ederiz. Her ikisi de BYTE boyutundadır.
Ancak abcdefgh byte ı , ijklmnop byte'ından daha yüksek değerliklidir.
Bu iki yeni terim ortaya çıkar LOWBYTE veya HIGHBYTE .

abcdefghijklmnop  word değerinin
abcdefgh tarafı  HIGHBYTE parcasıdır
ijklmnop tarafı  LOWBYTE parcasıdır.

Program içinde bir word yukunu gonder dediğimizde onu 2 parcaya ayırır ve önce LOWBYTE ı gönderir sonra HIGHBYTE ı gonderir.

Program içinde bir word yukunu al dediğimizde de 2 adet byte bekler, ilk geleni o word için o word'un LOWBYTE 'ı  kabul eder, ikinci geleni o word'un HIGHBYTE 'ı  kabul eder. Gelen bu 8 bitlik iki byte değerini yerlerine koyar ve 16 bitlik word u elde eder.
FORUMU İLGİLENDİREN KONULARA ÖM İLE CEVAP VERİLMEZ.

xcyqp09k2

@OG ellerine sağlık hocam. anlatım çok iyi. şöyle bir araya gelsek de 5 - 10 kişi proton için veya pic programlama için bir el kitabı yazsak. ben bu konuda istekliyim. yardımcı da olurum. Hiç değil millet faydalansın. Çünkü işin çok püf noktası var. Öğrenene kadar ömür bitiyor. böyle 40 50 sayfalık bi pdf hazılasak işin püf noktalarını anlatsak, gerekli yerlerin mantıklarını anlatsak süper olur. bu teklifim sadece size değil OG hocam. tüm foruma. Ben yardımcı olurum yani. vakit ayırırım böyle brişey için..

OG

Anlattığım konu genel sayı sistemleri ile ilgili.

Proton öğrenmek istiyorsan Help/Documents/Manuel ler var. TR arıyorsan bunun önceki versionlarından birini çevirip kitap halinde basmışlardı.

Forum başlı başına bir toplantı yeri, oturduğun yerden yardım almak mümkün.
FORUMU İLGİLENDİREN KONULARA ÖM İLE CEVAP VERİLMEZ.