I2C protokolü kullanan ads1115 cihaz kodu

Başlatan hkalaycioglu, 09 Ocak 2019, 21:20:35

hkalaycioglu

iyi akşamlar I2C komutlarında bulunan cihaz kodunu datasheette nereden buluyoruz veya datasheetteki hangi kısım cihaz kodunu ifade ediyor. Bulamadım picbasic de  ads1115 kullanmaya çalışıyorum ufak bir şey belki ama burada takıldım.

ete

#1
Datasheet Sayfa23 de , 9.5.1.1 bölüm başlığı altında  I2C Address Selection başlığı altında açıklanmış bütün her şey.
Orada bir tablo vermişler  Table 4. ADDR Pin Connection and Corresponding Slave Address başlığı altında 4 seçenek verilmiş. Adres pini şayet GND ye bağlı ise sağındaki %10010000 adresini kullanın demişler. Aynı pin şayet VDD ye bağlı ise &10010010 şeklinde bir cihaz kodu (yada adres) kullanın demişler. Diğer ikisine pek yanaşma bence bu ikisinden birini tercih et.
Aslında Sayfa 24 de tüm detaylarıda göstermişler. Orayada bakmanı tavsiye ederim.

Ete

hkalaycioglu

teşekür ederim ete hocam sağol. Datasheet okumak konusunda zayıfım.

hkalaycioglu

#3
iyi akşamlar kodu oluşturdum fakat ads1115 den bir bilgi alamıyorum benim gözden kaçırdığım bir şey mi var acaba bir bakarmısınız. teşekkürler.
@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _LVP_OFF & _CP_OFF & _PWRTE_ON   
             
DEFINE OSC 4   
CMCON=7        


Define LCD_DREG  PORTB
Define LCD_DBIT  4
Define LCD_RSREG PORTB
Define LCD_RSBIT 0
Define LCD_EREG  PORTB
Define LCD_EBIT  1
DEFINE I2C_SCL PORTA,1     
DEFINE I2C_SDA PORTA,0     
Define I2C_HOLD 1
PORTA = %00000000  
TRISA = %00000011
PORTB=0  
TRISB=0

a   VAR BYTE    
Data var word 
Pause 100       
LCDOut $fe, 1, "I2CX"  
Pause 1000
 
mainloop:

LCDOut $fe, 1, "HASAN"

   I2cwrite I2C_SDA,I2C_SCL,$90,$01,[%1100000100000011]  ; konfigürasyon
                                     ; |||
                                     ; 100 = AIN0 
                                     ; 101 = AIN1 
                                     ; 110 = AIN2 
                                     ; 111 = AIN3 
   Pause 100               
 
    I2Cread I2C_SDA,I2C_SCL,$90,$48,Data,bogus
    pause 150
    LCDOut $fe,1,dec5 data
    pause 1000
    a =Data*0.0001869
    pause 500     
   LCDOut $fe, 1,dec2 a     
    pause 1000                                
   GoTo mainloop                        
 
bogus:
   LCDOut $fe,1, "zaman bitti"
   pause 100            
   LCDOut $fe, 1,dec2 a 
   Pause 1000
   GoTo mainloop
 
   End

ete

#4
Şimdiye kadar hiç harici ADC entegresi kullanmadım. Bu entegreninde mantığını anlamış değilim. Anlamak için çok fazla okumak ve üzerinde vakit harcamak gerekiyor. Ama en azından mantıklı bir haberleşmenin nasıl olacağına dair fikirler edindim. Birinci kural komut kontrol adresi $90 bu doğru ondan sonra adress verme zorunluluğun yok. Bu bir option ve cihazdan cihaza değişiklikler arzediyor. Ama sende gerekli değil çünki o işi adress pointer yapıyor.
Köşeli parantez içindeki ilk byte adres pointer değer olmalı. %000000xx şeklinde bir değer ve yalnızca ilk iki bit 4 farklı adresi belirlemek için kullanılıyor. 00=0 nolu adres,  01=1 nolu adres 10=2 nolu adres ve 11=3 nolu adres olmak üzere 4 faklı adrese bu sayede erişebiliyorsun (anladığım bu)
Sen Config registerine bir şey yazmak istiyorsun o halde Config adresi olan 1 nolu adres için aşağıdaki komutu yollaman gerekir.
I2cwrite I2C_SDA,I2C_SCL,$90,[%00000001,buraya 16 bitlik config değeri yazılması gerekiyor]

