HDC1080 hakkında

Başlatan aRci, 21 Mayıs 2023, 14:00:25

aRci

Merhaba arkadaşlar hdc108 sensörden ısı ve nem değeri okumaya çalışıyorum ama başarılı olamadım bu sensör hakkında bilgisi olan varmı?

https://pdf1.alldatasheet.com/datasheet-pdf/view/813671/TI1/HDC1080.html

    i2cwrite  DIO,Clk,$40,$02,[%10010000,0]:pause 15

Basla:    
    i2cread   DIO,Clk,$40,$02,[HdcCnf,HdcCnf1]
    hserout [Dec HdcCnf," ",bin8 HdcCnf," ",bin8 HdcCnf1 ,13]
    toggle portb.3
    pause 500
    HdcCnf = 0 
    goto basla

ete

Pek çok kişinin başına gelen benzer bir sorunla karşı karşıyasın. Sorun Device number yani cihaz numarası.
Data sheet diyorki 7 bit olarak cihaz numarası %1000000 sen 7 biti sağdan itibaren almışsın. Halbuki 7 bit soldan alınmalı çünki en sağdaki bit olan sıfır nolu bit okumada "1" , yazmada "0" oluyor. Değişen bit sıfır nolu bit olunca sabit olanları 7 bit olarak veriyorlar.
Bu durumda cihaz numarası senin yazdığın gibi $40 (%01000000) değil $80 olmalı. Yani %10000000 şeklinde.
Sensöre bilgi yazarken $80, ve sensörden bilgi okurken $81 değerlerini kullanman gerekir.
PBP bu işi otomatik yapacağı için her zaman $80 kullansan da olabilir.

Programda fazla detay vermediğin için diğer olası sorunlara değinmedim.
Neler olabilir dersen okunan değer daima 14 bit olacak diyor data sheet ama bir yandan da sıcaklık hesabı formülünde 0-15 bitler şeklinde bir ifade kullanılmış. Hangisini kullanacaksın sen karar ver artık.

Ete

aRci

Merhaba;
Amacım sağlıklı bir haberleşme yapabilmek. dediğiniz gibi adres değerini hatalı girmişim fakat bir değişiklik olmadı malesef. şu varki bu sensörde haberleşme başlangıcı cevap ve son sinyalleri verilmesi gerekiyor datasheet de ki sinyaleri uygulamaya çalıştım ama başaramadım. altta bu sinyalleri yorumladığım kısım var ama shiftout ile nasıl yapacağımı çözemedim.

birde veri okurken ilk olarak yazma komutu ile başlaayıp cihaz adresi ve hafıza dan okunacak olan veri adresini gönderip daha sonrada okuma amacı ile cihaz adresini yazıp sonrada 2 byte veri okunmalı bu kısımında ise tamamaen takıldım. start stop ve ACK adındaki kısımlarda bir hatam var ama nedir çözemedim.


  
'===============================================================================  
 StartSeq:                                                                            
   HIGH DIO                                        
   HIGH CLK
   PAUSEUS 5                                       
   LOW DIO
   pauseus 5
   Low CLK
 Return     
'===============================================================================  
 AckSeq:
    LOW CLK 
    High DIO
    pauseus 210  
    low DIO
    pauseus 5     
    High CLK
    pauseus 5
    Low Clk 
    pauseus 10
    'output DIO
    'LOW DIO     
 Return
'===============================================================================  
  StopSeq:   
    LOW CLK                                        
    high DIO
    PAUSEUS 5
    HIGH CLK
    pauseus 5
    low Clk
    pauseus 2000 
 Return
'===============================================================================  
 

ete

Tamamen I2C ile çalışan bir sensörü  SPI ile okumak yanlış bence. Hata burada.

Açık kod vermeme gibi bir sıkıntın var. Sorunu da kendin bulacaksın bu durumda.

Kolay gelsin.
Ete


aRci

Merhaba;
Aslında yazdığım kod burada paylaştığım kadarı idi. Üst kısımda sadece sigorta ayarları ve değişkenlerim var başka bir kod yazılı değil. modülün datasheetinde ki sinyalleri uygulamayı denedim data başlangıcı ack ve stop sintallerinden bahsediyor I2C yada shift out komuyları bunun içeriğini uygulamak için denemeler yaptım fakat suraklı sabit değerler gördüm 65535 vb

daha ileri gidip arduino ile modulu çalıştırdım ve ardından logic analizor alarak sinyalleri takip etmeyi denedim

işte burada benzer sinyalleri üretirken herşey karıştı. örneğin modülden bir ack geleceği zamanı bulamadım yada arduinomu bu ack ı üretiyor çözemedim. altta okuma ve yazma anındaki analizör grafiğini ekliyorum.

