mikrocontroller.net

Forum: Compiler & IDEs Hilfe zu DS18S20


Autor: Marco M. (marco1987)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich frage jetzt einfach mal so vorne weg:


Ich brauche einen C Code für einen Temperaturfühler DS18S20.

Ich weisss, das das mehrfach hier diskutiert wurde nur ich möchte nichts 
über den Uart senden, keine extras einfach nur ein main programm, wo 
dieser Sensor ausgelesen wird.

Das Datenblatt habe ich schon gelesen nur steht da kein c code oder 
keine Anleitung zum genaueren Vorgehen.

Wenn man mir nur vllt eine Art Grundgerüst des Codes geben könnte oder 
einen guten Link, dann wäre ich sehr dankkbar

Autor: loetkolben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welch Zufall, das versuch ich auch gerade:

Hier mein bisheriger Code (nur Vorhandensein feststellen).
Achtung meine Schaltung nutzt den Parasite-Power mode mit 2 Drähten zum 
Sensor.
// ds18s20 support (data line at PD4, parasite power from port)
static void DS1820_Init(void)
{
  PORTD= (byte)~(1u<<4); // activate internal pullups to avoid floating input pins but..
                    // not for the data line, have external pullup of 4.7k required for DS1820

  // DDRD is initial input (output only if we send or are strong pullup mode)
}

// reset, returns true if any 1-wire device present, false elsewhere
static bool DS1820_Reset(void)
{
  PORTD |= (1u<<4); // prepare by setting port to high
  DDRD  |= (1u<<4); // port now output

  PORTD &= ~(1u<<4); // setting port to low (reset impulse)
  _delay_us(500); // min 480 us 
  DDRD  &= ~(1u<<4); // port now input

  _delay_us(10); // 15-60 us until DS1820 pulls down the bus (and here the pullup resistor must bring the bus from low to high)

  // high detected check (sample some pulses to be independent of spikes)
  byte b;
  for (b= 0; b < 10; ++b) {
    if ((PIND & (1u<<4)) == 0) {
      TRACE("no high after reset (wire problem - no pullup)");
      return false;
    }
  }

  // now wait for the down pulse from DS1820 (typ 25 us, counter=15 with above wait of 10 us)
  for (b= 0; b < 60; ++b) {
    if ((PIND & (1u<<4)) == 0)
      break;
    _delay_us(1);
  }
  if (b==60) {
    TRACE("no down-pulse after reset (no DS1820 present)");
    return false;
  }

  // count the down pulse length
  for (b= 0; b < 255; ++b) {
    if ((PIND & (1u<<4)) != 0)
      break;
    _delay_us(1);
  }

  // test if length meets requirements (typ 80-82 us)
  if (b < 60 || b > 240) {
    TRACE("down pulse length wrong");
    return false;
  }
  return true;
}

int main(void)
{
  AVR_Init();
  LCD_Init();
  LCD_Start();
  LCD_Clear();
  DS1820_Init();
  for (;;) {
    if (DS1820_Reset())
      TRACE("ds1820");
    else
      TRACE("no ds1820");
    waitforKey();
    _delay_ms(100);
  }
}

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Portpin für 1-Wire Devices steuert man sinnvollerweise 
ausschliesslich als "Open-Collector" an. Das heisst bei AVRs: Man setzt 
PORTxy fest auf 0 und steuert den Pin ausschliesslich über die Richtung 
DDRxy. Für 0 schaltet man auf Ausgang, für 1 auf Eingang. Man vermeidet 
so, dass das 1-Wire-Device irgendwann gegen den Porttreiber arbeitet und 
dabei zweiter Sieger bleibt.

Einzige Ausnahme: Wenn der Messzyklus läuft und das Device parasitär 
versorgt wird, dann muss der Pin den Strom liefern. Aber auch nur dann.

Autor: Marco M. (marco1987)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
loetkolben wrote:
> Welch Zufall, das versuch ich auch gerade:
>
> Hier mein bisheriger Code (nur Vorhandensein feststellen).
> Achtung meine Schaltung nutzt den Parasite-Power mode mit 2 Drähten zum
> Sensor.
>

hey cool und dein code gehtbei dir?

Autor: Marco M. (marco1987)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@loetkolben

du müsstest mal sagen welche bibliotheken du verwendet hast wo kommt 
denn byte usw vor?