DATA isimli bir değişken kullanımı mümkün değildir. DATA özel bir komut kelimesidir ve değişken adı olarak kullanılamaz. Derleyici burada hata vermesi gerekirdi !!!!!!!. Vermesede sen onun yerine başka bir isim kullan. Program komutları RESERVED WORDS sınıfına girerler ve değişken adı olrak kullanılamazlar.

Okuma yaparken format yine aynı,
I2Cread I2C_SDA,I2C_SCL,$90,[okunacak registerin pointer adresi, değişken adı]
Burada değişken adı şayet okunan register 16 bitlik ise değişkende 16 bitlik tanımlanmalıdır.

Bu komut gereklimidir bilemiyorum DEFINE I2C_HOLD 1 'Pause I2C transmission while clock held low
Bence onu kaldır sorun olursa deneyeceğin alternatiflerden birisi olarak denersin gerekirse.
Data ve CLK bacakları Pullup dirençli olmalıdır.

Basic  a =Data*0.0001869 bu şekilde bir çarpmaya müsaade etmez. Basic (PBP) yalnızca tam sayılarla çalışır.
Proton Basic Float denilen değişkenler yardımı ile söz konusu olan çarpma işlemini yapabilir .
PBP da bu işlemi yapmanın yolu var elbette.
0.0001869 sayısını 10.000 ile çarparsak 1.869 sayısını elde edersin. Bunu 256 ile çarparsan 478,464 sayısını elde edersin. Bu sayıyı çarpan olarak kullanıp 32 bit işlem yaptırarak sonuca şöyle ulaşabiliriz.
478,464 sayısını 100 ile çarparak 47846 sayısını buluruz (ondalık  kısmı atıyoruz)
Bu sabit çarpan ile A=(HAM */47846)/100  formülü ile elde edilen değer sonucun 10.000 ile çarpılmış halini verecektir sana. Örnek yaparak daha iyi anlarsın. HAM (senin DATA dediğin) bilgi 15750 olsun.
A=15750 * 0,0001869=2,943675 gibi bir değer verir. Aynı sonucu bulabilecekmiyiz bakalım.
Hemen belirteyim PBP da  (Z */Y)  işlemi Z sayısının Y ile çarpılarak 256 ya bölünmüş halini verir ve çarpma büyüklüğü 32 bitdir. Bu nedenle 47846 sayısını bulurken 256 ile çarptık. Formülümüzün normal matematik ile gösterilişi şöyle
A=((15750 * 47846)/256)/100= 29436 sonucunu elde ederiz. Bunu ekranda gösterirken.
LCDOUT $FE,$80,"A=",dec A/10000,",",dec A//10000 şeklinde olur bu satırın ekrandaki gösterim hali 2,9436 şeklinde olacaktır.
A/10000 sayının 10000'e bölünmüş halini verir ondalık kısımlar atılır ve tamsayı olarak 2 yi verir.
A//10000 ise MOD alma işlemidir. A sayısının 10.000 e bölündükten sonra kalanı sana verir yani 9436 rakamını verir. Araya biz bir virgül koyarak bu sayıyı 2,9436 olarak göstermiş oluruz.

Ete

hkalaycioglu

cevap için teşekkürler sağolun ete hocam. A0 girişini GND'ye bağladığımda 31743 5 volta bağladığımda 65535 değerini alıyorum ama çok sağlıklı bir değer alamıyorum. ads1115 i resetlemekmi lazım anlamadım ama çalışmaya devam.

hkalaycioglu

