www.elektronik.si
DS 18B20

www.elektronik.si -> Osnove programiranja AVR-jev

Avtor: lojzek PrispevekObjavljeno: Čet Apr 26, 2018 7:21 am    Naslov sporočila:  DS 18B20
----------------------------------------------------------------------------
Pozdravljeni, imam konkretne težave s tem(i) senzorji.

Enega od njih imam testno priklopljenega na Atmego s taktom 1MHz. Normalno napajanje.

1. Po datasheetu je najprej treba napraviti reset in preveriti prisotnost senzorja. To deluje, senzor se javi.
2. nato pošljem komando 0x33 (Read ROM), binarno je ta vrednost 0b00110011. Ker pa je po datasheetu treba poslati podatke od LSB do MSB, pa pravzaprav pošljem po takem vrstnem redu: 11001100.
3. Nato pa poskušam prebrati njegovo adreso - poženem proceduro branja po 1-wire vodilu (generiram read time slote), ampak nič ne pride nazaj - dobim samo enice (torej 0xFF)

Poskusil sem tudi z eno knjižnico 1wire z interneta..

Kje ga lomim? Ali je potrebno med temi koraki narediti kako pavzo? ali lahko na kakšen način ugotovim, če sem vsaj komando pravilno poslal? Močno dvomim, da so vsi senzorji zanič. Tudi datasheet sem že nekajkrat prebral, pa ne najdem ničesar, kar delam narobe.

Think

Avtor: lojzek PrispevekObjavljeno: Čet Apr 26, 2018 7:29 am    Naslov sporočila:  
----------------------------------------------------------------------------
Tukaj je pa še del programa za 1 wire vodilo, funkcije reseta, pisanja in branja.
Sicer sta tisti za branje in pisanje že 1000x spremenjeni, tako da res ne vem več, kje se me glava drži.

Koda:
unsigned char DS_init()
{
uint8_t a=0;
cli();
DS_DDR_port |= (1 << DS_pin);   //izhod
_delay_us (500);
DS_DDR_port &= ~(1 << DS_pin);   //preklopi na vhod
_delay_us (100);   // počakaj odziv DS
//preveri prisotnost in počakaj še zahtevani čas
a = (!(DS_port & (1 << DS_pin)));
_delay_us (400);
sei ();
return a;
}

unsigned char DS_read_byte()
{
unsigned char podatek = 0;
cli();
for (uint8_t a=0; a<8; a++)
   {
   DS_DDR_port |= (1 << DS_pin);   //izhod
   _delay_us (5);
   DS_DDR_port &= ~(1 << DS_pin);   //vhod
   _delay_us (5);
      //Prejeto je "1"
   if (DS_port & (1 << DS_pin)) { podatek |= (1 << a); }
   _delay_us (60);
   }
sei();
return podatek;
}


void DS_write_byte(uint8_t podatek)
{
cli();

for (uint8_t a=0; a<8; a++)
   {
   DS_DDR_port |= (1 << DS_pin);   //izhod
   _delay_us (5);
         
   //poslati je treba "0" drži low še 60us
   if (!(podatek & (1 << 0))) { _delay_us(60); }
   
   DS_DDR_port &= ~(1 << DS_pin);
   _delay_us (60);
   
   podatek = ( podatek >> 1 );
   }
sei();
}

Avtor: HighlagKraj: Črnuče PrispevekObjavljeno: Čet Apr 26, 2018 2:26 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Moj programček za LPC je zgledal takole:
Koda:

/******************************************************************************/
/* Programček za dostop do DS1820 senzorja                                    */
/* By P&P 24.9.2012                                                           */
/******************************************************************************/
#include <stdio.h>
#include "LPC13xx.h"                        // LPC13xx definitions ^
#include "systick_pp.h"
#include "DS1820_pp.h"
#include "LCD.h"

/******************************************************************************/
/* DS1820 je priključen na pin:                                               */
/* PIO3.1      Pin37 -> P0.26  ->P10-Pin1                                     */
/******************************************************************************/

#define PIN_DS1820                 (1 << 1)                     // ...0000 0010
// Pin da na izhod 1 ali 0
#define DS1820_Data(x) ((x) ? (LPC_GPIO3->DATA |= PIN_DS1820)  : (LPC_GPIO3->DATA &= ~PIN_DS1820) );
// Pin beremo
#define DS1820_beri LPC_GPIO3->DATA & PIN_DS1820
// Pin je definiran kot izhod - 1 / 0 - vhod
#define DS1820_IO(x)   ((x) ? (LPC_GPIO3->DIR |= (PIN_DS1820))  : (LPC_GPIO3->DIR &= ~(PIN_DS1820)) );

