Forum: Mikrocontroller und Digitale Elektronik DS1820 Liefert nur 0xFF zurück


von Makke (Gast)


Lesenswert?

Habe ein großes Problem mit der Temperaturmessung mit einem DS1820.
Habe das 1-wire Protokoll nach der Application Note 162 von Maxim
imlementiert und auch verstanden. Allerdings liefert der Sensor keine
vernünftigen Werte. Ich bin mir jetzt nicht schlüssig, ob der Fehler
beim Sensor liegt oder in meinem Zeitdelay:

void delay_us(unsigned int x){//x in µSekunden eingeben
   TCNT1=0x0000;
   TCCR1A=0b00000000;//Normal PORT Operation
                           //Normal Timer/Counter
   TCCR1B=0b00000001; //Normal Timer/Counter,CLK(1MHZ)
   while(x>=TCNT1){}  //Timer soll bis x laufen(ca. x µsekunden)
  }    //Timer-Funktion schließen

Als Prozessor benutze ich einen Atmega48 mit 1Mhz internem Oszillator.
Die Datenleitung ist an PB0 angeschlossen. Anschließend wird die
Temperatur auf einem LCD ausgegeben. Die Presence-Funktion erkennt den
Sensor(Geht von 1 auf 0 wenn der Sensor angeschlossen wird), allerdings
muss im Schreib oder Lesevorgang ein Fehler auftreten.

Kann mir jemand ungefähr sagen, was die gesamte delay_us Funktion in
echt an µSekunden braucht?Ich besitze leider kein Oszilloskop.
Vielleicht liegt das Problem darin, daß wenn ich delay_us(15) eingebe,
nicht 15µSekunden als Ergebnis rauskommen, sondern entsprechend mehr
was im Endeffekt zu dem Fehler führt.

Bin für jede Hilfe dankbar!

von Makke (Gast)


Lesenswert?

Kann denn wirklich keiner etwas dazu sagen? Keiner Idee oder sonst
irgendeinen Hinweis?

von Elektrikser (Gast)


Lesenswert?

Ich würde persönlich einen externen Quarz verwenden. Die delay_us ist
schon relativ genau, aber wie sieht es mit dem internen RC-Oszillator
aus? Der hat schon eine ziemliche Ungenauigkeit, deshalb kann man ihn
ja abeichen.

Gruß Elektrikser

von Makke (Gast)


Lesenswert?

Laut Datenblatt wird der ATmega48 mit einem Kalibrierregister auf 8MHz
genau getaktet und dann durch 8 geteilt. Aber vielleicht hast du recht
und nicht mal auf das kann man sich verlassen. Ist der 1-wire Bus denn
so Zeitempfinglich?

von Benedikt (Gast)


Lesenswert?

Der interne Takt des mega48 ist einfach miserabelst stabil.
Irgendwo in de Codesammlung gibt es schon fertige Routinen für den
DS1820 von peter danegger.

von Paul Baumann (Gast)


Lesenswert?

Hallo Elektrikser!
Ich verstehe zwar nichts von C, habe aber mit Bascom mit dem DS
gearbeitet. Du kannst den Sensor selbst abfragen, wann er mit dem
Umwandeln fertig ist. Dann brauchst Du keine Zeit zu programmieren;
er gibt ja selbst die Meldung zurück. Das steht im Datenblatt von
Dallas/Maxim und geht auch so.
MfG Paul
bis er fertig ist

von Makke (Gast)


Lesenswert?

Wie sieht es denn mit dem internen RC-Oszillator vom Mega8 aus? Ist der
auch so miserabel? Den hätte ich nämlich hier noch auf Lager und ließe
sich schnell tauschen!

von Elektrikser (Gast)


Lesenswert?

Hallo Paul,

das ist vollkommen richtig. Hat aber meines Wissens einen Nachteil:
Wenn man mit delays arbeitet ist aber die Buszeit kürzer. Das
Setzen/Rücksetzen von einen Bit in einem I/O-Register benötigt bei den
delays z.B. einen Zyklus, aber 14 Zyklen beim variablen Bus (wenn man
auf die Meldung vom Sensor immer wartet).

Gruß Elektrikser

von Paul Baumann (Gast)


Lesenswert?

Hallo Elektrikser!
Alles klar, da habe ich wieder was Neues erfahren. Naja, wie gesagt
ich habe stur den Ablauf, wie er im Datenblatt stand in ein Programm
eingesetzt, die Berechnungsformel "zersägt" (Bascom kann nicht mehr
als 2Terme auf einmal bearbeiten) und es mißt. Ich erzeuge einen
Interrupt mit 1 Sekunde Abstand und in der Interruptroutine drin
sitzt die Abfrage des Fühlers.
MfG Paul

von Alex10178 (Gast)


Lesenswert?

Hallo

Das gleiche Problem hatte ich auch mit einem DS1822 und dem M16c62
Mikrocontroller!

Das Problem liegt einen einen Zeitschlitzen!! die müssen genau so lang
sein wie es im Datenblatt steht!