#6
en sonunda devrem şimdilik bitti 4 kanaldan voltaj okuyabiliyorum. yazılımımızın son şekli budur ve çalışmaktadır. similasyon ekleyemiyorum direk olarak devre üzerinde çalıştırarak denedim.ads1115 proteus kütüphanesini bulamadım.
Bilmeyenler için Ads1115 modül girişleri 5 volt ölçebilir daha yüksek voltajları ölçmek için gerilim bölücü dirençler kullanmak gerektiğini belirteyim. İşlemci olarak 16F628 kullandım. 
   
@ __config _HS_OSC & _WDT_OFF & _MCLRE_OFF & _LVP_OFF & _CP_OFF & _PWRTE_ON & _BODEN_OFF             
DEFINE OSC 20   
CMCON=7        


Define LCD_DREG  PORTB
Define LCD_DBIT  4
Define LCD_RSREG PORTB
Define LCD_RSBIT 0
Define LCD_EREG  PORTB
Define LCD_EBIT  1
    

PORTA = %00000000  
TRISA = %00000001
PORTB=0  
TRISB=0

a VAR word
a1 VAR word
a2 VAR word
a3 VAR word
a=0
a1=0
a2=0
a3=0
ham var word
ham1 var word
ham2 var word
ham3 var word
ham=0
ham1=0
ham2=0
ham3=0
b var word
b1 var word
b2 var word
b3 var word
Pause 100       
LCDOut $fe, 1, "I2CX"  
Pause 1000
LCDOut $fe, 1

main:
   
  I2cwrite porta.0, porta.1, $90, $01,[%1101000100000011]  ; konfigürasyon
                                              ; |||
                                              ; 100 = AIN0 12-13-14 üncü bitler
                                              ; 101 = AIN1 12-13-14 üncü bitler
                                              ; 110 = AIN2 12-13-14 üncü bitler
                                              ; 111 = AIN3 12-13-14 üncü bitler
    pause 15  
    I2Cread porta.0, porta.1, $91, $48,[ham2]
    A2=(HAM2 */474)
    pause 15
    LCDOUT $FE,$80,"VOLT1=",dec a/10000,",",dec a//10000/100," V."
    PAUSE 1000
    LCDOUT $FE,1  
    
    
    
   I2cwrite porta.0, porta.1, $90, $01,[%1100000100000011]
    pause 15                
    I2Cread porta.0, porta.1, $91, $48,[ham1]
    A1=(HAM1 */474)
    pause 15
    lCDOUT $FE,$c0,"VOLT2=",dec a1/10000,",",dec a1//10000/100," V."
    PAUSE 1000
    LCDOUT $FE,1 
     
    i2cwrite porta.0, porta.1, $90, $01,[%1111000100000011]
    pause 15
    I2Cread porta.0, porta.1, $91, $48,[ham]
    A=(HAM */474)
    pause 15
    LcdOUT $FE,$80,"VOLT3=",dec A2/10000,",",dec a2//10000/100," V."
    PAUSE 1000
    LCDOUT $FE,1
    
    I2cwrite porta.0, porta.1, $90, $01,[%1110000100000011]
    pause 15
    I2Cread porta.0, porta.1, $91, $48,[ham3]
    A3=(HAM3 */474)
    pause 15
    LCDOUT $FE,$c0,"VOLT4=",dec a3/10000,",",dec a3//10000/100," V."
    PAUSE 1000
    LCDOUT $FE,1
    GoTo main                       
       

       


ete

#7
İki gündür ADS1115 , 16 bit harici ADC entegresi ile uğraşıyorum.
Sonunda düzgün bir okuma mantığı kurabildim. Bu entegre 16bit okuma yapıyor ama hem eksi hemde artı değerleri okuyabildiği için 15.ci bit işaret için bırakılmış. Bu nedenle bizim açımızdan okunan değer 15 bit oluyor. Yinede çok iyi bir çözünürlük.
Devre şemasını (16F1827 kullandım) ve programı ilişikte veriyorum. Birinin işine yarar umarım.

Referans olması açısından programı da buraya yerleştiriyorum ki incelemek isteyenler bakabilirler.

Sistem 4 kanal dan tek uçlu (single ended) okuma yapabildiği gibi 2 kanaldan differansiyel okumada yapabilmektedir. Ben tek uçlu okuma tercih ettim ve 4 kanal okuma yaptırdım.