deneme yaptığım kodlar ise bu sekilde.
gosub StartSeq
    shiftout  DIO,CLK,1,[$80]
    gosub AckSeq
    shiftout DIO,CLK,1,[$02]
    gosub AckSeq
    shiftout DIO,CLK,1,[%00010000]
    gosub AckSeq
    shiftout DIO,CLK,1,[$00]
    gosub AckSeq
    gosub StopSeq 
    pause 100
Basla: 
    HdcCnf = 0   
    gosub StartSeq
    shiftout   DIO,CLK,1,[$80]
    gosub AckSeq
    shiftout DIO,CLK,1,[$00]
    'gosub AckSeq
    gosub StopSeq
    pause 10

    gosub StartSeq
    shiftout  DIO,CLK,1,[$81]
    gosub AckSeq
    shiftin DIO,CLK,1,[HdcCnf.highbyte]
    gosub AckSeq
    shiftin  DIO,CLK,1,[HdcCnf.lowbyte]
    gosub AckSeq
    gosub StopSeq
    hserout  [Dec HdcCnf," - ",13]
 
    'HdcCnf = HdcCnf | HdcCnf1
    'HdcCnf = HdcCnf / 65535
    'HdcCnf = HdcCnf * 1250
    'i2cread   DIO,Clk,$80,$01,[HdcCnf,HdcCnf1]
    'hserout  [Dec HdcCnf ,13]
    toggle portb.3
    pause 2000
    goto basla
    
  
'===============================================================================  
 StartSeq:                                                                            
high CLk
low DIO                                     
 Return     
'===============================================================================  
 AckSeq:
    high DIO
    low DIO
    pauseus 1     
    High CLK
    pauseus 5
    Low Clk
    input DIO
    Pauseus 2
    'high DIO 
    output DIO
    LOW DIO     
 Return
'===============================================================================  
  StopSeq: 
     
    high CLK
                                            
    high DIO
 Return












ete

Bu sensör kesin olarak I2C ile haberleşior ve haberleşme protokolü ona göre yapılmalı.
Hangi derleyici olursa olsun hemen hepsinde I2C haberleşme komutları yer alıyor.
Bu nedenle hazır komut kullanmak işi çözmenin birinci anahtarı. Değilse boşuna uğraşır durursunuz.
Diğer taraftan her şeyi insanın kendisi yapmasıda güzel bir fikir. Ama usulüne uygun yapılırsa zevk alınıyor. Usul ise I2C formatını iyi bilerek ortaya çıkar. Öncelikle SCL ve SDA hatlarında pullup olmasına dikkat etmek gerekiyor. Çünki bunlar ACK anında pinleri HIGH yapacak ama sesör o anda çıkışı LOW yaparak ack vermiş olacak. Karşılıklı ack alıp verme işlemi bu esasa dayanıyor.
Sen ne yapıyorsun kendine ACK veriyorsun. DIO hattını önce HIGH (ki bu işlemi pullup otomatik yapacak) sonra hattı LOW yapıyorsunki bunuda sensörün yapması gerekiyor.  ACK bir onay işlemidir. Biri (Master) yollar diğeri (SLAVE) aldım diye onay verir. İşte bu iş ACK ile yapılmış oluyor. SOnuçta tek bir data hattı olunca bilgi de seri olarak verilince sıralamanın doğrulunun arada bir nevi kontrolüdür ACK olayı.
Senin ACK işinde yapman gereken tek şey 8 bitlik bilgiyi verdikten sonra "DIO" hattını giriş olarak ayarlamak. Bu sayede hat pullup dan dolayı otomatik HIGH olacak  ve sen ardından hattın LOW olup olmadığına bakacaksın. Olduğu anda ACK yi almış olacaksın. Hepsi bu. Daha sonra diğer işlemlere sırası ile geçeceksin.

Data sheet'e bakacak olursak Master (işlemci) adres bilgisini sensöre yazıyor ve ardından ACK bekliyor. Bekleme anı 8 bitlik bilginin verilmesinin hemen ardında olması gerekiyor. Sistem genel olarak 8 bit üzerinden çalıştığı için her bir 8 bitlik bilginin ardından ACK alınması gerekiyor.
Bütün bu işleri yani START verme STOP verme ve arada ACK işini I2C komutları otomatik yapmaktadır. Uğraşmaya değermi bilemiyorum.
Cihaz Adres bilgisi ile okunacak register adresini ver ve kaç byte alınacak ise al olsun bitsin.

Ete

aRci

Merhaba;
Yanıtınız için teşekkürler ve gene I2C komutunu kullanarak deneme yaptım. Bu sefer veri almayı başardım. Sebibini anlamadığım bir durum oldu ve bu muhtemelen yazma ve okumam komutlarının çalışmasını tam bilmediğimdendir. Belki siz açık lık getirebilirsiniz.

i2cwrite   DIO,CLK,$80,$02,[$10,$00]