int Senzor_Prisoten,Delcek_Stopinje,Izmerjena_Temperatura;
int Negativna_Temperatura;

// Tule se lahko vpiše kodo prebranega senzorja, ki jo izpiše
// funkcija PreberiSerijsko(); v prvo vrstico LCD.
// Izpis na LCD je že v Hex obliki, pred posamezne bajte je potrebno dodlati le "0x"
int koda[8]={0x94,0x00,0x08,0x01,0xD3,0x39,0x38,0x10}; // koda senzorja
int TipSenzorja=0;
int DS1820Data[]={0,0,0,0,0,0,0,0,0};
char bufer[20];
char *napis;

//**************************************************************
//    Inicializacija senzorja
//**************************************************************
void init1820(void){
   int vrednost;
   DS1820_IO(1);
   Delay_us(500);                // počakamo 500us
   DS1820_Data(0);               // Izhod na 0
   Delay_us(500);
   DS1820_IO(0);                 // Pin je vhod
   Delay_us(100);                // Po 100us preverimo odgovor
   vrednost=DS1820_beri;         // preberemo odgovor
   Delay_us(500);
  if (vrednost & (1<<0)) {       // je bit 0 spremenljivke vrednost 1?
   Senzor_Prisoten =0;           // Napaka, senzor se ni "oglasil"
   } else {
   Senzor_Prisoten =1;           // Vse v redu, nadaljujemo...
   }
}

//**************************************************************
// Na izhod za DS1820 zapiše 0
//**************************************************************
void write_0(){
   DS1820_IO(1)                  // Pin DS1820 je izhod
   DS1820_Data(0);               // Izhod na 0
   Delay_us(90);
   DS1820_IO(0)                  // Pin DS1820 je vhod
   Delay_us(10);
}
//**************************************************************
// Na izhod za DS1820 zapiše 1
//**************************************************************
void write_1(){
   DS1820_IO(1)                  // Pin DS1820 je izhod
   DS1820_Data(0);               // Izhod na 0
   Delay_us(3);
   DS1820_IO(0)                  // Pin DS1820 je vhod
   Delay_us(90);                 // počakamo 90us
}

//**************************************************************
// Na izhod za DS1820 pošlje 8 bitov podatkov
//**************************************************************
void send_to_ds1820(int podatki){
   int i;
   DS1820_IO(1);                 // Pin DS1820 je Izhod
   for (i=0;i<8;i++) {           // 1 byte je sestavljen iz 8 bitov
      if (podatki & (1<<i)) {    // ali je bit podatki(i) = 1?
      write_1();                 // podatiki(i) je 1,
      } else {
      write_0();                 //podatiki(i) je 0,
      }
   }
}

//**************************************************************
// Prebere 8 bitov z DS1820 vhoda v spremenljivko prebrano
//**************************************************************
int read_from_ds1820(void){
   int i;
   int prebrano=0;
  for (i=0;i<8;i++) {            // Podatki so sestavljenih iz 8 bitov
   DS1820_IO(1)                  // pin DS1820 je izhod
   DS1820_Data(0)                // izhod na 0
   Delay_us(3);                  // Malček počakamo
   DS1820_IO(0)                  // pin DS1820 je vhod
   Delay_us(10);                 // še malček počakamo
     if ( DS1820_beri ) {        // ali je prebran bit = 1?
      prebrano |= (1<<i);        // da, postavi bit[i] v prebrano na 1
      } else {
      prebrano &= ~(1<<i);       // ne, postavi bit[i] v prebrano na 0
      }
      Delay_us(70);
   }
   return prebrano;              // funkcija vrne spremenljivko prebrano
}
//**************************************************************
// Prebere serijsko številko DS1820 hrani jo v DS1820Data[]
//**************************************************************
void PreberiSerijsko() {
   int x;
   int x1 = 0;
   char bufer[20];
   init1820();
   send_to_ds1820(0x33);         // ukaz READ ROM
   Delay_us(200);
   for (x=0;x<8;x++) {           // tule pa že beremo serijsko št.
   DS1820Data[x]=read_from_ds1820();
   }
   for (x1=0; x1<=8; x1++) {
   sprintf(bufer, "%02x", DS1820Data[8-x1]);// številko stolpca pretvorim v char
   LCD_print (x1*2, 1, bufer);              // ter jo izpišem na LCD 
   }
 }