Ete

#CONFIG
 __config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
 __config _CONFIG2, _WRT_OFF & _PLLEN_OFF& _STVREN_ON & _BORV_19 & _LVP_OFF
#ENDCONFIG
'ansel-trıs-port SIRALAMA BU
Include "modedefs.bas" 
DEFINE OSC 16
DEFINE I2C_SLOW 1
Define LCD_DREG  PORTB
Define LCD_DBIT  4
Define LCD_RSREG PORTB
Define LCD_RSBIT 2
Define LCD_EREG  PORTB
Define LCD_EBIT  3

OSCCON      =%01101000      ' %0xxxx000 ,xxxx=1111 16Mhz, 1110=8Mhz, 1101=4Mhz, 1100=2 Mhz.
'OSCSTAT     =%11111101      'Timer1 Osilatör kullanıma hazır,4xPLL hazır
OSCTUNE     =0              'Osilatör modülü fabrika ayarlarında çalışacak
OPTION_REG  =%00000111      'Pull-up enabled,Yükselen kenat kesmesi kapalı,Tmr0 clock kaynağı içsel Fosc/4,Prescaler(Bölücüler) açık Tmr0 için,Bölme oranı 16Mhz için 1/256 
WPUA      =0              'MCLR için bit5 Pull-up enabled.Eğer MCLR ON yapılmışsa herzaman enabled.
WPUB      =0
  
ADCON0.0    =0              'ADC ölçümleri iptal edildi.
            
ANSELA=0:TRISA=%00000001:LATA=0:PORTA=0:WPUA=0 'MCLR PİNİ DAİMA GİRİŞ OLARAK AYARLANMALI !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ANSELB=0:TRISB=%00000000:LATB=0:PORTB=0:WPUB=0  

CCP1CON     =0             'Capture/Compare/PWM off
CCP2CON     =0             'Capture/Compare/PWM off

CM1CON0.7   =0              'Comparatör disable-kapalı.
CM2CON0.7   =0
FVRCON      =0              'Referans sabit voltaj çıkışları (COMPARATOR,DAC ve ADC) kapalı-disable.
DACCON0.7   =0              'DAC referans voltaj çıkışı kapalı.
CPSCON0.7   =0              'Capasitive sensing modulu disable yapıldı.
MDCON.7     =0              'Modülasyon modülü iptal edildi.DSM (Dijital Sinyal Modülü) iptal. Modüleli yani karışık sinyal çıkış kapalı.
MDSRC.7     =1              'Çevresel sinyallerin sürücü çıkış pinleri iptal.Modüleli sinyal çıkışı pinleri kapalı.
CLKRCON.7   =0              'Referasn clock modülü kapalı.

PIE1        =0              'TÜM ÇEVRESEL KESMELER KAPALI.
PIE2        =0              'Tüm Çeveresel Kesmeler Kapalı.
PIE3        =0
PIE4        =0              'Tüm çevresel kesmeler kapalı.
APFCON0=0  'CCP1=B3 de, CCP2=B6 da
APFCON1=0

HAM0  VAR WORD
HAM1  VAR WORD
HAM2  VAR WORD
HAM3  VAR WORD
' --- I2C Bağlantı Pinleri ---
SDA_PIN var PORTA.1
SCL_PIN var PORTA.0

' --- Değişken Tanımlamaları ---
ADDRESS   var byte
KANAL     VAR BYTE
HAMDEGER  var word
VOLT0     VAR WORD
VOLT1     VAR WORD
VOLT2     VAR WORD
VOLT3     VAR WORD
DAT       VAR WORD


LCDOUT $FE,1               '  AN0 İÇİN 111  AN1 İÇİN 100 AN2 İÇİN 101  AN3 İÇİN 110
PAUSE 200

ADDRESS = %10010000 