Üste yazılı haline göre kontrol adres ve 2 byte veri göndermesi gereken bu komut izlediğim analizörde sadece kontrol ve $10 verisini gönderiyor. ama 2 byte veriyi birleştirip word tipi bir veri yaınca toplamda 4 byte veri gönderdi her seferinde ack almaayıda başardı.

bu durum veri okuma kodlarındada yaşandı ve 2 ayrı byte yazınca doğru şekilde değer almaya başladım bu arada sensörden 14bit sıcaklık verisi alıyorum ve bu sebeple okuma komutunda 15ms bekleme yapınca veri almayı başardım.


i2cwrite   DIO,CLK,$80,$02,[4096]

pause 500
ttte:
i2cwrite DIO,CLK,$80,[0]
pause 15
i2cread DIO,CLK,$80,[ddd,eee]

artık değer almayı başardığım için değğerin karşılığı sıcaklık değerini hesaplamaya başladım sensörden aldığım değeri hesap makinesi ile işlem yapınca sıcaklık değeri doğru çıkıyor ama bu hesabı pic e nasıl yapacağımı bulamadım.

sıcaklık = (sensörden alınana değer / 65536) * 165 - 40

datasheet göre bu şekilde hesaplanıyor.

ete

Data sheet diyorki BU sensör maksimum 125 derece ölçebilir.
Formüle göre bu duruma bir bakalım.
Formül şöyle;
ISI = (sensördeğeri/ 65536) * 165 - 40
Bunu şöyle yazabiliriz.
ISI=(sensördeğeri/(256*256))*165-40
ISI=(sensördeğeri*165/(256*256)-40
(165/256)*256=165 olur ve bu bizim sabit çarpanımız olabilir.
Bu durumda formül,
ISI=(((Sensördeğeri*/165)*10)/256)-400 şekline sokulabilir.
Biraz daha kısa matematik kullanırsak;
TEMP=(Sensördeğeri*/165)*10
ISI=(DIV32 256)-400
Ekranada şöyle yansıtırız;
LCDOUT $FE,$C0,"ISI=",DEC ISI/10,",",DEC1 ISI//10

Sensör her ne kadar 125 dereceye kadar ölçer diyorsada datasheet ölçebileceği maksimum sıcaklık 124,99 derece olarak hesaplanabiliyor. Sensör değeri yerine 65532 (yani %1111 1111 1111 1100 değeriki sensörden alınabilecek maksimum değer bu oluyor) koyarsan sonucun 124,9 olarak hesaplandığını görebilirsin.

Ete

aRci

Merhaba;
Hesap makinesi ile 1 saat uğraştım ama tek bulduğum çözüm long değişkeni ile yapabilmiştim bu da beni 18f lere mahkum bırakacaktı verdiğiniz çözüm için teşekkürler. Belkide büyük sayılar yada matematiksel kodlar üzerine bir paylaşım yaparsınız kendim için oldukca zayıf olduğum aşıkar.

 
i2cwrite   DIO,CLK,$80,$02,[4096]

pause 500
ttte:
i2cwrite DIO,CLK,$80,[0]
pause 15
i2cread DIO,CLK,$80,[ddd,eee,aaa,bbb]
    HdcCnf1.highbyte = ddd
    HdcCnf1.lowbyte = eee
    
    HdcCnf1 = (HdcCnf1 */165)*10
    Drce = (div32 256)-400
    
    HdcCnf1.highbyte = aaa
    HdcCnf1.lowbyte = bbb
    
    HdcCnf1 = (HdcCnf1 */100)*10
    Nem = (div32 256)
    
    hserout  ["Drc: ",dec Drce," Nem: ",dec Nem," - ", bin8 ddd,bin8 eee,13]
    pause 3000
    goto ttte




ete

Yeri geldikçe u konuda örnekler veriyorum. Ama bu konu üzerinde az da olsa ders notlarında çalışmıştım. Genllikle sensör sonuçlarını değerlendirirken lazım oluyor bu kodlar. Bu verdiğimde bir örnek oldu.
Ete

aRci

Merhaba;
Programı biraz toparladım ve değişkenler vs düzenledim. Şimdi ise ısıtıcı üzerine deneme yapıp dakikada 5sn ısıtıcısını devreye alıp kapatıyorum. dolayısı ile hem sıcaklık hem de nem değeri değişiyor. bu kullanım şekli doğrumu bilemedim sensör hakkında tecrübesi olan varsa fikirlerini paylaşırsa sevinirim.

'===============================================================================
'===============================================================================
Nem          var word
Drce         var word
DrcTemp      var word
NemTemp      var word
CnfTemp      var byte
SnsTemp      var byte
HdrSay       var byte
HdcTemp      var byte
HEAT         var CnfTemp.5
pause 500
CnfTemp = 16: SnsTemp = 0
i2cwrite   DIO,CLK,$80,$02,[CnfTemp,SnsTemp]'4096]
pause 500
HdrSay = 0 
ttte:
    HdrSay = HdrSay + 1
    if HdrSay = 5 then Gosub HeaderOn
    if HdrSay> 19 then HdrSay = 0
    Gosub CnfOku
    Gosub SensorOku
    hserout  ["Drc: ",dec Drce," Nem: ",dec Nem," Heat: ",dec HEAT,13]
    pause 3000
goto ttte
'===============================================================================  
HeaderOn:
    CnfTemp = 48: SnsTemp = 0
    i2cwrite   DIO,CLK,$80,$02,[CnfTemp,SnsTemp]
    for HdcTemp = 0 to 4
        Gosub CnfOku
        Gosub SensorOku
        hserout  ["*** Drc: ",dec Drce," Nem: ",dec Nem," Heat: ",dec HEAT,13]
        pause 1000
    next HdcTemp
    CnfTemp = 16: SnsTemp = 0
    i2cwrite   DIO,CLK,$80,$02,[CnfTemp,SnsTemp]
return
'===============================================================================  
SensorOku:
    i2cwrite DIO,CLK,$80,[0]
    pause 15
    i2cread DIO,CLK,$80,[DrcTemp,NemTemp]
    
    DrcTemp = (DrcTemp */165)*10
    Drce = (div32 256)-400
    
    NemTemp = (NemTemp */100)*10
    Nem = (div32 256)
Return
'===============================================================================
CnfOku:
    i2cwrite DIO,CLK,$80,[2]
    pause 15
    i2cread DIO,CLK,$80,[CnfTemp,SnsTemp]
    hserout ["Config: ",bin8 CnfTemp," "]
return
'===============================================================================

ete

Sensör üzerindeki ısıtıcı aslında Nem ölçmede şayet sensör üzerinde bir su yoğunlaşması yaşanmış ise kullanılıyor. Bu gibi durumlarda ısıtıcı açılıp sensör ısıtılıyor ve üzerindeki yoğunlaşan nemi buharlaştırıp uzaklaşmasını sağlıyor. Bunu göz önüne alırsak havada yoğun halde bulunan su buharı ne zaman yoğunlaşmaya başlar onun üzerinde biraz düşünmek lazım. Sıcaklık arttıkça havanın nem taşıma kabiliyeti artar. 25 derecede 525 gr buharlaşmış nem taşıyabilen 1 m3 hava 30 derecede çok daha fazlasını taşır. Ama ortamı birden soğutursanız taşıyabileceğinden fazla nem barındıran hava adeta içindeki nemi kusar ve fazla nem anında nispeten soğuk yerlerde yoğunlaşır. Bu durumda sensörde de yoğunlaşma olması kuvvetle ihtimaldir. Bu nedenle ani soğumalar yaşandığı durumlarda ısıtıcı çalıştırılmalıdır. Bunuda ancak sıcaklığı takip ederek yapabilirsin. Yada günde 3 defa o ısıtıcıyı çalıştırıp sensörü nemsiz hale getirebilirsin.

Ete

aRci

Merhaba
10.000 mesajınız hayırlı olsun :)