Ich habe das Problem mit einem Logikanalyser gefunden! die Zeiten waren
viel zu lang!!

von Makke (Gast)


Lesenswert?

Ich komme einfach nicht mehr weiter. Mittlerweile kann ich die 1-wire
Funktionen auswendig. Vielleicht hat jemand Lust sich meine Routinen
anzuschauen, ob er noch einen Fehler entdeckt. Ich kann keinen mehr
finden, außer dass es an den Zeitroutinen liegen könnte oder der Sensor
kaputt ist. Danke für eure Hilfe!

Hier der Code:

void DQhigh(void){
   DDRB=0x00;       //PORTB ist Eingang
   PORTB=0x00;     //High-Z
   }
void DQlow(void){
   DDRB=0xFF;              //PORTB ist Ausgang
   PORTB=0x00;
   }

void delay_us(unsigned int x){ //Zeitverzögerung in µSekunden
   TCNT1=0x0000;         //Zähler auf 0 setzen
   TCCR1A=0b00000000;    //Normal PORT Operation,
                               //NormalTimer/Counter
   TCCR1B=0b00000001;    //Normal Timer/Counter,CLK(1MHZ)
   while(x>=TCNT1){}  //Timer soll bis x laufen(ca. x usekunden)
  }         //Timer-Funktion schließen

unsigned char ow_reset(void){
  unsigned char presence,temp;
  DQlow();         //pull DQ line low
  delay_us(480);       //leave it low for 480µs
  DQhigh();       //allow line to return high
  delay_us(70);       // wait for presence
  temp=PINB&0x01;
  presence=(PINB&0x01);      //get presence signal
  delay_us(400);       //wait for end of timeslot
  return(presence);     //presence signal returned
}           // 0=presence OK ; 1= no part False

unsigned char read_bit(void){
  unsigned char i,temp;
  DQlow();       //pull DQ low to start timeslot
  DQhigh();    //then return high
  delay_us(15);    //delay 15µs from start of timeslot
  temp=PINB&0x01;    //DQ einlesen
  delay_us(100);
  return(temp);    //return value of DQ line
  }
unsigned char read_byte(void){
  unsigned char i;
  unsigned char value=0;

  for(i=0;i<8;i++){
    if(read_bit())value|=0x01<<i;     //reads byte in,one bit at a time
and then shifts left
    delay_us(120);    //wait for rest of timeslot
    }
    return(value);
  }

void write_bit(char bitval){
   DQlow();    //pull DQ low to start timeslot
   if(bitval==1)DQhigh();  //return DQ high if write 1
   delay_us(100);
   DQhigh();
   }

void write_byte(char val){
   unsigned char i;
   unsigned char temp;

   for(i=0;i<8;i++){
     temp=val>>i;
    temp&=0x01;
    write_bit(temp);
    }
   delay_us(100);
   }

unsigned char read_temp(void){
  {
  unsigned char get[10],i;
  unsigned char temp_lsb,temp_msb;
  int k;
  unsigned char temp_f,temp_c;
  ow_reset();
  write_byte(0xCC); //Skip ROM
  write_byte(0x44); // Start Conversion
  for(i=0;i<20;i++){
  delay_us(64000);} //Warten bis Wandlung fertig

  ow_reset();
  write_byte(0xCC); // Skip ROM
  write_byte(0xBE); // Read Scratch Pad
  for (k=0;k<9;k++){get[k]=read_byte();}
  temp_msb = get[1]; // Sign byte + lsbit
  temp_lsb = get[0]; // Temp data plus lsb

        return temp_lsb;
        }
}

von Alex10178 (Gast)


Lesenswert?

Hallo

das sollte dir helfen!

http://www.m16c.de/PDF/AppNotes/APP_EXTMEM/reu05b0037_m16cap.pdf

Viel Spaß damit!
damit läuft es bei mir!

von A.K. (Gast)


Lesenswert?

Teste mal die delay()-Routine. Geht auch ohne Oszi.

Beispielsweise ein 10µs-Delay 100000mal hintereinander, und dann, also
offiziell jede Sekunde, eine LED umschalten.

Ich glaube kaum, dass es auch nur annähernd 0,5Hz werden. Weil die
Routine auch bei delay_us(0) schon um die 10µs mehr verbrutzelt als
vorgesehen.

von Makke (Gast)


Lesenswert?

Test war erfolgreich. Hab ein Delay von 100µSekunden eingestellt und das
10000 mal in einer Schleife durchlaufen lassen. Kam auf jeden Fall was
unter einem Hertz raus. Hat denn jemand eine Idee wie ich dann einen so
kurzen delay von etwa 15µSekunden mit einem Takt von 1MHz realisieren
kann? Wenn ich eine For-Schleife benutze bin ich doch bestimmt auch bei
for(i=0;i<0;i++){} auch schon wieder über 15µSekunden,oder nicht?
Danke schon mal für eure Tips.So weiß ich immerhin schon mal, dass das
Problem am Delay liegt und nicht an den Funktionen selber.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.