BASLA:
'--------------AN0 için OKUMA VE EKRANA VERME -----------------------------------
    KANAL=0:GOSUB KANAL_OKU
    HAM0=HAMDEGER
    LCDOUT $FE,$80,"ANO=",DEC5 HAM0
    VOLT0=(ham0*/481)/100
    LCDOUT $FE,$8A,"VOLT0=",DEC VOLT0/100,",",DEC2 VOLT0//100           
    
 '--------------------AN1 İÇİN OKUMA VE EKRANA VERME -----------------------------------
    KANAL=1:GOSUB KANAL_OKU
    HAM1=HAMDEGER
    VOLT1=(ham1*/481)/100
    LCDOUT $FE,$C0,"AN1=",DEC5 HAM1
    LCDOUT $FE,$CA,"VOLT1=",DEC VOLT1/100,",",DEC2 VOLT1//100   
    
 '---------------------AN2 için okuma ve ekrana verme------------------------------------   
    KANAL=2:GOSUB KANAL_OKU
    HAM2=HAMDEGER
    VOLT2=(ham2*/481)/100
    LCDOUT $FE,$94,"AN2=",DEC5 HAM2
    LCDOUT $FE,$9E,"VOLT2=",DEC VOLT2/100,",",DEC2 VOLT2//100         
        
'---------------------AN3 için okuma ve ekrana verme------------------------------------    
    KANAL=3:GOSUB KANAL_OKU
    HAM3=HAMDEGER
    VOLT3=(ham3*/481)/100
    LCDOUT $FE,$D4,"AN3=",DEC5 HAM3
    LCDOUT $FE,$DE,"VOLT3=",DEC VOLT3/100,",",DEC2 VOLT3//100 
           
    Goto Basla 
         

KANAL_OKU:
          DAT=%1100000110000011
          KANAL=KANAL & 3
          dAT= dat | (KANAL << 12)
          I2CWrite SDA_PIN, SCL_PIN, ADDRESS, $01, [DAT]    
          DO
          I2CREAD SDA_PIN, SCL_PIN, ADDRESS,$01,[HAMDEGER]  'CONFIG REG OKUNUYOR 
          Loop While HAMDEGER.15 = 0                         ' 15.Cİ BİT (OS) 1 OLUNCAYA KADAR BEKLİYORUZ.
                                                            
          I2CRead  SDA_PIN, SCL_PIN, ADDRESS,$00, [HAMDEGER]  'SONRA DA ÇEVRİLMİŞ DEĞERİ CONVERSION REG DEN OKUYORUZ.
          pause 8
          RETURN

kudretuzuner

#8
Merhaba, teşekkür eder sağlıklı günler dilerim.

elektro77

#9
Teoride değil, gerçek devrede bu çip ile 0.001V bir ölçüm nasıl yapılabilir?
Devre beslemesinin ve referans gerilimi beslemesi nasıl olmalıdır? Pcb si tasarlanırken nelere dikkat edilmelidir. Hangi filtreler nerelere uygulanmalıdır.
Hocam Elinize sağlık bu arada.
"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

#10
Bu konuda teori ile gerçek arasında bir fark olacağını sanmıyorum. Çok da emin değilim ama işin yolunu açıklayayım belki dener sonucu bildirirsin.

Yapılacak işleri sırası ile veriyorum.
1. Öncelikle hangi ANx girişinden ADC voltajını gireceğine karar vermen gerekiyor.
  Yer gelmiş iken girişi kim nasıl seçiyor ona bakalım. Bütün iş CONFIG register de bitiyor.
  Config registerin ham yada standart değeri %1100000110000011 oluyor. Bu registerin 14-12 arası bitleri giriş seçimini yapıyor. Seçim değerlerine göre nelerin seçilebileceğine bakalım.
Bu entegre hem differansiyel giriş hemde normal giriş şeklinde adc ölçebiliyor. Senin konun normal girişi ilgilendirdiği için differansiyel olanları atlıyorum. %000-001-010-011 şeklindeki girişler differansiyel lere ait.
%100----AN0 girişi seçer
%101----AN1 seçer
%110----AN2 seçer
%111----An3 seçer
Standart Config değeri üzerinden diyelimki AN1 girişinden ölçüm yapacağız. Bu durumda Config değerimiz %1101000110000011 neleri değiştirdiğimi anlamanız için %1xxx000110000011 şeklinde de yazayım. X ler değişen yerleri gösteriyor 14-12 arası bitler.