deneyim ve tecrünemizle bulamadığım bilgiler buldum çok katkınız oldu teşekkürler. Kuluçka makinesi yapmayı heves ettim bu amaçla sıcaklık kontrolü için PID ve AC dimmeri birleştirdim ama sensör konusunda karasızdım fiyatlı bir şey birde neyseki bunuda aştım desteğniz sayesinde. projemi uyuglayınca bir paylaşımda o vakit yaparım tekrardan. teşekkürler.

ete

Söylemesen 10.000 ci mesaj konusunu farketmeyecektim. Teşekkür ederim. Epeyce mesaj yazmışım.
Bu site bir kod paylaşım sitesi. Mümkün olduğunca açık kod yayınlamaya yada kod örnekleri vermeye çalışıyoruz ki yeni öğrenenler sıkıntı çekmeden olayı kavrayabilsinler.
Elbette ticari değeri olan programların tamamını burada vermek istemiyoruz. Daha doğrusu hazır kod vermek değil amacımız yol gösterici olmak desek daha doğru olur
Bu nedenle mümkün ise programın bittiğinde işin algoritmasını da içeren bir örnek buraya koyarsan sevinirim.
Pek çok kişiye kuluçka makinesi kodlarını yazmakta yardımcı oldum. Ben bu konuda bir program yazmadım. Genelde bir konuda ya meraktan yada istek gelirse kod yazıyorum. İşin merak kısmı daima ağır basar bende. Şu nasıl olur nasıl çalıştırılır nasıl yapılır diye yazdığım bir sürü kod mevcut.
Her neyse sana kolaylıklar dilerim.

Ete

Powered by EzPortal