Autor: Marco M. (marco1987)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
keiner mehr da?


hab meinen tempsensor jetzt an Vcc geschlossen, glaube der ist schon 
kaputt, denn er zeiht soviel Strom, dass das Netzteil in begrenzung (1 
A) geht :-(

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Q.E.D.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt übrigens gut funktionierenden Code von Peter Danegger. Müsste 
sich in der Codesammlung finden lassen.

Autor: Gerd G. (elektrikser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>hab meinen tempsensor jetzt an Vcc geschlossen, glaube der ist schon
>kaputt, denn er zeiht soviel Strom, dass das Netzteil in begrenzung (1
>A) geht :-(

Falsch angeschlossen. Bei parasitär von zwei Möglichkeiten genau die 
verkehrte genommen.

Ein Beispiel gibt es bei Martin Thomas:
http://www.siwawi.arubi.uni-kl.de/avr_projects/tem...

Autor: Sepp Hupf (seppl1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schaut mal bei avrfreaks.net vorbei. Dort gibt es eine 1-wire Bibliothek 
fix und fertig, die bei mir einwandfrei funktioniert.
http://www.avrfreaks.net/index.php?module=Freaks%2...

Wenn der Link nicht geht, nach dem Projekt "1wire" suchen. Dann kommen 
mehrere, das richtig Projekt ist vom 2004-09-02.

Noch ein Hinweis: ich habe mir mal notiert, dass in der Datei "1wire.c" 
in der Funktion "OWTouchReset()" eine Paus nicht richtig hast. Laut 
Datenblatt müsste vor dem Verlassen der Funktion eine Pause der "Länge" 
J (410us) statt I (70us) sein. Gegebenenfalls nochmal im Datenblatt 
überprüfen, aber so funktioniert die Bibliothek bei mir zuverlässig.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder der Pintreiber vom Controller hat sich bei Versuch die Leitung auf 
1 zu ziehen gegenüber dem DS18S20 bei seinem Versuch sie auf 0 zu ziehen 
endgültig durchgesetzt.

Man sollte meinen, dass man den DS18S20 als TO92 parasitär kaum falsch 
anschliessen kann, denn eindeutiger geht es kaum.

Autor: loetkolben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Marco,
das geht super, zu Deiner Frage:

aus einem common header,
// AVR: friendly typedef for a fundamental data type
// policy:
//   use byte, int, char for normal programming, 
//   but uint16_t etc for network data access (int etc may be > 16 bits on some procs)
typedef unsigned char byte;
typedef unsigned int uint;

Bitte jetzt keine Diskussion, manche bevorzugen die C99-Typen uintxx_t 
usw.

Und hier noch das Trace, gibt bei mir auf dem LCD die Texte aus, kannst 
Du erstmal auskommentieren:
#if 1
# define TRACE(x) Trace_LCD_P(PSTR(x))
#else
# define TRACE(x)
#endif


gruß,
jetzt geht es an die Daten...

Autor: loetkolben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Andreas

Danke für den Tip bzgl. Portpin, werd ihn also nicht aktiv auf high 
setzen, außer wenns ans Parasite Power Strom liefern geht.

Ich wollte halt gleich mal den 1-wire modus nehmen, find es cool das man 
den mit zwei Drähten ansteuern kann.

Autor: loetkolben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier nun der aktuelle Stand, Lesen des EPROM codes geht.

Danke für die Tips, habe jetzt keinen aktiven Pullup.
War auch noch n' Fehler in DS1820_Reset(), da muß auch ein Timeslot nach
Melden des DS1820 eingehalten werden.

Display zeigt: 10 74 8a 6b 1 8 0 10 - crc ok

Freu ;-)
// ds18s20 support (data line at PD4, parasite power from port)
static void DS1820_Init(void)
{
  PORTD= (byte)~(1u<<4); // activate internal pullups to avoid floating input pins but..
                    // not for the data line, have external pullup of 4.7k required for DS1820

  // DDRD is initial input (output only if we send or are strong pullup mode)
}


// reset, returns true if any 1-wire device present, false elsewhere
static bool DS1820_Reset(void)
{
  PORTD &= (byte)~(1u<<4); // ensure low value, if we switch port to output (is this paranoia?)

  DDRD  |= (1u<<4); // port now output (reset impulse - low value)

  _delay_us(500); // min 480 us

  DDRD  &= ~(1u<<4); // port now input again

  _delay_us(10); // 15-60 us until DS1820 pulls down the bus (and here the pullup resistor must bring the bus from low to high)

  // high detected check (sample some pulses to be independent of spikes)
  byte b;
  for (b= 0; b < 10; ++b) {
    if ((PIND & (1u<<4)) == 0) {
      TRACE("no high after reset (wire problem - no pullup)");
      return false;
    }
  }

  // now wait for the down pulse from DS1820 (typ 25 us, counter=15 with above wait of 10 us)
  for (b= 0; b < 60; ++b) {
    if ((PIND & (1u<<4)) == 0)
      break;
    _delay_us(1);
  }
  if (b==60) {
    TRACE("no down-pulse after reset (no DS1820 present)");
    return false;
  }

  // count the down pulse length
  for (b= 0; b < 255; ++b) {
    if ((PIND & (1u<<4)) != 0)
      break;
    _delay_us(1);
  }

  // test if length meets requirements (typ 80-82 us)
  if (b < 60 || b > 240) {
    TRACE("down pulse length wrong");
    return false;
  }

  _delay_us(500); // reset time slot must be min 480 us
  return true;
}

// write "0" slot (every write slot must be min 60 us + 1 us recovery time)
static inline void DS1820_Write0(void)
{
  DDRD  |= (1u<<4); // port now output (low value)
  _delay_us(60); // min 60 us
  DDRD  &= ~(1u<<4); // port now input again
  _delay_us(2); // min 1 us, complete the time slot by recovery time
}
// write "1" slot
static inline void DS1820_Write1(void)
{
  DDRD  |= (1u<<4); // port now output (low value)
  _delay_us(2); // min >1 us
  DDRD  &= ~(1u<<4); // port now input again
  _delay_us(60); // min 60 us, complete the time slot by recovery time
}
// read bit "0/1" slot
static inline bool DS1820_Read(void)
{
  DDRD  |= (1u<<4); // port now output (low value)
  _delay_us(2); // min >1 us
  DDRD  &= ~(1u<<4); // port now input again
  _delay_us(10-2); // start sampling the bit, 10 us after initiating transfer

  // sample the line, 16 times
  byte h= 0;
  for (byte n= 0; n < 16; ++n) {
    if ((PIND & (1u<<4)) != 0)
      ++h;
  }

  _delay_us(60); // min 60 us, complete the time slot by recovery time

  // test is this a high or low ?
  if (h==0)
    return false;
  if (h==16)
    return true;
  TRACE("Read unsure!");
  return h > 8;
}

static void DS1820_WriteByte(byte b)
{
  for (byte n=0; n < 8; ++n) {
    if (b & 1)
      DS1820_Write1();
    else
      DS1820_Write0();
    b= b >> 1u;
  }
}

static byte DS1820_ReadByte(void)
{
  byte b= 0;
  for (byte n=0; n < 8; ++n) {
    b= b >> 1;
    if (DS1820_Read())
      b |= 0x80;
  }
  return b;
}

int main(void)
{
  AVR_Init();
  LCD_Init();
  LCD_Start();
  LCD_Clear();
  DS1820_Init();
  for (;;) {
    if (!DS1820_Reset())
      TRACE("no ds1820");
    DS1820_WriteByte(0x33); // read rom cmd
    byte romcode[8];
    for (byte n= 0; n < 8; ++n)
      romcode[n]= DS1820_ReadByte();

    Print_LCD("\n");
    for (byte n= 0; n < 8; ++n) {
      char buf[80];
      ultoa(romcode[n], buf, 16);
      Print_LCD(buf);
      Print_LCD(" ");
    }

    byte crc= 0;
    for (byte n= 0; n < 8; ++n)
      crc= _crc_ibutton_update(crc, romcode[n]);
    if (crc == 0)
      Print_LCD("- crc ok");
    else
      Print_LCD("crc fail:");
    
    waitforKey();
    _delay_ms(100);
  }
}

Autor: Marco M. (marco1987)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die vielen Antowrten, wie gesgat ich bin mir eigentlich sicher 
das ich ncihts falsch angeschlossen habe ich denke eher das der code 
möglicherweise falsch war.

Also hab vcc an 5 V gnd halt an Gnd und Dq über pull up 4k7 dann wurde 
der sensor sehr heiss. Was ist wenn der datenport dauerhaft an 5 V liegt 
durch zb einem flaschen Code. kann er dann kaputt gehen?

Möglicherweise war er auch von anfang an defekt. naja jetzt darf ich mir 
erstmal einen neuen besorgen. welchen würdet ihr mir empfehlen den ds18S 
oder die B version?

MFG

Autor: Marco M. (marco1987)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@loetkolben

du hast immernoch nicht gesagt welche header du einbindet poste daoch 
mal deinen kompletten code von angfang bis ende danke

Autor: Marco L. (c-beginner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ein Beispiel gibt es bei Martin Thomas:
> http://www.siwawi.arubi.uni-kl.de/avr_projects/tem...

Hallo zusammen,

bin neu im Forum und wollte mich mit einer Frage mal vorstellen.
Am Anfang gleich mein outing! In C bin ich eine Niete. Da ich es nun 
eingesehen habe, will ich es ändern. Also kleinere Projekte realisieren.

Umgebung:RNCONTROL 1.4 mit atmega32 bei 16Mhz
         avr-gcc
         Windows XP mit Hyper Terminal an RNCONTROL über MAX232

Arbeite gerade daran einen DS1820 mit dem Code von Martin Thomas 
anzusprechen. Es läuft alles prima, jedoch habe ich versucht den DQ des 
DS1820 auf Port D5 statt D6 mit "define OW_PIN  PD5" in der onewire.h zu 
ändern, ohne Erfolg. (Ursache für den Änderungswunsch ist vorhandene 
Hardware mit der Beschaltung auf PD5)
Wie passe ich den Port an?


Ein weiterer Punkt ist, dass ich mit dem Code eine Ausgabe im Hyper 
Terminal erhalte, die immer in der gleichen Zeile schreibt. Also kein CR 
LF durchführt. Warum ist das so?


Danke für die Hilfe :-)

Autor: Gast^2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

bin im Moment am selben Thema. Ich mache das so:
//code

#define TIMESLOT   70
#define RESET_PULSE  480

//weiterer code

//-----------------------------------------------------------------------------
// Generate a 1-Wire reset, return 1 if no presence detect was found,
// return 0 otherwise.
// (NOTE: Does not handle alarm presence from DS2404/DS1994)
//
// Bus hängt am Pin PC3 
//
uint8_t OWTouchReset(void)
{
  uint8_t result;

  DDRC |= (1<<DDC3);   // Port-PIN als Ausgang konfigureren
  PORTC &= ~(1<<PC3); // Drives DQ low
  _delay_us(RESET_PULSE);
  
  PORTC |=  (1<<PC3); // Releases the bus
  _delay_us(TIMESLOT);
  
  DDRC &= ~(1<<DDC3);   // Port-PIN als Eingang konfigureren
  result = PINC & (1<<PC3); // Sample for presence pulse from slave
  _delay_us(RESET_PULSE-TIMESLOT);
  
  return result; // Return sample presence pulse result
}

aufgerufen wird das dann so:
i=OWTouchReset();

Gruß

Andreas

Autor: Marco L. (c-beginner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

zum Thema Hyper Terminal und kein CR LF:

Im Hyper Terminal kann man unter Einstellungen/ASCII-Konfiguration den 
Punkt "Beim Empfang Zeilenvorschub am Zeilenende anhängen" aktivieren.
Dann klappt es auch mit dem CR LF.

Gruß

Marco L.

Autor: Slevin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ebenfalls den RN-Control Atmega32 @ 16MHz mit einem D18S20+ 
(normale Beschaltung mit Vdd, Code von Martin Thomas) und bei mir 
funktioniert das schon ganz gut.
Im Parasite-Modus gibt der µC konstante +85,0°C aus, kennt jemand eine 
Lösung dafür (Delay anpassen?).
Außerdem kann ich ebenfalls nicht den Port ändern (aktuell auf PD6 (am 
Input Capture Pin)), gibt es da eine Möglichkeit diesen zu ändern, z.B 
auf Port A?

MfG
Slevin

Autor: Schlupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau mal Im Datenblatt nach... Dem Sensor geht während der 
Conwertierung der Saft aus, und somit gibt er nur den alten im 
Scratchpad gespeicherten Wert aus. Hierbei den Initialisierungswert. Das 
heißt du mußt während er convertiert den Datenport aus High setzen. 
Genaue Angaben findest du im Datenblat und Powermode.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.