2. Daha sonra ref voltajını yada başka bir deyişle maksimum ölçülecek voltaj değerini seçelim.
Bu seçimi 11-9 arası bitler yapıyor. Bitlerin aldığı değerlere göre maksimum FSR (Full Scale Range) değerleri şöyle.
%000  ---- 6,144V
%001  ---- 4,096V
%010  ---- 2,408V
%011  ---- 1,024V
%100  ---- 0,512V
%101  ---- 0,256V
%110- %111 ---0,256V (bu min değer oluyor.)
Ölçüm aralığına bakarak senin için uygun olanın 0,512 olacağına karar verdim. Değişik değerleride deneyebilirsin. Bu durumda benim seçimim %100 şeklinde olacak bunu CONFIG son değerine ekleyelim. %1101100110000011  (%1101xxx110000011)
Bu aşamadan sonra Config değerimiz kullanıma hazır durumda geriye okuma prosedürünü uygulamak kalıyor.DAT değişkeni Config son değerini içeriyor.
          I2CWrite SDA_PIN, SCL_PIN, ADDRESS, $01, [DAT]    
          DO
          I2CREAD SDA_PIN, SCL_PIN, ADDRESS,$01,[HAMDEGER]  'CONFIG REG OKUNUYOR 
          Loop While HAMDEGER.15 = 0                         ' 15.Cİ BİT (OS) 1 OLUNCAYA KADAR BEKLİYORUZ.
                                                            
          I2CRead  SDA_PIN, SCL_PIN, ADDRESS,$00, [HAMDEGER]  'SONRA DA ÇEVRİLMİŞ DEĞERİ CONVERSION REG DEN OKUYORUZ.
          pause 8
          RETURN          
Şimdi bir durum değerlendirmesi yapalım. Maksimum okuyacağımız voltaj 0,512V olacaktır. Buna karşılık okuyacağımız ADC değeri ise 32765 olacaktır.Normal matematik ile okunan ADC değerinden voltaj değerine ulaşmak için 0,512/32765=0,000015626 sabit çarpanımızı kullanmamız yeterli. Okunan değeri bu sayı ile çarparak voltajı bulabiliriz.
Bu işlemi pic ile yapmak istersek işimiz biraz zor zira bu sabit çarpan çok küçük bir sayı ve ancak float tipi değişkenler yada 32 bit değişkenler ile bu yapılabilir. Bunun için 18F serisinden bir işlemci kullanılır ise LONG (32 bit değişken) kullanılarak bu iş yapılabilir gerekirse istek olursa açıklarım.
Yada ufak bir eksikliğe razı olunur ise en yakın sonuç şu eşilikle alınabilir.
  VOLT3=(HAM3*/40): VOLT3=(volt3+1)/10
    LCDOUT $FE,$D4,"AN3=",DEC5 volt3 'HAM3
    LCDOUT $FE,$DE,"VO3=","0,",dec3 volt3

Ete

ete

Oldu olacak birde differansiyel giriş ölçümünü örnekleyelimde eksik bir şey kalmamış olsun.
Bu entegrenin 4 adet Analog girişi olduğunu söylemiş idik. Differansiyel giriş kullanınca AN0-AN1 veya AN0-AN3 ikilisi bir giriş, AN1-AN3 veya AN2-AN3 girişleride ikinci differansiyel girişi olarak kullanılıyor.
Bunların seçimini yine Config registerine ait 14-12 bitleri aracılığı ile yapıyoruz.
%000 --- AN0 Pozitif giriş, AN1 negatif giriş
%001 --- AN0 Pozitif giriş, AN3 negatif giriş
%010 --- AN1 Pozitif Giriş, AN3 negatif giriş
%011 --- AN2 Pozitif Giriş, AN3 negatif giriş

Bu seçimi yaptıktan sonra Ref Voltaj yada FSR değerini 11-9 bitleri ile yapıp önceden anlatıldığı çekilde ölçüm yapılabilmektedir.

Bir örnek devre kurabilirsem buraya koyarım sonradan.

Ete


Powered by EzPortal
▲