/**************************************************************/
//    Preberi scratchapd ob enem senzorju brez naslova
/**************************************************************/
void PreberiScratcpad() {
   int x;
   int x1 = 0;
   char bufer[20];
   init1820();
   send_to_ds1820(0xCC);         // 0xCC = Skip rom
   Delay_us(100);
   send_to_ds1820(0x44);         // 0x44 = Convert T
   Delay_us(750000);             // počakamo 750ms za pretvorbo
   init1820();
   send_to_ds1820(0xCC);         // 0xCC = Skip rom 
   Delay_us(100); 
   send_to_ds1820(0xBE);         // 0xBE = Read scratchpad
   Delay_us(100);
   
   for (x=0;x<8;x++) {           // tule pa že beremo vsebino scratcpada
   DS1820Data[x]=read_from_ds1820();
   }
   for (x1=0; x1<=8; x1++) {
   sprintf(bufer, "%02x", DS1820Data[8-x1]);// številko stolpca pretvorim v char
   LCD_print (x1*2, 2, bufer);              // ter jo izpišem na LCD 
   }
 }

 /**************************************************************/
//    Pošlje ukaz 0x55 - Match rom skupaj s serijsko številko
/**************************************************************/
void SendMatchROM() {
   int temp;
   send_to_ds1820(0x55);
   for (temp=0; temp<8; temp++) {
      send_to_ds1820(koda[7-temp]);
   }
}
 
void PreberiIzbraniDS1820() {
   int x;
   init1820();
   SendMatchROM();
   send_to_ds1820(0x44);         // 0x44 = Convert T
   Delay_us(750000);             // počakamo 750ms za pretvorbo
   init1820();
   SendMatchROM();
   Delay_us(100); 
   send_to_ds1820(0xBE);         // 0xBE = Read scratchpad
   Delay_us(100);
   for (x=0;x<8;x++) {           // tule pa že beremo vsebino scratcpada
   DS1820Data[x]=read_from_ds1820();
   }
 }

/**************************************************************/
//    Prebere vsebino scratchpada in iz nje izlušči temperaturo
//    primerno za prikaz na LCD
/**************************************************************/
void PreberiTemperaturo(){
  char decimalka;
  int temperatura;
  char predznak;
 
//  PreberiScratcpad();
  PreberiIzbraniDS1820();
 
// Določitev vrednosti za decimalno piko 
  if (DS1820Data[0] & (1<<0)){   // ali je bit 0 = 1
    decimalka=5;                 // da -> decimalka = 5
  } else {
    decimalka=0;                 // ne -> decimalka = 0
  }

  temperatura = DS1820Data[0] >> 1;// Določitev temperature 

  if (DS1820Data[1] & (1<<0)){   // Je temperatura pozitivna ali negativna? 
    predznak='-';
  } else{
    predznak='+';
  }   
// Sprintf tule združi nekaj spremenljivk in besedila in shrani v niz
// buffer 
sprintf(bufer, "Temperatura = %c%d.%d", predznak, temperatura, decimalka); 
napis=&bufer[0];                 // kazalec na niz buffer
}   


Mogoče ti kaj prav pride.

Avtor: pajo PrispevekObjavljeno: Čet Apr 26, 2018 7:16 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Povej, koliko je oddaljen senzor od uC?
Koliko jih imaš priključenih?
Si uporabil pull-up upor?

Avtor: lojzek PrispevekObjavljeno: Pet Apr 27, 2018 9:52 pm    Naslov sporočila:  
----------------------------------------------------------------------------
@highlag: hvala za primer, bom preštudiral, ko bo dan. Sedaj je prepozno.

Pajo,en senzor, na testni plošči, edino pullup je 15kOhm. tega sem v predalu imel.

Avtor: polkic PrispevekObjavljeno: Sob Apr 28, 2018 7:38 am    Naslov sporočila:  
----------------------------------------------------------------------------
Pozdravljen,

jaz uporabljam 4.7k Omega med 5V in data pinom.

Lep pozdrav.

Avtor: pajo PrispevekObjavljeno: Sob Apr 28, 2018 4:30 pm    Naslov sporočila:  
----------------------------------------------------------------------------
lojzek je napisal/a:

Pajo,en senzor, na testni plošči, edino pullup je 15kOhm. tega sem v predalu imel.


Če imaš tri 15k upore, jih veži vzporedno in dobiš nadomestno upornost 5k. Kar bo že mogoče dovolj blizu, da bo zadeva delala.

Avtor: lojzek PrispevekObjavljeno: Sob Apr 28, 2018 4:53 pm    Naslov sporočila:  
----------------------------------------------------------------------------
pajo je napisal/a:
upornost 5k. Kar bo že mogoče dovolj blizu, da bo zadeva delala.


Če je to to, se bom s trnovim protjem prešibal.
4,7k upor (skorraj celo lestvico vseh vrednosti pravzaprav) imam 200m preč od testne ploščice in se mi v nekaj dneh ni zdelo vredno bliže prinest.
V ponedeljek poročam

Avtor: pajo PrispevekObjavljeno: Sob Apr 28, 2018 5:06 pm    Naslov sporočila:  
----------------------------------------------------------------------------
lojzek je napisal/a:


Če je to to, se bom s trnovim protjem prešibal.
4,7k upor (skorraj celo lestvico vseh vrednosti pravzaprav) imam 200m preč od testne ploščice in se mi v nekaj dneh ni zdelo vredno bliže prinest.
V ponedeljek poročam


Very Happy
Sem imel podobne težave. Če se dobro spomnim, sem imel celo nižjo vrednost od 4,7k.

Res je, da nisem nikoli raziskoval, zakaj tako, ampak nekdo (mislim da celo na tem forumu) mi je sveoval, da naj upor postavim čim bližje senzorju (pri večjih razdaljah).

Po mojem mnenju so DS1820 dobra izbira, dokler so na mizi. Ko jih pa postaviš v realno okolje, pa nastane "štala". Ko eden "zasade" vodilo, je konec. Zakaj, ne vem. Sem obupal nad njimi.
Tako sem vse svoje "odpustil". Mad Mad

Avtor: HighlagKraj: Črnuče PrispevekObjavljeno: Ned Apr 29, 2018 12:57 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Meni se pa zdijo teli senzorji precej robustni. Imam dva grozda senzorjev v uporabi že po nekaj let in vsi delujejo brezhibno. V obeh primerih imam po več senzorjev na eni veji, 4,7K upor za napajanje.

Prvi grozd ima napeljavo dolgo cca 18m, vsebuje 4 senzorje, priklopljeni pa so na malino, tako da je napajalna napetost celo 3,3V. Za varovanje imam pri skrajnih čipih v zaporni smeri vezano diodo.

Drugi grozd vsebuje tudi 4 senzorje, skrbi pa za centralno ogrevanje. (dolžina ene 5m)

Je pa treba upoštevat navodila proizvajalca, da lahko kličeš posamezne senzorje.

Avtor: lojzek PrispevekObjavljeno: Pon Apr 30, 2018 6:59 am    Naslov sporočila:  
----------------------------------------------------------------------------
Vrag si ga vedi kako in kaj Think Think

Po vseh kolobocijah z internetnimi knjižnicami, mojimi funkcijami in upori, sem ga sedaj oživel Applause

Dela s 4,7k uporom in tudi s 15k uporom... uporabil sem moje funkcije za komunikacijo in prvič prebral njegov ID Smile

mislim da moje funkcije, prilepljene zgoraj nisem nič spreminjal..?

Hvala vsem za pomoč in sugestije. Kaj je bilo pa narobe da mi ni funkcioniralo.... Think Eh?

Avtor: tigerKraj: Škofja Loka PrispevekObjavljeno: Čet Maj 03, 2018 9:46 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Pozdrav

Imam 4 senzorje na 70 m kabla in delujejo, le upor sem dal na 2k.

LP

Avtor: lojzek PrispevekObjavljeno: Sre Jun 06, 2018 11:09 am    Naslov sporočila:  
----------------------------------------------------------------------------
Sedaj pa še eno vprašanje na to temo in sicer se tiče parazitnega napajanja...

Na testni plošči imam en senzor. Z normalnim napajanjem deluje, parazitno pa (tako kot pričakovano) komunikacija deluje, merjenje temperature pa ne - oz. slabo. To tudi v datasheetu piše in vem, da moram uporabiti strong pullup.

Ker pa sem hotel stvari iz datasheeta še poenostavit, sem za "strong pullup" uporabil kar komunikacijski pin, ki sem ga lepo nastavil kot izhod in postavil na 1 (torej 5V). na tej vrednosti je dovolj časa za pretvorbo temperature, glede na datasheet. Nato pa taisti pin uporabim zopet kot vhod za normalno komunikacijo (ki mi deluje), pa vedno preberem 85 stopinj. Kot bi se vsakič pri spremembi vloge pina med izhod/vhod senzor resetiral...

Uporabil sem tudi drugi pin kot strong pullup - torej vezan paralelno komunikacijskemu (poskrbel sem seveda da nista oba naenkrat izhoda in na različnih potencialih), stanje enako

Dolgo časa sem iskal programsko napako, brez sprememb...

Sem pa po naključju ugotovil, da če med komunikacijska pina mikrota in senzorja dam 680 ohmski upor zaporedno (pa seveda klasični pullup za komuniciranje), pa stvar lepo oživi v parazitnem napajanju. Pri 100 ohmskem uporu pa ne deluje več...

Ali sem kaj očitnega spregledal, da parazitno napajanje preko pina direkt ne deluje, ali pa je res treba uporabit FET tranzistor, kot nakazano v datasheetu? In seveda dodaten pin? In seveda, kje je tu bistvena razlika?

Stran 1 od 1

Powered by phpBB © 2001,2002 phpBB Group