Forum: Projekte & Code DS1820, DS18B20 in C


von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Anbei der komplette Code für 1-Wire in C auf dem AVR.

Wer meine AVR Assembler und C51 Beispiele schon kennt, wird große
Ähnlichkeiten entdecken.

Es werden alle gefundenen Sensoren in 0,1°C Schritten ausgegeben.
Dabei erfolgt die Anzeige der DS1820 nur in 0,5°C Schritten.
Die Routine muß für negative Werte leicht geändert werden.
Die Ausgabe erfolgt über die UART.

Die nötigen Delay-Zeiten für den 1-Wire werden mit dem Timer erzeugt.
Dadurch ergibt sich eine Unabhängigkeit vom Compiler und die
Quarzfrequenz kann einfach geändert werden.


Peter

von Matthias Reiter (Gast)


Angehängte Dateien:

Lesenswert?

@Peter:
Ich mache erste Gehversuche mit C und WINAVR.
Dein 1-wire Beispiel bekomme ich aber nicht fehlerfrei compiliert.
Ich bekomme nach make all folgende Fehler:

-------- begin --------
avr-gcc (GCC) 3.3.2
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is
NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.


Linking: main.elf
avr-gcc -mmcu=at90s8535 -I. -g   -Os -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -Wall
-Wstrict-prototypes -Wa,-adhlns=main.o  -std=gnu99
-Wp,-M,-MP,-MT,main.o,-MF,.dep/main.elf.d main.o  1WIRE.C DELAY.C
TIMEBASE.C TEMPMEAS.C UART.C   --output main.elf
-Wl,-Map=main.map,--cref    -lm
cc1plus.exe: warning: "-std=gnu99" is valid for C/ObjC but not for
C++
cc1plus.exe: warning: "-std=gnu99" is valid for C/ObjC but not for
C++
cc1plus.exe: warning: "-std=gnu99" is valid for C/ObjC but not for
C++
TIMEBASE.C: In function `void init_timer()':
TIMEBASE.C:40: warning: assignment of negative value `-1' to `volatile
unsigned
   int'
TIMEBASE.C:40: warning: argument of negative value `-1' to `unsigned
int'
cc1plus.exe: warning: "-std=gnu99" is valid for C/ObjC but not for
C++
TEMPMEAS.C: In function `void read_meas()':
TEMPMEAS.C:37: error: invalid conversion from `unsigned char*' to
`char*'
TEMPMEAS.C:38: error: invalid conversion from `unsigned char*' to
`char*'
TEMPMEAS.C:45: error: invalid conversion from `unsigned char*' to
`char*'
TEMPMEAS.C:46: error: invalid conversion from `unsigned char*' to
`char*'
TEMPMEAS.C:47: error: invalid conversion from `unsigned char*' to
`char*'
TEMPMEAS.C:48: error: invalid conversion from `unsigned char*' to
`char*'
cc1plus.exe: warning: "-std=gnu99" is valid for C/ObjC but not for
C++
UART.C: In function `void uinit()':
UART.C:6: error: `UBRRL' undeclared (first use this function)
UART.C:6: error: (Each undeclared identifier is reported only once for
each
   function it appears in.)
UART.C:7: error: `UBRRH' undeclared (first use this function)
UART.C:8: error: `UCSRA' undeclared (first use this function)
UART.C:9: error: `UCSRC' undeclared (first use this function)
UART.C:9: error: `URSEL' undeclared (first use this function)
UART.C:9: error: `UCSZ1' undeclared (first use this function)
UART.C:9: error: `UCSZ0' undeclared (first use this function)
UART.C:10: error: `UCSRB' undeclared (first use this function)
make.exe: *** [main.elf] Error 1

> Process Exit Code: 2

Müssen bei Deinem Code SFR-Bezeichnungen für den AT90S8535 angepaßt
werden?

Was ist mit den Umwandlungen von Uchar zu Char??

Liegen die ganzen Fehlermeldungen möglicherweise an meinem makefile?

Ich bin dankbar für jeden Hinweis.

BTW: Danke für Deine zahlreichen Codebeispiele.

Gruß

Matthias

von Peter D. (peda)


Lesenswert?

Tut mir leid, aber mit dem make kenne ich mich nun überhaupt nicht aus.

Ich compiliere immer in der DOS-Box mit einer Batch:


@echo off

:set mcu=90s2313
:set mcu=tiny26

set mcu=mega8

set main=test

set ac=c:\avr\winavr

path %ac%\bin;%path%
avr-gcc.exe -Os -mmcu=at%mcu% -Wall -g -o main.out *.c
if not exist main.out goto end
cmd /c avr-objdump.exe -t -h -S main.out >%main%.lst
cmd /c avr-objcopy.exe -O ihex main.out %main%.hex
avr-size.exe -B main.out
del main.out

:end


Peter

von Matthias Reiter (Gast)


Lesenswert?

@ Peter:

Danke für die Antwort. Ich werds mal auf Deine Art probieren.

Zwei Fragen zu Deinen Code habe ich noch:

1. Für welchen Controller hast Du Ihn geschrieben? Für den Mega8, wie
Dein Batchfile andeutet? Ich könnte dann leichter die Fehlermeldungen
mit den SFR-Definitionen verstehen.

2. Sind die Fehlermeldungen zu den Umwandlungen von uchar* nach char*
in der TEMPMEAS.C berechtigt?

Beispiel:
TEMPMEAS.C:37: error: invalid conversion from `unsigned char*' to
`char*'
Zeile 37:   sprintf( s, "%02X ", id[i] );
s ist uchar

Grüße Matthias

von Matthias Reiter (Gast)


Lesenswert?

@Peter:

Frage 1 hat sich erledigt: bei mcu=atmega8 sind die Fehlermeldungen zu
den SFRs weg.

Matthias

von Ronny Schulz (Gast)


Lesenswert?

Ich möchte mich nochmal bei Peter bedanken. Lange hatte ich mit dem
1-Wire-Protokoll rumgefummelt. Und irgendwie hat nichts so recht
geklappt. Inzwischen geht es endlich, da ich hier ein sehr gutes
Beispiel hatte. Somit bin ich zumindest schon in der Lage so ein Teil
auszulesen.

Was noch offen ist, wäre Search-ROM und Match-ROM. Das ist wirklich
sehr schwer zu verstehen und vor allem umzusetzen, wenn man mal das
iButton-Guide gelesen hat. Obwohl ja alles ausführlich dasteht.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Matthias: Die Dateinamen müssen auf ".c" enden, sonst behandelt sie
der Compiler als C++, nicht C:
"cc1plus.exe: warning: "-std=gnu99" is valid for C/ObjC but not for
C++"

von Matthias Reiter (Gast)


Lesenswert?

@ Andreas:
Danke für den Hinweis. Meine C-Dateien waren "*.C".
Ich verstehe deshalb die Meldung von make nicht.
Ich nehme an, dass ich irgend einen Unsinn in meinem Makefile habe.

von Matthias Reiter (Gast)


Lesenswert?

Nun funktioniert es. Danke

von Martin Schuhmacher (Gast)


Lesenswert?

das gepostete batch file bringt bei mir
[...Warnings...]
uart.c: In function `uinit':
uart.c:6: error: `UBRRL' undeclared (first use in this function)
uart.c:6: error: (Each undeclared identifier is reported only once
uart.c:6: error: for each function it appears in.)
uart.c:7: error: `UBRRH' undeclared (first use in this function)
uart.c:8: error: `UCSRA' undeclared (first use in this function)
uart.c:9: error: `UCSRC' undeclared (first use in this function)
uart.c:9: error: `URSEL' undeclared (first use in this function)
uart.c:9: error: `UCSZ1' undeclared (first use in this function)
uart.c:9: error: `UCSZ0' undeclared (first use in this function)
uart.c:10: error: `UCSRB' undeclared (first use in this function)
uart.c: In function `uputchar':
uart.c:16: error: `UCSRA' undeclared (first use in this function)

die dateien sind *.c
in der main.h habe ich noch
#include <avr/signal.h>
verbessert sowie in der batch den pfad geändert.

von Peter D. (peda)


Lesenswert?

@Martin,

lies alle Beiträge in Ruhe durch, besonders die von Matthias.


Peter

von Michael (Gast)


Lesenswert?

@ Peter,
im Hauptprogramm setzt du die Sekunden auf 0. Must du eigentlich nicht
auch den Prescaler auf 0 setzen, um das Timing sicherzustellen? In
dieser Applikation evtl. nicht so wichtig, aber durch irgendwelche
Interrupt-Sachen kann der Prescaler ja weiter zählen, bis im
Hauptprogramm Sekunden auf Null gesetzt werden.
Michael

von Peter D. (peda)


Lesenswert?

Hast recht, guter Programmierstil ist es, alle globalen Variablen zu
initialisieren, damit das Programm besser lesbar ist.

Oft wird das Initialisieren mit 0 weggelassen, da das der Compiler
automatisch macht.


Peter

von Michael Kramer (Gast)


Lesenswert?

Hi ...

nachdem ich Sie nirgends finden kann - Peter Dannegger hat mal Routinen
in C51 veröffentlicht - gibts die noch irgendwo ?

danke
  michael

von Peter D. (peda)


Lesenswert?


von Leo (Gast)


Lesenswert?

@peter

... On bigger applications this time may be longer, but should not
exceed 500ms. Otherwise the user can think, there is Windows working
inside ...

W U N D E R B A R E S    S T A T E M E N T!!!


leo

von Andreas (Gast)


Lesenswert?

Hallo liebes Forum,

hat jemand einen C-oder Assembler -code für den ds18s20 an einem 8051?
Oder einen entsprechenden Link?

MFG
Andreas

von Bernhard Waterkamp (Gast)


Lesenswert?

Hi!
Ich brauche dringend Hilfe. Ich möchte den DS1820 mit meiner C-Control
auslesen. Allerdings hab ich nur einen Assemblerocde ohne viele
Erklärungen (http://www.b-kainka.de/ccbsp.htm; ganz unten).
Kennt wer einen Beispielcode in Basic und Assemblercode?

Gruß

Bernie

von Elektrikser (Gast)


Lesenswert?

C-Control I oder II?

Bei der C-Control I wird es nicht möglich sein das ganze in Basic zu
machen. Das wird zu langsam und der Ein-Draht-Bus ist im Timing
ziemlich empfindlich. Du wirst um Assembler nicht herumkommen, und da
gehen ohne Tricks nur 256 Bytes, wenn ich mich nicht irre.

Gruß Elektrikser

von Bernhard Waterkamp (Gast)


Lesenswert?

Hi!
Ja ich habe die C-Control I. Wenn Assemblercode dabei ist, wäre es ja
nicht schlimm. Aber die oben genannten Seite beinhaltet nur den
Assemblercode. Ich weiß nur nicht wie das Basic-Programm dazu
aussieht.

Gruß Bernie

von Elektrikser (Gast)


Lesenswert?

Autsch, die CControl ist bei mir schon lang her. Aber die asm-Datei
müsste mit "syscode" in das Basic-Programm eingebunden werden. Und
der Rest? Hmm, Das asm-Programm hat auf der linken Seite Sprungmarken,
die du im Basic-Programm anspringen kannst. Da gab es noch den
"sys"-Befehl. Schau mal in deine Beschreibung rein.
In dem Assemblerprogramm müsste es; reset, byte_read, byte_write, delay
geben.
Ich muss mal suchen, ob ich überhaupt noch was mit der CControl
habe...

Ich hoffe, dass ich da jetzt nicht zuviel durcheinander gebracht habe.

Gruß Elektrikser

von Bernhard Waterkamp (Gast)


Lesenswert?

Wie ich den Assembler in den Code einbinde und "anspringe" habe ich
auch schon herrausgefunden. Aber ich glaube, dass es im Basic-Programm
noch mehr Code erforderlich ist um die Temperatur auszulesen, denn als
Kommentar bei der Variabeldeklarierung steht: "bas_2  .equ $b8 ;
zweite Basic Variable => Daten Rein&Raus". Falls du da durchblickst:
Ich habe ein BASIC-Programm gefunden, aber es ist recht komplex und ich
habe keine Erklärung dazu gefunden.
(http://homepages.compuserve.de/BernardWeiler/DS1820.BAS).
Ich habe den Code ausprobiert und auch etwas herum experimentiert aber
ich bekomme nur Fehlermeldungen, dass der Sensor nicht gefunden worden
ist. Da ich von diesem Code wenig Ahnung und keine Informationen habe,
weiß ich nicht wo ich mit der Fehlersuche beginnen soll.

Gruß Bernie

von Thomas (Gast)


Lesenswert?

Auch wenn ich diesen alten Thread mal wieder rauskrame, habe ich mal
eine Frage zu der Leseroutine:
Ich versuche gerade meine eigenen 1-Wire Funktionen zu schreiben, da
das Lesen aber nicht so recht funktioniert habe ich mir mal die
Funktionen von Peter angesehen.

Aus dem Datenblatt des DS1820 verstehe ich den Read-Time Slot
folgendermaßen:

- 1 Byte über den 1-Wire Bus lesen:
Ein Read-Time-Slot hat eine Mindestdauer von 60µs. Zwischen den
einzelnen Slots muss einer Erholungszeit von mindestens 1µs liegen.
Der Slot wird gestartet, indem der Master den Bus für mindestens 1µs
auf 0 zieht, und dann wieder vom Pull-Up auf 5V gehen lässt.
Der DS1820 überträgt daraufhin sein Bit:
Lesen einer 0:
  Der DS1820 zieht den Bus nach der fallenden Flanke vom Master auf 0.
  Das Signal muss innerhalb von 15µs nach Beginn vom Master gesampelt
werden.
Lesen einer 1:
 Der DS1820 lässt den Bus weiterhin auf 5V (vom Pull-Up hochgezogen)
 Das Signal muss innerhalb von 15µs nach Beginn vom Master gesampelt
werden.

So habe ich das auch programmiert, erhalte aber keine Daten zurück.
(Ich habe vorher ein READ ROM (0x33) gesendet)

Die Funktion w1_bit_io() von Peter funktioniert auch anders:
Er programmiert erst den Pin als Ausgang, nach 1µs Wartezeit dann
wieder als Eingang, liest dann nach 14µs den Pin ein.
Zum Abschluss wird der Pin nochmals als Eingang programmiert (wohl nur,
weil die Funktion auch zum Bits senden benötigt wird).

Wieso funktioert das bei Peter, obwohl er den Ausgang ja garnicht auf 0
zieht und dem Slave mitzuteilen dass der Slot gestartet wird?

von Peter Dannegger (Gast)


Lesenswert?

@Thomas

es wird ja ein open-drain Ausgang benötigt, d.h. das Ausgangsbit bleibt
immer auf 0 und mit dem Direktionbit wird dann nur der untere Transistor
ein- bzw. ausgeschaltet.


Peter

von Thomas (Gast)


Lesenswert?

Achso OK, das aktive auf 0 setzen des Ausgangs machst du nur einmal in
der 1-Wire Initialisierungsroutine. Naja, reicht ja auch eigentlich, da
diese vor jedem Übertragungsbeginn sowieso einmal durchlaufen wird.

von Simons (Gast)


Lesenswert?

Hallo!
Wo ich syscode ds1820.obj erhalten kann, das ich im Programm benötige.
Danke!

von xzibit (Gast)


Lesenswert?

Das Du kann erhalten compilieren. Mit Compiler.

von Wolf4124 (Gast)


Lesenswert?

Hallo

Ich wollte einen anderen Pin verwenden.
Habe die Zeilen

#define OW_PIN  PD6
#define OW_IN   PIND
#define OW_OUT  PORTD
#define OW_DDR  DDRD
 auf

#define OW_PIN  PC5
#define OW_IN   PINC
#define OW_OUT  PORTC
#define OW_DDR  DDRC

geändert.
Ich verwende einen ATMEGA8.
Es funkt super aber eben nur mit dem PD6.
Wenn ich die andere Festlegung verwenden funkt es auch.?????
Aber nur über den PD6????
Vielleicht habe ich ja etwas übersehen.

Gruß

von Peter D. (peda)


Lesenswert?

@Wolf4124

diese Macros stehen nirgends in meinem Code.

Ist also kein Wunder, daß auf nicht verwendete Macros keine Reaktion
erfolgt.


Peter

von wolf4124 (Gast)


Lesenswert?

Upps

Falsche Baustelle.  ;-(

Gruß

von H-Joachim (Gast)


Lesenswert?

Hallo Peter.

Habe Deinen Source auf einem ATMEGA16 mit 8Mhz Quartz
ausprobiert. Nachdem es immer die Meldung "DATA_ERR" gab,
habe ich dann angefangen mit einem Scope zu messen.
Als erstes habe ich mir eine kleine Schleife geschrieben,
mit der ich messen konte, ob die delay-Funktion richtig
funktioniert (timing). Das tat sie.
Ich habe dann gesehen, daß Du bei einem READ immer erst
nach 15usec. die Daten des Sensors einließt. Laut Spec.
sollte das aber innerhalb von 15usec. passieren.
Habe dann Deinen Code zum Testen wie folgt "gepatcht":

#if 0
uchar w1_bit_io( bit b )
{
  cli();
  W1_DDR |= 1<<W1_PIN;
  DELAY( DELAY_US( 1 ));
  if( b )
    W1_DDR &= ~(1<<W1_PIN);
  DELAY( DELAY_US( 15 - 1 ));
  if( (W1_IN & (1<<W1_PIN)) == 0 )
    b = 0;
  DELAY( DELAY_US( 60 - 15 ));
  W1_DDR &= ~(1<<W1_PIN);
  sei();
  return b;
}
#else
uchar w1_bit_io( bit b )
{
  cli();
  W1_DDR |= 1<<W1_PIN;
  DELAY( DELAY_US( 1 ));
  if( b )
  {
    W1_DDR &= ~(1<<W1_PIN);
    DELAY( DELAY_US( 10 - 1 )); // beim LESEN kurzer delay
  }
  else
    DELAY( DELAY_US( 15 - 1 ));
  if( (W1_IN & (1<<W1_PIN)) == 0 )
    b = 0;
  DELAY( DELAY_US( 60 - 15 ));
  W1_DDR &= ~(1<<W1_PIN);
  sei();
  return b;
}
#endif

Damit funktionierte es.
Der DS1820 hat bei einer "0" das Signal schon nach 15usec
wieder auf 1 gesetzt. Das hatte ich mit dem Scope gesehen.
Darum natürlich "DATA_ERR".
Jetzt frage ich mich, wieso hat das bei Euch funktioniert?
Sind die Teile vom Timing so unterschiedlich? Allerdings laut
meinem Datenblatt (DS18S20) soll man auch innerhalb der 15usec lesen.
Liegt es an dem DS18S20 (S!!!!)?

Hast Du eine Idee?

Danke und Gruß
Joachim

von peter dannegger (Gast)


Lesenswert?

@Joachim,

ich habs nicht nachgemessen.

Ich hab auch einige Meter Leitung dazwischen, deren Kapazität wird wohl
die Flanke etwas verzögern.

Der genaue Wert, wann der Slave wieder auf 1 geht, darf laut Datenblatt
irgendwo zwischen 15µs und 60µs liegen.

Du hast warscheinlich ein Exemplar erwischt, was genau am unteren Limit
liegt.


Peter

von Dubbster (Gast)


Angehängte Dateien:

Lesenswert?

kann mir jemand beim 1 wire port helfen,ich muss das in c programmiern!

von Dubbster (Gast)


Lesenswert?

hey kann mir wer sagen,ob das hier richtig ist!

#include<reg517.h>
#include<stdio.h>


//---------------------------------------
// Initialize serial port
//---------------------------------------



void InitSerial(void)
{
    TMOD = 0x20;    // Timer 1=8-Bit-relod
    TH1  = 0xFD;    // TH1
  TR1   = 1;      // Timer 1 starten
  SCON = 0x52;    // Freigabe von Sender & Empfänger
}

bei mir steht immer undefined identifier! jedoch sollte es meiner 
meinung stimmen,blick da jetzt ned durch

von Serge Polish (Gast)


Lesenswert?

Good day, Peter!

Thanks for the "1Ware.zip"!

Best regards, P.S.

von Karl (Gast)


Lesenswert?

Hallo

Ich habe das Programm ProfiLab Expert. Mit dem Programm kann man 
Schaltungen am PC realisieren.
Für meine Anwendung (Heizungsregeler) muss ich Temperaturen erfassen die 
ich über den 1 wire Bus auslesen möchte. Es gibt fertige Lösungen z.B. 
von der Firma Hygrosens, die mir aber etwas zu teuer sind.
In ProfiLab kann man aber DLL Dateien importieren die in C++ oder Delphi 
geschrieben werden müssen.
Gibt es eine DLL um den 1 wire Bus in Profilab Expert auszulesen um 
damit die Temperatur zu messen?

Ich habe hier einmal einen Auszug der Hilfe zum DLL-Import von ProfiLab 
reingestellt.


DLL-Import

Funktion
Mit dem DLL-Import haben Sie ein Bauteil zur Verfügung, dass eine 
Programmierschnittstelle darstellt, die es ermöglicht selbst eigene 
Bauteile, z.B. zur Ansteuerung spezieller Hardware, o.ä., für ProfiLab 
zu programmieren. Dazu benötigen Sie natürlich eine Programmiersprache, 
die es ermöglicht DLL-Dateien (Dynamic Link Libraries) zu erzeugen, 
sowie die entsprechenden Programmierkenntnisse.

Bei der Programmierung der DLL müssen Sie sich an bestimmte Vorgaben von 
ProfiLab halten. So muss Ihre DLL bestimmte Routinen enthalten und 
exportieren, mit denen Sie die Anzahl der Ein- und Ausgänge, deren 
Bezeichnung und natürlich die interne Funktion des Bauteils bestimmen. 
Folgende Funktionen muss Ihre DLL bereitstellen:

Delphi: function NumInputs: Byte;
C++: unsigned char _stdcall NumInputs()
Das Ergebnis dieser Funktion muss einen Bytewert mit der gewünschten 
Anzahl von Bauteileingängen zurückliefern.

Delphi: function NumOutputs: Byte;
C++: unsigned char _stdcall NumOutputs()
Das Ergebnis dieser Funktion muss einen Bytewert mit der gewünschten 
Anzahl von Bauteilausgängen zurückliefern.

Delphi: function InputName(Channel: Byte): ShortString;
C++: void _stdcall GetInputName(unsigned char Channel, unsigned char 
*Name)
Das Ergebnis dieser Funktion muss einen Text für die Beschriftungen 
jedes Eingangs (Channel) zurückliefern. Das Bauteil ruft diese Funktion 
für jeden Eingang (Channel) auf und fragt so die Beschriftung für jeden 
Eingangs-Pin ab. Der Parameter CHANNELS gibt an welcher Pin gemeint ist, 
und läuft von 0 bis NumInputs-1.

Delphi: function OutputName(Channel: Byte): ShortString;
C++: void _stdcall GetOutputName(unsigned char Channel, unsigned char 
*Name)
Das Ergebnis dieser Funktion muss einen Text für die Beschriftungen 
jedes Ausgangs (Channel) zurückliefern. Das Bauteil ruft diese Funktion 
für jeden Eingang (Channel) auf und fragt so (von oben nach unten) die 
Beschriftung für jeden Eingangs-Pin ab. Der Parameter CHANNELS gibt an 
welcher Ausgangs-Pin gemeint ist, und läuft von 0 bis NumOutputs-1.

Delphi: Procedure Calculate(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CCalculate(double *PInput, double *POutput, double 
*PUser)
Die ist die zentrale Berechnungsroutine Ihres DLL-Bauteils, die die 
Funktion des Bauteils definiert. Mit den Parametern PINPUT, POUTPUT und 
PUSER bekommt die Routine drei Zeigervariablen (Pointer) übergeben die 
folgende Funktion haben:

Der Pointer PINPUT zeigt auf einen Speicherbereich, der dazu dient die 
Eingangswerte des Bauteils an die DLL zu übergeben.
Der Pointer POUTPUT zeigt auf einen Speicherbereich, der dazu dient die 
berechneten Ausgangswerte der DLL an das Bauteil zurückzugeben.
Der Pointer PUSER stellt einen Pointer auf einen Speicherbereich zur 
Verfügung, in dem die DLL eigene (lokale) Werte speichern kann. 
Hintergrund: Variablen, die die DLL selbst deklariert sind globale 
Variablen. Werte die in diesen Variablen gespeichrt werden, würden sich 
gegenseitig überschreiben, wenn man dieselbe DLL mehr als einmal in 
einem ProfiLab-Projekt verwendet. Um lokale Werte speichern zu können, 
stellt ProfiLab der DLL den lokalen Speicherbereich zur Verfügung, auf 
den PUSER zeigt. (Alternativ kann man auch Variablen in der DLL selbst 
deklarieren. Dann muß man die DLL aber mehrfach unter verschiedenen 
Dateinamen speichern und importieren, um sie mehrfach in einem 
ProfiLab-Projekt verwenden zu können.)

Alle drei Pointer PINPUT, POUTPUT und PUSER zeigen jeweils auf einen 
Speicherbereich in dem 100 Variablen vom Typ EXTENDED in einem Array 
abgelegt sind. Die Pointer sind vom Typ PDLLParams, dessen Deklaration 
in Delphi so aussieht:

type TDLLParams = array[0..100] of extended;
     PDLLParams = ^TDLLParams;

Die Extended-Variablen des Pointers PINPUT enthalten die 
Eingangszustände des Bauteils. Auf den Wert eines Eingangs des Bauteils 
können Sie wie folgt zugreifen:

PInput^[0] enthält den numerischen Eingangswert des 1. Eingangs,
PInput^[1] enthält den numerischen Eingangswert des 2. Eingangs, usw.

Die Extended-Variablen des Pointers POUTPUT nehmen die Ausgangszustände 
des Bauteils auf. Um den Wert der Ausgänge des Bauteils zu setzen, 
benutzen Sie:

POutput^[0] nimmt den numerischen Ausgangswert des 1. Ausgangs auf,
POutput^[1] nimmt den numerischen Ausgangswert des 2. Ausgangs, usw.

Entsprechend können Sie mit PUser^[0] bis PUser^[99] frei verwenden um 
eigene Werte zu speichern. Die Werte in diesen Variablen werden von 
ProfiLab mit in der Projektdatei abgespeichert, und sind so beim 
nächsten Laden des Projekts wieder verfügbar. Die Variable PUser^[100] 
wird von ProfiLab gesetzt, und enthält die Nummer des DLL-Bauteils in 
Ihrem Projekt: 1 für DLL1, 2 für DLL2, usw.

Die Routine Calculate wird im RUN-Modus ständig von ProfiLab aufgerufen, 
um neue Eingangswerte zu übergeben und neue Ausgangswerte für das 
Bauteil abzurufen. Diese Routine muss daher unbedingt zeitoptimiert 
programmiert werden, und sollte auf keinen Fall Pausen (in Form von 
SLEEP-Befehlen oder Warteschleifen) enthalten. Nach dem Abfragen der 
Eingangswerte und dem Setzen der Ausgangswerte sollte die Routine so 
schnell wie möglich wieder verlassen werden. Die Rechenzeit für die 
Routine wirkt sich unmittelbar auf die Simulationsfrequenz von ProfiLab 
aus.

Delphi: Procedure SimStart(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CSimStart(double *PInput, double *POutput, double 
*PUser)
Diese Routine wird beim Starten eines ProfiLab-Projekt aufgerufen, und 
kann z.B. benutzt werden, um Anfangswerte Ihrer DLL zu initialisieren. 
Die Funktion der Parameter wurde zuvor bereits beschrieben.

Delphi: Procedure SimStop(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CSimStop(double *PInput, double *POutput, double 
*PUser)
Diese Routine wird beim beenden des RUN-Modus eines ProfiLab-Projekt 
aufgerufen, und kann z.B. um geöffnete Dateien zu schliessen, etc.. Die 
Funktion der Parameter wurde zuvor bereits beschrieben.

Delphi: Procedure Configure(UserValues: PDLLParam);
C++: void _stdcall CConfigure(double *PUser)
Sofern Ihre DLL diese Prozedur exportiert, wird die Schaltfläche 
EINSTELLUNGEN... im Eigenschaftendialog des DLL-Bauteils aktiviert. Wird 
dann diese Schaltfläche betätigt, so springt ProfiLab die 
CONFIGURE-Prozedur in Ihrer DLL an. Hier können Sie dann z.B. einen 
eigenen Dialog zum Konfigurieren Ihrer DLL ausführen.

Mit diesen Routinen haben Sie alle Möglichkeiten um eigene Bauteile für 
ProfiLab programmieren zu können. Der Fantasie sind dabei keine Grenzen 
gesetzt. Sie könnten z.B. Treiber für eigene Hardwaregeräte 
programmieren, einen eigene Programminterpreter integrieren, oder 
beliebige andere komplexe Berechnungen in einer DLL ausführen. Um 
digitale Bauteile zu programmieren, setzen Sie den numerischen 
Ausgangswert auf 5 um einen HIGH-Pegel zu erzeugen und auf 0 um einen 
LOW-Pegel zu erzeugen. Ebenso entspricht ein Eingangswert >2.5  einem 
logischen HIGH-Pegel und ein Eingangswert darunter einem logischen 
LOW-Pegel.

Beim Laden einer DLL-Datei über den Eigenschaften-Dialog des 
DLL-Bauteils, werden die aus der DLL importierten Routinen zur Kontrolle 
aufgelistet. Das Bauteil erscheint danach mit den von Ihnen definierten 
Ein- und Ausgängen im Schaltplan.  Um den Aufrufkonventionen von 
C-Compilern zu genügen, kann dem Namen von exportierten Funktionen und 
Prodeduren jeweils auch ein Unterstrich _ vorangestellt sein, z.B. 
_SimStart statt SimStart. Derart exportiere Routinen werden 
gleichermassen von ProfiLab erkannt und importiert. Beim Compilieren 
eigener DLL-Projekte müssen Sie ggf. darauf achten, dass Sie die 
Linkeroption "Dynamische RTL" deaktivieren. Anderfalls kann Ihre DLL auf 
Systemen ohne installierte C++-Umgebung nicht geladen werden.

von Peter D. (peda)


Lesenswert?

@Karl,

für ellenlange Texte hat der Forenbetreiber den Dateianhang gedacht.


Ein PC für ne Heizungsregelung wäre mir zu unzuverlässig, teuer und 
stromfressend.
Hier im MC-Forum nimmt man eigentlich nen MC dafür.


Fragen zur PC-Programmierung sind außerdem besser in der Rubrik 
"PC-Programmierung" aufgehoben.


Peter

von Falk (Gast)


Lesenswert?

@Peter Dannegger

> Ein PC für ne Heizungsregelung wäre mir zu unzuverlässig, teuer und
> stromfressend.

Der PC IST die Heizung ;-)

MFG
Falk


von Karl (Gast)


Lesenswert?

@ Peter

Danke für die schnelle Antwort und den Tip mit dem anderen Forum.
Nur noch eine Frage: Kann man mit einem PC den überhaupt den 1 wire bus 
auslesen, ohne ein MC dazwischenzuschalten (ist der PC schnell genug)?

P.S. Die Energiekosten die der PC zur Steuerung braucht, spar ich durch 
geringere Pumpenlaufzeiten ein. Außerdem kenne ich mich mit MC nicht so 
aus.

MFG
Karl

von Falk (Gast)


Lesenswert?

@Karl

> Kann man mit einem PC den überhaupt den 1 wire bus
> auslesen, ohne ein MC dazwischenzuschalten (ist der PC schnell genug)?

Naja, es sollte schon mindestens ein P4 mit 3 GHz sein ;-)

Im Ernst, der PC ist schnell genug, aber das Timing der One-wire ICs ist 
recht schnell und du brauchst dafür einen Low-Level Treiber. Knifflige 
Sache. Für einen uC kein Problem, der muss nicht WinXP mit sich 
rumschleppen.

Ich behaupte mal, der Aufwand sich in uC einzuarbeiten ist geringer als 
eine low-level Treiber für winXP zu schreiben. Und am Ende hast du eine 
wesentlich bessere und zweckmässigere Heizungssteuerung. uCs kannst du 
einfach in C programmieren, so wie deinen PC auch.

MFG
Falk



von irgendein Rahul (Gast)


Lesenswert?

>P.S. Die Energiekosten die der PC zur Steuerung braucht, spar ich durch
>geringere Pumpenlaufzeiten ein

Wozu dann die Steuerung, wenn es keine Verbesserung gibt?
(Ich hab mir nicht den langen Post durchgelesen; vielleicht gibt es die 
Antwort ja auch in Kurzform...).

>Außerdem kenne ich mich mit MC nicht so aus.

Was spricht dagegen, das zu ändern?

Schade, dass ich sonst nichts zu diesem Thema beitragen kann.

von Pete (Gast)


Lesenswert?

Den 1-wire bus kann man sehr schön auch in Java programmieren. Gibt es 
auf der Herstellerseite www.maxim.de. Schnell genug ist der PC.

Am einfachsten geht es mit dem DS9490R über USB.

Und hier ein Link für eine einfache Ansteuerung : 
lena.franken.de/hardware/temperaturmessung.html

Selbst mit einem Epia-Board braucht der PC immer noch 20W. Mit 
Mikrocontroller liegt man eher bei 20mW (!).

20W sind immerhin 175kWh pro Jahr...

Das Problem bei den DS1820 ist die breite Messfläche. Lufttemperatur 
lässt sich gut messen, aber als Anlegesensoren sind sie eher weniger 
geeignet.
Die Sensoren muss man sehr gut isolieren, wenn man sie direkt auf das 
Kupferrohr klebt. Ich habe teilweise bis zu 5 Grad Unterscheid zur 
Heizungsregelung gehabt. Wärmeleitpaste und schön Festzurren 
(Kabelbinder) hilft auch ein bischen.

Gruss,
Pete

von Axel (Gast)


Lesenswert?

"Kann man mit einem PC den überhaupt den 1 wire bus
auslesen, ohne ein MC dazwischenzuschalten (ist der PC schnell genug)?"

Gibt es Digitemp für. Ältere Versionen liefen auch unter Windows. Da 
wird die serielle Schnittstelle für verwendet.

Gruss
Axel

von EFI (Gast)


Lesenswert?

@Karl

Hallo Karl,

ich betreibe seit ca. 1 Jahr meine kpl. Haus-Heizungssteuerung via PC. 
Als Sensorik fungieren 32 DS18B20 (Boden-, Luft-, Vor- und 
Rücklauftemperaturen). Die Sensoren sind via DS2482-800 und I2C via 
Parallel-Port angeschlossen. Die komplette Steuerung (nebst kpl. 
Haussteuerung) ist in C++ geschrieben. Wenn ich Dir diesbezüglich 
weiterhelfen kann, gern.

von Karl (Gast)


Lesenswert?

Hallo EFI

Danke für dein Angebot. Ich kenne mich in C++ nicht aus, deshalb wollte 
ich meine Steuerung mit ProfiLab Expert realisieren. Mit dem Programm 
kann man Schaltungen erstellen, ohne eine Zeile zu programmieren. In dem 
Programm ist schon einiges an Hardware eingebunden, aus für den 1 wire 
bus. Es gibt aber ein Bauteil womit man eine DLL-Datei importieren kann. 
Diese DLL-Datei kann in C++ geschrieben werden und müste den 1-wire bus 
bzw die angeschlossenen Sensoren auslesen. Bei der Programmierung der 
DLL-Datei müssen nur einige Vorgaben eingehalten werden.

Wie leicht oder schwer ist es in C++ zu programmieren und wie lange hast 
du für dein Programm gebraucht gebraucht?

Ist deine Steuerung kpl. in C++ und ist sie visualisiert d.h 
Temperaturanzeigen, Temperaturganglinien, Optischer und Akustischer 
Alarm, Welche Eingabe möglichkeiten gibt es usw..

Wie Regelst du die Heizung nach Vor oder Rücklauftemperatur, Heizkurve, 
Zeit, Warmwasseraufbereitung?

Also nochmals Danke!!!

von wesch (Gast)


Lesenswert?

Hallo Forum!

Ich hab mal studienhalber die Bibliotheken getestet und alles 
funktioniert wunderbar.

Da ich jedoch verstehen will wie das alles so tickt (bin AVR-Anfänger) 
hab ich mein Problem bei der Funkion w1_reset

bit w1_reset(void)
{
  bit err;

  W1_OUT &= ~(1<<W1_PIN);
  W1_DDR |= 1<<W1_PIN;
  DELAY( DELAY_US( 480 ));
  cli();
  W1_DDR &= ~(1<<W1_PIN);
  DELAY( DELAY_US( 66 ));
  err = W1_IN & (1<<W1_PIN); // no presence detect
  sei();
  DELAY( DELAY_US( 480 - 66 ));
  if( (W1_IN & (1<<W1_PIN)) == 0 )    // short circuit
    err = 1;
  return err;
}

1. Problem mit der Zeile err = W1_IN & (1<<W1_PIN);
   err ist ein bit und kann 0 oder 1 werden
   W1_IN ist doch der Status des Eingangs
   doch mit dem & (1<<W1_PIN); komm ich nicht klar

   Was passiert da?

2. DELAY( DELAY_US( 480 - 66 ));
   Die DELAY-Funktion bekommt dann als Argument DELAY_US....?


vielen Dank schon mal

von Jankey (Gast)


Lesenswert?

@EFI: Wie weit sind deine Sensoren voneinander entfernt?

lg Jan

von Frank Se. (Gast)


Lesenswert?

Hallo Peter,

ich habe mir deinen 1Wire C-Code heruntergeladen.
Zuerst habe ich auf dem AT90S8535 (8Mhz Takt) die Reset Funktion 
getestet.
Wenn ich die Funktion ResetDS1820 ausführe erhalte ich immer den Wert 2.
Das verstehe ich nicht. Dies bedeutet doch dass der DS1820 nicht erkannt 
wurde oder?

// Diese Funktion habe ich zuerst erstellt. Ohne dass ich deinen Code 
// kannte
// Bei der Ausführung dieser Funktion erhalte ich "0"
char ResetDS1820(void)
{
 presence = 0xFF;
 DDRD.2=1;    // PORTD.2 --> OUTPUT
 PORTD.2 = 0;           // PORTD.2 den Wert 0 ausgeben
 delay_us(480);   // Zeitverzögerung von 500us
 PORTD.2 = 1;           // PORTD.2 den Wert 0 ausgeben
 delay_us(66);          // Zeitverzögerung von 70us
 DDRD.2=0;              // PORTD.2 --> INPUT
 presence = PIND.2;   // Signal mit PIND.2 einlesen und der Variable
                        // presence zuweisen
 delay_us(480-66);   // Zeitverzögerung von 250us
 DDRD.2=1;              // PORTD.2 --> OUTPUT
 return presence;       // Ausgabe von presence
}// 0=presence, 1=no part


// Diese Funktion habe ich von deiner ZIP Datei übernommen
#ifndef W1_PIN
#define W1_PIN  PORTD.2
#define W1_IN         PIND
#define W1_OUT  PORTD
#define W1_DDR  DDRD
#endif

unsigned char w1_reset(void)
{
  unsigned char err;
  err = 0x00;
  W1_OUT &= ~(1<<W1_PIN);
  W1_DDR |= 1<<W1_PIN;
  delay_us(480);      // 480 us
  W1_DDR &= ~(1<<W1_PIN);
  delay_us(66);
  err = W1_IN & (1<<W1_PIN);      // no presence detect
  delay_us(480-66);
  if( (W1_IN & (1<<W1_PIN)) == 0 )    // short circuit
    err = 1;
  return err;
}

Hier erscheint bei mir immer 2 als Rückgabewert.

Ich programmiere mit dem CodeVision AVR

von Peter D. (peda)


Lesenswert?

Frank Se. wrote:


> #define W1_PIN  PORTD.2

So gehts nicht.

Der Code ist für WINAVR geschrieben und der kennt keine Bitvariablen.

Also mußt Du da die Bitnummer (0..7) eintragen.


> Hier erscheint bei mir immer 2 als Rückgabewert.

Das ist möglich, wenn Du Pin 1 eines Ports benutzt.
0 = o.k.
!0 = Fehler


Peter



von Frank Se. (Gast)


Lesenswert?

Danke Peter für die Unterstützung.
Ich habe die Funktion nochmals auf den CodeVision_AVR abgestimmt.
An Pin PD2 ist die Datenleitung vom DS1820 angeschlossen.

#define W1_PIN  PORTD.2 // Ausgang
#define W1_IN  PIND.2  // Eingang
#define W1_OUT  PORTD.2 // Ausgang
#define W1_DDR  DDRD.2  // die Richtung kann hiermit bestimmt werden.

unsigned char w1_reset(void)
{
  unsigned char err;
  err = 0x00;
  W1_OUT &= ~(W1_PIN);
  W1_DDR |= W1_PIN;
  delay_us(480);       // 480 us
  W1_DDR &= ~(W1_PIN);
  delay_us(66);
  err = W1_IN & (W1_PIN);      // no presence detect
  delay_us(480-66);
  if( (W1_IN & (W1_PIN)) == 0 )// short circuit
    err = 1;
  return err;
}

Leider erscheint auf meinem Display eine "1".
Dies bedeutet DS1820 wurde nicht erkannt.
Warum eigentlich "W1_PIN" und "W1_IN"?
Es kann sein das ich bei der Definition noch einen Fehler habe.
ich weiss allerdings nicht wo.

von Frank Se. (Gast)


Lesenswert?

Ich verstehe es nicht. WIe müsste ich dann die Definitionen unter 
CodeVision_AVR deklarieren?

von Frank Se. (Gast)


Lesenswert?

Also ich denke die Definition ist bei mir falsch.

Wie müsste die Definition dann bei mir aussehen?
#ifndef W1_PIN
#define W1_PIN  PD6
#define W1_IN  PIND
#define W1_OUT  PORTD
#define W1_DDR  DDRD
#endif

von Frank Se. (Gast)


Lesenswert?

So ich habe mal das ganze ohne define erstellt.

unsigned char w1_reset(void)
{
  unsigned char err;
  err = 0x00;
  PORTD.2=0;
  DDRD.2=1;
  delay_us(480);
  DDRD.2=0;
  delay_us(66);
  err = PIND.2;
  delay_us(480-66);
  if( (PIND.2) == 0 )
    err = 1;
  return err;
}

Wenn ich diese Funktion ausführe, dann erhalte ich auch den Wert "0".
Also funktioniert doch das ganze oder?

von Frank Se. (Gast)


Lesenswert?

W1_OUT &= ~(1<<W1_PIN); --> PORTD.2=0;
W1_DDR |= 1<<W1_PIN;    --> DDRD.2=1;
W1_DDR &= ~(1<<W1_PIN); --> DDRD.2=0;
W1_IN & (1<<W1_PIN);    --> PIND.2

Stimmt meine Interpetation so?

von Frank Se. (Gast)


Lesenswert?

Vielen Dank nochmals!
Der DS1820 läuft bei mir jetzt. Bin jetzt voll happy.
Nur noch eine Sache hätte ich da, ich kann nur ganze Temperaturen 
darstellen,
wie z.B. 21 C°. Was muss ich tun, damit ich z.B. so einen Wert 21.5 C° 
auslesen kann?

von hansl (Gast)


Lesenswert?

Servus Peter,

irgendwie bekomm ich dieses 1wire zeug einfach nicht zum
laufen.

mein hardwaresetup habe ich nun mehrmals aufgebaut.
die strippen und widerstaende ausgetauscht. alles ohne erfolg.
deine software meldet mir BusError.

funktioniert dein code auch mit ds1821?

hast du nen vorschlag wie ich den bus debuggen koennte?

mfg
 hansl

von hansl (Gast)


Lesenswert?

ok, der ds1821 hat einen andren befehlssatz und funtionen.

dennoch, debugginbgtips fuer 1wire?

von Peter D. (peda)


Lesenswert?

@hansl,

wenn mich nicht alles täuscht, hat der DS1821 gar keine Adresse.
Die ganzen ROM-Kommandos gehen also nicht.

Nach dem Reset macht man sofort die gewünschte Aktion (Messung starten, 
Wert auslesen usw.).

Es gibt da allerdings auch noch nen Temperaturschaltermodus. Wenn er da 
drin ist, muß man ihn erstmal mit ner speziellen Sequenz zurückschalten.

Er kann auch kein parasite Power.


Peter

von hansl (Gast)


Lesenswert?

danke peter,

werd mich jetzt mal ans portieren deines programms machen
und hier hoffentlich bald die ds1821 version hochladen.

mfg
 hansl

von Markus Hiller (Gast)


Lesenswert?

Hi Leutz,

bin grad am rumtesten mit dem von P.D. geposteten Code. Mit einem DS1820 
Sensor funktioniert alles wunderbar.
Nun hab ich hier ausm Forum/Markt DS1822 gekauft. Leider läuft keiner 
dieser Sensoren an der Schaltung. Laut Datasheets sind die Dinger völlig 
identisch bis auf die größere Ungenauigkeit des DS1822. Oder hab ich das 
was übersehen?

Gruß  -  Markus

von Hansl (Gast)


Lesenswert?

mit der portierung auf DS1821 wirds nun endgueltig nix. hab nun meinen
zweiten sensor verpolt und gegrillt. sollt mir mal ne 2.te rolle
litze in ner andren farbe kaufen, bei der gelegenheit hol ich mir
dann auch gleich nen DS1820 und gut ists.

sorry for the inconvenience.

mfg
Hansl

von Peter D. (peda)


Lesenswert?

Hansl wrote:
> mit der portierung auf DS1821 wirds nun endgueltig nix. hab nun meinen
> zweiten sensor verpolt und gegrillt.

Gehörst Du etwa auch zu den unbelehrbaren, die ein 5V/100A PC-Netzteil 
zum Basteln benutzen ?

Für MC-Experimente nehme ich ne Wandwarze und nen 78L05 dahinter.
Der 78L05 begrenzt auf etwa 100mA, dann wird nichts mehr gegrillt.


Peter

von Andreas K. (eisenkoch)


Lesenswert?

leider erhalte ich immer den folgenden Fehler:
1
../TEMPMEAS.C:37: error: invalid conversion from 'unsigned char*' to 'char*'
2
../TEMPMEAS.C:37: error: initializing argument 1 of 'int sprintf(char*, const char*, ...)'
3
../TEMPMEAS.C:38: error: invalid conversion from 'unsigned char*' to 'char*'
4
../TEMPMEAS.C:38: error: initializing argument 1 of 'void uputs(char*)'

woran kann das liegen?

von Peter D. (peda)


Lesenswert?

@Andreas,

das hat historische Gründe:

Früher wurden nur 7Bit Zeichen verwendet und deshalb sind die 
C-Stringfunktionen vom Typ char, was eigentlich Blödsinn ist, denn es 
gibt keine negativen Zeichen.

Heutzutage ist ASCII 8Bit unsigned (0..255), aber die Funktionen sind 
scheinbar vorzeichenbehaftet geblieben.

Scheinbar deshalb, weil sie die ASCII Zeichen intern als unsigned char 
behandeln. Es sind also die ASCII-Zeichen von 0..255 erlaubt und gültig.


Um nun nicht durcheinander zu kommen, machen Compiler üblicher Weise 
eine implizite Pointerkonvertierung, wenn der Bassistyp stimmt.

Dein Compiler scheint nun weit über das Ziel hinausgeschossen zu sein, 
indem er das verweigert.

Als Workaround bleibt dann nur eine explizite Pointerkonvertierung:

sprintf( (char*)s ...

Man könnte auch das Array als char definieren, dann könnte aber der 
Compiler wieder meckern, wenn man ASCII-Zeichen >127 reinschreibt.


Peter


P.S.:
Könnte das ne neue Macke des AVR-GCC 4.1.1 sein ?

von A.K. (Gast)


Lesenswert?

Wenn "char" mit Vorzeichen ist, dann ist die "char *" zwar kompatibel 
mit "signed char "*, nicht aber mit "unsigned char *". Alles andere wäre 
ein Compilerfehler.

Die Entscheidung dafür, "char" vorzeichenbehaftet zu verstehen, geht 
zurück auf Eigenschaften der ersten Implementierung auf einer PDP-11. 
Und lässt sich mit -funsigned-char beheben.

Soweit C, soweit so einfach. Interessanter wird es bei C++. Hier 
möglicherweise relevant, da ohne ausdrückliche Gegenwehr ein gross 
geschriebenes ".C" als C++ übersetzt wird.

Da man beim Overloading sonst in Teufel's Küche landet, hat man sich 
nach anfänglichem Durcheinander zu 3 Varianten entschlossen. "char", 
"signed char" und "unsigned char". Sachlich sind davon zwar 2 gleich, es 
sind aber dennoch 3 verschiedene Typen.

von Peter D. (peda)


Lesenswert?

A.K. wrote:

> Soweit C, soweit so einfach. Interessanter wird es bei C++. Hier
> möglicherweise relevant, da ohne ausdrückliche Gegenwehr ein gross
> geschriebenes ".C" als C++ übersetzt wird.

Stimmt, daran kanns liegen. Ich schreibe deshalb immer:

avr-gcc.exe -xc ...


Peter

von Paul Reichenbach (Gast)


Lesenswert?

Hallo,
ich verstehe in der Datei tempmeas.c folgenden Ausdruck nicht:
1
 sprintf( s, "%4d.%01d", temp >> 4, (temp << 12) / 6553 ); // 0.1 auflösung

genauer gesagt den Part wo die Kommastelle gebildet wird. Warum wird 
durch 6553 geteilt? Ich versuche das ganze in 0,5° Schritten 
darzustellen und komme nicht weiter.

Sehe ich das richtig, wenn ich negative Zahlen darstellen möchte, das 
ich das zwölfte Bit auswerten muss ?

Viele Grüße

Paul

von Fabio (Gast)


Lesenswert?

hey Leute ich versuche gerade die 1wire zip zu kompelieren und bekomme 
da ein paar fehler. kann mir da vieleicht jemand weiter helfen

> "make.exe" all

-------- begin --------
avr-gcc (GCC) 4.1.2 (WinAVR 20070525)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is 
NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR 
PURPOSE.


Compiling: main.c
avr-gcc -c -mmcu=atmega32 -I. -g   -Os -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -Wall 
-Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 
-Wp,-M,-MP,-MT,main.o,-MF,.dep/main.o.d main.c -o main.o

Linking: main.elf
avr-gcc -mmcu=atmega32 -I. -g   -Os -funsigned-char -funsigned-bitfields 
-fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o 
-std=gnu99 -Wp,-M,-MP,-MT,main.o,-MF,.dep/main.elf.d main.o 1WIRE.C 
DELAY.C TIMEBASE.C TEMPMEAS.C UART.C   --output main.elf 
-Wl,-Map=main.map,--cref    -lm
cc1plus.exe: warning: command line option "-Wstrict-prototypes" is valid 
for C/ObjC but not for C++
cc1plus.exe: warning: command line option "-std=gnu99" is valid for 
C/ObjC but not for C++
cc1plus.exe: warning: command line option "-Wstrict-prototypes" is valid 
for C/ObjC but not for C++
cc1plus.exe: warning: command line option "-std=gnu99" is valid for 
C/ObjC but not for C++
cc1plus.exe: warning: command line option "-Wstrict-prototypes" is valid 
for C/ObjC but not for C++
cc1plus.exe: warning: command line option "-std=gnu99" is valid for 
C/ObjC but not for C++
cc1plus.exe: warning: command line option "-Wstrict-prototypes" is valid 
for C/ObjC but not for C++
cc1plus.exe: warning: command line option "-std=gnu99" is valid for 
C/ObjC but not for C++
TEMPMEAS.C: In function 'void read_meas()':
TEMPMEAS.C:37: error: invalid conversion from 'unsigned char*' to 
'char*'
TEMPMEAS.C:37: error:   initializing argument 1 of 'int sprintf(char*, 
const char*, ...)'
TEMPMEAS.C:38: error: invalid conversion from 'unsigned char*' to 
'char*'
TEMPMEAS.C:38: error:   initializing argument 1 of 'void uputs(char*)'
TEMPMEAS.C:45: error: invalid conversion from 'unsigned char*' to 
'char*'
TEMPMEAS.C:45: error:   initializing argument 1 of 'int sprintf(char*, 
const char*, ...)'
TEMPMEAS.C:46: error: invalid conversion from 'unsigned char*' to 
'char*'
TEMPMEAS.C:46: error:   initializing argument 1 of 'void uputs(char*)'
TEMPMEAS.C:47: error: invalid conversion from 'unsigned char*' to 
'char*'
TEMPMEAS.C:47: error:   initializing argument 1 of 'int sprintf(char*, 
const char*, ...)'
TEMPMEAS.C:48: error: invalid conversion from 'unsigned char*' to 
'char*'
TEMPMEAS.C:48: error:   initializing argument 1 of 'void uputsnl(char*)'
cc1plus.exe: warning: command line option "-Wstrict-prototypes" is valid 
for C/ObjC but not for C++
cc1plus.exe: warning: command line option "-std=gnu99" is valid for 
C/ObjC but not for C++
make.exe: *** [main.elf] Error 1

> Process Exit Code: 2
> Time Taken: 00:02


wäre echt klasse wenn wir das hin bekommen würden. viel dank Fabio

von Peter D. (peda)


Lesenswert?

Versuch mal:

avr-gcc -xc


Peter

von Fabio (Gast)


Lesenswert?

Sorry das verstehe ich nicht so ganz. Ich bin noch in der lernphase und 
kenne deswegen noch nicht alle kürzel usw. Vieleicht hilft ja das ich 
programmiere mit Programmers Notepad 2. mfg Fabio

von Simon K. (simon) Benutzerseite


Lesenswert?

Dein Compiler versucht die Datei(en) nach C++ Standard zu kompilieren. 
mit dem Compilerparameter -xc erzwingt man (denke ich?) den C Standard. 
Alternativ kannst du die Dateieendung von ".C" nach ".c" ändern. Daran 
erkennt der Compiler das nämlich.

von Fabio (Gast)


Lesenswert?

alles klar klingt logisch sagt ja auch der compiler. Also habe ich die 
datei endungen von "C" auf "c" geändert. Tut sich aber nichts! gleicher 
fehler. Kann man das irgendwo einstellen ? mfg Fabio

von Andreas K. (a-k)


Lesenswert?

Musst den Namen im Makefile/Projektfile ändern. Wenn im Protokoll .C 
statt .c drinsteht hast du verloren.

von Fabio (Gast)


Lesenswert?

Sorry das ich euch nochmal belästigen muss aber ich bin leider nicht so 
der crack! der alte Fehler ist behoben aber dafür giebt es einen neuen.

Compiling: TEMPMEAS.c
avr-gcc -c -mmcu=atmega32 -I. -g   -Os -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -Wall 
-Wstrict-prototypes -Wa,-adhlns=TEMPMEAS.lst  -std=gnu99 
-Wp,-M,-MP,-MT,TEMPMEAS.o,-MF,.dep/TEMPMEAS.o.d TEMPMEAS.c -o TEMPMEAS.o
TEMPMEAS.c: In function 'read_meas':
TEMPMEAS.c:37: warning: pointer targets in passing argument 1 of 
'sprintf' differ in signedness
TEMPMEAS.c:38: warning: pointer targets in passing argument 1 of 'uputs' 
differ in signedness
TEMPMEAS.c:45: warning: pointer targets in passing argument 1 of 
'sprintf' differ in signedness
TEMPMEAS.c:46: warning: pointer targets in passing argument 1 of 'uputs' 
differ in signedness
TEMPMEAS.c:47: warning: pointer targets in passing argument 1 of 
'sprintf' differ in signedness
TEMPMEAS.c:48: warning: pointer targets in passing argument 1 of 
'uputsnl' differ in signedness

Compiling: UART.c
avr-gcc -c -mmcu=atmega32 -I. -g   -Os -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -Wall 
-Wstrict-prototypes -Wa,-adhlns=UART.lst  -std=gnu99 
-Wp,-M,-MP,-MT,UART.o,-MF,.dep/UART.o.d UART.c -o UART.o
UART.c:1: error: expected identifier or '(' before numeric constant
UART.c:19:11: error: invalid suffix "B9" on integer constant
UART.c:21:11: error: invalid suffix "BC" on integer constant
UART.c:23:11: error: invalid suffix "BB8" on integer constant
UART.c:25:6: error: invalid digit "8" in octal constant
UART.c:26:6: error: invalid suffix "a" on integer constant
UART.c:26:11: error: invalid suffix "BD" on integer constant
UART.c:28:6: error: invalid suffix "c" on integer constant
UART.c:29:6: error: exponent has no digits
UART.c:29:11: error: invalid suffix "AB9" on integer constant
UART.c:31:11: error: invalid digit "9" in octal constant
UART.c:44:11: error: invalid suffix "D9B" on integer constant
UART.c:45:11: error: invalid suffix "C0" on integer constant
UART.c:47:11: error: invalid suffix "CB9" on integer constant
UART.c:49:6: error: invalid digit "8" in octal constant
UART.c:49:11: error: invalid digit "9" in octal constant
UART.c:60:6: error: invalid suffix "a" on integer constant
UART.c:61:6: error: invalid suffix "c" on integer constant
UART.c:61:11: error: invalid suffix "C0" on integer constant
UART.c:67:6: error: exponent has no digits
UART.c:67:11: error: invalid suffix "D9B" on integer constant
UART.c:68:11: error: invalid suffix "C0" on integer constant
UART.c:76:11: error: invalid suffix "CB9" on integer constant
UART.c:83:6: error: invalid digit "8" in octal constant
UART.c:84:6: error: invalid suffix "a" on integer constant
UART.c:84:11: error: invalid suffix "F4" on integer constant
UART.c:86:6: error: invalid suffix "c" on integer constant
UART.c:86:11: error: invalid digit "9" in octal constant
UART.c:98:6: error: exponent has no digits
UART.c:104:11: error: invalid suffix "D9B" on integer constant
UART.c:105:11: error: invalid suffix "C0" on integer constant
UART.c:107:11: error: invalid suffix "DE0" on integer constant
UART.c:108:6: error: invalid digit "8" in octal constant
UART.c:108:11: error: invalid suffix "CB9" on integer constant
UART.c:112:6: error: invalid suffix "a" on integer constant
UART.c:112:11: error: invalid digit "9" in octal constant
UART.c:119: error: stray '\' in program
UART.c:119: error: stray '\' in program
UART.c:119: error: stray '\' in program
UART.c:119: error: stray '\' in program
UART.c:119:56: error: invalid suffix "f" on integer constant
UART.c:120: error: stray '\' in program
UART.c:120: error: stray '\' in program
UART.c:120: error: stray '\' in program
UART.c:120: error: stray '\' in program
UART.c:120:56: error: exponent has no digits
UART.c:121: error: stray '\' in program
UART.c:121: error: stray '\' in program
UART.c:121: error: stray '\' in program
UART.c:121: error: stray '\' in program
UART.c:121:56: error: invalid suffix "d" on integer constant
UART.c:122: error: stray '\' in program
UART.c:122: error: stray '\' in program
UART.c:122: error: stray '\' in program
UART.c:122: error: stray '\' in program
UART.c:123: error: stray '\' in program
UART.c:123: error: stray '\' in program
UART.c:123: error: stray '\' in program
UART.c:123: error: stray '\' in program
UART.c:124: error: stray '\' in program
UART.c:124: error: stray '\' in program
UART.c:124: error: stray '\' in program
UART.c:124: error: stray '\' in program
UART.c:125: error: stray '\' in program
UART.c:125: error: stray '\' in program
UART.c:125: error: stray '\' in program
UART.c:125: error: stray '\' in program
UART.c:126: error: stray '\' in program
UART.c:126: error: stray '\' in program
UART.c:126: error: stray '\' in program
UART.c:126: error: stray '\' in program
UART.c:126:56: error: invalid suffix "a" on integer constant
UART.c:127: error: stray '\' in program
UART.c:127: error: stray '\' in program
UART.c:127: error: stray '\' in program
UART.c:127: error: stray '\' in program
UART.c:127:56: error: exponent has no digits
make.exe: *** [UART.o] Error 1

> Process Exit Code: 2
> Time Taken: 00:01


was könnte das sein ?

von Andreas K. (a-k)


Lesenswert?

Un Anbetracht der Tatsache, dass uart.c nur 33 Zeilen hat, möchte ich 
mal die These aufstellen, dass du dieses File mittlerweile durch etwas 
anderes ersetzt hast.

Und die Fehlermeldungen in tempeas sind m.E. recht selbsterklärend.

von Fabio (Gast)


Lesenswert?

Moin Moin,

so hat funktioniert! ich kann alles kompalieren. Ist aber irgendwie 
komisch da ich mich nicht errinern kann in der Datei groß was geändert 
zu haben aber naja egal.

Aber 1ne hab ich noch. Ich denke mal das die Funktionen Start_meas für 
das starten der messung ist und Read_meas für das auslesen der 
Temperatur. Ich will die Temperatur auf mein LCD anzeigen lassen und 
frage mich nun in welcher Variablen der Wert drin steht! vieleicht kann 
mir da ja nochmal jemand helfen. Ach und 1 wollte ich nochmal los 
werden. VIELEN VIELEN DANK AN ALLE DIE SICH MEINE TEXTE DURCHLESEN UND 
MIR SO WEITERHELFEN! mfg Fabio

von Fabio (Gast)


Lesenswert?

hi Leute sagt mal in welcher Variablen ist der Temperatur wert 
gespeichert ? mfg Fabio

von Peter D. (peda)


Lesenswert?

Fabio wrote:
> hi Leute sagt mal in welcher Variablen ist der Temperatur wert
> gespeichert ? mfg Fabio

Nirgends.

Er wird vom Sensor ausgelesen und per sprintf ausgegeben (erst in hex, 
dann dezimal).


Peter

von Fabio (Gast)


Lesenswert?

ok danke kannst du mir vieleicht die datei nennen und die zeile in der 
das geschieht? vielen dank

von Fabio (Gast)


Lesenswert?

moin leute,

also wenn ich das richtig sehe dann wird der temperaturwert mit

sprintf( s, "%4d.%01døC", temp >> 4, (temp << 12) / 6553 ); // 0.1øC;

dieser zeile in der Tempeas.c ausgelesen oder ?

Temperatur = sprintf( s, "%4d.%01døC", temp >> 4, (temp << 12) / 6553 ); 
// 0.1øC;

dann müste doch der Temperatur wert in der Variablen gespeichert werden 
oder ?

danke

von Fabio (Gast)


Lesenswert?

hey leute,

wie bekomme mann das hin das der Temparaturwert in eine Variable 
geschrieben wird? bitte helft mir. mfg Fabio

von Werner A. (homebrew)


Lesenswert?

hast du dir die syntax von sprintf schonmal angeschaut?

ansonsten, der wert steht schon in der variablen temp...

von Fabio (Gast)


Lesenswert?

steht er da dezimal drin ? ich habe zu dem befehl irgendwie keine gute 
referenz gefunden. nur für php aber ich denke mal das der da vieleicht 
ein bischen anders ist. vielen dank fabio

von Manuel B. (baeri3)


Lesenswert?

Hallo,

danke erstmal für die Lib. Allerdings bekomme ich hier an einem Mega8 
auf dem STK500 (mit 3,86MHz Osz) immer "nur" ein Bus-Error.

Ich habe den DQ Pin mit PD6 und per 4,7KOhm mit +5V verbunden. Den VDD 
und GND Pin habe ich auf GND gelegt.

Wenn ich z.B. den Sensor mit +5V auf VDD Speise dann bekommme ich keinen 
Bus-Error, dann findet er gar keinen Sensor oder gibt "Short Circuit" 
aus!

Was kann ich (noch) tun?

von Sean (Gast)


Lesenswert?

Hi,
mich würde das auch mal interessieren in welcher Form der Wert in der 
VAriable temp abgespeichert ist....

von KAZERONI (Gast)



Lesenswert?

SD1 IN
SD2 IN
SD3 GND
SD4 +3.3V
SD5 IN
SD6 GND
SD7 OUT
SD8 D1
SD9 D2
PKN (OFF)
START(ON)

von Christian (Gast)


Lesenswert?

Hallo,
ich versuche gerade das Programm auf einen ATMEGA32 mit einem internen 
Takt von 1 MHz laufen zu lassen.
Jedoch erhalte ich immer einen Bus Fehler...

Was ich nicht blicke ist, das wenn ich die CPU auf 8 MHz am kaufen habe 
klappts. Wenn ich aber die Fuse Bitas auf 1 MHz unstelle und in der 
main.h die Frequenz anpasse klappts es nicht mehr...

Der Buss Fehler resultiert aus einem Fehler bei der Verarbeitung der 
Funktion w1_bit_io , ich vermute mal das es am Timing liegt, jedoch 
steige ich da nicht so ganz durch ;-(

Kann mir hier vielleicht jemand helfen?

Gruss

von Peter D. (peda)


Lesenswert?

Christian wrote:

> Der Buss Fehler resultiert aus einem Fehler bei der Verarbeitung der
> Funktion w1_bit_io , ich vermute mal das es am Timing liegt, jedoch
> steige ich da nicht so ganz durch ;-(

Ja, kann sein, daß bei 1MHz das Timing zu knapp wird, d.h. die 
Zykluszeit der CPU dominiert.

Warum willst Du nicht 4MHz oder 8MHz nehmen ?


Peter

von Christian (Gast)


Lesenswert?

Es ging ums RS232, habe jetzt aber ein 8MHz Quarz genommen und dadurch 
lief auch die RS232 stabil ;-)

Kann mir mal jemand erklären wie ich den Messwert ordentlich in ein Char 
konvertiert bekomme? Ich möchte den via Funk übertragen und da habert es 
noch am Format und ich bin icht gerade der Programmier Held ;-)

von Basingstoke (Gast)


Lesenswert?

Also ich habe den "SEARCH ROM" mechanismus noch nicht richtig
verstanden. Nach dem "Flowchart 2" müsste ich beliebig viele Devices 
finden können. Das will ich auch aber ich versteh den eine Stelle 
einfach nicht! Und zwar handelt es sich um:
"Set search_direction bit to id_bit_number bit in ROM_NO"

ATmega8 6Mhz
DS18s20

link: http://www.maxim-ic.com/appnotes.cfm/appnote_number/187

von Markus (Gast)


Lesenswert?

Ich habe da eine Frage zu der Globalen Variable Second...

Alle fünf Sekunden wird ja ein Messwert via UART übertragen. Ich würde 
aber gerne nur alle 20 Sekunden durchführen. Dazu würde es doch genügen 
in main.c folgenden Code einzufügen/zu ändern:
1
for(;;)
2
  {
3
  
4
          if( second == 3 )  
5
    {
6
      start_meas();
7
      second = 4;      
8
      
9
    }
10
    if( second == 6 )    
11
    {
12
      read_meas();
13
      //second = 0;
14
      
15
    }
16
    
17
    if ( second == 20)
18
    {
19
      second=0;
20
    }
21
  }

Leider klappt das nicht. Er wartet zwar, aber überträgt mir dann 32 
Messwerte statt nur einen ??!!??

Woran kann das liegen? Bzw. ist meine Überlegung mit der Varibale so 
richtig?

Viele Grüße

von Markus (Gast)


Lesenswert?

Ich habe herrausgefunden das er in der zweiten ebene read_meas hängen 
bleibt und diese mehrmals durchläuft -nur warum?-

von Markus (Gast)


Lesenswert?

ok ;-) habs selbst gefunden...

Ich muss im Fall second=6 nach erfolgreicher Durchführung um eins 
hochzählen ;-))

von Andreas K. (a-k)


Lesenswert?

Kleine Korrektur an Peters Code: Am Ende der w1_bit_io Routine sollte 
nach der Deaktivierung des Ausgangs eine Verzögerung von einigen µs 
eingebaut werden.

Laut 1-Wire Doku reicht es zwar aus, wenn das Signal für 1µs high ist, 
was sich bei langsamen Prozessoren von selbst ergibt, aber das kann je 
nach Leitungslänge und sich daraus ergebender kapazitiver Last zu wenig 
sein, weil der übliche Pullup-Widerstand die Leitung in der Zeit nicht 
schnell genug hochgezogen bekommt. Vor allem wenn man es auch noch mit 
einer schnellen CPU zu tun hat.

Also lieber 10µs dort einplanen, bei langen Leitungen darf es auch 
deutlich mehr sein.

von Andreas K. (a-k)


Lesenswert?

> Also lieber 10µs dort einplanen, bei langen Leitungen darf es auch
> deutlich mehr sein.

Naja, wenn mehr als 10µs nötig, dann scheitert das woanders, da muss der 
Widerstand kleiner werden. Aber 10µs erscheinen mir schon sinnvoll.

von VirmAnnem (Gast)


Lesenswert?

Hi
:)
G'night

von SedOrdise (Gast)


Lesenswert?

Hello my friends :)
;)

von Ricardo (Gast)


Lesenswert?

Hallo,


ein sehr Interessanter Thread, der aber leider einige gestellte Fragen 
unbeantwortet lässt (ok bei manchen is das verständlich ;) ), aber 
manche sind dabei die gerade mich momentan auch interessieren. So zum 
Beispiel:


"Ich habe den DQ Pin mit PD'x' und per 4,7KOhm mit +5V verbunden.
Den VDD und GND Pin habe ich auf GND gelegt."

soweit ok... aber:

"Wenn ich z.B. den Sensor mit +5V auf VDD Speise dann bekommme ich 
keinen
Bus-Error, dann findet er gar keinen Sensor oder gibt "Short Circuit"
aus!

Was kann ich (noch) tun?"

So auch meine Frage!

Vielen Dank im voraus!

von Peter D. (peda)


Lesenswert?

Ricardo wrote:

> Was kann ich (noch) tun?"

Nicht so zugeknöpft sein, das hier ist kein Hellseherzirkel.

Welcher Code, AVR, Takt, Schaltung?

Vielleicht VDD mit GND vertauscht (Datenblattansicht ist von unten!).


Peter

von Ricardo (Gast)


Lesenswert?

Sorry, wenn das blöd rüber kam!

Die gestellte Frage war ein Zitat von "Manuel B." un interessierte mich 
eben auch. Wurde aber eben leider nicht beantwortet damals.

Bei mir handelt es sich um einen ATmega8 mit 8MHz. Ich verwende im 
moment den Code von Dir Peter zum Testen im AVR Studio mit GCC Compiler.
Mittlerweile hab ich nach langer suche doch noch einen ausschlaggebenden 
Hinweis bekommen im Forum. Geholfen hat letztendlich der zusätzliche 
Compilereintrag "-xc" um alles C-konform und nicht C++-konform zu 
kompilieren. Jetzt funktioniert es auch. Vorher hatte ich einfach 
versucht den Code so "hinzubiegen" in eines meiner Programme, was aber 
fehl schlug. Btw vielen Dank für die Unterstützung in der 1-Wire 
Angelegenheit!

Komm jetz erstmal klar soweit! .. bis zum nächsten Prob ;)

von Manuel B. (baeri3)


Lesenswert?

Hallo zusammen,
ich muss (leider) nochmals auf meinen Post vom 09.08.2007 zurück kommen 
nachdem das Projekt nun fast ein Jahr geschlafen hat. Ich bekomme 
weiterhin einen "Bus Error". Verwendet habe ich den Original Quellcode 
von Peter, compiliert mit AVR Studio.
Der BUS ERROR tritt auf, sobald ich den Pull-Up Widerstand vom PD6 auf 
VCC anklemme. Evtl. kann der Sensor das Signal nicht gegen GND ziehen? 
Evtl defekt?

von Marco M. (marco1987)


Lesenswert?

@Peter Dannegger


ich wollte deine biblios für meinem Tempsensor nehmen, dazu hätte ich 
ein paar Fragen.

Erstmal allgemein, kannst du mir sagen was das an Vorteile bringt ein 
Programm in soviele unterprogramme, header und c files zu zerlegen?

Ich habe bisher immer nur im main programm und vllt mal 1,2 datein 
eingebunden....

und nun zu meinem hauptproblem was binde ich denn bei dir wo ein, oder 
einfach main file compilieren?
Zur info:
Takt: 16 Mhz
AVR Atmega16

Danke marco

von Frank I. (icelase)


Lesenswert?

Hallo zusammen,

ich hab auch ein komisches Problem mit meinen DS18S20 Sensoren.

Nutze einen Atmega32 mit dem auf dem STK500 befindlichen Oszillator bei 
3,68 MHZ  (UART Timing funktioniert)

Code natürlich angepasst:
#define F_CPU 3686400
#define XTAL 3686400

Habe Pin1 (GND) und Pin3 ( Vdd ) gebrückt und zusammen an GND 
angeschlossen.
Pin2 geht an PC6 und via 4,7kOhm an VTG (+5V)


Code hab ich natürlich entsprechend angepasst:

#ifndef W1_PIN
#define W1_PIN  PC6
#define W1_IN  PINC
#define W1_OUT  PORTC
#define W1_DDR  DDRC
#endif


FEHLERBILD:

Wenn alles angeschlossen ist, bekomme ich ein "Bus Error".
Ziehe in den Sensor aus meinem Experimentierboard raus, bekomme ich ein 
"No Sensor Found"

Entferne ich das kabel zum PC6  bekomme ich ein "Short Circuit. No 
Sensor Found"


Habe auch schon den code von 
http://www.siwawi.arubi.uni-kl.de/avr_projects/tempsensor/index.html 
probiert.

Selbes Problem/Selbe Fehlermeldungen :-(

Weis einer was ich noch versuchen kann? Bin AVR Anfänger, also ist es 
sicher irgend eine kleinigkeit.

Grüße,
Frank

von Peter D. (peda)


Lesenswert?

@Frank,

die 15µs könnten etwas zu lang sein:
1
DELAY( DELAY_US( 15 - 1 ));

Versuch mal statt der 15 Werte von 5..10.


Peter

von Frank I. (icelase)


Lesenswert?

Hi Peter,
klappt leider nicht :(

verzweifel

von Kurt.P (Gast)


Lesenswert?

Habe das Prg mit dem Pollin Board getestet.
Funktioniert mit DS18S20.
Sensor tauschen?
Gruß
Kurt

von Frank I. (icelase)


Lesenswert?

Hi Kurt,

Sensor hab ich schon getauscht. Habe 3 Stück schon probiert... die 
werden ja nicht alle kaputt sein oder?

Sind die normalen DS18S20 von Reichelt. (DS1820 steht drauf)

Was kann man sonst noch für anfängerfehler machen bzgl Timing?



Grüße,
Frank

von Peter D. (peda)


Lesenswert?

@Frank,

Schreib besser:

#define XTAL 3686400L


Versuch mal nen schnelleren Quarz, z.B. 11.0592MHz


Peter

von Frank I. (icelase)


Lesenswert?

Hi Peter,

dank dir :-) das wars!

Hab jetzt erstmal den internen Oszi mit 8 MHZ am laufen... und es funzt 
;)
Lag also an den 3,68mhz die wohl zu langsam waren ( komischerweise )

Naja jetzt läufts.

Danke nochmal!


Grüße,
Frank

von Christian J. (elektroniker1968)


Angehängte Dateien:

Lesenswert?

Hier ist mein Code in C für PIC, kurz und leicht verständlich.

von athobaben (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Peter
Hallo Zusammen

ich verwende das Olimex P28 Board (siehe Datei) und das Program lässt 
sich einwandfrei compilieren und rennt auf meinem ATMega8 mit 8Mhz.

Wenn kein Sensor angeschlossen ist, kommt die entsprechende Meldung. 
Leider bekomme ich die Meldung "Buss Error", wenn ich einen anschliesse. 
Es ist ein DS18S20 - sollte also Funktionieren.

Da ich ein Rookie in Sache MC bin, bin ich sicher, dass ich den 
Wiederstand falsch angeschlossen habe.

Kannst Du mir bitte - gerne auch per Hand oder screenshot, PPT oder 
sonstwie die Schaltung so ergänzen, dass ein DS18S20 an PC1 dran ist? 
Ich möchte damit meinen Aufbau Zuhause kontrollieren.

Vielen Dank - und Asche auf mein Haupt...

Gruss,
Axel

von Peter D. (peda)


Lesenswert?

athobaben wrote:
> Kannst Du mir bitte - gerne auch per Hand oder screenshot, PPT oder
> sonstwie die Schaltung so ergänzen, dass ein DS18S20 an PC1 dran ist?

So, wie im Datenblatt, GND an 0V, VCC an 5V und den Datenpin an den IO. 
und nen Pullup (2,2k) gegen 5V.


Peter

von Axel T. (athobaben)


Lesenswert?

Hallo Peter

mit GND des Sensors an 0V und DG mit 4,7k Pullup gegen den Datenpin 
funktioniert meine Schaltung.

ID: 10 60 4F 4E 01 08 00 96   T: 0188 =   24.5?C

Ich habe auch kapiert, wie die Fuse mit dem Takt und der Baudrate 
zusammenspielen.

Soweit so gut...

Leider habe ich noch 2 ungereimtheiten.

1) wenn ich VCC an 5V lege bekomme ich einen Bus-Error - da Du irgendwo 
im Source etwas von Parasite Power schreibst, habe ich den Pin 
weggelassen. Wenn meine Schaltung und das Mess-Objekt Mass-Kontakt haben 
ist alles i.O und ich kann wunderbar messen. Ist das richtig?

2) Wenn ich nun 2 DS18S20 an den Anschluss klemme (GND1 und GND2 an OV 
und DG1 mit DG2 an den selben Datenpin mit dem selben 4,7k Pullup) kommt 
leider wieder ein Bus-Error.

Kannst Du mir den Neben lichten und mir ggf. den Thread nennen, in dem 
Du das bestimmt schon zig mal erklärt hast? Es sind sehr viele und z.T. 
sehr lange Threads... .

Ich würde gerne mehr als einen Sensor auswerten.

Danke für den Code und die bisher geleistete Hilfe.

Gruss,
Axel

von Peter D. (peda)


Lesenswert?

Der Bus-Error kann daran liegen,. daß die 15µs in "w1_bit_io" vielleicht 
etwas zu lang sind. Schreib da mal 5 oder 10 rein.
Die älteren Sensoren hatten wohl ein langsameres Timing.


Peter

von AThobaben (Gast)


Lesenswert?

Hallo Peter

ich habe
1
DELAY( DELAY_US( 15 - 1 ));

in "w1_bit_io" von 2 bis 15 in 1-Schritten durchgetestet. Leider immer 
noch Buss-Error, wenn ich mehr als einen DS1820 dranhänge.

Weiter oben gibst Du den Rat einen schnelleren Quarz zu nehmen - ATMega8 
und 8Mhz - sollten doch aber funktionieren wenn ich oben das so lese... 
.

Für prasitäre Spannungsversorgung muss doch GND und VDD vom Sensor 
zusammen auf 0V und der DQ mit 4,7k Pullup auf den IO Pin. Wenn ich das 
machen komme ich immer Bus-Error, wenn ich VDD offen lasse geht es 
wenigstens mit einem Sensor.

Idee?

Danke und GRuss,
Axel

von Werner B. (werner-b)


Lesenswert?

Nur weil ich gerade (mal wieder) ein Bild gesehen habe auf dem ein User 
den Vcc Pin bei Parasite Power offen gelassen hat (und sich wundert 
warum sein DS18x20 nicht funktioniert).

Wer sich das Datenblatt durchliest erfährt: "Den soll man auf GND 
legen!"

von Peter D. (peda)


Lesenswert?

AThobaben wrote:
> in "w1_bit_io" von 2 bis 15 in 1-Schritten durchgetestet. Leider immer
> noch Buss-Error, wenn ich mehr als einen DS1820 dranhänge.

Benutzt Du die Optimierung -Os ?

Stimmt denn Dein Takt wirklich mit der Definition von XTAL überein?

Hast Du noch andere Interupts im Programm?

Poste mal Dein komplettes Programm mit dem erzeugten Assemblerlisting.


Peter

von Axel Thobaben (Gast)


Lesenswert?

Hallo Peter,
Hallo Werner

@Werner:
Das komische ist ja, wenn ich VCC auf GND lege - bekomme ich den 
Bus-Error, wenn er offen bleibt funktioniert ein DS18S20 aber eben nur 
einer.

@Peter:
Sorry das es länger gedauert hat. Kann Sein, dass die Optimierung 
wirklich auf -Os steht. Ich setze die mal auf -O1 oder -O3 und teste 
das.

Nein - meines Wissens habe ich keine anderen Dinge drin ausser die, die 
Du in Deinem ersten Thread gaaaanz oben geposted hast.

Ich kann aber gerne ein ZIP posten mit allem, was drinnen ist...

XTAL steht auf 800000 (8Mhz) sollte das auf 800000L stehen?

Gruss und Danke,
Axel

von Peter D. (peda)


Lesenswert?

Axel Thobaben wrote:

> XTAL steht auf 800000 (8Mhz) sollte das auf 800000L stehen?

weder noch, 8MHz entspricht 8000000L.


Peter

von fantomas (Gast)


Lesenswert?

Hallo Petter, mit schnelleren Takt funktioniert alles wunderbar aber 
nicht mit 1 MHz. Gibts da neue Lösungen oder Ansätze?

thx

PS
benutze 18s20

von Wolfgang H. (hastekene)


Lesenswert?

Hallo Peter,
ich hab mir mal deinen 1 wire Code heruntergeladen und hab jetzt 
folgende Probleme mit AVR Studio 4:

AVR Studio melde mir folgende Fehler:
../main.h:11:16: error: io.h: No such file or directory
../main.h:12:23: error: interrupt.h: No such file or directory
../main.h:15:20: error: signal.h: No such file or directory

wenn ich jetz die dateien aus AVR lade mit

#include <avr/io.h>
#include <avr/interrupt.h>

meckert AVR Studio

../TEMPMEAS.C:37: error: 'sprintf' was not declared in this scope
../TEMPMEAS.C:48: error:   initializing argument 1 of 'void 
uputsnl(char*)'
usw.

kannst du mir sagen wo ich den Fehler suchen muss

By
Wolfgang

von Daniel B. (dbuergin)


Angehängte Dateien:

Lesenswert?

Hallo Wolfgang

Lies mal den ganzen Thread durch.

Wenn ein C-Programm mit einem GROSSEN .C endet, bedeutet das für
aktuelle C-Compiler, dass dies ein C++ Programm ist. Du hast wohl den
Code von Peter genommen, und nicht alle Files auf Kleinbuchstaben
geändert. Aendere alle Filenamen auf Kleinbuchtstaben, und es sollte
gehen.

Hab das Ganze mal für den GCC 4.3.0 angepasst. Bei mir kommen so keine
Fehlermeldungen mehr. Ob es läuft weiss ich nicht, da ich keinen
ATmega8 habe und ich auch noch nicht weiss, ob der GCC 4.3.0, welcher
bei meinem aktuellen Ubuntu Linux 8.10 dabei ist, fehlerfrei ist.

Daniel

von Wolfgang H. (hastekene)


Lesenswert?

Danke für den Tipp c ist halt leider nicht Pascal

By Wolfgang

von Johannes (Gast)


Lesenswert?

Hi,

ich habe versucht die hier angegebenen Files zu verwenden. Und zwar für 
einen ATmega16 im AVR-Studio mit avrgcc. Beim kompilieren bekomm ich 
folgende Fehler:

../../../../../WinAVR-20080610/avr/include/TEMPMEAS.C:37: error: invalid 
conversion from 'unsigned char*' to 'char*'
../../../../../WinAVR-20080610/avr/include/TEMPMEAS.C:37: error: 
initializing argument 1 of 'int sprintf(char*, const char*, ...)'

Der dazu passende Code-Ausschnitt:

sprintf( s, "%02X ", id[i] );

Diese Fehler bekomm ich bei jeder sprintf().
Kenn mich selber aber nicht so gut aus. Kann mir jemand sagen wo das 
Problem liegt und wie ich es beheben kann.

grüße Johannes

von Peter D. (peda)


Lesenswert?

Johannes wrote:

> ../../../../../WinAVR-20080610/avr/include/TEMPMEAS.C:37: error: invalid
> conversion from 'unsigned char*' to 'char*'

Kann ich mir nur so erklären, daß Du in Deinem Make nen Schalter hast: 
wandle Warnings in Errors um.

Die AVR-GCC-ler haben so nen Spleen, daß es negative Buchstaben gibt, 
daher müssen die vom Typ char sein, kein anderer 8-bit Typ wird 
geduldet.
Ist ähnlich nervig, wie die überflüssigen Klammer-Warnings.


> sprintf( s, "%02X ", id[i] );

Mach nen cast
1
> sprintf( (char*)s, "%02X ", id[i] );


Peter

von Johannes (Gast)


Lesenswert?

Danke Peter!

Funktioniert nun einwandfrei, vielen dank für die Hilfe.
Übrigens echt tolle software!

von Feissy (Gast)


Lesenswert?

hallo, ich würde auch gerne die 1wire ds1820 auslesen, nur möchte ich 
die temperaturen auf einem lcd angezeigt bekommen die routinwn für den 
lcd sind mir bereits bekannt, nur ist mir nicjht wirklich klar, welche 
funktion oder variable ich auf dem lcd ausgeben muss??
kann mir da jm helfen oder hat soetwas schon jm mal gemacht??
mfg

von Daniel L. (grorkef)


Lesenswert?

Hallo,

Ich hätte da mal ne Frage. Wenn ich nun einen Systemtakt benutzte der 
nicht durch 256 teilbar ist, dann wird ja nach jeweils 256 Overflows der 
Rest aus der Divison von Systemtakt durch 256 zum Comparewert 
hinzugefügt.

Nun stellt sich mir die Frage: Wird dann nicht jedesmal der Abstand zu 
einer Sekunde größer, weil es ja dann von einer zu nächsten sekunde 
immer länger dauert bis Prescaler 256 erreicht oder mach ich da einen 
Denkfehler?

1
SIGNAL (SIG_OUTPUT_COMPARE1A)
2
{
3
  uchar tcnt1h = TCNT1H;
4
5
  OCR1A += XTAL / DEBOUNCE;    // new compare value
6
7
  if( ++prescaler == (uchar)DEBOUNCE ){
8
    prescaler = 0;
9
    second++;        // exact one second over
10
#if XTAL % DEBOUNCE      // handle remainder
11
    OCR1A += XTAL % DEBOUNCE;     // compare once per second
12
#endif
13
  }
14
  TCNT1H = tcnt1h;      // restore for delay() !
15
}

Ich hoffe es ist verständlich was ich meine.

MFG Daniel L.

von Wen kiat teh T. (Firma: HS Karlsruhe) (wenkiat84)


Lesenswert?

Kann jemand mir vielleicht helfen,ein funktionierende C-Code für 
DS18S20,die auf Infineon XC164CM (mit Keil MicroVision3) zu 
erzeugen?Oder ein paar Tipps und Links,wo ich die C-Code finden kann?

Gruss
Aaron

von Proteus (Gast)


Lesenswert?

Moin,

versuche gerade dem Code auf nem atmega32 zum laufen zu bringen. Benutze 
AVR Studio mit GCC Compiler... nachdem ich das "GROßSCHREIBEPROBLEM" 
oben schon gefunden habe taucht bei mir was Neues auf:

H:\1 Wire\default/../Main.c:13: undefined reference to `init_timer'
H:\1 Wire\default/../Main.c:14: undefined reference to `uinit'
H:\1 Wire\default/../Main.c:16: undefined reference to `uputsnl'
H:\1 Wire\default/../Main.c:17: undefined reference to `second'
H:\1 Wire\default/../Main.c:20: undefined reference to `second'
H:\1 Wire\default/../Main.c:21: undefined reference to `start_meas'
H:\1 Wire\default/../Main.c:22: undefined reference to `second'
H:\1 Wire\default/../Main.c:24: undefined reference to `second'
H:\1 Wire\default/../Main.c:25: undefined reference to `read_meas'
H:\1 Wire\default/../Main.c:26: undefined reference to `second'

Verstehe nicht warum der die nicht kennt! z.B. wird `init_timer' doch 
aus "timebase.h" in "main.h" includiert!
Kann mir mal jemand nen Tip geben was ich hier falsch mache?!?

Danke.

von hastekene (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Proteus,

ich kenne zwar deinen Code nicht bei mir funkts aber mit atmega 32 
problemlos

sende dir mal meinen bisherigen code beinhaltet Temperaturauswertung 
DS18B20
und noch etwas mehr
vielleicht hilft es dir

by
Wolfgang

von Werner B. (werner-b)


Lesenswert?

Hast du evtl. ein Leerzeichenproblem?

> H:\1 Wire\default/../Main.c:26: undefined reference to ...
     ---

von Proteus (Gast)


Lesenswert?

Wow, danke für die viele schnelle Hilfe!

@ Werner B. War ne gut Idee, hat abe auch nicht geholfen, werde trotzdem 
in Zukunft mit sowas aufpassen!
@ Wolfgang Prima, dein Code läss sich Fehlerfrei bei mir compilieren! 
Auch der 1wire Part! Damit komme ich auf jeden Fall schon mal weiter!

Gruss Proteus

von Timo P. (latissimo)


Lesenswert?

Hallo!

Lt. anderem Beitrag konnte ich jetzt kompilieren. Soweit so gut.

einen Sensor habe ich bisher nicht angeschlossen. Hyperteminal zeigt mir 
keinerlei (vom Mega32 gesendete Zeichen) Oszilloskop bestätigt, das der 
tx-Pin schön auf high bleibt.


Sendet die SW nur, wenn ein Sensor vorhanden ist?
Oder wann genau wird was gesendet?

Danke im Voraus!

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:

> Sendet die SW nur, wenn ein Sensor vorhanden ist?
> Oder wann genau wird was gesendet?

Schau in den Code und analysiere ihn. So schwer ist das nicht.
Fremden Code einfach so zu übernehmen, ohne zu wissen was man da tut und 
ohne ein gewisses Grundlagenwissen in der verwendeten Programmiersprache 
zu haben funktioniert nun mal nicht.

von Timo P. (latissimo)


Lesenswert?

habe es jetzt gesehen im code.
short circuit und no sensor found kommt beides

von Timo P. (latissimo)


Lesenswert?

Den code anzupassen ist nicht das Ding! trotzdem ist es oft hilfreich, 
einer zipdatei eine readme beizufügen, wo in ein paar sätzen kurz und 
knapp der programmablauf beschrieben ist.

Dies spart zeit und macht den code( wenn er wie hier) für andere 
offengelegt wird viel attraktiver.

Bitte nicht als negative Kritik aufnehmen. C-Code ist mir wohl ein 
Begriff, also das Verständnis ist nicht das problem, auch wenn es vorhin 
mit den includes vllt so schien.

z.B habe ich statt <headerfile> "headerfile" ausprobiert. soweit ich 
weiß, sucht der compiler die headers via <> im compilerverzeichnis und 
via "" im aktuellen source-verzeichnis.

anmerkung: ich finde es toll, das es Leute gibt, die hier ihren Code 
veröffentlichen, und sich auch noch den Problemen der Leute annehmen.
Besten Dank für den Code an PEDA!

von Timo P. (latissimo)


Lesenswert?

hallo!


Hat jemand einen sinnvollen tip in Bezug auf Eigenerwärmung? Bisher 
betreibe ich einen DS18S20 mit externer Versorgung. Derzeit 5V.

1) Bald habe ich eine Schaltung, die mit 3v3 läuft.(müsste doch 
eigentlich
   die Eeigenerwärmung reduzieren??)
2) Den Sensor werde ich dann in Zeitintervallen bestromen(vielmehr die
   SensorEN) sollte auch was bringen.

noch eine Frage:

3) Hat jemand eine Berechnung für negative Temperaturwerte realisiert?

von Timo P. (latissimo)


Lesenswert?

im Datenblatt steht was von: Highbyte ist entweder 0xFF oder 0x00.

bei Highbyte = 0xFF hat man ne negative Zahl


die Werte für low und highbyte kombiniert sind bei mir aber

z.B 44 für +22.5°C anstatt:

mindestens 65280 also:  1111 1111 xxxx xxxx
1
temp =1_byte_rd();      // low byte
2
temp |= (uint)w1_byte_rd() << 8;  // high byte
3
4
sprintf(s,"Hier temp als dezimalzahl : %d \r\n", temp);  
5
uputs(s );

von Wolfgang-G (Gast)


Lesenswert?

>Bald habe ich eine Schaltung, die mit 3v3 läuft.(müsste doch
>eigentlich die Eeigenerwärmung reduzieren??)
Bei +-0.5°C Fehlergrenze würde ich mir keine Gedanken darüber machen
MfG

von R. B. (p1ng)


Lesenswert?

Hallo Leute,

ALso momentan basstel ich gerade mit 1-Wire rum und komme net wirklich 
weiter.

Ich benutze das myAVR Workpad weil ich mit dem Studio nicht wirklich 
klar komme. Irgendwie bekomme das Programm nicht richtig übersetzt, das 
ich es sauber in das Workpad bekomme, hatt einer von euch damit schon 
gearbeitet und weis rat. Bzw. Hatt das programm schon in dem Format. Ich 
benutze die Aktuelle WinAVR. Es reicht mir ja schon das ich nur einen 
Sensor auslesen kann.

Hardware: myAVR MKII Board --> ATmega8 --> 3,68400 MHz

Bitte um Hilfe
Danke

von Timo P. (latissimo)


Lesenswert?

@p1ng:

Hast du deine Schaltung ans Laufen bekommen? Wenn ja, wie hast du 
Timing-Probleme in den Griff bekommen? Bin der Meinung, dass der 
gewählte Quarztakt zu niedrig ist wenn du Pedas SW nutzt.

von hakan (Gast)


Lesenswert?

Hallo Peter,
erstmal, ein schönes neues Jahr 2010 wünsche ich Dir und schöne 
Weihnachten.

Ich habe den Code  1Wire übersetzt und den Stk500 an den PC 
angeschlossen.
Aber ich bekomme keine Ausgabe der Temperaturen über RS232.
Was mach ich falsch???
Ich habe Atmega8515 und DS1820.

Viele Grüsse
hakan

von (prx) A. K. (prx)


Lesenswert?

Da der Code nachweislich funktioniert, jedenfalls bei nicht zu langem 
Kabel oder bei längerem Kabel und langsam getaktetem Controller, kann es 
nicht an Peters Code liegen.

Folglich hast du was falsch gemacht. Mehr lässt sich aufgrund der 
überbordenden Detailfülle deines Beitrags kaum sagen.

Es könnte beispielsweise helfen, wenn du mitteilst wie du den 
angeschlossen hast. Und wie die entsprechenden Anpassungen im Code bei 
dir aussehen. Ganz ohne geht's ja nicht.

von Harald C (Gast)


Lesenswert?

Hallo,
kann mir jemand erklären, wozu der Search Rom Algorithmus in der Praxis 
gut sein soll ?
Man kann damit zwar die Rom-IDs aller Bausteine ermitteln, aber: wenn 
ich z.B. 10 DS1820 im System habe, bekomme ich 10 IDs, weiß aber 
trotzdem nicht, welche ID zu welchem Sensor gehört, kann also keine 
sinnvolle Zuordnung des Sensors zu einem bestimmten Meßpunkt machen.

Vielen Dank

Harald

von (prx) A. K. (prx)


Lesenswert?

Wenn man sie nacheinander dranhängt ist das überhaupt kein Problem. In 
manchen Anwendungen kann man die Sensoren auch über den Wert 
unterscheiden, d.h. man zeigt in der Systemkonfiguration alle gefundenen 
Sensoren mitsamt Wert an und überlässt dem Anwender die Zuordnung zu 
beispielsweise Aussen/Innen/Wassertemperatur.

von Harald C (Gast)


Lesenswert?

Hallo A.K,
bei zwei, drei Sensoren ist das sicherlich kein Problem.
Was aber wenn man 10 und mehr Sensoren einsetzt, die in einer Anlage 
Temperaturen messen, die im gleichen Bereich liegen z.B. 20 - 80 Grad 
und dann immer nur um 10 - 20 Grad differieren ?
Dann kommst Du so aber nicht weiter.

Harald

von (prx) A. K. (prx)


Lesenswert?

(1) Man die steckbar und schliesst sie nacheinander an.
(2) Man hat ein Prüfgerät, das vor Einbau der Sensoren die ID anzeigt.

von Harald C (Gast)


Lesenswert?

So hatte ich mir das auch gedacht.
Ich war nur etwas verwundert über den doch recht "aufwendigen" ROM 
search algorithmus und was der dann in der Praxis bringen sollte.

Vielen Dank und noch schöne Festtage

Harald

von hakan (Gast)


Lesenswert?

Hi,
ich hatte vergessen den kompilierten Code in den Atmega8515 zu brennen.
Jetzt klappt es. Nur ich bekomme irgendwie falsche werte.

Habe schon mit verschiedenen Baudraten versucht.

Kann es daran liegen, dass ich DS1820 verwende und nicht den DS18B20?

Oder vielleicht die Schaltung nicht richtig? da ich GND und VCC des 
PORTD
von Stk500 benutze.

Viele Grüsse viel spaaass
hakan

von cloud (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe das Programm so geändert, dass es mir den Temperaturwert auf 
einem LCD darstellt.
(Atmega8 auf Pollin Evu-Board, DS1820, 2x16 LCD. AVR-Studio 4.15, 
WinAVR.)

Ich würde aber gerne 2 Temperaturwerte auf dem Display darstellen.

Schließe ich 2 Sensoren an den Bus an wird nur die ID und die Temperatur 
eines Sensors angezeigt.

Meine Überlegeung bisher war folgende:
In der tempmeas.c geht der ja in die for-schleife und sucht die Sensoren 
und gibt dann die ID und Temperatur nacheinander für beide Sensoren aus. 
Beim UART bestimmt kein Problem aber für die Darstellung auf dem LCD 
unbrauchbar.
Soll ich in der main.c 2 Messungen aufrufen? Wie ist es mir möglich 
einen Sensor gezielt abzufragen? über die ID? Wahrscheinlich ist diese 
Herangehensweise total falsch.


Habt ihr Ideen wie ich mein kleines Projekt am Besten umsetzen kann?

Anbei der Code im zip-file.

von Josef D. (Gast)


Angehängte Dateien:

Lesenswert?

DS18x20 mit Namen versehen
Die DS1820 haben doch zwei Byte Ram, in die man selbst was reinschreiben 
kann, z.B. einen Namen aus zwei Buchstaben; die ID braucht man dann gar 
nicht zu kennen.
Ich habe die erforderlichen Änderungen in die Datei „TEMPMEAS.c“ aus 
clouds Post vom 08.01.2010 eingepflegt, konnte aber nur bis zur 
fehlerfreien Compilierung testen, da ich keine passende Hardware habe 
(mein LCD ist mittels I2C angeschlossen).
Die ursprüngliche Version, die ich auch vor ca. zwei Jahren als 
Ausgangspunkt genommen habe, stammt wohl von Peter Dannegger (vielen 
Dank dafür; seine Programme waren mir schon an vielen Stellen eine große 
Hilfe und eine gute Lehre). Meine aktuelle Version ist mittlerweile zu 
sehr auf meine eigenen Bedürfnisse zugeschnitten und wäre so für viele 
nicht brauchbar, so dass ich diesen Weg vorgezogen habe.
Die Ausgabe-Funktionen gehören eigentlich nach main.c, aber ich habe es 
vorgezogen, nur eine Datei zu verändern. Wenn man es so lässt, müssen in 
main.c die Zeilen, die für die LCD-Ausgabe zuständig sind, noch entfernt 
werden.
Die Funktionsweise ist folgende (weiter Kommentare im Quelltext):
In einer Überschrift (die dann in meinem Projekt zusammen mit den 
Messdaten über SD-Karte oder UART schließlich auf dem PC landen und mit 
Excel weiter verarbeitet werden) stehen die Namen, die die Sensoren 
erhalten sollen.
In der Lese-Funktion wird zusätzlich zu ID und Temperatur noch der 
zwei-buchstabige Name ausgelesen. Dann wird geprüft, ob dieser Name in 
der Überschrift existiert. Wenn ja, ist damit auch bekannt, an welche 
Stelle im Array mit den Temperaturen der Wert eingetragen werden muss. 
Zusätzlich wird in einem BitArray (valid) vermerkt, welcher Name schon 
gefunden wurde.
Wenn der Name nicht in der Überschrift vorkommt, wird davon ausgegangen, 
dass es sich um einen neuen Sensor handelt, dem noch kein Name 
zugewiesen wurde. Diese Sonderbehandlung findet aber nur im zweiten 
Durchgang statt (initReady==1). Dafür darf im ersten Durchgang 
(initReady==0) am Ende valid nicht gelöscht werden, damit im zweiten 
Durchgang noch bekannt ist, welche Namen schon erkannt wurden. Dann wird 
der erste noch nicht erkannte Name aus der Überschrift in den Sensor 
geschrieben.
Bei der Inbetriebnahme schließt man also die Sensoren in der Reihenfolge 
einzeln an, wie sie in der Überschrift stehen, und schaltet jeweils 
einmal kurz ein. Sollte einmal ein Sensor defekt sein, kann man ihn 
einfach durch einen neuen ersetzen, einschalten und fertig.

von strikeforce (Gast)


Lesenswert?

Hey  danke schonmal für das C.

Habe nur eine frage
Wie kann ich am einfachsten negative werte ausgeben ?

Mfg strikeforce

von Michael S. (Gast)


Lesenswert?

Die Umwandlung der Temperaturen habe ich nach einigen umständlichen 
Ansätzen wie folgt gelöst:

1. Das High-Byte mit 10 multiplizieren (als int16).
2. Aus dem Low-Byte die Nachkommastelle berechnen
   (als Wert zwischen 0 .. 9).
3. Diesen Wert zum (High-Byte * 10) addieren.
4. Nun hat man die mit 10 multiplizierte Temperatur incl. 
Nachkommastelle.

Um ein Dezimaltrennzeichen einzubauen, kann man die Zahl in einen String 
umwandeln, das letzte Zeichen um 1 nach rechts schieben, statt dessen 
ein Komma einfügen (und dann ggf. wieder ein terminierendes 0 anhängen.

Die Nachkommastellen berechne ich so:

Das Low_Byte >> 4 um 4 Stellen nach rechts schieben
und mit 0.625 multiplizieren (das geht natürlich so nicht !!).

Statt dessen wird mit 625 multipliziert und durch 1000 dividiert.

Einfacher ist, mit 640 zu multiplizieren und durch 1024 zu dividieren.

Wenn man auch die Schiebeaktion mit in die Berechnung einbaut, dann kann 
man alternativ rechnen:

(Low_Byte / 16) * (640 / 1024) = Low_Byte * 40 / 1024.

Im Moment haben wir ja die richtigen Temperaturen, um die 
Funktionsfähigkeit dieser Berechnung im Bereich unter 0° zu prüfen.


Michael S.

von Sebastian (Gast)


Lesenswert?

Hallo
Mal eine Anfängerfrage :
Da ich erst alles löten muss bevor ich loslegen kann mit dem LCD + 
DS1820 fehlen mir noch die Pins für Uart, DS1820 und LCD. Welche Ports 
werden benötigt? Ich werde das ganze mit einem ATMEGA8 bauen.

Grüße und Danke
Sebastian aus Stuttgart

von Peter D. (peda)


Lesenswert?

Die beiden Pins für die UART findest Du im Datenblatt.
Die Pins für LCD und 1-Wire können beliebige IO-Pins sein.


Peter

von Sebastian (Gast)


Lesenswert?

Hallo Peter

Ja aber bezogen auf die CodeBeispiele von :

Autor:  Josef D. (Gast)
Autor:  cloud (Gast)

ich sehe das aus dem code nicht sofort raus wie ich es zusammenlöten 
muss.
Ich wollte erst löten und dann den code fertig nehmen zum basteln.

grüße
Sebastian

von Michael S. (Gast)


Angehängte Dateien:

Lesenswert?

Konvertierung (negativer) Temperaturwerte beim DS18B20

Zu diesem Thema hatte ich kürzlich eine Anmerkung gemacht.

In der Annahme, dass das Datenformat des DS18B20 und des DS1631 gleich 
sind, zumindest sehen die Datenblätter zunächst wie Kopien aus.

Aber leider sind die Formate nur fast gleich.

Während beim DS1631 die 12 Datenbits linksbündig ausgerichtet sind, 
stehen sie beim DS18B50 rechtsbündig.
Daher müssen die Nibbles beim DS18B50 anders geschoben werden als ich es 
beschrieben habe.

Dazu ein Codeschnipsel als Anlage und Korrektur.

Michael S.

von Timo S. (kaffeetas)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe die w1_byte_wr() Funktion um eine CRC Prüfung erweitert.

Auslesevorgang:
w1_crc auf 0 setzten.
scratchpad komplett auslesen.
wenn w1_crc gleich null ist dann war die CRC Prüfung erfolgreich.

Vielleicht kann es jemand brauchen.
Ich habe allerdings die Funktion nur mit dem Scratchpad vom DS18S20 und 
ohne ROM SEARCH getestet.

Grüße
 Timo

von Sebastian (Gast)


Angehängte Dateien:

Lesenswert?

Hallo  Josef D.

ich verwende deinen Code.
Bei mir tritt aber ein Anzeigefehler auf.
Ganze zahlen wie 23,24,25 Grad werden gut angezeigt.
Kommazahlen  wie 23,5 werden als 23.-5 angezeigt (siehe Foto)

Gibt es dafür eine Lösung ?

Grüße
Sebastian

von Josef D. (jogedua)


Lesenswert?

Hallo Sebastian,
wenn ich mich recht erinnere, stammt der Code für die Ausgabe nicht von 
mir, wohl aber die Bemerkung, dass der für negative Werte falsche 
Ergebnisse liefert, mit einem Kommentar, wie man das korrigieren kann.
Aus deinem Beitrag geht nicht hervor, ob du meine vorgeschlagene 
Änderung eingebaut hast.
Für eine Hilfe wären die paar Zeilen Code, die bei dir zu der Ausgabe 
führen, schon sehr hilfreich.

Josef D.

von Josef D. (jogedua)


Lesenswert?

Hallo Sebastian,
erst beim nochmaligen Lesen ist mir aufgefallen, dass es dir gar nicht 
um negative Werte geht. Habe daraufhin noch mal den von mir geposteten 
Code angesehen und festgestellt, dass doch wohl meine Änderung für den 
Fehler verantwortlich ist, die ich nicht testen konnte, wie ich auch 
angemerkt hatte.
Vermutliche Lösung (auch nicht getestet):
Es muss in der for-Schleife uint16_t temp statt int16_t temp
heißen, wenn man nur mit nicht-negativen Werte rechnen und den 
unveränderten Code verwenden will (eine Variable uint temp wird weiter 
ebenfalls benutzt, da hätte ich besser auch einen anderen Namen gewählt)

Sorry

Josef D.

von Sebastian A. (xxlxx)


Lesenswert?

Perfekt ! Danke !

jetzt sind Kommawerte kein Problem mehr.

für den Rest der Welt.
Diese Zeile (140) muss geändert werden :

    int16_t  temp=thermoValues[i];
in

    uint16_t temp=thermoValues[i];

Noch eine Frage :
was muss ich anstellen um mehr als einen Sensor zu lesen ?
Ein Sensor T1 wirft den Output aus wie auf dem Bild weiter oben.
Schalte ich einen weiteren Sensor dazu (Parallel) änders sich nichts.
T2 und T3 zeigen nichts an. Werden die ID´s für T1 fest im µProc 
abgelegt?
Muss man T2 neu anlernen? Achso ich habe zwei sensoren die beide einzeln 
als T1 laufen, nur zusammen eben nicht.

Sorry die Fragen aber ich mache Hardware + AVR + GCC erst seit 5 Tagen.
und bin schon recht weit ...

grüße
Sebastian

von Sebastian A. (xxlxx)


Lesenswert?

Problem selber gelöst und neue erkenntnis gewonnen :

- Der EEprom im Ds1820 bleibt dauerhaft geschrieben.
- Der erst Sensor heist T1 und legt das auch im Sensor so ab.
- Wenn man nun wieder einen Sensor anschließt wird er wieder T1 genannt
- Schließt man beide an hat man zwei T1 Sensoren und das geht nicht.

Also

- aus T1 bis T3 in dem Code zb. A1 bis A3 machen
- Sensor 1 an schließen und A1 einlernen
- Sensor 2 dazu anschließen --> sensor zwei bekommt A2 gelernt

jetzt gehts ...

Grüße Sebastian

von Stefan M. (Gast)


Lesenswert?

Hallo

ih verwende die 1Wire.zip Routine. ich habe Sie erweitert damit man 0.1 
Grad sprünge mit dem DS18S20 sieht. Leider verstehe ich die Routinen von 
Peter nicht so genau. Gibt es zum Code von Peter eine Readme?  ich 
möchte gerne die Read Messung so abwandeln das ich die sensoren einzeln 
ansprechen kann?
Wo werden die ID´s gespeichert? wie kann ich sie einzeln abrufen? Fragen 
über Fragen ... eine Readme währe hilfreich.

Thanks Stefan M. aus Eisenach

von Christoph (Gast)


Lesenswert?

Hallo

kannst Du dein C Programm mal hier hochladen.

Ich kann jetzt eine Temperatur auf meinem Display (4bit) darstellen, 
jedoch nur ein Sensor und keine negativen Temperaturen.

christoph

von JOZO (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
Ich spreche nict Deutsch, please forgive me...

Can anybody help me with reading and store the device ID from 18b20 on 
1-wire? I enclose my simple source code. I use the LCD 2x16 and one 
18b20 succesfully. I would like improve :
1. The time of temperature reading (with only tvo decimal-pointed, not 
four)
2. how to add the second temperature sensor 18b20. ?

In enclosed file there are full functional project for AVRstudio, photos 
and schematics (schema.jpg).


I see, that you are good in this area.
THX a lot
JOZO

PS:
(main program:ATmegatest.c, sensor:therm_ds18b20.c and h., owi.c,h is 
not used)
In main program for measure the temperature,i use only this:
char x[20] = {0};
therm_read_temperature(x);
lcd_puts("T= ");
lcd_puts(x);

von Sebastian A. (xxlxx)


Angehängte Dateien:

Lesenswert?

Messung der Luftfeuchte (psychometer) mittels DS1820

Also ich habe das jetzt so gemacht.

2x Ds1820 mit 0.1C auslösung (formel siehe datenblatt)
1x ATmega8
1x LCD 2x40
1x Modul mit lüfter + bewässerung (eigenbau)

Routinen von Peter mit nur kleinen Änderungen.

Messwete:
- Feuchte
- Taupunkt
- Temperatur

grüße
Sebastian

von Xx D. (delaware)


Lesenswert?

Sebastian Albrecht schrieb:
> Problem selber gelöst und neue erkenntnis gewonnen :
>
> - Der EEprom im Ds1820 bleibt dauerhaft geschrieben.
> - Der erst Sensor heist T1 und legt das auch im Sensor so ab.
> - Wenn man nun wieder einen Sensor anschließt wird er wieder T1 genannt
> - Schließt man beide an hat man zwei T1 Sensoren und das geht nicht.
>
> Also
>
> - aus T1 bis T3 in dem Code zb. A1 bis A3 machen
> - Sensor 1 an schließen und A1 einlernen
> - Sensor 2 dazu anschließen --> sensor zwei bekommt A2 gelernt

Einen Sensor ran, erkennen lassen, zweiten ran und Prozessor resetten.
Wenn dieser erkannt ist, dritten Sensor ran und Prozessor resetten.

So ging es bei mit.

Christoph.


!!!!!!!!!!!!!!!!!!!!1
Wie kann ich denn die Routine abändern, damit negative Tempraturen und 
Nachkomma korrekt dargestellt wird ?.

----------------------------------------
 sprintf( (char*)s, "%3d.%01dC", temp >> 4, (temp << 12) / 6553 ); // 
0.1øC
      // Achtung: liefert bei negativen Temperaturen falsche Ergebnisse!
----------------------------------------




>
> jetzt gehts ...
>
> Grüße Sebastian

von Sebastian A. (xxlxx)


Lesenswert?

@Christoph Scheicht

Negative Werte habe ich nicht benötigt. Deshalb auch keine Idee.
Die Nachkommawerte sind mit der Formel aus dem Datenblatt recht einfach 
zu errechnen.
1
TEMPERATURE = TEMP READ  -  0.25 +  COUNT PER C- COUNT REMAIN
2
                                    -------------------------
3
                                          COUNT PER C
4
Beispiel : 
5
6
TEMPERATURE = 25C  -  0.25    +     16 - 12    =  24,5C
7
                                    -------
8
                                       16

COUNT PER C und COUNT REMAIN werden aus dem Scratchpad ausgelesen.

grüße
Sebastian XXlXX

von Alfred (Gast)


Lesenswert?

Hallo Sebastian,

wie misst du die Luftfeuchte mit dem DS1820?

Der Taupunkt errechnet sich doch aus Druck, Temperatur und Feuchte, 
oder?

Lieg ich falsch?

Grüße,

Konstantin

von Gerhard O. (gerhard_)


Lesenswert?


von Sebastian (Gast)


Lesenswert?

Ja du hast recht der Druck wird benötigt. ABER : für diesen Wert nutzt 
man einen Mittelwert. Das macht keinen großen Unterschied.

Ich habe das Gerät mal zum prüfen einem Wettermann mitgegeben. Mein 
Gerät hat 2% Abweichung wenn ich es min 5 Minuten laufen lasse. Zur 
bestimmung der Hausfeuchte (neubau) ist das jetzt so prima.

grüße
Sebastian

von Sebastian (Gast)


Angehängte Dateien:

Lesenswert?

NACHTRAG

hier mal die Formel als Excel.
Ist dann einfach in C umzusezen.

Grüße
Sebastian
xxlxx

von Gerhard O. (gerhard_)


Lesenswert?

Hallo Sebastian,

koenntest Du mir bitte den Titel und ISBN Nummer von Deinem PDF Dokument 
bekannt geben.


Gruss,
Gerhard

von Sebastian (Gast)


Lesenswert?

Gerhard O. schrieb:

> koenntest Du mir bitte den Titel und ISBN Nummer von Deinem PDF Dokument
> bekannt geben.

Leider habe ich PDF auch nur so von meinem Wettermann bekommen.

Sorry


grüße
Sebastian

von Gerhard O. (gerhard_)


Lesenswert?

Vielen Dank, Sebastian !

Gruss,
Gerhard

Sebastian schrieb:
> Gerhard O. schrieb:
>
>> koenntest Du mir bitte den Titel und ISBN Nummer von Deinem PDF Dokument
>> bekannt geben.
>
> Leider habe ich PDF auch nur so von meinem Wettermann bekommen.
>
> Sorry
>
>
> grüße
> Sebastian

von Sebastian (Gast)


Lesenswert?

Der Text (PDF) kommt von  :

http://openlibrary.org/b/OL4622634M/Aspirations-Psychrometer-Tafeln

Deutscher Wetterdienst


grüße
Sebastian

von JOZO (Gast)


Lesenswert?

I used your source code from this forum and it works now fine.
I solved only problem with negative temperature additionally.

von Wolfi (Gast)


Lesenswert?

Hallo Leute bin ein anfänger im Programmieren. Muss mit dem Temp.Sensor 
DS1820 in AVR programmieren. ATMEGA8 werde ich verwenden kann mir da 
jemand helfen.
MfG Wolfi

von Wolfi (Gast)


Lesenswert?

Sorry Leute ich meinte ATMega128. Sag ich ja ich bin ein Anfänger.

Danke vorhinein

MfG Wolfi

von sebastian xxlxx (Gast)


Lesenswert?

Ja also das wird nicht reichen was du da so schreibst.
Ein AVR + DS1820 ist schnell genbaut.
Ohne Dispaly oder Ausgabe wird nie einer prüfen können ob dú alles 
richtig gemacht hast.
Wie möchtest du dein Endprudukt haben ?

Ich bin auch Anfänger vor ca 30 Baustundenstunden gewesen.
nach 30 Stunden habe ich das Endprodukt fertig gehabt.
(Siehe weiter oben die Bilder)

Grundlagen :

- AVR beschalten (+ - usw.)
- Sensoren an einen eingangspin
- Genial ist ein display zum testen & prüfen
- dann die Codes hier aus dem Forum auf dem AVR brennen (mit Brenner)
- Sehen was passiert und Grundlagenforschung betreiben.

So ging es bei mir erste erfolge hatte ich nach ca 2 Stunden.

Es gibt fertige Test Boards mit allem schon drauf.
Oder selber bauen (Viel Billiger)

Grüße Sebastian

von T. A. (wambly)


Lesenswert?

>hastekene schrieb:
> Autor:         hastekene (Gast)
>       Datum: 08.07.2009 17:35
> Angehängte Dateien: Heizung-32-4.zip (163,8 KB, 446 Downloads)
>       Hallo Proteus,
> ich kenne zwar deinen Code nicht bei mir funkts aber mit atmega 32
> problemlos
> sende dir mal meinen bisherigen code beinhaltet Temperaturauswertung
> DS18B20  und noch etwas mehr
> vielleicht hilft es dir
>
> by Wolfgang

Hallo an Alle
und Danke für alle angehängten Programme.

Hab ca 1Woche AVR-GCC erfahrung, hab aber den DS18S20 über Bascom auf 
FabianG. Testboard mit LCD am laufen.

Hab mit dem original ZIP GCC Probleme, Bei den 'neueren' Prog's 
kompiliert er mit Atmega8 mit 0Error. Dann ändere ich im Makefile 
Atmega8->Atmega88, dann hagelt es ERROR's. Das Obige Prog ist auch auf 
M8 nicht auf M32 mit den selben Umstellungsproblemen. Hier meker er 
wegen PortA, den hat der Mega8 aber auch nicht. Mal sehen ob irgendwo 
doch der M32 definiert ist???
Sonst muss ich einen M8 einsetzten, aber das LCD hab ich auch zum Laufen 
gebracht.
Gruss Toni

von xxlxx Sebastian (Gast)


Lesenswert?

Gratulation ! Ich habe das auch am ATmega8. Meine Luftfeuchtessung 
funktioniert super. Damals hatte ich auch erst 10 tage Erfahrung und 
dann gleich das projekt : Mega8 + LCD + DS1820 + Eigenbau (kein Board) 
... Aber das forum hier ist super und hat mir sehr geholfen.

grüße Sebastian ( xxlxx )

von T. A. (wambly)


Lesenswert?

Danke für die Aufmunterung.

Ich hab zwar schon viel erfahrung mit Elektronik(5Jahre 
Nachrichtentechnik Schule mit Abi vor 20Jahren). 2004 hab ich die JCU 
(Java Control Unit) für meine Kachelofensteuerung erworben und 
Programiert mit Messverstärker und i2c Schrittmotor.

Für kritische Anwendungen ist mir dieser Controller zu teuer und mager 
mit I/O.
Hab aber Bascom-Avr Erfahrung, dort muss man meist nur eine Zeile 
ändern, dann Compiliert es mit der anderen yC Einstellung. Aber wenn man 
die Routinen mal hat, is es kein Problem mehr.
Bascom mit 1Wire lief innerhalb 15Minuten, musste nur etwas Code 
entfernen, da über 4KB mit der Demo nicht compiliert wird.
Abber mit GCC wirds auch bald.
Hab ja noch DCF77 und CAN vor mir. Und Auto Drehzahlmesser wird 
irgendwann auch noch in C konvertiert.

Das Testboard ist mit Tonertransfer nach
[[http://www.kreatives-chaos.com/artikel/atmega168-testboard-v2]]
nachgebaut. Das 32/64 Board hab ich auch, aber etwas stark geätzt.

Gibts Registerlisten zB für Timer1 für ATmega8-48/88/168 nur im 
Datenblatt, oder kann man die in den IncludeDateien auch schnell finden, 
dann wäre das Handkonvertieren wesentlich einfacher.

Danke Toni

von ch-world (Gast)


Lesenswert?

Hallo,

ich bekomme mit Peters Code bei 50m Kabel den besagten Bus-Error. Da ich 
mit Bascom bereits die entsprechende Schaltung mit der Kabellänge zum 
laufen bekomme habe, habe ich mir Peters Code nochmal genau angeschaut.
Das Problem entsteht hier:
1
      b = w1_bit_io( 1 );      // read bit
2
      if( w1_bit_io( 1 ) ){      // read complement bit
Zu beginn der w1_bit_io wird der Bus auf high geschaltet. Am ende wieder 
of low. Durch den direkt hintereinander folgenden Aufruf der Funktion 
scheint die zeit die vergeht für 50m Kabel einfach zu gering. Wenn man 
am ende der w1_bit_io noch ein delay von 1ms einfügt funktioniert das 
ganze bei mir einwandfrei.

von ch-world (Gast)


Lesenswert?

hopala, ich mein natürlich 1us und nicht 1ms ;)

hier noch ein Beispiel um die Temperatur eines DS18S20 in einen String 
umzuwandeln:
1
void temp_to_string( signed int temp, char *s ) {
2
  itoa( temp >> 1, s, 10 );
3
  while( s++ && *s != '\0' ); // search end of string
4
  *s = '.';
5
  s++;
6
  if( temp & 1 ) {
7
    *s = '5';
8
  } else {
9
    *s = '0';
10
  }
11
  s++;
12
  *s = '\0';
13
}
Das interessante ist, dass der DS18S20 die Temperatur bereits als signed 
integer liefert. Somit kann man wunderbar mit itoa umwandeln.

von Lukas B. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo
ich habe die Software von Matthias heruntergeladen (vielen Dank!!) und
versucht für den ATMEGA8 zu complimieren.
Leider bekomm ich immer einen Fehler:

uint8_t  docrc8 ( uint8_t number_of_bytes_to_read )  /// HIER ist der 
Fehler
{
  uint8_t   crc;
  uint16_t loop_count;
  uint8_t  bit_counter;
  uint8_t  data;
  uint8_t  feedback_bit;

  crc = CRC8INIT;

  for (loop_count = 0; loop_count != number_of_bytes_to_read; 
loop_count++)
  {
    data = ow_buffer[loop_count];

    bit_counter = 8;
    do {
      feedback_bit = (crc ^ data) & 0x01;

      if ( feedback_bit == 0x01 ) {
        crc = crc ^ CRC8POLY;
      }
      crc = (crc >> 1) & 0x7F;
      if ( feedback_bit == 0x01 ) {
        crc = crc | 0x80;
      }

      data = data >> 1;
      bit_counter--;

    } while (bit_counter > 0);
  }

  return crc;
}

Mit folgender Fehlermeldung:
../crc8.c:10: error: expected '=', ',', ';', 'asm' or '__attribute__'
before 'uint8_t'

Ich weis leider nicht wiso, ich habe die h - Files includiert und denke
das diese passen müssten.
Weis jemand von euch an was dies liegen könnte?

Ich habe das komplette Projekt hochgeladen, vl ist es einfacher was zu
finden. ( Ich verwende AVR Studio 4.16 und WinAVR-20090313)

Grüße
Luke

von Josef D. (Gast)


Lesenswert?

uint8_t ist nicht definiert, weil "#include <stdint.h>" fehlt

von Northernhessian (Gast)


Lesenswert?

Hi Lukas,
poste mal den Code-Teil davor, der ist  interessant, den in Deiner 
Fehlermeldung steht "....before 'uint8_t'" !
Da liegt wohl auch der Hase begraben.
Wahrscheinlich ein ';' vergessen oder so etwas!

von Luke (Gast)


Lesenswert?

Hallo,
danke für die Tipps, es lag leider nicht am #include <stdint.h>;
Der fehler befindet sich im crc8.c...
Weis leider nicht weiter

der Vorherige Code:
1
/* please read copyright-notice at EOF */
2
3
#include <stdint.h>
4
#include "global.h"
5
6
#define CRC8INIT  0x00
7
#define CRC8POLY  0x18              //0X18 = X^8+X^5+X^4+X^0
8
9
10
uint8_t  docrc8 ( uint8_t number_of_bytes_to_read )
11
{
12
  uint8_t   crc;
13
  uint16_t loop_count;
14
  uint8_t  bit_counter;
15
  uint8_t  data;
16
  uint8_t  feedback_bit;

grüße
Lukas

von eProfi (Gast)


Lesenswert?

Hier der Verlauf der Scratchpad- und 12-Bit-Werte um den Nullpunkt 
herum:
Beitrag "Re: DS18S20 - extended resolution bei Temperaturen um 0°C"


Hier gibt es kompakten Code zum Berechnen des 12-Bit-Wertes für 
DS18[S]20
und zu dessen Ausgabe mit zwei Nachkommastellen, Unterdrückung führender 
Nullen mit Verschiebung des Vorzeichens,
ohne Verwendung von speicherfressenden printf, itoa * % /  etc.

Beitrag "Re: DS18S20 - extended resolution bei Temperaturen um 0°C"
(leider ist der erste Teil des Posts eine Kopie des vorigen)

Im mittleren Teil eine Version, die die Vorkomma- und Nachkommabits 
direkt aus dem Scratchpad errechnet und ausgibt,

im letzten Teil eine Version, die die Vorkomma- und Nachkommabits über 
den 12-Bit-Wert berechnet und ausgibt.

von Hiorica (Gast)


Lesenswert?

Hallo,

im Code steht ja das 0.1 Schritten ausgegeben werden. Bei mir wird die 
Temperatur in 0.5 schritten ausgegeben. Muss ich was beachten damit das 
klappt? Oder ist das einfach falsch?

von Sebastian xxlxx (Gast)


Lesenswert?

Hallo

0,5 Werte kann der Sensor ohne Umrechnung ausgeben.
0,1 Werte müssen berechnet werden.
Formel steht im Datenblatt.
Ich habe das auch so gemacht.
Wichtig ist noch welche Sensoren du hast.
Da1820 gibt es mit unterschiedlichen Auflösungen.

von Hiorica (Gast)


Lesenswert?

Die Formel habe ich gesehen, hat bei mir aber mit dem Code von Peter 
nicht richtig funktioniert. Werde gleich nochmal versuchen.

Verwende DS18S20

von Hiorica (Gast)


Lesenswert?

Was ich gerade versuche ist:
1
float count_remain = id[6];
2
float count_per_c = id[7];
3
4
float bruch = ((count_per_c - count_remain) / count_per_c);
5
int temp_read = temp >> 4;
6
float ftemp = temp_read - 0.25 + bruch;
7
8
int v = (int)ftemp;
9
int n = (ftemp - v)*10;
10
11
sprintf(s, "%4d.%01d, v, n");

Bekomme jetzt immer 22.7 Grad oder halt 23.7. Also immer x.7

von Sebastian xxlxx (Gast)


Lesenswert?

Ich habe das immer so gemacht.
Alle Werte ausgeben lassen auf ein Display.
Und dann das ganze auf dem papier probiert.
Dann ein paar testreihen gemacht.
Wenns dann stimmt den Code dazu getippt.
Anders gings bei mir auch nicht.

Das gleiche habe ich dann mit minus Temperatur gemacht.
Peter sein Code kann glaube ich nur plus grade.

Wenn du's nicht hinbekommst such ich morgen mal den Code.
Baue gerade ein temp datenlogger mit sd Karte.
Da steht die Formel im Code ...

Gruesse

von Hiorica (Gast)


Lesenswert?

Danke das wäre nett.

Das Problem liegt glaube ich nicht an der Formel (die sollte ja richtig 
sein), sondern viel mehr an der id[x]. count_per_c ist bei mir 0. Kann 
sein, dass ich es schon dort falsch mache.

von Sebastian xxlxx (Gast)


Lesenswert?

Schicke mal deinen kompletten Code als zip.
Lese mal alle werte vom scratchpad aus 0-7 und häng sie mal an.
Den Fehler werden wir schon finden.

von Hiorica (Gast)


Lesenswert?

Hallo,

ich bekomme folgende Werte:

10-57-15-29-02-08-00-24-31

Ist etwas umständlich, weil ich es über LCD ausgeben muss.

von Sebastian A. (xxlxx)


Lesenswert?

Hallo --> Hiorica (Gast)

also irgend etwas läuft bei dir  schief.
1
byte 0 Temperature LSB (AAh)
2
byte 1 Temperature MSB (00h) EEPROM
3
byte 2 TH Register or User Byte 1
4
byte 3 TL Register or User Byte 2
5
byte 4 Reserved (FFh)
6
byte 5 Reserved (FFh)
7
byte 6 COUNT REMAIN (0Ch)
8
byte 7 COUNT PER °C (10h)
9
byte 8 CRC*

wenn ich nun die 10 (byte0 = 0001 0000) und die 57 (byte1 = 0101 0111) 
mal als temperatur nehme.
kommt da keine zimmertemperatur raus.

   MSB   +   LSB
0101 0111 0001 0000

1
TEMPERATURE/DATA RELATIONSHIP Table 2
2
+85.0°C* 0000 0000 1010 1010 00AAh
3
+25.0°C 0000 0000 0011 0010 0032h
4
+0.5°C 0000 0000 0000 0001 0001h
5
0°C 0000 0000 0000 0000 0000h
6
-0.5°C 1111 1111 1111 1111 FFFFh
7
-25.0°C 1111 1111 1100 1110 FFCEh
8
-55.0°C 1111 1111 1001 0010 FF92h

zur info byte 7 ist immer 10h nur bei dir nicht?
1
 
2
Note that the COUNT PER °C register is hard-wired to
3
16 (10h)

sind deine angaben in HEX oder dezimal ?
aber bit 7 muss 10H (dezimal 16) sein.

prüfe das mal bitte und sende mal den code zu als zip!

sebastian

von Sebastian A. (xxlxx)


Lesenswert?

NACHTRAG :

ändert sich was an deinem code bei temperaturwechsel ?
wenn nicht dann könnte es sein das du hier die Seriennummer vom Chip 
darstellst oder so.

prüfe das mal bitte

von Hiorica (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

es kommen keine Änderung, wenn sich die Temperatur ändert. Leider 
verstehe ich den Code von Peter noch nicht so ganz. Die Temperatur in 
0.5 Schritten klappte damals soweit.

von Sebastian xxlxx (Gast)


Lesenswert?

Hallo

Hatte ich mir fast gedacht.
Warum eigentlich 0.1 grad ?
Ich habe 20 Sensoren auf eine metall Platte geklebt.
Alle ausgelesen und Werte von - + 2 grad erhalten.
Die sensoren haben auch leichte eigenerwärmung.
Für mein Projekt weiter oben hier im forum (Bilder mit gelben gehäuse) 
habe ich von den 20 Sensoren die besten zwei genommen.  Ich guck mal 
deinen Code heute Abend durch.

von Hiorica (Gast)


Lesenswert?

Ja es geht mir nicht um das genauere messen. Das bekomme ich mit den 
DS18S20 nie hin, ich will nur das die Anzeige in 0.1 Schritten sich 
ändert.

Soweit ich das nun verstehe, ist das wirklich die ID vom Chip die ich 
auslese.

von Sebastian A. (xxlxx)


Lesenswert?

Hallo

ich habe was angepasst. die anderen id´s wurden nicht gelesen.
es müssen alle 9 byte gelesen werden.
1
void read_meas( unsigned char *s )
2
{
3
    uchar id[8], diff;
4
    uchar i;
5
    uint temp;
6
7
    for( diff = SEARCH_FIRST; diff != LAST_DEVICE; ) {
8
      diff = w1_rom_search( diff, id );
9
10
      if( diff == PRESENCE_ERR ) {
11
      sprintf( s, "no Sensor Found" );
12
      return;
13
      }
14
15
      if( diff == DATA_ERR ) {
16
      sprintf( s, "bus error" );
17
          return;
18
      }
19
20
      if( id[0] == 0x28 || id[0] == 0x10 ) {           // temperature sensor  //prüfung ob Ds1820 Version S oder B 
21
          w1_byte_wr( READ );                          // read command
22
          temp = w1_byte_rd();                         // low byte            // ID[0] Bit 0 lesen und in temp ablegen
23
          temp |= (uint)w1_byte_rd() << 8;             // high byte           // ID[1] bit 1 lesen und an temp anbinden MSB + LSB
24
          if( id[0] == 0x10 )                          // 9 -> 12 bit         // prüfen ob 9 oder 12 Bit sensor (wie oben) du hast 10
25
            temp <<= 3;
26
                        
27
      id[2] = w1_byte_rd();      //id[2] einlesen 
28
      id[3] = w1_byte_rd();      //id[3] einlesen
29
      id[4] = w1_byte_rd();      //id[4] einlesen
30
      id[5] = w1_byte_rd();      //id[5] einlesen
31
      id[6] = w1_byte_rd();      //id[6] einlesen    
32
      id[7] = w1_byte_rd();      //id[7] einlesen
33
      id[8] = w1_byte_rd();      //id[8] einlesen
34
35
      unsigned char temp[20];
36
      sprintf( temp, "%2X-%2X-%2X-%2X-%2X", id[0], id[1], id[2], id[3], id[4] );  // ausgabe vorbereiten
37
      lcd_string_xy( temp, 0, 1 );                // display ausgabe zeile 1
38
      sprintf( temp, "%2X-%2X-%2X-%2X", id[5], id[6], id[7], id[8] );             // ausgabe vorbereiten
39
      lcd_string_xy( temp, 0, 2 );                                                // display ausgabe zeile 2
40
41
//          sprintf( s, "%4d.%01d C", temp >> 4, (temp << 12) / 6553 ); // 0.1øC
42
      }
43
    }
44
}

von Sebastian A. (xxlxx)


Lesenswert?

Hiorica schrieb:

> Soweit ich das nun verstehe, ist das wirklich die ID vom Chip die ich
> auslese.

nein du hast ID[0] bis [id8] nie eingelesen.
Du hast ID oben definiert aber dann nie werte da hin geschrieben.
die temp werte liegen in der Variable temp.

viel spaß beim bauen ...

NACHTRAG nach 10 minten denken ....

kann es sein das der code von dir aus zwei codes zusammengeschmissen 
ist?
du legst die Variable "ID" fest. und fragst dann ab ob ID[0] 10 oder 28 
ist. Ohne aber vorher den chip zu lesen und ID[0] zu befüllen?
wenn ich richtig liegen sollte das du code zusammengeschmissen hast dann 
sollte man den ganzen code berichtigen. aktuell ist es nur zufall das 
der code geht, weil ID[0] mit 10 gefüllt ist ...

:-)

von Hiorica (Gast)


Lesenswert?

Hallo,

der Code ist Original von Peter. Ich habe es nur für meine Zwecke auf 
ein LCD umgeschrieben.

Die Werte für ID werden in der Funktion w1_rom_search( diff, id ) 
beschrieben. Gibt es vielleicht ein besser Beispiel?

von Sebastian xxlxx (Gast)


Lesenswert?

Hallo

Ja aber Peter ließt nur bit 0 + Bit 1 ein.
Teste mal mein Code.

Viel Spaß

von stefan (Gast)


Lesenswert?

Hallo

w1_rom_search( diff, id ) ließt nur die ID ein.
das Scratchpad wird nicht von peter komplett gelesen.
Sebastian hat recht der Code sieht ganz gut aus.

grüße
stefan

von Hiorica (Gast)


Lesenswert?

Hallo,

Vielen Dank, es funktoniert nun. Bekomme nun das richtige Scratch pad.

von sebastian (Gast)


Lesenswert?

bitte ...

von malptech (Gast)


Angehängte Dateien:

Lesenswert?

hallo.

hab mich jetzt im Forum so durchgelesen aber nichts gefunden, was man 
für einen PIC 18F4550 verwenden könnte. könnte jemand vielleicht codes 
bereitstellen.

ich versuche derzeit über ds1820 treiber mit vorgefertigten Funktionen 
den Befehl für eine Temperaturmessung zu geben, doch mein µC hängt sich 
auf dabei.
1
        sensor_count = 0;
2
3
        if ( DS1820_FindFirstDevice() )
4
        {
5
            do
6
            {
7
                // Die Rohtemperatur des DS18B20 erhalten (Aufloesung 1/256°C)
8
                temperature_raw = DS1820_GetTempRaw();
9
10
                // Konvertiere die Rohdaten in ein String fuer die Ausgabe
11
                DS1820_GetTempString(temperature_raw, temperature);
12
                
13
                // Temperatur als Float-Werte erhalten
14
                temperature_float = DS1820_GetTempFloat();
15
               
16
               // Ausgabe ueber USB-RS232 emulator an PC
17
/*                putsUSART("Sensor %d: %s°C (temperature_float = %f), temperature_raw = %ld)\n\r",
18
                       sensor_count,
19
                       temperature,
20
                       temperature_float,
21
                       temperature_raw);
22
                */
23
                putsUSART("TEST\n");
24
                sensor_count ++;
25
            }
26
            while ( DS1820_FindNextDevice() );
27
            
28
            sensor_count = 0;
29
        }


Ich habe versucht über Matlab mir den String "Test" ausgeben zu lassen, 
aber offensichtlich kommt er gar nicht erst ins if- rein.

2. wie kann ich dem Sensor (ohne die Treiber zu verwenden) befehlen, 
eine Messung durchzuführen?

von malptech (Gast)


Lesenswert?

Ich schätze dass es am delay liegt, weil er den PIC abschaltet. die 
verbindung über USB wird damit auch unterbrochen. wie könnte man das 
noch machen, ohne ein delay zu benutzen.

Danke im Voraus.

Lg,
alptech

von Sebastian xxlxx (Gast)


Lesenswert?

Ich denke mal du bist falsch hier. In diesem Beitrag geht es immer um 
atmega CPU's.
Ich habe hier auch schon viel getippt aber bei deinem Problem kann ich 
dir nicht helfen.

Sebastian xxlxx

von malptech (Gast)


Lesenswert?

wo finde ich den was. ich habe schon wie wild im forum rumgesucht, aber 
bisher nichts gefunden. oder wo platziere ich mein frage.

lg,

von Sebastian xxlxx (Gast)


Lesenswert?

Versuche doch mal teile von deinem grundcode zu suchen.
Ich denke mal du hast fertige Teile genommen.
Wenn du dann im Forum was findest - schliese sich Diesem Beitrag an.
Dein Thema ist sehr komplex USB ds1820 + pic.
Für die ds1820 gibt es gute pdf beim Hersteller.
Bekommst du eine datenverbundung hin?
Daten vom pic zum pc senden ? Wenn ja dann ccersuche dir doch einen code 
helper zu bauen.
Jeder step eine Ausgabe und an jeder Position was anzeigen. Dann siehst 
du schnell wo der Fehler liegt. Ich mache das oft mit nur einer LED. 1 x 
blinken = in der Schleife usw.

Viel spaß

Sebastian xxlxx

von malptech (Gast)


Lesenswert?

verbindung zum pc funktioniert. doch wenn ich die fertigen funktionen 
für den ds1820 aufrufe hängt es sich auf, die leds blinken dann nicht 
mehr.

ich probier es mal so wie du es sagst. danke.

lg,
alptech

von Sebastian xxlxx (Gast)


Lesenswert?

Was mir noch einfällt : ein ds1820 kann auch falsch angeschlossen sein.
Wie versorgst du ihn ? Hast du einen oszi? Verlass dich nicht auf 
fertigen Code. Ich denke auch dein Code muss wie beim atmega an die 
Hardware angepasst werden.

Sebastian
Xxlxx

von malptech (Gast)


Lesenswert?

hallo.
ist alles richtig angeschlossen. hab jetzt auch den code fürs abrufen 
der temperatur. ich kriege auch werte in den PIC geschrieben, doch wie 
gebe ich die aus. die usb-verbindung zum PIC funktioniert seit dem 
aufrufen der Temperatur nicht mehr. kann man mit dem PIC18F4550 an eine 
R232 gehen und dann von hier mit einem USB-Adapter zum PC.

hier ist der Code für die USB-Ansteuerung:
1
// USBTasks()
2
// "Service loop for USB tasks."
3
void USBTasks(void)
4
{
5
    /*
6
     * Servicing Hardware
7
     */
8
    USBCheckBusStatus();                    // Must use polling method
9
    if(UCFGbits.UTEYE!=1)
10
        USBDriverService();                 // Interrupt or polling method
11
    
12
    #if defined(USB_USE_CDC)
13
      CDCTxService();
14
    #endif
15
}
16
17
// High priority interrupt vector
18
#pragma code InterruptVectorHigh = 0x08
19
void InterruptVectorHigh (void)
20
{
21
  _asm
22
    goto InterruptHandlerHigh        //jump to interrupt routine
23
  _endasm
24
}
25
26
// High priority interrupt routine
27
// Hier Behandlung von Trigger- und Timer-Interrupt
28
#pragma code
29
#pragma interrupt InterruptHandlerHigh
1
.
2
.
3
.
4
// LED-Blinken zur USB-Statusanzeige
5
// beide an: "Attached"
6
// Nur RC0 an: "Powered"
7
// Nur RC1 an: "Default"
8
// Nur RC0 blinkt: "Address"
9
// Nur RC1 blinkt: "Detached"
10
// Abwechselndes Blinken: "Configured" (funktionsfähiger Zustand)

Im moment leuchten beide LEDs.

Lg,
alptech

von malptech (Gast)


Lesenswert?

Nachtrag:

Ich habe einen Oszi an dem 1-wire-bus angeschlossen. dabei habe ich 
gemerkt, dass der bus nie auf 0 gezogen wird. wenn ich den ds1820 
rausnehmen, sehe ich die flanken usw. aber mit dem ds1820 wird es nur 
auf 5V-480mV runter gezogen. offenbar verhindert er dass die leitung 
komplett auf 0 gezogen wird. warum ist das so?

angeschlossen habe ich (wie im Datenblatt steht) Gnd-> Gnd, mittleren 
Pin (DQ)-> Port des PIC und den VDD-> 5V.

Bin für jede Hilfe dankbar. Lg,
malptech

von teo (Gast)


Lesenswert?

Hallo

Ich habe den Code von Peter aus dem ersten Post eingebunden und zum 
Laufen bekommen - allerdings sind die angezeigten Werte etwas mysteriös:
Bei einem Sensor bekomme ich die Zahl "10.6250" angezeigt, welche auch 
bei Temperaturänderungen gleich bleibt - ich gehe davon aus, dass dieser 
Sensor kaputt ist (?), denn:
Zwei andere liefern "3.xxx", wenn ich sie einsetze und sinken dann 
langsam auf exakt "3.000".

Hat jemand eine Idee, was hier schief läuft (denn hier ist es definitiv 
wärmer als 3 Grad :-))?

Ich benutze einen DS1820 (ohne S, Jahre altes Sample) an einen ATmega8 
(16 MHz Quarz). VDD ist direkt verbunden, also kein Parasite Power. Als 
Pullup verwende ich einen 5kOhm-Widerstand (2x 10kOhm), da ich 4,7kOhm 
nicht parat habe. Könnte hier die Ursache liegen? Oder klingt das eher 
nach einem Software-Fehler?

von sebastian xxlxx (Gast)


Lesenswert?

hört sich an wie software fehler.
pullup ist unkritisch.
hast du ein display oder wie machst du die ausgabe ?
versuche doch mal das scratchpad in Hex zu lesen.
es kann sein das du da einfach die falschen hexwerte nimmst.
ich habe damit viel gebaut und code selber geschrieben.
ließ mal beitrag von mir 16.2.2011 da hatte einer glaub ich auch so ein 
problem. ich kann dir nur das pdf vom hersteller empfehlen da steht drin 
wie sich das scratchpad zusammen setzt. also viel erfolg

von ede (Gast)


Lesenswert?

Versuche seit Stunden die Datei 1wire.zip zum laufen zu bringen. Die 
Verschachtelung ist ein Alptraum. Es ist kaum was Beschriftet. Ich 
könnte heulen.
Im Main wird auf "#include "main.h" "hingewiesen. im "main.h" wird auf:
#include "1wire.h"
#include "delay.h"
#include "tempmeas.h"
#include "timebase.h"
#include "uart.h"
hingewiesen und zu jeder header datei exestiert eine .c datei. Ein 
Alptraum. Das AVR Studio erkennt die .c Dateien nicht obwohl ich diese 
ins Verzeichnis kopiert habe. Habe versucht alles in eine main zu 
stopfen aber nun is das ganze kommplett unübersichtlich.
Hat jemand eine Version die auch mit AVR Studio 5.0 geht oder ein Tip 
warum die Dateien trotz #include Befehl nicht erkannt werden.

Danke im vorraus

Software: AVR Studio 5.0
Programmiersprache: C
IC: Atmega16
Board: Pollin Eva Board v.2.01

von Sebastian xxlxx (Gast)


Lesenswert?

Hallo

Ich habe inzwischen eine 1wire Lösung die aus ca 8 Funktionen besteht 
und man kann sie einfach in die Main kopieren ohne Zusatz Daten.
Leider kann sie nur einen Sensor pro Portpin.
Reicht dir das ?

von Simon K. (simon) Benutzerseite


Lesenswert?

Was soll der Unsinn alles in die Main zu kopieren? Das ist Unsinn. 
Einfach die .c Dateien dem Projekt hinzufügen und kompilieren. Fertig.

von sebastian xxlxx (Gast)


Lesenswert?

Simon K. schrieb:
> Was soll der Unsinn alles in die Main zu kopieren? Das ist Unsinn.

wer war hier gemeint ? ich ?

von Simon K. (simon) Benutzerseite


Lesenswert?

Alle die sowas machen sind natürlich gemeint.

von Sebastian xxlxx (Gast)


Lesenswert?

Simon K. schrieb:
> Alle die sowas machen sind natürlich gemeint.

Ein Code der nur 50 Zeilen hat wird doch in die Main.c gehören.
Warum sollte ich so etwas auslagern ?

von ede (Gast)


Angehängte Dateien:

Lesenswert?

Hab den Fehler gefunden. Es lag an dem Programm AVR Studio 5.0.
Die Verschachtelung wird in das Projekt nicht aufgenommen wenn man die 
zusatz Header Dateien (.h) in das verzeichnis kopiert und im Programm 
#include .... eingibt.
In dem "Solution Explorer" Fenster (rechtses extra Fenster) muss man 
erst auf "Show all files" klicken und dann unter "Output files" die 
ganzen .h dateien mit rechter maus taste ins Projekt hinzufügen. Schwups 
es wird alles gefunden und ausgeführt.
Würde mich trotzdem über eine einfachere Lösung freuen. Möchte nur den 
einen Temp. Sensor zum laufen bringen und danach versuchen die 
Funktionsweise zu erkunden.
MfG ede

von Volker U. (volkeru)


Lesenswert?

Mal ne Frage an alle Temperaturmesser: Ich benutze auch die hier 
veröffentlichten Routinen, um 3 Sensoren auszulesen, die mit maximal 15 
Meter langen Zwillingslitzen im parasite power Modus angeschlossen sind. 
Normalerweise funktioniert dies auch wunderbar. Ich starte alle 20 
Sekunden eine Konvertierung. Das geht meist gut, aber so etwa alle 3-15 
Minuten bekomme ich nach einer Messung von allen drei Sensoren den Wert 
85 °C zurück. Also wie nach dem Start, bevor eine Messung eingeleitet 
wurde. Ich habe schon mit dem Pullup-Widerstand experimentiert von 1 
kOhm bis 3,3 kOhm - aber immer das selbe. Auch das Timing der Funktionen 
w1_reset(), w1_rom_search() und w1_bit_io() habe ich leicht geändert - 
ebenfalls ohne Erfolg. Auch habe ich die Wartezeit zwischen der 
Initialisierung der Messung und dem Auslesen des Scratchpads bis zu 2 
Sekunden verlängert. Auch ohne Erfolg.

Hat jemand ähnliche Probleme oder eine Idee, woran das liegen könnte? 
Lassen sich bei euch alle Sensoren immer fehlerfrei auslesen? Ich bin 
etwas ratlos. Dass immer ALLE 3 Sensoren hin und wieder 85 Grad 
zurückmelden ist seltsam, denn dann muss es doch eigentlich ein 
systemisches Problem sein und kann keine Störung bei der Übertragung 
sein.

Danke schon vorab für spannende Ideen oder Kommentare! :-)
Tschö, Volker

von sebastian xxlxx (Gast)


Lesenswert?

ede schrieb:
> Würde mich trotzdem über eine einfachere Lösung freuen. Möchte nur den
> einen Temp. Sensor zum laufen bringen und danach versuchen die
> Funktionsweise zu erkunden.

Hallo

diesen code verwende ich.
Hier die Grundlage :

http://www.mikrocontroller.net/attachment/highlight/20338

1
//***************************************************************
2
//************ T E M P E R A T U R - S E N S O R ****************
3
//***************************************************************
4
5
//Reset 1-Wire-Bus
6
//-------------------------------------------------------------
7
unsigned char ow_reset(void)
8
{
9
  uint8_t stat;
10
11
  DDRC = 0xff;      //PortC auf Ausgang
12
  PORTC = 0x00;      //PortC = "Low"
13
  delay1(151);        //480us warten
14
  DDRC = 0x00;      //PortC auf Eingang
15
  stat = PINC;
16
  delay1(29);
17
  return(stat);
18
}
19
20
//Bit auf 1-Wire schreiben
21
//-------------------------------------------------------------
22
void write_bit(char bit)
23
{
24
  DDRC = 0xff;      //PortC auf Ausgang
25
  PORTC = 0x00;      //PortC = "Low"
26
  if(bit==0) delay1(30);  //30 us warten
27
  if(bit==1)
28
  {
29
    delay1(1);
30
    PORTC = 0xFF;
31
    delay1(30);
32
  }  
33
  DDRC = 0x00;      //PortC auf Eingang
34
}
35
36
//Byte auf 1-Wire schreiben
37
//-------------------------------------------------------------
38
void write_byte(char val)
39
{
40
  unsigned char i;
41
  unsigned char temp;
42
43
  for(i=0;i<8;i++)
44
  {
45
    temp = val >> i;
46
    temp &= 0x01;
47
    write_bit(temp);
48
  }
49
  delay1(15);
50
}
51
52
//Bit von 1-Wire lesen
53
//-------------------------------------------------------------
54
unsigned char read_bit(void)
55
{
56
  uint8_t bitstat;
57
  
58
  DDRC = 0xff;      //PortC auf Ausgang
59
  PORTC = 0x00;      //PortC = "Low"
60
  delay1(0);
61
  DDRC = 0x00;      //PortC auf Eingang
62
  bitstat=PINC;
63
  return(bitstat);
64
}
65
66
//Byte von 1-Wire lesen
67
//-------------------------------------------------------------
68
unsigned char read_byte(void)
69
{
70
  unsigned char i;
71
  unsigned char value = 0;
72
  for(i=0;i<8;i++)
73
  {
74
    if(read_bit()) value|=0x01<<i;
75
    delay1(15);
76
  }
77
  return(value);
78
}
79
80
//Temperatur auswerten
81
//-------------------------------------------------------------
82
void get_temperatur(void)
83
{
84
  char get[10],i;
85
  unsigned char temp_lsb,temp_msb;
86
  int k;
87
  unsigned char negative;
88
  
89
  ow_reset();        //Reset
90
  write_byte(0xCC);    //Skip Rom
91
  write_byte(0x44);    //Convert T
92
93
  delay1(15);
94
  ow_reset();        //Reset
95
  write_byte(0xCC);    //Skip Rom
96
  write_byte(0xBE);    //Read Scratchpad
97
  for(k=0;k<9;k++){get[k]=read_byte();}
98
99
  temp_msb = get[1];
100
  temp_lsb = get[0];
101
  
102
  
103
  negative = 0;
104
  i = (temp_msb << 8) + temp_lsb;
105
  if (i < 0)
106
    {
107
    negative = 1;
108
    i = -i;
109
    }
110
  i = (i * 10) / 16;
111
  if (negative == 1) i = -i;
112
  
113
  Transmit_string_to_LCD((LCD_DDRAM_Line_1+0),"101");
114
115
  /*if(temp_msb<=0x80){temp_lsb = (temp_lsb/2);}
116
  temp_msb = temp_msb & 0x80;
117
  if(temp_msb>=0x80){temp_lsb = (~temp_lsb)+1;}
118
  if(temp_msb>=0x80){temp_lsb = (temp_lsb/2);}
119
  if(temp_msb>=0x80){temp_lsb = ((-1)*temp_lsb);}*/
120
    
121
}
122
123
//*************************************************************************************************
124
//*************************************************************************************************
125
126
void main(void)
127
{
128
 get_temperatur();
129
}

von sebastian xxlxx (Gast)


Lesenswert?

Volker U. schrieb:
> Hat jemand ähnliche Probleme oder eine Idee, woran das liegen könnte?

Hi

85 grad kommt ja oft vor. Ich habe im haus ca 20 sensoren. und hatte 
dieses problem sehr oft. ich habe dann 3 adern 5V - Ground - Daten 
gemacht. der fehler war weg. kannst du aber testen. hänge doch in 15 
metern einfach 3x1,5V Zellen dran um erstmal zu prüfen. Was für kabel 
benutzt du ( mm²)?
ich habe netzwerkkabel - Telefonkabel verdrillt genommen.

grüße
Sebastian

von Volker U. (volkeru)


Lesenswert?

Hi Sebastian!

Vielen Dank für deine Hinweise! Erstmal beruhigt es mich, dass das 
Problem nicht nur bei mir auftritt.

sebastian xxlxx schrieb:
> 85 grad kommt ja oft vor. Ich habe im haus ca 20 sensoren. und hatte
> dieses problem sehr oft. ich habe dann 3 adern 5V - Ground - Daten
> gemacht. der fehler war weg. kannst du aber testen. hänge doch in 15
> metern einfach 3x1,5V Zellen dran um erstmal zu prüfen.

Ja, ich hatte auch schon die Vermutung, dass es mit der Beschaltung über 
Parasite Power zusammenhängt.

> Was für kabel benutzt du ( mm²)?

Leider muss ich ein sehr dünnes Spezialkabel verwenden, da die Leitung 
auf Putz über Wände geht und nicht groß auffallen darf. Daher habe ich 
eine hochflexible Zwillingslitze mit 2 x 0,14 mm² (Spezialkabel von 
Klasing) genommen, die auch nicht verdrillt ist. Der Schleifenwiderstand 
des Kabels beträgt bei 15 Meter Anschlusslänge (also 30 m Kabellänge) 
ca. 5 Ohm. Der Widerstand kann hier also keine Rolle spielen. Kämen noch 
elektromagnetische Störungen in Frage.

Was die Störungen betrifft, gibt es aber ein sehr gewichtiges Argument 
dagegen: Wenn Störungen auftreten würden, warum dann nur beim 
Konvertierungskommando (CONVERT_T) und niemals beim Auslesen des 
Scratchpads? Das Auslesen des Scratchpads mit 9 Bytes ist doch viel 
aufwändiger und störanfälliger als das kurze CONVERT_T-Kommando! Ich 
habe aber noch NIEMALS einen CRC-Fehler gehabt! Und das spricht 
erheblich gegen irgendwelche Störungen als Ursache der Probleme.

Prüfst du auch die CRC-Summe, oder liest du nur die Temperaturwerte aus?

Ich denke, es hat nur was mit der Parasite Power zu zun und nicht mit 
den Kabeln. Ich fürchte, es ist ein systemischer Fehler in den Sensoren, 
da ja wohl alle das gleiche Problem haben.

Gruß, Volker

von sebastian xxlxx (Gast)


Lesenswert?

hi

ja das mit dem kabel sollte kein problem sein. teste doch mal das mit 
dem power. so musst du erstmal kein kabel verlegen wenn du 3x1,5V Zellen 
nimmst. Das sollte reichen ging ja bei mir auch :-)

aus dem Datenbaltt : The power-on reset value of the temperature 
register is +85°C.

was ich auch schon hatte : bei temperaturen um 10-40 grad war alles ok. 
alles was über 40 grad lag zeige der sensor 85 grad an. da reicht die 
power nicht aus. 5V an den sensor und schon ging es wieder.

viel spaß

und berichte über deine ergebnisse

sebastian

von Volker U. (volkeru)


Lesenswert?

sebastian xxlxx schrieb:
> ja das mit dem kabel sollte kein problem sein. teste doch mal das mit
> dem power. so musst du erstmal kein kabel verlegen wenn du 3x1,5V Zellen
> nimmst. Das sollte reichen ging ja bei mir auch :-)

Joa, aber bei allen drei Sensoren einen Batterieklotz dranhängen ist 
auch keine besonders elegante Lösung ;-). Die Sensoren sollen ja nicht 
groß auffallen. Aber zum Testen ist das auf jeden Fall mal eine 
Maßnahme. Im Notfall muss ich eben damit leben, dass nicht jede 
Konvertierung okay ist. Ich mache es auch jetzt schon so, dass ich, wenn 
alle drei Sensoren +85,0°C melden, die Werte verwerfe und sofort eine 
erneute Konvertierung einleite. Meist klappt das dann auch sofort beim 
nächsten Mal.

> was ich auch schon hatte : bei temperaturen um 10-40 grad war alles ok.
> alles was über 40 grad lag zeige der sensor 85 grad an. da reicht die
> power nicht aus. 5V an den sensor und schon ging es wieder.

Ich habe einen Sensor mal zum Testen in einen Kochtopf gehängt und im 
Wasser gekocht. Da gab es keine Probleme bis 100°C. Begeisternd ist 
wirklich die hohe Genauigkeit der Sensoren. Diese ist bei mir deutlich 
höher als im Datenblatt angegeben. Ich löse auf 0,1°C auf und die 
Temperatur ist von 0 bis 100 Grad etwa auf 0,2°C genau. In meinem 
kochenden Wasser wurden bei geschlossenem Topfdeckel und nach einigen 
Minuten Kochen exakt 100,0 Grad angezeigt. Damit hatte ich absolut nicht 
gerechnet! Und im Eiswasser wurden exakt 0,0° angezeigt. Die Genauigkeit 
entschädigt allemal für die kleinen Fehler.

> viel spaß
> und berichte über deine ergebnisse

Vielen Dank! Das werde ich tun!
Tschaui, Volker

von Volker U. (volkeru)


Lesenswert?

Sodele, das Problem ist gelöst!!! Mein System läuft seit mehreren 
Stunden ohne eine einzige Fehl-Konvertierung! Und Schuld war (wie so 
oft) nicht die Hardware, sondern die Software.

Unsere ganzen Vermutungen waren völlig richtig: Es hatte nichts mit 
Störungen auf der Leitung zu tun, sondern lediglich mit einem nicht 
korrekt verarbeiteten CONVERT_T Kommando und mit falscher Parasite 
Power.

Die Hersteller-Dokumentation ist in dem Punkt leider etwas unzureichend. 
Und so ist mal wieder nicht der Hardware-Produzent schuld, sondern der 
Software-Entwickler. Die Parasite Power muss SOFORT nach dem CONVERT_T 
Kommando geschaltet werden. Da darf man keine 10 us warten. Im 
vorliegenden Fall wird sie in der Funktion start_meas() in tempmeas.c 
geschaltet. Das ist aber VIEL zu spät, weil zwischen der Übertragung des 
letzten Bit von CONVERT_T (0x44) und dem Schalten des Ausgangs auf High 
viel zu viel Zeit vergeht!

Die Parasite Power muss schon in der Funktion w1_bit_io() in 1Wire.c 
geschaltet werden. Und zwar sofort nach der Übertragung des letzten Bit 
zur Konvertierung. Da darf nicht vorher erst wieder der Ausgang 
hochohmig geschaltet und noch zahlreiche weitere Operationen ausgeführt 
werden.

D.h. die Funktionen w1_bit_io(), w1_byte_wr() und w1_rom_search() müssen 
modifiziert werden.

w1_bit_io() könnte so aussehen:
1
uchar w1_bit_io( bit b, bit pull )
2
{
3
  cli();
4
  W1_DDR |= 1<<W1_PIN;
5
  DELAY( DELAY_US( 2 ));
6
  if( b )
7
    W1_DDR &= ~(1<<W1_PIN);
8
  DELAY( DELAY_US( 10 - 2 ));
9
  if( (W1_IN & (1<<W1_PIN)) == 0 )
10
    b = 0;
11
  DELAY( DELAY_US( 60 - 10 ));
12
  if( pull ) {
13
    W1_OUT |= (1<<W1_PIN);
14
    W1_DDR |= (1<<W1_PIN);
15
  } else
16
    W1_DDR &= ~(1<<W1_PIN);
17
  sei();
18
  return b;
19
}

Wenn das "pull"-Flag True ist, wird der W1_PIN nicht erst hochohmig 
geschaltet, sondern sofort auf Ausgang und auf High, damit die Parasite 
Power anliegt. Zu beachten ist auch, dass ich das Timing DELAY_US() 
etwas verändert und den Spezifikationen besser angenähert habe.

w1_byte_wr() ist natürlich entsprechend zu modifizieren:
1
uint w1_byte_wr( uchar b )
2
{
3
  uchar i = 8, j;
4
  bit cnv = (b == CONVERT_T);
5
  do {
6
    j = w1_bit_io( b & 1, cnv && i == 1 );
7
    b >>= 1;
8
    if( j )
9
      b |= 0x80;
10
  } while( --i );
11
  return b;
12
}

Wurde ein CONVERT_T Kommando abgesetzt, wird beim letzten zu 
übertragenden Bit (i == 1) das "pull"-Flag gesetzt.

Alle weiteren Aufrufe von w1_bit_io() müssen jetzt natürlich um den 
zweiten Parameter (das "pull"-Flag) ergänzt werden, das dann immer auf 
"0" steht. Diese Aufrufe finden nur noch in w1_rom_search() statt:
1
uchar w1_rom_search( uchar diff, uchar idata *id )
2
{
3
  uchar i, j, next_diff;
4
  bit b;
5
6
  if( w1_reset() )
7
    return PRESENCE_ERR;      // error, no device found
8
  w1_byte_wr( SEARCH_ROM );      // ROM search command
9
  next_diff = LAST_DEVICE;      // unchanged on last device
10
  i = 8 * 8;          // 8 bytes
11
  do {
12
    j = 8;          // 8 bits
13
    do {
14
      b = w1_bit_io( 1, 0 );      // read bit
15
      _delay_us(2);
16
      if( w1_bit_io( 1, 0 ) ){      // read complement bit
17
        if( b )          // 11
18
          return DATA_ERR;      // data error
19
      } else {
20
        if( !b ){        // 00 = 2 devices
21
          if( diff > i ||
22
              ((*id & 1) && diff != i) ){
23
            b = 1;        // now 1
24
            next_diff = i;      // next pass 0
25
          }
26
        }
27
      }
28
      w1_bit_io( b, 0 );           // write bit
29
      *id >>= 1;
30
      if( b )          // store bit
31
        *id |= 0x80;
32
      i--;
33
    } while( --j );
34
    id++;          // next byte
35
  } while( i );
36
  return next_diff;        // to continue search
37
}

Bei mir konvertiert er nun schon stundenlang ohne einen einzigen Fehler. 
Und das mit 3 Sensoren an insgesamt 30 Meter langen, unverdrillten und 
unabgeschirmten Leitungen, die quer durch die Gegend laufen. Selbst ein 
kräftiges Gewitter, das vorhin war, konnte da nix stören!

Nun ist meine Begeisterung für den DS18S20 wirklich komplett :-).

Tschö, Volker

von sebastian xxlxx (Gast)


Lesenswert?

Hallo

Perfekt & super erklärt !!!

von Volker U. (volkeru)


Lesenswert?

sebastian xxlxx schrieb:
> Perfekt & super erklärt !!!

Danke, es freut mich, wenn ich hilfreich sein konnte :). Ich habe 
übrigens in mittlerweile 24 Stunden nur einmal einen 
Konvertierungsfehler gehabt. Dies war aber kein 85-Grad-Fehler, sondern 
ein DATA_ERR in w1_rom_search(). Beim Lesen des Complement Bits ist wohl 
was schief gelaufen. Aber ich denke, bei 10000 Lesevorgängen darf ruhig 
mal ein Fehler auftreten ;-). Das ist schon enorm wenig.

Übrigens habe ich nochmal ins Datenblatt geschaut und festgestellt, dass 
Maxim sehr wohl exakte Angaben über das Pullup macht! Dort steht:

Time to Strong Pullup On (Start Convert T Command issued): 10 us.

10 us sind also maximal erlaubt zwischen CONVERT_T und dem Pullup am 
Ausgangs-Pin. Mein Controller läuft "nur" mit 4 MHz. D.h. jeder 
Taktzyklus ist 0,25 us lang. Nach CONVERT_T dürfen also bis zum Pullup 
nur 40 Taktzyklen vergehen. Und das war bei 4 MHz mit dem "alten" Code 
von Peter Dannegger nicht gewährleistet. Wenn man den Controller mit 8 
oder 10 MHz taktet, tritt das Problem vermutlich nicht auf.

Grüßle, Volker

von Beks (Gast)


Lesenswert?

Ich bekomme beim kompilieren immernoch diese Fehler, hab mir den Beitrag 
hier schon 5 mal durchgelesen. Ich weiß nicht was ich machen soll. Was 
führt zu dem Fehler?
1
../TEMPMEAS.C:37: error: invalid conversion from 'unsigned char*' to 'char*'
2
../TEMPMEAS.C:37: error:   initializing argument 1 of 'int sprintf(char*, const char*, ...)'
3
../TEMPMEAS.C:38: error: invalid conversion from 'unsigned char*' to 'char*'
4
../TEMPMEAS.C:38: error:   initializing argument 1 of 'void uputs(char*)'
5
../TEMPMEAS.C:45: error: invalid conversion from 'unsigned char*' to 'char*'
6
../TEMPMEAS.C:45: error:   initializing argument 1 of 'int sprintf(char*, const char*, ...)'
7
../TEMPMEAS.C:46: error: invalid conversion from 'unsigned char*' to 'char*'
8
../TEMPMEAS.C:46: error:   initializing argument 1 of 'void uputs(char*)'
9
../TEMPMEAS.C:47: error: invalid conversion from 'unsigned char*' to 'char*'
10
../TEMPMEAS.C:47: error:   initializing argument 1 of 'int sprintf(char*, const char*, ...)'
11
../TEMPMEAS.C:48: error: invalid conversion from 'unsigned char*' to 'char*'
12
../TEMPMEAS.C:48: error:   initializing argument 1 of 'void uputsnl(char*)'

von Sebastian xxlxx (Gast)


Lesenswert?

Hallo


Welche Version benutzt du ???
4 oder schon 5.

von Beks (Gast)


Lesenswert?

avr studio 4

von Sebastian xxlxx (Gast)


Lesenswert?

Hi

4 nutze ich auch. Bei nur ging es sofort.
Ich meine schon einmal etwas gelesen zu haben das das ".C" am Ende der 
Datei klein sein muss damit der Code richtig erkannt wird.
Leider kann ich dir da aber auch nicht weiterhelfen.
Gib doch mal den output in die Suche ein.

Sebastian

von Volker U. (volkeru)


Lesenswert?

Also normalerweise sollte die implizite typkonvertierung von unsigned 
auf signed char kommentarlos erfolgen. Vielleicht hilft ja ein 
expliziter cast. Also vor die variable s überall ein (signed char *) 
setzen?!

Gruß, volker

von DirkB (Gast)


Lesenswert?

Da wird aber kein (signed char *) erwartet sondern ein (char *).

Normalerweise sollte das kein Fehler sonder eine Warnung sein.
Mal die Compileroptions anschauen.

von Volker U. (volkeru)


Lesenswert?

(char *) und (signed char *) sind das selbe. Normalerweise ist (char *) 
immer vorzeichenbehaftet, es sei denn, es wurde anders deklariert. 
printf erwartet einen zeiger auf einen vorzeichenbehafteten string. Du 
hast aber recht, dass das höchstens eine warnung erzeugen sollte.

von DirkB (Gast)


Lesenswert?

Volker U. schrieb:
> Normalerweise ist (char *)
> immer vorzeichenbehaftet, es sei denn, es wurde anders deklariert.

Du schreibst es ja selber, man kann char (per Compileroption) auch 
anders deklarieren. Dann ist dein (signed char *) aber falsch. Das (char 
*) aber richtig.

Da wird ein char* verlangt, also kommt auch nur ein (char *) als cast in 
Frage.

von Volker U. (volkeru)


Lesenswert?

DirkB schrieb:
> Da wird ein char* verlangt, also kommt auch nur ein (char *) als cast in
> Frage.

Aber nicht, wenn (char *) aus irgendeinem grund als unsigned umdefiniert 
wurde, wie du ja selbst schriebst. Dann wäre (char *) falsch, weil 
printf immer einen signed erwartet. Es sei denn, man hat auch seine 
printf-funktion umdefiniert, wovon ich aber mal nicht ausgehe! Die 
diskussion ist aber akademisch, weil im vorliegenden fall aller 
wahrscheinlichkeit nach beides richtig wäre. (char *) ebenso wie (signed 
char *).

von Sebastian xxlxx (Gast)


Lesenswert?

Hi

Das wird beks nicht weiter helfen. Er nimmt den Code von der Seite hier 
und bekommt diesen Fehler. Da der Code ob Char hin oder her bei den 
anderen und mir geht. Muss wohl etwas bei den Optionen nicht stimmen. 
Oder ?

Sebastian

von Volker U. (volkeru)


Lesenswert?

Wo du recht hast, hast du recht, sebastian. :-)

Ich benutze winavr und nicht avr studio. Das wäre vielleicht nochmal ne 
maßnahme: Winavr, "programmers notepad" und dann ein nativ generiertes 
makefile... dann klappt es auch mit dem übersetzen. ;-)

von Sebastian xxlxx (Gast)


Lesenswert?

Hallo

Ich nutz Avr Studio 4.

@ Beks kannst du den Code mal gezippt schicken?
Bzw. Welchen Code von der Seite hier nutzt du. Hier gibt es viele Files 
inzwischen.

Sebastian.

von Volker U. (volkeru)


Lesenswert?

Falls ihr die Ursache findet, bitte hier posten! Könnte für andere ja 
auch interessant sein...

von sebastian xxlxx (Gast)


Lesenswert?

hier meldet sich Beks nicht mehr ...
erst frage stellen und dann weg sein ...
wie schade ...

:(

von Volker U. (volkeru)


Lesenswert?

Tja, ohne fleiß kein preis. Das muss der gute wohl noch lernen. Bei der 
heutigen jugend muss ja alles immer sofort klappen, sonst wirds 
hingeschmissen. Da ist man dann allerdings in der elektro- und 
softwaretechnik ganz falsch, weil man nur misserfolge erntet. ;-)

von Sebastian xxlxx (Gast)


Lesenswert?

Wie jetzt :) grinse gerade da ich 24 Jahre bin.
Aber ein Vollblut Elektroniker & It Mensch im Beruf.
Und dieses Forum hier ist echt Klasse!

Habe gerade meine erste heizungssteuerung gebaut.
Wärmepumpe + Solar Kopplung und alles mit einem atmega.
So macht optimieren Spaß ... Den die Buderus und alpha Inotec 
steuerteile hatten viele kleine Macken die ich jetzt nicht mehr habe. 
Ds1820 ist da ein super Sensor!

Sebastian

von Volker U. (volkeru)


Lesenswert?

:-) Ausnahmen bestätigen die regel. Aber es ist schon so, dass natur- 
aber vor allem ingenieurwissenschaften zunehmend unbeliebter wurden. 
Kein wunder, wenn die kids sehen, dass man auch ganz ohne mühe viel geld 
verdienen kann.

Ich habe dieses forum zu nutzen begonnen, als ich mit atmel mcs 
angefangen habe. Vorher hatte ich motorola benutzt. Aber die waren käse. 
Deshalb habe ich fast nur analogtechnik entwickelt.

Mein erstes projekt zum kennenlernen von atmels war eine 
temperaturmessstation mit 3 sensoren ds18s20 (innen- u. 
außentemperatur), lc-display, dcf-empfänger, datenspeicher, 
untertemperaturwarnung und pc-ankopplung über rs232. Damit mache ich 
jetzt klimadiagramme. ;-) Ganz lustig und sogar nützlich.

Hast du technische unterlagen zu dem heizungssystem gehabt? Denn aus dem 
stehgreif ist es ja sicher kaum möglich, so eine anlage sinnvoll zu 
regeln, oder?

von Sebastian xxlxx (Gast)


Lesenswert?

Ja so schlimm war das gar nicht. Die Anlage hatte ich mit meinem Bruder 
geplant.
Dann erstmal so gebaut wie es sein sollte. Dann eine Wetterstation in 
der Nähe gefragt um jeden Tag Daten zu bekommen. Nach ca 1 Jahr hatte 
ich so viele Daten die ich auswerten konnte. Viele Daten habe ich mit 
ds1820 und atmel + sd Card geloggt. Dann bemerkte ich die Fehler in der 
Steuerung der wärmepumpe. Es gab Tage wo die Sonne schien aber die 
Leistung im Puffer Stillstand. Eine wärmepumpe zu steuern ist gar nicht 
so schwer. Es gibt 3 Sensoren ( Vorlauf - Rücklauf - Kompressor temp ) 
der Rest sind Pumpe und Mischer. Ich kenne meine Anlage sehr genau. Das 
reine steuern war recht einfach. Was echt krass war ist eine menu 
Steuerung. Ich habe ca 40 Werte im original gerät die man ändern kann. 
Diese ganzen Werte mussten im atmel auch gemacht werden. So Werte wie 
bei 2 grad ausen muss der Vorlauf immer laufen damit das Wasser im 
ausenbereich nicht in der wärmepumpe einfriert.

Es waren ca 100 Tage Planung - 10 Tage bauen - einbauen und dem original 
zuschalten ( Vorteil notsteuerung ).

War aber ein schönes Projekt für kalte Regentage :)

Es gibt da noch ein super Forum für haustechnik wo sich viele wie ich 
treffen.

Meine Heizung kostet im Jahr ca 400 Euro das gleiche haus nebenan 
benötigt 1400€. Da macht das sparen mehr Spaß :)

von Robin (Gast)


Lesenswert?

peter dannegger schrieb:
> Die Routine muß für negative Werte leicht geändert werden.

Weiss jemand, wie man die Routine ändern muss, damit positive und 
negative Werte angezeigt werden können?

von Sebastian xxlxx (Gast)


Lesenswert?

Hi

Das kann man im Handbuch sehen. Ich glaube ich hab's so gemacht.
Ist das erste Bit ff ff ff ff dann ist das plus. Ist es 00 00 00 00 dann 
war's Minus. Sieht man aber anhand der Tabelle in der PDF ganz gut. 
Einfach das erste Bit auswerten. Meine Routinen sind immer so aufgebaut.

Wenn es nicht klappt Schau ich mal nach.

Viel Spaß
Sebastian unterwegs vom iPhone :)

von Robin (Gast)


Lesenswert?

Hi!

Danke für die schnelle Antwort.
Das die Bits 8 bis 15 das Vorzeichen bestimmen habe ich schon verstanden 
:)

Bei 1111 1111 xxxx xxxx wäre laut dem Handbuch negativ.

Ich denke mal im Code müsste man dann in der Funktion void 
read_meas(void)
etwas ändern?

Ich bin nur noch nicht dahinter gestiegen, wie ich die ersten Bits 
bekomme und dann prüfen kann.

Gruß Robin

von sebastian xxlxx (Gast)


Lesenswert?

hi

es gibt in der datei tempmeas.c die leseroutine
1
      w1_byte_wr( READ );      // read command
2
      temp = w1_byte_rd();      // low byte
3
      temp |= (uint)w1_byte_rd() << 8;    // high byte
4
      if( id[0] == 0x10 )      // 9 -> 12 bit
5
        temp <<= 3;
6
      sprintf( s, "  T: %04X = ", temp );  // hex value
7
      uputs( s );
8
      sprintf( s, "%4d.%01døC", temp >> 4, (temp << 12) / 6553 ); // 0.1øC
9
      uputsnl( s );


diese habe ich so ersetzt :

1
      w1_byte_wr( READ );        // read command
2
      bite1 = w1_byte_rd();        // byte 1
3
      bite2 |= (uint)w1_byte_rd() << 8;  // high byte
4
    if( id[0] == 0x10 )        // 9 -> 12 bit
5
          bite1 <<= 3;
6
      bite3 = w1_byte_rd();        // byte 3
7
      bite4 = w1_byte_rd();        // byte 4
8
      bite5 = w1_byte_rd();        // byte 5
9
      bite6 = w1_byte_rd();        // byte 6
10
      count_remain = w1_byte_rd();            // byte 7 
11
      count_per_c = w1_byte_rd();                 // byte 8
12
      bite9 = w1_byte_rd();        // byte 9

so lese ich alle bits ein. jetzt kann ich auswerten und spielen.

ich mache damit eine luftfeuchtemessung.

hier die ganze datei. ist aber viel formel für Wetterberechnung
1
#include "main.h"
2
#include "util/delay.h"
3
#include <stdio.h>
4
5
void start_meas( void ){
6
  if( W1_IN & 1<< W1_PIN ){
7
    w1_command( CONVERT_T, NULL );
8
    W1_OUT |= 1<< W1_PIN;
9
    W1_DDR |= 1<< W1_PIN;      // parasite power on
10
11
  }else{
12
  set_cursor(0,2);
13
    lcd_string( "Short Circuit !" );
14
  }
15
}
16
17
void read_meas( void )
18
{
19
  uchar id[8], diff;
20
  uint bite1;
21
  uint bite3;
22
  uint count_remain;
23
  uint count_per_c;
24
  uchar i;
25
  uchar s[30];
26
  float temper1;
27
  float temper2;
28
  float temp_all;
29
  float temp_komma;
30
  float muell;
31
  float muell1;
32
  char output[20];
33
34
35
  for( diff = SEARCH_FIRST; diff != LAST_DEVICE; ){
36
    diff = w1_rom_search( diff, id );
37
38
39
    if( diff == PRESENCE_ERR ){
40
  set_cursor(0,2);
41
    lcd_string( "No Sensor found" );
42
      break;
43
    }
44
    if( diff == DATA_ERR ){
45
  set_cursor(0,2);
46
      lcd_string( "Bus Error" );
47
      break;
48
    }
49
    if( id[0] == 0x28 || id[0] == 0x10 ){  // temperature sensor
50
  set_cursor(0,1);
51
    //lcd_string( "ID:" );
52
53
  //Wert der ID ausgeben
54
    //  for( i = 0; i < 8; i++ ){
55
    //  sprintf( (char*)s, "%02X ", id[i] );
56
  //  lcd_string( (char*)s );    
57
  //  _delay_ms (500);
58
    //  }
59
      
60
      w1_byte_wr( READ );        // read command
61
      bite1 = w1_byte_rd();        // low byte
62
    bite1 |= (uint)w1_byte_rd() << 8;  // high byte
63
    if( id[0] == 0x10 )        // 9 -> 12 bit
64
        bite1 <<= 3;
65
      bite3 = w1_byte_rd();        // low byte
66
      bite3 = w1_byte_rd();        // low byte
67
      bite3 = w1_byte_rd();        // low byte
68
      bite3 = w1_byte_rd();        // low byte
69
      count_remain = w1_byte_rd();    // low byte
70
      count_per_c = w1_byte_rd();    // low byte
71
      bite3 = w1_byte_rd();        // low byte
72
73
74
      
75
76
    //Messwert in Grad Celsius auf LCD ausgeben
77
      //sprintf( (char*)s, "%3d.%01dC ", bite1>> 4, (bite1 << 12) / 6553 ); // 0.1øC
78
    set_cursor(0,2);
79
      //lcd_string( (char*)s );
80
     
81
      bite1 = bite1 >> 4;
82
    muell = bite1 - 0.25;
83
    muell1 = count_per_c - count_remain;
84
    temp_all = muell +(muell1 / count_per_c);
85
      
86
    temp_komma = temp_all;
87
88
      if (id[1]== 0x83 ) {
89
    temper1=temp_komma;
90
    set_cursor(0,2);
91
    dtostrf (temper1,3,2,output);
92
      lcd_string( output);
93
    lcd_string(" Nass");
94
    }
95
    
96
    if (id[1] == 0xE6) {
97
    temper2=temp_komma;
98
    set_cursor(20,2);
99
    dtostrf (temper2,3,2,output);
100
      lcd_string( output);
101
    lcd_string(" Trocken");
102
   
103
    //formel 
104
    double luftdruck;
105
    double klein_e;
106
    double gross_e_TF;
107
    double gross_e_T;
108
    double bsp_1; //FEUCHT
109
    double bsp_2; //TROCKEN
110
      double feuchte;
111
112
    luftdruck= 1013.25; // ca. Luftdruck
113
    bsp_1 = temper1;         // 19 Grad nass
114
      bsp_2 = temper2;      // 20 grad Trocken 
115
116
      gross_e_TF = 6.11 * exp((17.017 * bsp_1) / (234.175 + bsp_1 ));
117
    gross_e_T  = 6.11 * exp((17.017 * bsp_2) / (234.175 + bsp_2 ));
118
      klein_e    = gross_e_TF - 1013.25*(bsp_2 - bsp_1) / 1515;
119
    feuchte   = klein_e / gross_e_T * 100;
120
121
122
      dtostrf (feuchte,3,2,output);
123
    set_cursor(0,1);
124
    lcd_string("Luftfeuchte: ");
125
    lcd_string( output);
126
      lcd_string("%      ");
127
128
    double logEx;
129
    double taupunkt;
130
      double h;
131
      double t;
132
133
    t = temper1;
134
      h = feuchte;
135
136
      logEx = 0.66077+7.5*t / (237.3+t) + (log10(h)-2);
137
138
      taupunkt = (logEx - 0.66077)*237.3/(0.66077+7.5-logEx);
139
      dtostrf (taupunkt,3,2,output);
140
    set_cursor(21,1);
141
    lcd_string("Taupunkt: ");
142
    lcd_string( output);
143
      lcd_string("C   ");
144
145
  }
146
147
    }
148
  }
149
150
}

grüße
Sebastian

von sebastian xxlxx (Gast)


Lesenswert?

nachtrag :

steht im text weiter oben schon drin.

Datum: 16.02.2011 16:44

Bitte besser alles von oben nach unten lesen ...

grüße
Sebastian

von Alex (Gast)


Lesenswert?

Könnte mir denn bitte mal eiiner von euch sagen was ich im Code umändern 
muss damit auch negative Temperraturen ausgegeben werden.
Mfg

von Sebastian xxlxx (Gast)


Lesenswert?

Hallo

Schau dir die PDF an. Dort siehst du Beispiele. Du Must nur das Byte 
auswerten ich glaube ff oder 00 ist - oder +. War eigentlich ganz 
einfach. Guck dir die Beispiele an.

von Cyblord -. (cyblord)


Lesenswert?

Also das geht in C doch automatisch. Der Sensor liefert den Wert als 
Zweierkomplement. D.h. man steckt die 2 Bytes, also den 16 Bit Wert in 
ein int16_t Datentyp und hat automatisch das korrekte Vorzeichen. Wenn 
man die Temperatur in Grad haben möchte kann man das auch in einen 
double stecken und durch 16 Teilen. Fertig. Da muss absolut nichts 
selber rumgerechnet werden mit dem Vorzeichen. Selbst wenn die 
eigentliche 1Wire-Routine nur einen Unsigned Typ liefert reicht ein Cast 
nach int16_t aus.

Hier mal ein Auszug aus meinem Code. Die ow_read_word Funktion liefert 
auch nur einen unsigned typ:
1
uint16_t ow_read_word() {
2
  uint8_t b1=ow_read_byte();
3
  uint8_t b2=ow_read_byte();
4
  uint16_t result=b2;
5
  result<<=8;
6
  result+=b1;
7
  return result;
8
}
9
10
int16_t DS18B20_getRawTemp() {
11
  ow_reset();
12
  ow_write(OW_SKIP);
13
  ow_write(DS_CMD_TEMP);
14
  _delay_ms(1500);
15
  ow_reset();
16
  ow_write(OW_SKIP);
17
  ow_write(DS_CMD_READ);
18
  return ow_read_word();
19
}
20
21
22
void DS18B20_getTempAsText(int16_t t,char *s) {
23
  char tmp[10];
24
  int16_t t1=t/16;
25
  int16_t t2=abs(t % 16);
26
  t2*=10;
27
  t2/=16;
28
29
  itoa(t1,s,10);
30
31
  strcat(s,",");
32
33
  itoa(t2,tmp,10);
34
  strcat(s,tmp);
35
  tmp[0]=(char)223;
36
  tmp[1]='C';
37
  tmp[2]='\0';
38
  strcat(s,tmp);
39
}
gruß cyblord

von Alex (Gast)


Lesenswert?

HALLO,
vielen Dank erstmal,aber bei mir haut das nicht hin.
ich bekomme nur eine vorkommastelle und eine nachkommastelle angezeigt,
2,9  und ohne vorzeichen.

vielleicht kann mir hier von ihnen jemand weiterhelfen
mfg



1
// --- lokale Variablen -------------------------------------------------------
2
3
// --- lokale Funktionen ------------------------------------------------------
4
uint8_t OWReset(void);
5
void    OWWriteByte(unsigned char byte_value);
6
void    OWWriteBit(unsigned char bit_value);
7
uint8_t OWReadByte(void);
8
uint8_t OWReadBit(void);
9
uint8_t docrc8( uint8_t number_of_bytes_to_read );
10
11
// ----------------------------------------------------------------------------
12
// liest den ROM-Code des in diesem Moment einzigen (!) angeschlossenen One-Wire-Devices,
13
// der ROM-Code steht anschließend im globalen Array ow_buffer[].
14
// Danach wird die CRC geprüft
15
// Rückgabe: - TRUE wenn CRC und Family-Code stimmt 
16
uint8_t OW_read_rom_code(void)
17
{
18
uint8_t i;
19
20
OWReset();
21
OWWriteByte(READ_ROM);
22
for (i = 0; i < 8; i++) ow_buffer[i] = OWReadByte();
23
                            // nun steht der ROM-Code in ow_buffer
24
put_c(13);
25
for (i = 0; i < 8; i++)             // ROM-Code ausgeben
26
  {
27
  put_s(utoa(ow_buffer[i], msg, 16));
28
  put_c(' ');
29
  }
30
31
if ((ow_buffer[7] == docrc8(7)) && (ow_buffer[0] == DS18B20))
32
  {
33
  put_s("ok ");
34
  return (TRUE);                  // TRUE zurückgeben, wenn CRC identisch
35
  }
36
else 
37
  {
38
  put_s("crc");                  // Fehlermeldung geben, wenn CRC nicht stimmt
39
  return (FALSE);
40
  }
41
}
42
43
44
// ----------------------------------------------------------------------------
45
// liest das komplette Scratchpad eines Temperatursensors aus,
46
// die Daten steht anschließend im Array ow_buffer[],
47
// es wird noch die CRC geprüft
48
uint8_t OW_read_scratchpad(uint8_t idx)
49
{
50
uint8_t i;
51
EEPROM_read_rom_code(idx);            // den zugehörigen ROM-Code aus dem
52
                            // EEprom nach ow_buffer[] einlesen
53
OWReset();                      // ein Reset senden
54
OWWriteByte(MATCH_ROM);
55
for (i = 0; i < 8; i++) OWWriteByte(ow_buffer[i]);
56
OWWriteByte(READ_SCRATCHPAD);
57
for (i = 0; i < 9; i++) ow_buffer[i] = OWReadByte();
58
                            // nun steht der ROM-Code in ow_buffer
59
return (ow_buffer[8] == docrc8(8));
60
}
61
62
// ----------------------------------------------------------------------------
63
// sendet ein SKIP ROM mit nachfolgendem CONVERT an alle mithörenden Sensoren
64
// danach muss ca. 1 Sekunde gewartet werden, bis die konvertierten Daten aus
65
// den einzelnen Sensoren ausgelesen werden können.
66
void OW_convert_all(void)
67
{
68
uint8_t i = 80;
69
70
OWReset();
71
OWWriteByte(SKIP_ROM);
72
OWWriteByte(CONVERT);
73
74
// ggf. DQ auf HIGH ziehen
75
// ONE_WIRE_PORT &= ~(1<<ONE_WIRE_POWER_PIN);
76
77
while(i--) _delay_ms(10);             // 0.8 Sekunden warten
78
79
// ggf. DQ wieder freigeben
80
// ONE_WIRE_PORT |= 1<<ONE_WIRE_POWER_PIN;
81
// rx_flag = FALSE;                // während des Wartens empfangene Kommandos verwerfen
82
}
83
84
85
// ----------------------------------------------------------------------------
86
// liefert FALSE, wenn im EEPROM kein Platz mehr für Sensordaten ist,
87
// sonst den Index für den nächsten freien Speicherplatz 
88
// Die Eeprom-Adresse wird aus dem Index ermittelt durch Multiplikation mit 8 !
89
uint8_t OW_eeprom_free(void)
90
{
91
uint8_t i;
92
for (i = 1; i < (EEPROM_SIZE / 8); i++)  // die Adressen 0 - 7 sind reserviert
93
  {
94
  if (ee_read_byte(i * 8) == 0xFF)
95
    {
96
    return(i);                  // die erste Stelle zurückgeben, an der
97
    }                        // Byte.0 == 0xFF
98
  }                          // denn bei einem Sensor muss hier der Family-Code stehen
99
return(0);                      // wenn kein freier Platz gefunden
100
}
101
102
// ----------------------------------------------------------------------------
103
// durchsucht das EEPROM, ob der neu angelernte ROM_CODE im Array ow_buffer[] 
104
// bereits im EEPROM gespeichert ist,
105
// liefert TRUE, wenn der Code bereits vorhanden ist !
106
uint8_t OW_rom_code_exists(void)
107
{
108
uint8_t i, j, z, result = FALSE;
109
110
for(i = 8; i < (EEPROM_SIZE - 8); i = i+8)
111
  {
112
  z = 0;
113
  for (j = 0; j < 8; j++)
114
    {
115
    if (ee_read_byte(i + j) == ow_buffer[j]) z++;
116
    }
117
  if (z == 8) 
118
    {
119
    result = TRUE;                // wenn alle 8 Bytes identisch waren
120
    break;                    // die Suche abbrechen
121
    }
122
  }
123
124
return (result);
125
}
126
127
// ----------------------------------------------------------------------------
128
// liest das EEPROM aus, ermittelt die Anzahl der Sensoren (sensor_cnt)
129
// liest das Messintervall (messintervall) ein.
130
//
131
void OW_read_eeprom(void)
132
{
133
uint8_t i;
134
sensor_cnt = 0;
135
for (i = 8; i < (EEPROM_SIZE - 8); i += 8)
136
  {
137
  if ((ee_read_byte(i) == DS18B20))    // der Family-Code muss 0x28 sein
138
    {
139
    sensor_cnt++;                // Anzahl der registrierten Sensoren
140
    }
141
  }
142
  
143
messintervall  = (ee_read_byte(ADR_MESSINTERVALL) << 8); // high-Byte
144
messintervall +=  ee_read_byte(ADR_MESSINTERVALL + 1);   // low-Byte
145
                            // wenn == 0xFF, dann default-Wert wählen
146
if (messintervall == 0xFFFF) messintervall = MESSINTERVALL;
147
148
start_modus = ee_read_byte(ADR_AUTOSTART);
149
}
150
151
// ----------------------------------------------------------------------------
152
// wandelt den Messwert, der aus 2 Byte besteht, in einen String (mit einer Nachkommastelle) um.
153
// Der Messwert steht rechtsbündig in den globalen Variablen ow_buffer[0] und ow_buffer[1],
154
// (die Werte entsprechen scratchpad.Byte[0] / scratchpad.Byte[1])
155
// Das Ergebnis wird über den globalen String msg[] zurückgegeben.
156
void DS18B20_convert_temperatur(void)
157
{
158
int16_t temp16;
159
uint8_t i = 0;
160
161
ow_buffer[1] = ow_buffer[1] << 4;        // lower nibble im high-Byte nach links schieben
162
                              // upper nibble im low-Byte nach rechts schieben und
163
                              // zum high-Byte addieren.
164
ow_buffer[1] += (ow_buffer[0] >> 4);      // die Vorkommastellen stehen jetzt in ow_buffer[1]
165
                              // da upper-nibble der Nachkommastellen maskieren,
166
ow_buffer[0] &= 0x0F;                 // die Nachkommastellen stehen in ow_buffer[0]
167
168
temp16  = (int16_t) ow_buffer[1] * 10;
169
// die Nachkommastelle: temp_lo * 0.625 = temp_lo * 625 / 1000 = temp_lo * 640 / 1024
170
temp16 += (int16_t)ow_buffer[0] * 640 / 1024;
171
                              // Nun das Dezimaltrennzeichen einschmuggeln:
172
itoa(temp16, msg, 10);                // die Zahl in einen String umwandeln
173
while(msg[i]) i++;                  // die Position der terminierende /0 finden
174
msg[i] = msg[i - 1];                  // die Nachkommastelle nach rechts schieben
175
msg[i - 1] = '.';                    // statt dessen ein Dezimaltrennzeichen einfügen
176
msg[++i] = 0;                      // Am Ende wieder eine /0 anfügen
177
178
179
}
180
181
//-----------------------------------------------------------------------------
182
// 1-Wire Functions to be implemented for a particular platform
183
//-----------------------------------------------------------------------------
184
185
//-----------------------------------------------------------------------------
186
// Reset the 1-Wire bus and return the presence of any device
187
// Return TRUE  : device present
188
//        FALSE : no device present
189
// alle Wartezeiten gem. APP_Note 126, Page 2-3 
190
// Gesamtdauer: DELAY_G + DELAY_H + DELAY_I + DELAY_J = 1 + 480 + 70 + 410 = 921us
191
uint8_t OWReset(void)
192
{
193
uint8_t r;
194
195
_delay_us(DELAY_G);
196
197
DQ_LOW;                        // DQ auf Low ziehen
198
_delay_us(DELAY_H);
199
DQ_INPUT;                      // DQ als Eingang schalten
200
DQ_HIGH;                        // auf high schalten (Pullup aktivieren)
201
_delay_us(DELAY_I);                // warten bis zum Lesen der Antwort
202
203
r = DQ_READ;                    // Antwort einlesen
204
if (r) r = FALSE; else r = TRUE;        // die Leitung sollte auf LOW gezogen sein
205
DQ_OUTPUT;                      // DQ wieder als Ausgang schalten
206
_delay_us(DELAY_J);
207
  
208
return(r);
209
}
210
211
//-----------------------------------------------------------------------------
212
// Send 8 bits of data to the 1-Wire bus
213
//
214
void OWWriteByte(unsigned char byte_value)
215
{
216
uint8_t i = 8;
217
218
while(i--)
219
  {
220
  OWWriteBit(byte_value & 0x01);      // das rechts stehende Bit senden
221
  byte_value = byte_value >> 1;        // um 1 Stelle nach rechts schieben
222
  }
223
}
224
225
//-----------------------------------------------------------------------------
226
// Send 1 bit of data to the 1-Wire bus
227
// DG ist durchgängig als Ausgang geschaltet
228
// alle Wartezeiten gem. APP_Note 126, Page 2-3 
229
// Gesamtdauer: DELAY_A + DELAY_B = DELAY_C + DELAY_D = 6 + 64 = 60 + 10 = 70us
230
void OWWriteBit(uint8_t bit_value)
231
{
232
cli();
233
DQ_LOW;                        // DQ auf Low ziehen
234
235
if (bit_value)                    // Write 1
236
  {
237
  _delay_us(DELAY_A);              // 5 us auf Low lassen
238
  DQ_INPUT;                    // DQ durch Pullup auf High ziehen
239
  _delay_us(DELAY_B);              // 40us warten
240
  }
241
  
242
else                          // Write 0
243
  {
244
  _delay_us(DELAY_C);              // 45us auf Low lassen
245
  DQ_INPUT;                    // DQ durch Pullup auf High setzen
246
//  DQ_HIGH;
247
  _delay_us(DELAY_D);
248
  }
249
250
DQ_OUTPUT;                      // DQ wieder als Ausgang schalten
251
DQ_HIGH;
252
sei();
253
}
254
255
// ----------------------------------------------------------------------------
256
uint8_t OWReadByte(void)
257
{
258
uint8_t i = 8;
259
uint8_t data = 0;
260
while(i--)
261
  {
262
  data >>= 1;
263
  if (OWReadBit()) data |= 0x80;
264
  }
265
return(data);
266
}
267
  
268
269
//-----------------------------------------------------------------------------
270
// Read 1 bit of data from the 1-Wire bus
271
// Return 1 : bit read is 1
272
//        0 : bit read is 0
273
// alle Wartezeiten gem. APP_Note 126, Page 2-3 
274
// Gesamtdauer: DELAY_A + DELAY_E + DELAY_F = 6 + 9 + 55 = 70us
275
uint8_t OWReadBit(void)
276
{
277
uint8_t r;
278
cli();
279
DQ_LOW;                        // DQ auf Low ziehen
280
_delay_us(DELAY_A);                // 6 us warten
281
DQ_INPUT;                      // als Eingang schalten
282
DQ_HIGH;
283
284
_delay_us(DELAY_E);                // warten und dann messen
285
r = DQ_READ;
286
287
_delay_us(DELAY_F);
288
289
DQ_OUTPUT;                      // DQ wieder als Ausgang schalten
290
291
sei();
292
return (r);
293
294
}
295
296
// ----------------------------------------------------------------------------
297
// liest den ROM_Code von Device idx (ROM-ADresse = idx * 8) aus dem EEProm
298
// und schreibt ihn in das globale Array ow_buffer[]
299
// gibt TRUE zurück, wenn die CRC stimmt
300
uint8_t EEPROM_read_rom_code(uint8_t idx)
301
{
302
uint8_t i;
303
idx *= 8;                      // jeweils 8 Byte bilden einen ROM_Code
304
305
for ( i = 0; i < 8; i++) ow_buffer[i] = ee_read_byte(idx + i);
306
307
return (ow_buffer[7] == docrc8(7));      // wenn die CRC stimmt, TRUE zurückgeben
308
}
309
310
// ----------------------------------------------------------------------------
311
// schreibt den ROM_Code aus ow_buffer[] ins EEPROM an die Position idx
312
// die EEPROM-Adresse dazu ist mit vorher mit 8 zu multplizieren
313
void EEPROM_write_rom_code(uint8_t idx)
314
{
315
uint8_t i;
316
idx *= 8;                      // jeweils 8 Byte bilden einen ROM_Code
317
318
for ( i = 0; i <  8; i++) ee_write_byte((idx + i), ow_buffer[i]);
319
}
320
321
// ----------------------------------------------------------------------------
322
// vergleicht den ROM_Code aus ow_buffer[] mit dem im EEPROM an der Stelle idx
323
// liefert TRUE zurück, wenn ROM_CODE in ow_buffer[] == ROM_CODE im Eeprom
324
// Der ROM-Code steht an der EEPROM-Adresse idx * 8.
325
uint8_t EEPROM_compare_rom_code(uint8_t idx)
326
{
327
uint8_t i;
328
uint8_t cmp = TRUE;
329
330
idx *= 8;                      // jeweils 8 Byte bilden einen ROM_Code
331
332
for ( i = 0; i < 8; i++) if(!(ee_read_byte(idx + i) == ow_buffer[i])) cmp = FALSE;
333
return (cmp);
334
}

von Alex (Gast)


Lesenswert?

also bei mir sinds derzeit 23.1 grad
aber als ausgabe  erhalte ich nur 3.1
kann mir keiner weiterhekfen
mfg

von Josef D. (jogedua)


Lesenswert?

Leider mal wieder nicht das komplette Programm gepostet.
Die fehlende '2' könnte durch eine fehlerhafte Ausgabefunktion 
verursacht sein, die ich nicht kenne.
Bist du sicher, dass DS18B20_convert_temperatur() das macht, was du 
erwartest (besonders für negative Zahlen)?
Vorschlag: für alle möglichen Werte in einer Schleife testen.
Vermutlicher Fehler:
   ow_buffer[1] += (ow_buffer[0] >> 4);
ow_buffer ist vermutlich signed char (im Post nicht definiert).
Wenn das höchst Bit gesetzt ist, werden bei >> 1en eingefügt, die hier 
vermutlich falsch wären.

von Josef D. (jogedua)


Lesenswert?

Der DS18B20 liefert das Ergebnis in 16-tel Grad vorzeichenbehaftet als
16-bit-Zahl, die bei dir in ow_buffer[0] und ow_buffer[1] ankommt.
Du möchtest aber 10-tel Grad haben.
Also musst du nur doch nur die beiden Bytes richtig auf eine int16_t 
zuweisen, mit 10 multiplizieren und durch 16 dividieren
(bitte selbst testen):
1
int16_t temp16 = (uint16_t)ow_buffer[0];  // low-Byte
2
temp16 |= ((uint16_t)ow_buffer[1]<<8);    // high-Byte
3
temp16 *=10;  // Anzeige als 10-tel Grad
4
temp16 /=16;  // Sensor liefert 16-tel

von Cyblord -. (cyblord)


Lesenswert?

Josef D. schrieb:
> Der DS18B20 liefert das Ergebnis in 16-tel Grad vorzeichenbehaftet als
> 16-bit-Zahl, die bei dir in ow_buffer[0] und ow_buffer[1] ankommt.
> Du möchtest aber 10-tel Grad haben.
> Also musst du nur doch nur die beiden Bytes richtig auf eine int16_t
> zuweisen, mit 10 multiplizieren und durch 16 dividieren
> (bitte selbst testen):
>
1
> int16_t temp16 = (uint16_t)ow_buffer[0];  // low-Byte
2
> temp16 |= ((uint16_t)ow_buffer[1]<<8);    // high-Byte
3
> temp16 *=10;  // Anzeige als 10-tel Grad
4
> temp16 /=16;  // Sensor liefert 16-tel
5
>

Steht btw genau so in dem Code den ich hier gepostet habe.

von Josef D. (jogedua)


Lesenswert?

"so ähnlich" würde ich ja gelten lassen.
Die Sonderbehandlung der Nachkommastelle(n) und negativer Zahlen ist 
nicht erforderlich und fehlerträchtig.
Auch der Modulo-Operator hat so seine Tücken:
http://embeddedgurus.com/stack-overflow/2011/02/efficient-c-tip-13-use-the-modulus-operator-with-caution/

von Volker U. (volkeru)


Lesenswert?

Moin moin,

vielleicht kann ja jemand was mit dem Code anfangen, den ich seit über 
einem Jahr sehr zuverlässig zum Auslesen meiner Sensoren benutze. Er 
basiert auf dem Code von Peter Dannegger (*.h Dateien sowie 1wire.c) 
sowie meiner weiter oben vorgestellten Anpassung zur Verhinderung von 
Fehlkonvertierungen durch zu langsam zugeschaltete Parasite Power. Er 
liest sämtliche am Bus angeschlossene Sensoren aus (egal ob DS18S20 oder 
DS18B20). Für die Zwischenspeicherung der in temp zurückgelieferten 
Werte muss man bei Anschluss mehrerer Sensoren allerdings selbst sorgen. 
Die Routine arbeitet mit Komplementbildung, ist aber mit allen 
Temperaturen getestet (auch nahe 0°, also -0.1, 0.0, +0.1 etc.) und 
arbeitet absolut sauber. Außerdem kann sie von selbst erkennen, ob ein 
DS18S20 oder DS18B20 Sensor angeschlossen ist. Der DS18B20 kann 
konfiguriert werden auf 9, 10, 11 oder 12 Bit Auflösung. Der 
Rückgabewert in der Integer-Variablen Temp ist in 1/10 Grad. Also -456 
für -45.6 Grad oder 237 für +23.7 Grad.

1
#define DS_TEMP_LS 0
2
#define DS_TEMP_MS 1
3
#define DS_TH 2
4
#define DS_TL 3
5
#define DS_RES1 4
6
#define DS_RES2 5
7
#define DS_REM 6
8
#define DS_PER 7
9
#define DS_CRC 8
10
11
// Initialisierung der Sensoren
12
void init_meas( unsigned char resolution ) { // resolution in Bit (9-12)
13
  uchar id[8], diff;
14
15
  for( diff = SEARCH_FIRST; diff != LAST_DEVICE; ){
16
    diff = w1_rom_search( diff, id );
17
    if( diff == PRESENCE_ERR )
18
      return;
19
    if( diff != DATA_ERR && id[0] == 0x28 ){
20
      w1_byte_wr( WRITE );    // write command
21
      w1_byte_wr( '\0' );
22
      w1_byte_wr( '\0' );
23
      w1_byte_wr( (uchar)( resolution << 5 ) );
24
    }
25
  }
26
27
  temp_buffer[DS_TEMP_ERR] = 0; /* Error-Register */
28
}
29
30
// Messung starten
31
void start_meas( void )
32
{
33
  if( W1_IN & 1<< W1_PIN ){
34
    w1_command( CONVERT_T, NULL );
35
    //W1_OUT |= 1<< W1_PIN;
36
    //W1_DDR |= 1<< W1_PIN;      // parasite power on
37
  } else {
38
    temp_buffer[DS_TEMP_ERR] = 1; /* Error-Register */
39
    //softuart_puts( "DS1820: Short Circuit !\r\n" );
40
  }
41
}
42
43
// Daten auslesen (vorher ausreichend Zeit warten - je nach 
44
// Sensor-Auflösung zwischen 100 und 800 ms)
45
void read_meas( void )
46
{
47
  uchar id[8], diff;
48
  uchar scratchpad[9];
49
  int temp;
50
51
  for( diff = SEARCH_FIRST; diff != LAST_DEVICE; ) {
52
    diff = w1_rom_search( diff, id );
53
54
    temp_buffer[DS_TEMP_ERR] = 0; /* Error-Register */
55
    if( diff == PRESENCE_ERR ){
56
      temp_buffer[DS_TEMP_ERR] = 2; /* Error-Register */
57
      //softuart_puts( "DS1820: No Sensor found\r\n" );
58
      break;
59
    }
60
    if( diff == DATA_ERR ){
61
      temp_buffer[DS_TEMP_ERR] = 3; /* Error-Register */
62
      //softuart_puts( "DS1820: Bus Error\r\n" );
63
      break;
64
    }
65
    if( id[0] == 0x28 || id[0] == 0x10 ){  // temperature sensor (10h = DS18S20, 28h = DS18B20
66
      // Scratchpad im Temperatursensor lesen
67
      w1_byte_wr( READ );      // read command
68
      for( temp = 0; temp < 9; temp++ )
69
        scratchpad[temp] = w1_byte_rd();  // Scratchpad füllen (9 Bytes)
70
71
      // CRC8 berechnen
72
      if (crc8( scratchpad, 8 ) != scratchpad[DS_CRC] ) {
73
        temp_buffer[DS_TEMP_ERR] = 5; /* Error-Register */
74
        break;
75
      }
76
77
      if( id[0] == 0x10 ) { // DS18S20
78
        if( scratchpad[DS_TEMP_MS] ) { // Negativer Temperaturwert
79
          scratchpad[DS_TEMP_LS] ^= 0xFF; // Einer-Komplement
80
          scratchpad[DS_TEMP_LS]++; // inkrementieren
81
        }
82
        scratchpad[DS_TEMP_LS] >>= 1; // rechtes Bit für 0,5 °C rausschieben (durch 2 teilen)
83
        // Temperatur mit 0,1 °C Genauigkeit berechnen
84
        temp = (int)scratchpad[DS_TEMP_LS]*100 - 25 + (int)(scratchpad[DS_PER] - scratchpad[DS_REM]) * 100 / scratchpad[DS_PER];
85
        if( scratchpad[DS_TEMP_MS] ) // Negativer Temperaturwert
86
          temp *= -1;
87
        temp /= 10; // Zweite Nachkommastelle abtrennen
88
      } else { // 0x28: DS18B20
89
        if( scratchpad[DS_TEMP_MS] & 0xF8 ) { // Negativer Temperaturwert
90
          scratchpad[DS_TEMP_LS] ^= 0xFF; // Einer-Komplement
91
          scratchpad[DS_TEMP_LS]++; // inkrementieren
92
          scratchpad[DS_TEMP_MS] ^= 0xFF; // Einer-Komplement
93
          temp = -( ((int)scratchpad[DS_TEMP_MS] << 8) | (int)scratchpad[DS_TEMP_LS] ) * 10 / 16;
94
        } else {
95
          temp = ( ((int)scratchpad[DS_TEMP_MS] << 8) | (int)scratchpad[DS_TEMP_LS] ) * 10 / 16;
96
        }
97
      }
98
99
      if( (temp == 850 && temp_buffer[DS_TEMP_ERR] == 0 ) {
100
        // Konvertierung nicht erfolgreich oder nicht abgeschlossen
101
        temp_buffer[DS_TEMP_ERR] = 4; /* Error-Register */
102
      } else {
103
      // Hier die erfolgreich gelesenen Temperaturwerte verarbeiten und zwischenspeichern
104
      }
105
    }
106
  }
107
}

von Volker U. (volkeru)


Lesenswert?

Bei meinem obigen Beispiel ist der Parameter "resolution" bei 
init_meas() etwas missverständlich beschrieben. Für 9 bit Auflösung muss 
als Wert in resolution 0 übergeben werden, für 10 Bit eine 1, für 11 Bit 
2 und für 12 Bit 3. Also nicht etwa der Wert 9-12, wie man vermuten 
könnte. Sorry!

Volker

von Volker U. (volkeru)


Lesenswert?

Der Beitrag von Sebastian ist zwar schon über ein Jahr alt, aber bisher 
wurde er nicht kommentiert. Aus meiner Erfahrung heraus ist dazu aber 
was zu sagen:

Sebastian xxlxx schrieb:
> Warum eigentlich 0.1 grad ?
> Ich habe 20 Sensoren auf eine metall Platte geklebt.
> Alle ausgelesen und Werte von - + 2 grad erhalten.
> Die sensoren haben auch leichte eigenerwärmung.

Also das mit der Eigenerwärmung stimmt, ist aber nur relevant, wenn man 
bei sehr niedrigen Temperaturen (unter -10 Grad) in Luft arbeitet und 
jede Sekunde eine Messung mit 12 Bit Auflösung durchführt. Nur dann 
kommt es meiner Erfahrung nach zu Abweichungen von mehr als 0,1 Grad.

Wenn der Sensor auf einer Metallplatte klebt, ist eine so extreme 
Abweichung von 2 Grad (oder gar 4 Grad absolut) für mich nicht 
nachvollziehbar! Ich habe 10 Sensoren aus 3 unterschiedlichen Chargen 
nebeneinander liegend (in Luft) getestet und keiner zeigte eine größere 
Abweichung als 0,1 Grad an. Die Auflösung war dabei 12 Bit und das 
Messintervall 5 Sekunden.

Die großen Abweichungen müssen meiner Meinung nach andere Ursachen haben 
und liegen sicher nicht an der Hardware der Sensoren.

Es sei denn, die von dir getesteten Sensoren sind sehr alt und Maxim hat 
vor einigen Jahren die Produktion geändert. Neuere Sensoren sind m.E. 
nicht so extrem ungenau.

Tschö, Volker

von Alex (Gast)


Lesenswert?

ich nutze den DS18S20 Temperratur wird auch richtig ausgegeben wie 
Volker es beschrieben hat.

nun meine Frrage,
ich wollte das gerne so lösen das ich als ausgabe bei Plus-Temperraturen
zB. +22.3  oder +05.3 als Ausgabe erhalte und bei den Minuswerten das 
gleiche.
nur bei der Umsetzung tu ich mich ein bischen schwer.

so wie ichs jetzt habe bekomme ich ein minus und plus als Vorzeichen und 
der Temperraturwert stimmt auch nicht mehr
vielleicht kann von euch mir da noch weiterhelfen.
mfg
1
 char gs[30];
2
 int8_t Vorzeichen;
3
 int  temp1;
4
 int  temp;
5
 int8_t Vorkommastelle;
6
 int16_t Nachkommastelle;    
7
8
        if( scratchpad[DS_TEMP_MS] ) { // Negativer Temperaturwert
9
          scratchpad[DS_TEMP_LS] ^= 0xFF; // Einer-Komplement
10
          scratchpad[DS_TEMP_LS]++; // inkrementieren
11
        }
12
        scratchpad[DS_TEMP_LS] >>= 1; // rechtes Bit für 0,5 °C rausschieben (durch 2 teilen)
13
        // Temperatur mit 0,1 °C Genauigkeit berechnen
14
        temp = (int)scratchpad[DS_TEMP_LS]*100 - 25 + (int)(scratchpad[DS_PER] - scratchpad[DS_REM]) * 100 / scratchpad[DS_PER];
15
        if( scratchpad[DS_TEMP_MS] ) // Negativer Temperaturwert
16
        {
17
         temp *= -1;
18
        }
19
        
20
        else 
21
        {
22
         Vorzeichen = '+';            // 
23
        }  
24
       
25
         // temp /= 10; // Zweite Nachkommastelle abtrennen
26
  Vorkommastelle = temp;
27
  Nachkommastelle = temp;
28
29
  Nachkommastelle = (temp1 * 10.0);
30
  Nachkommastelle = (Nachkommastelle % 100);
31
  Nachkommastelle = Nachkommastelle % 10;
32
  
33
  
34
  sprintf(gs,"%2d,%1d", Vorkommastelle, Nachkommastelle);
35
  put_c(Vorzeichen);
36
  put_s( gs);

von Alex (Gast)


Lesenswert?

ein kleiner fehler
1
 char gs[30];
2
 int8_t Vorzeichen;
3
 int  temp1;
4
 int  temp;
5
 int8_t Vorkommastelle;
6
 int16_t Nachkommastelle;    
7
8
        if( scratchpad[DS_TEMP_MS] ) { // Negativer Temperaturwert
9
          scratchpad[DS_TEMP_LS] ^= 0xFF; // Einer-Komplement
10
          scratchpad[DS_TEMP_LS]++; // inkrementieren
11
        }
12
        scratchpad[DS_TEMP_LS] >>= 1; // rechtes Bit für 0,5 °C rausschieben (durch 2 teilen)
13
        // Temperatur mit 0,1 °C Genauigkeit berechnen
14
        temp = (int)scratchpad[DS_TEMP_LS]*100 - 25 + (int)(scratchpad[DS_PER] - scratchpad[DS_REM]) * 100 / scratchpad[DS_PER];
15
        if( scratchpad[DS_TEMP_MS] ) // Negativer Temperaturwert
16
        {
17
         temp *= -1;
18
        }
19
        
20
        else 
21
        {
22
         Vorzeichen = '+';            // 
23
        }  
24
       
25
         // temp /= 10; // Zweite Nachkommastelle abtrennen
26
  Vorkommastelle = temp;
27
  temp1= temp;
28
29
  Nachkommastelle = (temp1 * 10.0);
30
  Nachkommastelle = (Nachkommastelle % 100);
31
  Nachkommastelle = Nachkommastelle % 10;
32
  
33
  
34
  sprintf(gs,"%2d,%1d", Vorkommastelle, Nachkommastelle);
35
  put_c(Vorzeichen);
36
  put_s( gs);

von Volker U. (volkeru)


Lesenswert?

Also erst einmal:

Vorkommastelle ist ein char und temp ein Integer. Das Zuweisen von temp 
an Vorkommastelle fürt zu einer unzulässigen Datenkonvertierung. 
Vorkommastelle muss also auch ein Integer sein (int16_t).

temp enthält zudem die Temperatur in 1/100 Grad.

So wird ein Schuh draus:
1
  int16_t Vorkommastelle;
2
3
  [..]
4
5
  Vorkommastelle = temp / 100;
6
  temp1= temp;
7
8
  Nachkommastelle = (temp1 % 100);
9
  Nachkommastelle = (Nachkommastelle / 10);
10
11
  printf("%2d,%1d", Vorkommastelle, Nachkommastelle);

Zu beachten ist, dass temp auch negativ sein kann. Wenn du das 
Vorzeichen also manuell erzeugst, musst du entweder die Zeile
"temp *= -1;" weglassen, oder auf temp bzw. auf die daraus erzeugten 
Daten später die Funktion abs() anwenden.

Gruß, Volker

von Alex (Gast)


Lesenswert?

Volker U. schrieb:
> Zu beachten ist, dass temp auch negativ sein kann. Wenn du das
> vorzeichen also manuell erzeugst, musst du entweder die Zeile "temp *=
> -1;" weglassen, oder auf temp später die Funktion abs() anwenden.
>

ich wollte nur das Plus zeichen separat  ausgeben aber leider 
funktiniert das bei mir nicht.

der sensor liegt grad im eisfach dort sinds -9.0grad aber das 
Pluszeichen wird mitausgegeben.

Laut Datenblat;
The sign bits (S) indicate if the
temperature is positive or negative: for positive numbers S = 0 and for 
negative numbers S = 1.

       if( scratchpad[DS_TEMP_MS] == 1 ) // Negativer Temperaturwert
        {
         temp *= -1;
        }

        else
        {
         Vorzeichen = '+';            //
        }

  Vorkommastelle = temp / 100;
  temp1= temp;

  Nachkommastelle = (temp1 % 100);
  Nachkommastelle = (Nachkommastelle / 10);

        sprintf(gs,"%2d,%1d", Vorkommastelle, Nachkommastelle);
  put_c(Vorzeichen);
  put_s( gs);

von Josef D. (jogedua)


Lesenswert?

Alex schrieb:
> nun meine Frrage,
> ich wollte das gerne so lösen das ich als ausgabe bei Plus-Temperraturen
> zB. +22.3  oder +05.3 als Ausgabe erhalte und bei den Minuswerten das
> gleiche.
> nur bei der Umsetzung tu ich mich ein bischen schwer.

Das sollte doch printf schon können:
printf("%+03d,%1d", Vorkommastelle, Nachkommastelle)
         ^^^

von Volker U. (volkeru)


Lesenswert?

Alex schrieb:
> ich wollte nur das Plus zeichen separat  ausgeben aber leider
> funktiniert das bei mir nicht.

HALT, HALT, HALT!

Erst jetzt sehe ich, dass du meinen Code unzulässig verändert hast! Der 
Test auf negative Temperaturwerte lautete bei mir

        if( scratchpad[DS_TEMP_MS] ) { // Negativer Temperaturwert

bei dir aber

        if( scratchpad[DS_TEMP_MS] == 1 ) { // Negativer Temperaturwert

Das MS-Byte im Scratchpad kann niemals 1 sein!!! Entweder stehen alle 8 
Bit auf 1 oder alle 8 Bit auf 0! Der Test muss also so lauten, wie bei 
mir oben, oder alternativ

        if( scratchpad[DS_TEMP_MS] == 0xFF ) { // Negativer 
Temperaturwert

Und was machst du, wenn der Temperaturwert negativ ist? Die Variable 
"Vorzeichen" wird ja nur gesetzt, wenn die Temperatur positiv ist, wenn 
sie negativ ist, bleibt "Vorzeichen" unverändert, kann also irgendein 
beliebiges (unbekanntes) Zeichen enthalten. Das ist nicht so sinnvoll.

Sollte es nicht eher so aussehen?:

        if( scratchpad[DS_TEMP_MS] ) // Negativer Temperaturwert
         {
          temp *= -1;
          Vorzeichen = '-';
         }

         else
         {
          Vorzeichen = '+';            //
         }

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
Ich komme nicht weiter  den Code habe ich im Anhang.
wenn ich mehr als einen sensor anschliesse bekomme ich als ausgabe 
Fehler,
der erste Sensor der am Bus hängt wird korregt angezeigt.
vielleicht kahn vohn ihnen wer weiterhelfen
mfg

von Volker U. (volkeru)


Lesenswert?

Hast du denn im EEPROM auch die richtigen ROM-Codes aller 
angeschlossenen Sensoren liegen?

Ich würde mal ein paar Debug-Ausgaben auf die serielle Schnittstelle in 
den Code einfügen, um den Ablauf mitzuverfolgen und das Programm 
debuggen zu können! Vor allem in OW_read_scratchpad, OW_read_rom_code 
und OW_rom_code_exists. So auf dem Trockenen dürfte das sonst extrem 
schwierig werden!

Gruß, Volker

von Alex (Gast)


Lesenswert?

Im EEprom stehen die richtigen ROM-Codes drin.
ich habe jetzt mal zwei nagelneue DS18S20 Genommen,sie  werden aber nur 
sporadischerkannt.
Stecke ich nur einen von beiden DS18S20 ande Bus  Wird dieser sofrt 
erkannt.
mfg

von Andreas (Gast)


Lesenswert?

Guten Tag
hallo  peter dannegger geniales Projekt habs mir grad 
nachgebaut,allerdings hätt ich da noch ne Frage bezüglich zum 
unterscheiden der Sensoren.
zB.ich habe 5Sensoren  am Bus angeschlossen und hätte dann gern bei der 
Temperraturausgabe 1 24,5 für den ersten und 5 32,0 für den fünften 
Sensor
wie kann mann dass in ihren code Realiesieren.

vielleicht könnte mir da einer von euch unter die arme greifen.
mfg

von Josef D. (jogedua)


Lesenswert?


von Volker U. (volkeru)


Lesenswert?

Alex schrieb:
> Im EEprom stehen die richtigen ROM-Codes drin.
> ich habe jetzt mal zwei nagelneue DS18S20 Genommen,sie  werden aber nur
> sporadischerkannt.
> Stecke ich nur einen von beiden DS18S20 ande Bus  Wird dieser sofrt
> erkannt.

Du verwendest die Sensoren im "parasite power" Modus? Wenn ja: Was für 
einen Pullup-Widerstand hast du an dem Bus liegen? Und sorgst du auch 
dafür, dass der Bus nach dem CONVERT_T Kommando innerhalb von 10 µs ein 
"strong pullup" erfährt? Datenblatt: "Time to Strong Pullup On (Start 
Convert T Command issued): 10 us." Falscher Pullup-Widerstand und/oder 
Timing könnten das seltsame Verhalten erklären.

von Alex (Gast)


Lesenswert?

Hallo Volker,
Also als Pullup verwende ich 4,7K .
Den Parasitären Modus verwende ich nicht bei dem Programm was ich 
gepostet habe nicht.
Da ich noch nicht ganz fit bin in C dachte ich mir könnte jemannd bei 
der Fehleranalyse weiterhelfen.
Mfg

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

so ich warte jetzt nach dem CONVERT_T Kommando 10ms aber leider kann ich 
nur einen Sensor am bus auslesen.
mfg

von Volker U. (volkeru)


Lesenswert?

Wenn du nicht den Parasite Power Modus nutzt, ist das Strong Pullup zur 
Konvertierung egal. Dann sind deine Sensoren ja nicht über zwei Drähte 
angeschlossen, sondern über drei (VDD auf positiver Versorgungsspannung, 
GND auf Minus und Datenleitung DQ mit 4,7 k Pullup).

Beim DS18S20 musst du nach dem CONVERT_T Kommando mindestens 800 ms 
warten, bevor du das Scratchpad ausliest! Denn so lange dauert die 
Messung im Sensor.

Dein Programm ist relativ umfangreich. Sich da einzuarbeiten, um "auf 
dem Trockenen" dann einen Fehler zu finden, ist mit einem gewissen 
Zeitaufwand verbunden. Deshalb ist es einfacher, erstmal mögliche 
offensichtliche Fehlerursachen auszuschließen.

von Alex (Gast)


Lesenswert?

Volker U. schrieb:
> sondern über drei (VDD auf positiver Versorgungsspannung,
> GND auf Minus und Datenleitung DQ mit 4,7 k Pullup).
Genauso sind die Sensoren Angeschlossen


> Beim DS18S20 musst du nach dem CONVERT_T Kommando mindestens 800 ms
> warten, bevor du das Scratchpad ausliest! Denn so lange dauert die
> Messung im Sensor.

Hier wird ja 800ms gewartet
void OW_convert_all(void)
{
uint8_t i = 80;

OWReset();
OWWriteByte(SKIP_ROM);
OWWriteByte(CONVERT);

while(i--) _delay_ms(10);
}

wenn ich die wartezeit etwass erhöhe ändert sich nichts.

Es bleibt dabei das nur ein Sensor am Bus erkannt wird
mfg

von Volker U. (volkeru)


Lesenswert?

Alex schrieb:
> wenn ich die wartezeit etwass erhöhe ändert sich nichts.
>
> Es bleibt dabei das nur ein Sensor am Bus erkannt wird

Und wie sieht es damit aus, mal ein paar Debug-Ausgaben (auf die 
serielle Schnittstelle) in die entsprechenden Prozeduren einzustreuen, 
um dem Fehler auf die Spur zu kommen? Wie schon oben von mir 
vorgeschlagen.

Wenn du aber sagst, dass die Sensoren sporadisch mal erkannt und 
ausgelesen werden können und dann wieder nicht, deutet das eher auf ein 
Timing-Problem im 1wire-Protokoll hin. Die Sensoren sind da recht 
pingelig, was das Timing betrifft. Ich würde dann vielleicht nochmal die 
Wartefunktionen und das Timing überprüfen. In jedem Falle hilfreich sind 
aber Debug-Ausgaben an den entscheidenden Stellen im Programm!

von Volker U. (volkeru)


Lesenswert?

Wenn du den Fehler findest, kannst du ja mal sagen, woran es gelegen 
hat, damit andere vielleicht auch davon profitieren können!

von Jan (Gast)


Lesenswert?

Hallo Leute!
Es ist wieder gerade 2:40 Nacht.... Gestern ist es 6:00 morgens 
geworden.
Das zieht sich schon seit ein paar Tagen so, aber ich kann es nicht 
lassen.
Erstmal danke sehr an alle die hier Die ganze Arbeit geleistet haben. 
Solche Sachen stehen in keinem Buch. Ich denke ich habe schon das ganze 
Internet durchgelesen um eine Lösung für mein Problem zu finden- leider 
vergeblich...
Aber zu meinem Problem... Zu viel nicht labern , sonst wird jemand hier 
böse..:)
Ich nutze die Tempmes.c Routine von Josef D die ich hier im Forum 
gefunden habe. Hut ab, Respekt und Anerkennung . Sowas tolles findet man 
sehr selten.
Sehr hilfreich und sehr vorbildlich beschrieben. Ich habe die wie folgt 
an meine Bedürfnisse angepasst:
1
#include "main.h"
2
#define  DS18B20_12bit  0x7F
3
#define THERMOanzahlMax  2  // auch thermoNamen anpassen!
4
#define THERMO1WNAMEN  "    T1    T2"  // Überschrift, rechtsbündig
5
#define THERMO1NameLen  6
6
#define THERMO1NameOffset  (THERMO1NameLen-2) // hier steht das 1. Zeichen
7
#define DEFoffset    0x10      // = 1°
8
#define DEFmask      ((int16_t) 0x1)
9
10
void start_meas( void ){
11
  if( W1_IN & 1<< W1_PIN ){
12
    w1_command( CONVERT_T, NULL );
13
    W1_OUT |= 1<< W1_PIN;
14
    W1_DDR |= 1<< W1_PIN;  }}    
15
static  char  thermoNamen[] =  THERMO1WNAMEN;
16
static  int16_t  thermoValues[THERMOanzahlMax];
17
static  uint8_t initReady;
18
static  uint8_t valid;   
19
20
static uint8_t NameValid( char * name ) { // prüft, ob Name aus scratch mit Name aus Tabelle übereinstimmt
21
  uint8_t ret = 0; // wenn ja, ret = index+1!!!; andernfalls 0
22
  char * pC = thermoNamen+THERMO1NameOffset;
23
  while (ret++ < THERMOanzahlMax) {
24
    if ( *(int16_t*) name== *(int16_t*) pC)  // 2 Byte vergleichen
25
      return ret;
26
    pC += THERMO1NameLen;  }
27
  return 0; }
28
29
void read_meas( void )
30
{
31
  uchar id[8], diff;
32
  uchar s[30];
33
  uchar i;
34
  uint temp;
35
36
  for( diff = SEARCH_FIRST; diff != LAST_DEVICE; ){
37
    diff = w1_rom_search( diff, id );
38
  
39
    if( id[0] == 0x28 || id[0] == 0x10 ){
40
41
      w1_byte_wr( READ );      
42
      temp = w1_byte_rd();      
43
      temp |= (uint)w1_byte_rd() << 8;    
44
      if( id[0] == 0x10 )      
45
        temp <<= 3;
46
    char name[2]; uint8_t nIndex;
47
    name[0] = w1_byte_rd();      
48
    name[1] = w1_byte_rd();      
49
    if (!initReady)  {      
50
    }
51
    if ((nIndex = NameValid(name))) {
52
      thermoValues[--nIndex] = temp;
53
      valid |= (1<<nIndex);
54
    } else if (initReady==1){ // alle im 0. Durchgang als gültig erkannten sind ausnahmsweise noch gesetzt
55
      i = 0;
56
      while ((1<<i++) & valid); 
57
      if (--i<THERMOanzahlMax) {  
58
        valid |= (1<<i);          
59
        i *= THERMO1NameLen;
60
        i += THERMO1NameOffset;
61
        w1_command( WRITE, id );
62
        w1_byte_wr( name[0]=thermoNamen[i++] );
63
        w1_byte_wr( name[1]=thermoNamen[i] );
64
        w1_byte_wr( DS18B20_12bit );  
65
        w1_command( EE_WRITE, id );}}} }
66
        
67
        
68
   lcd_setcursor(0,2); // Warum lässt sich das nicht verschiebenda wo es hingehört ??
69
  
70
  for( i=0; i<THERMOanzahlMax; i++) {  
71
72
    int16_t  temp=thermoValues[i];
73
    if (!(valid &(1<<i))) {  
74
      if ( temp & DEFmask)  
75
        temp = (temp-DEFoffset) & ~DEFmask; 
76
      else   // addieren und bit setzen
77
        temp = (temp+DEFoffset) | DEFmask;
78
      thermoValues[i]=temp;
79
    }
80
    sprintf( (char*)s, "%3d.%01dC", temp >> 4, (temp << 12) / 6553 ); // 0.1øC
81
      
82
  lcd_string( (char*)s );  
83
    
84
  }
85
  if (initReady)
86
    valid = 0;
87
  if (initReady<255)  
88
    ++initReady;
89
  
90
}

Alles lässt sich wunderbar ohne Fehler und Warnungen Compilieren, 
bekomme auch klare Temperaturwerte auf dem Display.

Die Probleme aber, die ich habe sind folgende:

1. wird die lcd_setcursor Zeile direkt über lcd_string ((Char*)s) Zeile 
gesetzt, wird am Display nichts angezeigt ... Warum ?

2. Ich muss die Thermometer einzeln auslesen, nicht alle zusammen in 
einen String, und einzeln mit Lcd_print ausgeben. Da hackt es bei mir
Ich benutze auch nur drei stück und hätte die Namen gerne einzeln 
definieren können- da stehen die wieder aber in einem Array. Später 
müssen die Werte andere Prozesse steuern wie Lüfter und Kontrolllampen. 
Natürlöich kann man auch den fertigen String zerlegen, aber ich denke 
dass ist keine gute Lösung. Vielleicht kann mir jemand helfen und sagen 
wie ich die Werte in einzelne Variablen bekomme mit den ich dann 
weitermachen kann ?

Ich bedenke mich in voraus für jede brauchbare Hilfe und schönen Grüss 
an alle...
 Ups..3:06 ... Ich denke ich gehe heute ein wenig früher schlafen.

mfg
Jan

von Lars H. (hufnala)


Lesenswert?

Hallo,

nachdem ich die Sourcen gestern problemlos in Betrieb nehmen konnte und 
sie super funktionieren vorab mal ein riesiges Dankeschön. Da ich nicht 
so der C-Guru bin und ich Peters Code in meine Spären nur ansatzweise 
folgen kann habe ich noch eine große Frage ;-)

Wo/Wann muss ich TCNT1H restoren. Die ISR von Peter verstehe ich auch 
nicht, aber sie funktioniert. Ich hätte es anders gemacht, aber Peter 
hat definitv die exaktere Sekunde herausbekommen!

Hintergrund : Ich möchte auf dem ATMega8 noch eine Soft-PWM laufen 
lassen. Bitte nicht schmunzeln, das Thema Soft-PWM ist mir bewusst, aber 
ich brauche 4 oder 5 Kanäle und der Mega8 hat ja nur 3 Hardware PWMs - 
und ein Timer ist eh schon für die 1s und den Delay weg. Anderen µC mit 
mehr HW PWMs tue ich mir erst mal nicht an. Ich bin mir auch nicht 
sicher, ob die HW PWM bzgl. der Frage einen Unterschied macht, da der 
TCNT1H ja von der HW PWM vermtl. auch geändert würde.

Peter schreibt in seinem Code:
"//        Attention !!!
// take care, that during delay no interrupt access a timer register
// or restore TCNT1H
"
Wie das sichern bzw. rücksichern geht ist mir denke ich klar - siehe 
Peters ISR. Warum nur TCNT1H ist mir nur zum Teil bewusst
1
/*EDIT: , vermtl. aber wegen der Maskierung auf 0x8000. 
2
Mist, RTFM, gemeinsame Verwendung 16 Bit Register, Sorry! 
3
EDIT*/
Die große Frage die sich mir stellt, WO muss ich TCNT1H sichern
- zu Beginn/Ende meiner zus. ISR z.B. vom Timer 2? Wenn ja warum, die 
Ausführungszeit der ISR ist doch alle mal futsch?
- in der Delay Routine, wenn ja, wo? In der Schleife?
- In der ISR vom Original, aber da wird der TCNT1H schon gesichert und 
zurückgesichert?

Ich hatte auch schon überlegt, den Delay direkt in meinem PWM interrupt 
(der dann für 1-wire deutlich schneller sein müsste als für die nackte 
PWM) runter zu zählen und auszuwerten, und im Hauptprogramm nichts 
anders zu machen (bzw. in der Endlosschleife) als dass in der ISR 
generierte Flag abzufragen. Bin mit meinen Versuchen aber noch nicht so 
weit, dass ich weiß wie weit ich mit dem Delay runter komme, ob das von 
der Auflösung her passt.
1
in etwa so:
2
volatile int8_t  iDelay
3
volatile uint8_t fDelay
4
5
ISR (alle 5µs)? --> Auflösung 5µs
6
{
7
 If (iDdelay--) <= 0 Delay.flag = TRUE;
8
 else 
9
 {
10
 PWM;
11
 }
12
}
13
14
void MyDelay (int8_t Delay)
15
{
16
 Delay.flag = FALSE;
17
 iDelay(Delay);                        //1/5 des us Wertes
18
 while (Delay.flag == 0);
19
}
gelaufen ist das ganze schon mal testweise ohne 1-wire und ich habe die 
Grenzen der kürze nicht ausgelotet. Letztendlich bin ich mir nicht 
sicher ob die Befehlszahl der ISR nicht zu groß wird und mit der 
Auflösung des Delays in Konflikt kommt. Letzendlich ist mir auch noch 
nicht klar, warum ich den TCNT1H restoren muss, Timer 2 greift doch auf 
den Wert gar nicht zu, er müsste als beim Interrupt von Timer 2 einfach 
weiterzählen?

Den ATMega lasse ich übrigens bei 8MHz laufen. Die DCF Uhr kriege ich 
hin, alle 10min abwechselnd DCF lesen und 1-wire messen reicht mir. 
Leider bin ich zu diesem Thema in keinem anderen Thread zum 1-wire 
fündig geworden, und die Leuchten PWM ist auch was anderes als eine 
langsame Temp-Steuerung.

Wäre super, wenn mir Anfänger das näher gebracht werden könnte.

Vielen Dank im Voraus!

//hufnala

von Volker U. (volkeru)


Angehängte Dateien:

Lesenswert?

Hi Lars,

der Code von Peter ist schon einigermaßen veraltet. Er unterstützt z.B. 
nicht die heute gebräuchlichen DS18B20 Sensoren, deren Auflösung man 
frei konfigurieren kann (dazu gibt es eine zusätzliche Prozedur 
init_meas()). Außerdem hat er Probleme bei Parasite Power und 
niedrigeren Taktraten (z.B. 4 MHz), da funktioniert das Auslesen der 
Sensoren nicht mehr zuverlässig, wie man hier im Thread nachlesen kann. 
Es gibt dann regelmäßig Fehler.

Ich habe den Code über die Zeit weiter entwickelt und angepasst. Er 
läuft mittlerweile seit Jahren absolut zuverlässig. Z.B. benutze ich 
überhaupt keinen Interrupt mehr und auch keine Timer-Register. Damit 
fallen auch alle von dir genannten Probleme weg. Die Wartezeiten werden 
einfach mit einer Assembler-Routine (wait.S) generiert. Derzeit sind die 
Werte für wait_x_075u() auf 4 MHz eingestellt. Bei anderen Taktraten 
müssen einfach nur die Werte beim Aufruf von wait_x_075u() entsprechend 
vergrößert oder verkleinert werden. Während der 1wire-Operationen dürfen 
ohnehin keine Interrupts auftreten, da du die Ergebnisse sonst wegwerfen 
kannst. Das muss sichergestellt sein. Die Sensoren sind äußerst 
zeitkritisch. Wenn sie angesprochen werden, darf nichts anderes 
passieren.

Anbei mal meine Routinen zum Angucken und vielleicht Ausprobieren (bitte 
das zweite Archiv benutzen, im ersten fehlt tempmeas.h!). Sie 
ermöglichen den Betrieb von DS18S20 und DS18B20 Sensoren (auch 
gemischt). Außerdem sind sie zeitunkritisch, d.h. auch bei 2 oder 4 MHz 
Takt gibt es keine Probleme, da die Parasite-Power nicht erst mit einer 
(zu) großen Zeitverzögerung in start_meas() geschaltet wird, sondern 
immer sofort in w1_bit_io().

Die Routine zum Auslesen der Sensoren und zum Konvertieren der Werte 
fehlt im beiliegenden Archiv, weil sie sehr individuell gestaltet werden 
kann und sollte. Ein Beispiel dazu findest du hier weiter oben im 
Thread:

Beitrag "Re: DS1820, DS18B20 in C"

Gruß, Volker

von Volker U. (volkeru)


Lesenswert?

Ergänzung: Wenn man das Error-Register nutzen will, sollte man einen 
entsprechenden char in tempmeas.h definieren:
1
volatile unsigned char temp_buffer[1];

Wer den crc nach Maxim-Handbuch berechnen will, braucht auch noch eine 
CRC-Routine:

crc8.c:
1
/* please read copyright-notice at EOF */
2
3
#include <stdint.h>
4
5
#define CRC8INIT    0x00
6
#define CRC8POLY    0x18              //0X18 = X^8+X^5+X^4+X^0
7
8
uint8_t crc8( uint8_t *data, uint16_t number_of_bytes_in_data )
9
{
10
  uint8_t  crc;
11
  uint16_t loop_count;
12
  uint8_t  bit_counter;
13
  uint8_t  b;
14
  uint8_t  feedback_bit;
15
  
16
  crc = CRC8INIT;
17
18
  for (loop_count = 0; loop_count != number_of_bytes_in_data; loop_count++)
19
  {
20
    b = data[loop_count];
21
    
22
    bit_counter = 8;
23
    do {
24
      feedback_bit = (crc ^ b) & 0x01;
25
  
26
      if ( feedback_bit == 0x01 ) {
27
        crc = crc ^ CRC8POLY;
28
      }
29
      crc = (crc >> 1) & 0x7F;
30
      if ( feedback_bit == 0x01 ) {
31
        crc = crc | 0x80;
32
      }
33
    
34
      b = b >> 1;
35
      bit_counter--;
36
    
37
    } while (bit_counter > 0);
38
  }
39
  
40
  return crc;
41
}
42
43
/*
44
This code is from Colin O'Flynn - Copyright (c) 2002 
45
only minor changes by M.Thomas 9/2004
46
47
Permission is hereby granted, free of charge, to any person obtaining a copy of
48
this software and associated documentation files (the "Software"), to deal in
49
the Software without restriction, including without limitation the rights to
50
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
51
the Software, and to permit persons to whom the Software is furnished to do so,
52
subject to the following conditions:
53
54
The above copyright notice and this permission notice shall be included in all
55
copies or substantial portions of the Software.
56
57
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
58
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
59
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
60
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
61
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
62
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
63
*/

und crc8.h:
1
#ifndef CRC8_H_
2
#define CRC8_H_
3
4
#ifdef __cplusplus
5
extern "C" {
6
#endif
7
8
#include <stdint.h>
9
10
uint8_t crc8( uint8_t* data, uint16_t number_of_bytes_in_data );
11
12
#ifdef __cplusplus
13
}
14
#endif
15
16
#endif
17
18
/*
19
This is based on code from :
20
21
Copyright (c) 2002 Colin O'Flynn
22
23
Permission is hereby granted, free of charge, to any person obtaining a copy of
24
this software and associated documentation files (the "Software"), to deal in
25
the Software without restriction, including without limitation the rights to
26
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
27
the Software, and to permit persons to whom the Software is furnished to do so,
28
subject to the following conditions:
29
30
The above copyright notice and this permission notice shall be included in all
31
copies or substantial portions of the Software.
32
33
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
35
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
36
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
37
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
38
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39
*/

von Lars H. (hufnala)


Lesenswert?

Hallo Volker,

vielen Dank, schaue ich mir gerne an, und schön dass sich das ganze a) 
weiterentwickelt und b) auch in einem alten Tread immer mal wieder 
jemand rein schaut.

Habe gerade noch etwas gebastelt, und vordergründig tut es erst mal am 
Board.

--> PWM auf Timer2, Taktrate so um 20us -> Auflösung PWM
    PWM liegt bei ca. 160Hz
--> das Timerregister in meiner Routine gesichert und Restored
--> 1 Wire läuft, aktuell problemlos
--> USART zu einem angeschlossenen uC 250k

Sensoren habe ich ein paar DS18S20 vom Pollin, vielleicht sind die ja 
unkritischer. Für meine Zwecke reicht es. Was ich mir noch anschauen 
muss, ist die negative Temp. Aber immer eines nach dem anderen, momentan 
ist es hier warm, und vom Eisfach bis zur Schaltung war der Sensor 
gestern jedes mal schon wieder auf +15°C bei RT.

Ob Deine Aussage
"Während der 1wire-Operationen dürfen
ohnehin keine Interrupts auftreten, da du die Ergebnisse sonst wegwerfen
kannst. Das muss sichergestellt sein." damit stimmt weiß ich nicht, hier 
kann ich erst mal ändernde Temperaturen (Sensor von Hand erwärmen, 
reicht für ein paar Grad). Die Werte/das Verhalten ist aktuell auch 
stabil ggü. vorher ohne Soft-PWM.

Werden soll das ganze eine Außenlampe mit Groß-Anzeige (habe ich über 
einen extra Tiny gemacht). Abwechselnd Hausnummer, Temp, Uhrzeit, Datum. 
Die PWM für eine Bunte Effektbeleuchtung (Temp-abhängig?), und die zus. 
PWM Kanäle für etwas Power für ein paar Hochleistungs-LED. Dann noch der 
PIR für das hochschalten der Leuchte.

Nochmals Danke und einen schönen Abend.

Bevor ich den Code Poste (falls es je dazu kommt) muss ich erst mal 
aufräumen und ordentlich machen - Anfänger halt :-), ich glaube aber das 
wird dann endgültig off-topic...

Gruß Lars

von Volker U. (volkeru)


Lesenswert?

Lars Hufnagel schrieb:
> Habe gerade noch etwas gebastelt, und vordergründig tut es erst mal am
> Board.

Klar, Peters Teil tut es, keine Frage :-). Und ab 8 MHz gibts i.d.R. 
auch keine Probleme. Aber bei niedrigeren Taktraten kommen zwischendurch 
gern mal 85 Grad zurück, weil die Parasite Power nicht schnell genug 
zugeschaltet wurde.

> Sensoren habe ich ein paar DS18S20 vom Pollin, vielleicht sind die ja
> unkritischer.

Nein, vom Timing her unterscheiden sie sich nicht vom DS18B20. Die 
DS18B20 haben den Vorteil, dass man sie auf eine geringere Auflösung 
schalten kann. Nicht immer braucht man ja eine Auflösung von 1/16 °C. 
Und bei geringeren Auflösungen verringert sich die Wartezeit zwischen 
CONVERT_T-Kommando und der fertigen Konvertierung erheblich. Jedes Bit 
weniger Auflösung bedeutet nur halbe Wartezeit. Wenn einem also eine 
Genauigkeit von 0,5 °C ausreicht, muss man nur noch 100 ms warten. Das 
spart Zeit und Energie.

> Für meine Zwecke reicht es. Was ich mir noch anschauen
> muss, ist die negative Temp.

Wie gesagt, dort bietet sich die Konvertierungs-Routine an, auf die ich 
oben verlinkt habe. Sie arbeitet mit Komplementbildung, was manche hier 
unsinnig finden, aber von der Rechenzeit her ist es der schnellste Weg.

> Ob Deine Aussage
> "Während der 1wire-Operationen dürfen
> ohnehin keine Interrupts auftreten, da du die Ergebnisse sonst wegwerfen
> kannst. Das muss sichergestellt sein." damit stimmt weiß ich nicht,

Das Problem ist, dass die Wartezeiten im Mikrosekundenbereich liegen 
beim Lesen der Sensoren. Die Leitungen müssen da ganz exakt getaktet 
werden. Wenn nur ein paar falsche Takte dazwischen kommen, sind die 
Ergebnisse unbrauchbar. Deshalb schaltet Peter ja in w1_bit_io() auch 
schon das Interruptssystem sicherheitshalber vorübergehend ab und 
verhindert somit jede Unterbrechnung. Das muss man berücksichtigen, wenn 
man Timer-Interrups benutzt. Ich hatte zuerst nicht daran gedacht und 
wunderte mich, wieso meine Timer-Interrupt-gesteuerte Real-Time-Clock 
mal vor- und mal nachging. Dafür war natürlich die vorübergehende 
Abschaltung des Interrupt-Systems verantwortlich, die die Ereignisse 
unzulässig verzögerte.

Es ist darüberhinaus auch nicht ganz unsinnig, die gelesenen Daten mit 
der CRC-Routine auf Plausibilität zu überprüfen, wie es der Hersteller 
empfiehlt.

> Werden soll das ganze eine Außenlampe mit Groß-Anzeige (habe ich über
> einen extra Tiny gemacht). Abwechselnd Hausnummer, Temp, Uhrzeit, Datum.

Hoffentlich verwechselt der Briefträger dann die Temperatur nicht mit 
der Hausnummer. ;-)

Frohes Basteln!
Volker

von Josef D. (jogedua)


Lesenswert?

Volker U. schrieb:
> ... Dafür war natürlich die vorübergehende
> Abschaltung des Interrupt-Systems verantwortlich, die die Ereignisse
> unzulässig verzögerte.
>
Das kann aber nur dann der Fall sein, wenn du nicht den richtigen 
Timer-Modus verwendet hast.
Solange die ISR-Sperre nicht dazu führt, dass ein Timer-Interrupt ganz 
übersehen wird, spielt die Verzögerung für eine RTC überhaupt keine 
Rolle. Die Sperre beträgt, wenn ich mich recht erinnere, nur ca. 60 µs.
So kurze Timer-Intervalle wirst du vermutlich nicht haben.

von Volker U. (volkeru)


Lesenswert?

Josef D. schrieb:
> Solange die ISR-Sperre nicht dazu führt, dass ein Timer-Interrupt ganz
> übersehen wird, spielt die Verzögerung für eine RTC überhaupt keine
> Rolle.

Nicht immer kann man das automatische Rücksetzen des Counters auf 0 
verwenden. Wenn man die Uhr sehr genau justieren will (z.B. auf weniger 
als 1 Sekunde Abweichung pro Monat), muss man den Counter in der ISR 
selbst setzen. Der Interrupt tritt dann zeitlich verzögert ein und zwar 
erst dann, wenn die Interrupts mit sei() wieder freigegeben wurden. Erst 
dann wird das Counter-Register zurückgesetzt und ein neues 
Zähl-Intervall beginnt. Auf diese Weise summieren sich die Verzögerungen 
im Laufe der Zeit zu ganz erheblichen Abweichungen. Und zwar abhängig 
davon, wie häufig der Interrupt zeitlich verzögert auftritt. Daher darf 
der Counter in der ISR in diesem Fall nicht auf 0 gesetzt werden, 
sondern es muss ein konstanter Betrag vom aktuellen Zählerstand 
subtrahiert werden.

von Josef D. (jogedua)


Lesenswert?

wir sollten jetzt nicht weiter diesen Thread für ein Uhren-Thema kapern.

Wenn man hier im Forum nach "genaue Sekunde" sucht, erhält man mehrere 
Seiten mit Treffern.
In diesen steht das Wichtigste dazu beschrieben:
http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC
Beitrag "Genaue Sekunde AVR"

von Volker U. (volkeru)


Lesenswert?

Es ging ja auch nur darum zu sagen, dass man aufpassen muss, weil das 
Interruptsystem bei der Kommunikation mit dem Sensor zwischendurch immer 
wieder mal deaktiviert wird. Was die Uhr betrifft, kann man alternativ 
zum Counterwert natürlich auch den Compare-Wert entsprechend ändern und 
den Counterwert automatisch auf 0 setzen lassen. Man muss ihn dann aber 
immer wieder auf den Ausgangswert zurücksetzen, weshalb ich die Änderung 
des Counterwerts bevorzuge.

von Cyblord -. (cyblord)


Lesenswert?

Man kann auch den anderen Weg gehen und Interrupts nicht deaktivieren.
Wenn dann in die 1Wire Kommunikation ein Interrupt reinfunkt dann gibts 
eben Datensalat, erkennbar am falschen CRC. Wenn man dann den Zugriff 
auf den Sensor noch ein wenig zufällig gestaltet, so kann man mit hoher 
Wahrscheinlichkeit eine ausreichende Anzahl von erfolgreichen Zugriffen 
pro Zeiteinheit erhalten. Damit hätte der Interrupt immer prio.

gruß cyblord

von Volker U. (volkeru)


Lesenswert?

Nuja, das Konzept finde ich aber sehr unschön: Datensalat bewusst in 
Kauf zu nehmen, um nachträglich anhand von Prüfsummen die fehlerhaften 
Daten rauszuwerfen. Man muss mal bedenken, dass ein 8-Bit-CRC auch nur 
begrenzte Sicherheit bietet. Wenn zu häufig Datensalat auftritt, steigt 
die Wahrscheinlichkeit nicht unerheblich, dass der CRC zufällig doch 
richtig ist, obwohl die Daten falsch sind. Ich würde daher immer auf 
sichere Übertragung setzen.

von Cyblord -. (cyblord)


Lesenswert?

Das Konzept kommt häufig zum Einsatz. Bei Ethernet z.B. ebenso WLAN. 
Aber auch in Datenbank- und Betriebssytemen werden oft Deadlocks o.ä. 
nicht aktiv verhindert, sondern falls etwas passiert, dann halt unter 
größerem Aufwand wieder ausgebügelt. Wenn aber dieser Aufwand geringer 
als der sonst benötigte Overhead ist, dann lohnt das.

Etwas seltener allerdings bei Atomkraftwerken oder in der 
Luft/Raumfahrt.

gruß cyblord

von Volker U. (volkeru)


Lesenswert?

Ähm, Ethernet arbeitet aber nicht mit 8 Bit CRCs und Deadlocks sind auch 
was anderes als Datenfehler. Es kommt darauf an, wie hoch die zu 
erwartende Fehlerquote ist und welche Quote toleriert werden kann. Es 
gibt auch Anwendungen, da darf es keine Fehler geben. Keine heißt in 
diesem Fall eine Quote gegen Null.

von Cyblord -. (cyblord)


Lesenswert?

Volker U. schrieb:
> Ähm, Ethernet arbeitet aber nicht mit 8 Bit CRCs und Deadlocks sind auch
> was anderes als Datenfehler.
Dir ist der Begriff "Konzept" klar?

> Es kommt darauf an, wie hoch die zu
> erwartende Fehlerquote ist und welche Quote toleriert werden kann.
Ja, das muss man vorher ausrechnen ob es passt.

gruß cyblord

von Lars H. (hufnala)


Lesenswert?

Hi,

zunächst verspätet noch vielen Dank. Also bisher läuft das ganze 
anscheinend stabil. Endausbau ist noch lange nicht fertig, und wenig 
Zeit momentan, aber ich probiere immer mal wieder. Momentan sieht es 
nicht so aus als hätte ich Datensalat empfangen bisher alle Werte 
zwischen 18 - 24°C, und die PWM LED flackert auch nicht.

"Hoffentlich verwechselt der Briefträger dann die Temperatur nicht mit
der Hausnummer. ;-)"

Yepp, auf die Idee bin ich noch gar nicht gekommen, Mal sehen wann hier 
was für 36C ankommt statt 20b - könnte sich auch zur Marktlücke bzgl.
unerwünschter Werbung & Rechnungen entwickeln ;-)

CU //hufnala

von Volker U. (volkeru)


Lesenswert?

cyblord ---- schrieb:
> Dir ist der Begriff "Konzept" klar?

Also ich finde, der Vorschlag, Daten zu verwerfen, weil der 
Übertragungskanal unzureichend ausgelegt ist, ist ein anderes Konzept 
als das der unvermeidbaren Kollisionsvermeidung bei gemeinsamer Nutzung 
einer Transportschicht z.B. im Ethernet oder WLAN ;).

Aber unabhängig davon, ist dieses Konzept untauglich bei Nutzung von 
8-Bit-CRC. Und darum ging es hier ja eigentlich.

von Cyblord -. (cyblord)


Lesenswert?

Volker U. schrieb:
> cyblord ---- schrieb:
>> Dir ist der Begriff "Konzept" klar?
>
> Also ich finde, der Vorschlag, Daten zu verwerfen, weil der
> Übertragungskanal unzureichend ausgelegt ist, ist ein anderes Konzept
> als das der unvermeidbaren Kollisionsvermeidung bei gemeinsamer Nutzung
> einer Transportschicht z.B. im Ethernet ;).

Das ist genau dasselbe. Der Kanal ist nicht unzureichend ausgelegt, es 
kann nur eben vorkommen dass die Übertragung kurz stockt (durch 
Interrupt) und daher die Daten fehlerhaft sind, genauso wie beim 
Ethernet eben auch mal 2 gleichzeitig senden und dadurch die Daten 
fehlerhaft werden. Dies wird erkannt, und kurze Zeit später nochmal 
versucht.
Und Kollisionen in einem Netzwerk sind nicht unvermeidbar, es gibt auch 
Protokolle die das anders machen. z.B. TokenRing.

Aber egal, ich würde den Interrupt auch abschalten. Wollte nur mal eine 
weitere Option einbringen.


Und btw: Ethernet != Transportschicht ;-)

von Volker U. (volkeru)


Lesenswert?

cyblord ---- schrieb:
> Das ist genau dasselbe.

Ich glaube, das ist Interpretationssache ;-).

> Der Kanal ist nicht unzureichend ausgelegt, es
> kann nur eben vorkommen dass die Übertragung kurz stockt (durch
> Interrupt) und daher die Daten fehlerhaft sind,

Das sehe ich z.B. als unzureichende Auslegung. Unzureichend ist eben 
auch subjektiv.

> genauso wie beim
> Ethernet eben auch mal 2 gleichzeitig senden und dadurch die Daten
> fehlerhaft werden.

Auch das ist für mich unzureichend. Weshalb man ja auch keine Hubs mehr 
benutzt, sondern Switches, wodurch auch beim Ethernet Kollisionen 
vermieden werden.

> Aber egal, ich würde den Interrupt auch abschalten. Wollte nur mal eine
> weitere Option einbringen.

Nur halte ich diese Option bei einer 8-Bit-Prüfsumme für keine solche 
:-).

> Und btw: Ethernet != Transportschicht ;-)

Eben! Das Ethernet ist aber nicht für die Stauvermeidung zuständig, um 
die es uns ja ging, sondern die Transportschicht, also TCP oder UDP. 
Deshalb war dein Beispiel nicht so sinnvoll.

von Cyblord -. (cyblord)


Lesenswert?

Volker U. schrieb:
> cyblord ---- schrieb:
>> Das ist genau dasselbe.
>
> Ich glaube, das ist Interpretationssache ;-).
Ach je


>> Der Kanal ist nicht unzureichend ausgelegt, es
>> kann nur eben vorkommen dass die Übertragung kurz stockt (durch
>> Interrupt) und daher die Daten fehlerhaft sind,
>
> Das sehe ich z.B. als unzureichende Auslegung. Unzureichend ist eben
> auch subjektiv.
>
>> genauso wie beim
>> Ethernet eben auch mal 2 gleichzeitig senden und dadurch die Daten
>> fehlerhaft werden.
>
> Auch das ist für mich unzureichend. Weshalb man ja auch keine Hubs mehr
> benutzt, sondern Switches, wodurch auch beim Ethernet Kollisionen
> vermieden werden.
Also beides für dich(!) unzureichend, also passt doch mein Beispiel.
Das nun Ethernet heute nicht mehr per Koax oder Hub läuft ist doch hier 
absolut egal.

> Nur halte ich diese Option bei einer 8-Bit-Prüfsumme für keine solche
> :-).
Nur weil du die CRC als einzige Möglichkeit siehst. Der Interrupt könnte 
auch ein Flag setzen wenn er auftritt, und die 1Wire Routine könnte 
dieses Flag am Ende abfragen und weiß dann dass ein Interrupt irgendwo 
während der Übertragung aufgetreten ist.

>
>> Und btw: Ethernet != Transportschicht ;-)
>
> Eben! Das Ethernet ist aber nicht für die Stauvermeidung zuständig, um
> die es uns ja ging, sondern die Transportschicht, also TCP oder UDP.
> Deshalb war dein Beispiel nicht so sinnvoll.

Was eben? Du hast Ethernet als Transportschicht bezeichnet was falsch 
ist.

Und natürlich brauchen auch die physikalischen Schichten immer eine 
Sicherung ihrer Daten auch gegen Kollision. Bei Ethernet CSMA/CD, bei 
WLAN CSMA/CA. Deine Aussage, das bräuchte man nicht, weil ja dafür TCP 
zuständig ist und deine Gleichsetzung mit Staukontrolle, entlarvt dich 
leider als wenig qualifiziert für diese Diskussion.

Du magst meinen Ansatz nicht, kannst aber nicht artikulieren warum. 
Lassen wirs doch dabei, das ist mir zu anstrengend.

gruß cyblord

von Volker U. (volkeru)


Lesenswert?

cyblord ---- schrieb:
>> Nur halte ich diese Option bei einer 8-Bit-Prüfsumme für keine solche
>> :-).
> Nur weil du die CRC als einzige Möglichkeit siehst. Der Interrupt könnte
> auch ein Flag setzen wenn er auftritt, und die 1Wire Routine könnte
> dieses Flag am Ende abfragen und weiß dann dass ein Interrupt irgendwo
> während der Übertragung aufgetreten ist.

Das ist jetzt aber ein völlig neues Konzept, über das hier bisher nicht 
einmal gesprochen wurde!

> Was eben? Du hast Ethernet als Transportschicht bezeichnet was falsch
> ist.

Wiebitte? Wo habe ich das denn getan? Ich habe geschrieben "[..] als das 
der unvermeidbaren Kollisionsvermeidung bei gemeinsamer Nutzung
einer Transportschicht z.B. im Ethernet oder WLAN ;)." Du wirst wohl 
nicht abstreiten, dass es im Ethernet und WLAN eine Transportschicht 
gibt, oder?

> Und natürlich brauchen auch die physikalischen Schichten immer eine
> Sicherung ihrer Daten auch gegen Kollision. Bei Ethernet CSMA/CD, bei
> WLAN CSMA/CA. Deine Aussage, das bräuchte man nicht, weil ja dafür TCP
> zuständig ist und deine Gleichsetzung mit Staukontrolle, entlarvt dich
> leider als wenig qualifiziert für diese Diskussion.

Sie brauchen es nicht immer. Man kann in der Sicherungsschicht eine 
Kollisionsvermeidung implementieren, aber es ist für die 
Sicherungsschicht nicht zwangsläufig vorgeschrieben. Fehlererkennung und 
Kollisionsvermeidung sind ja zwei ganz unterschiedliche Dinge. Du 
sprachst von Fehlererkennung und ich von Kollisionsvermeidung.

> Du magst meinen Ansatz nicht, kannst aber nicht artikulieren warum.

Ich denke, ich habe mehrfach gesagt, warum ich diesen Ansatz für 
unbrauchbar halte: Weil eine 8-Bit-CRC zur Fehlererkennung nicht 
ausreicht. Wenn du jetzt noch zusätzliche Mechanismen einführst, um die 
Erkennung zuverlässiger zu machen, kannst du das gerne tun, aber es war 
zu Beginn nicht Gegenstand dieser Diskussion!

Wenn du mich nicht als qualifiziert für diese Diskussion hältst, warum 
diskutierst du dann mit mir? ;-)

von Volker U. (volkeru)


Lesenswert?

Lars Hufnagel schrieb:
> "Hoffentlich verwechselt der Briefträger dann die Temperatur nicht mit
> der Hausnummer. ;-)"
>
> Yepp, auf die Idee bin ich noch gar nicht gekommen, Mal sehen wann hier
> was für 36C ankommt statt 20b - könnte sich auch zur Marktlücke bzgl.
> unerwünschter Werbung & Rechnungen entwickeln ;-)

Das dürfte nur problematisch werden, wenn der Briefträger nicht nur 
Werbung, sondern auch wichtige Post für dich hat ;-).

von Conny G. (conny_g)


Lesenswert?

Hallo Peter,

herzlichen Dank für die 1-wire-Sources.
Funktionierte auf Anhieb nachdem ich den DS18S20 richtig verkabelt hatte 
(hatte den Pullup-Widerstand vergessen...).

Was m.E. noch nicht drin ist oder für den DS18S20 nicht funktioniert 
hat, war die Auflösungserhöhung via "count per C" und "count remain" 
Register.
(datasheet S.3)

Falls es jemand braucht, sieht bei mir im Code so aus (ersetzt die 
READ-passage):
1
      w1_byte_wr( READ );      // read command
2
3
      // read 9 bytes scratch pad
4
      uint8_t tempLow   = w1_byte_rd();
5
      uint8_t tempHigh  = w1_byte_rd();
6
      uint8_t T_H       = w1_byte_rd();
7
      uint8_t T_L       = w1_byte_rd();
8
      uint8_t Res1      = w1_byte_rd();
9
      uint8_t Res2      = w1_byte_rd();
10
      uint8_t cntRemain = w1_byte_rd();
11
      uint8_t cntPerC   = w1_byte_rd();
12
      uint8_t CRC       = w1_byte_rd();
13
14
      uint16_t tempRead = ( ( ( tempHigh << 8 ) | tempLow ) << 3);
15
      tempRead += cntPerC - cntRemain;
16
17
      sprintf( s, "  T: %4d.%1d°C", tempRead >> 4, (tempRead << 12) / 6553 );
18
      usartSendString( s );

VG,
Konrad

von Richard S. (richards)


Angehängte Dateien:

Lesenswert?

Hallo,

ich bedanke mich für die Codes hier, das hat mir viel Zeit erspart.
Ich habe für meinen Projekt auch mehrere Sensoren DS18B20 verwenden 
wollen, und habe auch ohne große Probleme erstmal 2 Sensoren an einer 
Leitung zum Laufen gebracht. Allerdings gefiel mir eben nicht die 
Tatsache, daß die negativen Temps nicht korrekt angezeigt wurden.
Erste Versuche mit kleinen Änderungen am vorhandenen code haben nicht 
gebracht.
Dann habe ich "richtig" umgebaut und hier ist das Ergebnis:


/***********************************************************************


 ein Vorschlag vom Josef: Beitrag "DS1820, DS18B20 in C"

 Allerdings: korrigiert von mir bei Ausgabe von negativen Temperaturen


***********************************************************************/


#include "main.h"
#include "HD44780_2.h"

#define MIT_NAMEN  1    // 0= ohne, 1=mit Namen in DS1820

void start_meas( void ){
  if( W1_IN & 1<< W1_PIN ){
    w1_command( CONVERT_T, NULL );
    W1_OUT |= 1<< W1_PIN;
    W1_DDR |= 1<< W1_PIN;      // parasite power on

 _delay_ms(600);                     // Verzögerung wg parasite power

  }
}

#if MIT_NAMEN
#define  DS18B20_12bit  0x7F

//           #define THERMOanzahlMax  3  // auch thermoNamen anpassen!
#define THERMOanzahlMax  2  // auch thermoNamen anpassen!

//                          "123456123456123456"
//   #define THERMO1WNAMEN  "    T1    T2    T3"  // Überschrift, 
rechtsbündig

#define THERMO1WNAMEN  "    T1    T2"  // Überschrift, rechtsbündig

#define THERMO1NameLen  6
#define THERMO1NameOffset  (THERMO1NameLen-2) // hier steht das 1. 
Zeichen
static  char  thermoNamen[] =  THERMO1WNAMEN;  // ToDo PROGMEM

static  float  thermoValues[THERMOanzahlMax];

static  uint8_t initReady;
#if (THERMOanzahlMax<=8)
  static uint8_t valid;   // Indizes mit gültigen Namen merken, je 1 bit
#else
  static uint16_t valid;
#endif

static uint8_t NameValid( char * name ) {
  // prüft, ob Name aus scratch mit Name aus Tabelle übereinstimmt
  // wenn ja, ret = index+1!!!; andernfalls 0
  uint8_t ret = 0;
  char * pC = thermoNamen+THERMO1NameOffset;
  while (ret++ < THERMOanzahlMax) {
    if ( *(int16_t*) name== *(int16_t*) pC)  // 2 Byte vergleichen
      return ret;
    pC += THERMO1NameLen;
  }
  return 0;
}
#endif

void read_meas( void )
{
  uchar id[8], diff;
  char s[30];
  uchar i;
  int16_t temp1,temp2;
  float temp=0;

  for( diff = SEARCH_FIRST; diff != LAST_DEVICE; ){
    diff = w1_rom_search( diff, id );

    if( diff == PRESENCE_ERR ){

      break;
    }
    if( diff == DATA_ERR ){

      break;
    }
    if( id[0] == 0x28 || id[0] == 0x10 ){  // temperature sensor
#if !MIT_NAMEN

    //Wert der ID ausgeben
    for( i = 0; i < 8; i++ ){
      sprintf (s, "ID: %02X ", id[i] );

    LCD_GoTo_2(0);
        LCD_WriteText(s);
                              }
#endif

      w1_byte_wr( READ );      // read command
      temp1 = w1_byte_rd();      // low byte
      temp2 = w1_byte_rd();        // high byte

      temp=(float)(temp1+(temp2*256))/16;


#if MIT_NAMEN
    char name[2]; uint8_t nIndex;

    name[0] = w1_byte_rd();      // high Index
    name[1] = w1_byte_rd();      // low  Index

    if (!initReady)  {      // nur beim 1. Durchgang
      // PrintId( id, name );  //  erkannte Sensoren mit Namen ausgeben, 
z.B. auf Uart


/*************************************
          LCD_GoTo_2(5);
          LCD_WriteText(name);
          LCD_WriteText(" ");
**************************************/


    }
    if ((nIndex = NameValid(name))) {

      thermoValues[--nIndex] = temp;

      valid |= (1<<nIndex);
    } else if (initReady==1){ // alle im 0. Durchgang als gültig 
erkannten sind ausnahmsweise noch gesetzt
      i = 0;
      while ((1<<i++) & valid);   // 1. freien Platz finden (i ist dann 
1 zu groß)
      if (--i<THERMOanzahlMax) {  // also vorher 1 abziehen
        valid |= (1<<i);          // jetzt belegt
        i *= THERMO1NameLen;
        i += THERMO1NameOffset;
        w1_command( WRITE, id );
        w1_byte_wr( name[0]=thermoNamen[i++] );
        w1_byte_wr( name[1]=thermoNamen[i] );
        w1_byte_wr( DS18B20_12bit );  // ggf. anpassen für anderen 
Sensor!
        w1_command( EE_WRITE, id );
        // PrintId( id, name );      // Namensänderung protokollieren
      }
    }

#else
    //Messwert in Grad Celsius auf LCD ausgeben

                      dtostrf(temp, 3, 1, s);

        LCD_GoTo_3(2);
          LCD_WriteText(s);
          LCD_WriteData (2);        //  " Grad "
          LCD_WriteText("C");
          LCD_WriteText("   ");

#endif
    }
  }

#if MIT_NAMEN

  for( i=0; i<THERMOanzahlMax; i++) {  // Error-Detection

/*********************************************************************** 
**
  * es treten gelegentlich Lesefehler auf (Detektor wird nicht 
gefunden).
  *   Ausgelassene Werte machen viel Arbeit in Excel und verunstalten 
die Grafik.
  *   Deshalb jetzt: alten Messwert +/- Konstante, z.B. 1°=0x10 (1*16).
  *   und das letzte Bit gibt an, ob addiert oder subtrahiert werden 
muss (abwechselnd)
  *  Wenn man das nicht braucht, kann man auch einfach einen sonst nicht 
vorkommenden
  *  Wert einsetzen, z.B. 0.
************************************************************************ 
*/

           temp=thermoValues[i];

    if (!(valid &(1<<i))) {  // keinen neuen Wert gelesen ?
                          // dann den alten nehmen
      thermoValues[i]=temp;
                           }

           dtostrf(temp, 3, 1, s);

//  die Überschrift muss ggf. an die Stellenzahl dieser Ausgabe 
angepasst werden


          LCD_GoTo_4(i*10);

          LCD_WriteText("  ");
          LCD_WriteText(s);
          LCD_WriteData (2);        //  " Grad "
          LCD_WriteText("C");
      LCD_WriteText("   ");
                                    }

  if (initReady)
    valid = 0;

    // d.h. beim ersten Durchgang stehen lassen für Erkennung der freien 
Plätze für unbekannte Sensoren
  if (initReady<255)  // Überlauf verhindern
    ++initReady;
#endif
}

von Richard S. (richards)


Angehängte Dateien:

Lesenswert?

und hier bitte das Bild vom Versuchsaufbau.

Die Ausgabe funktioniert jetzt ohne "fremde" Zeichen
und bei negativen Temperaturen absolut einwandfrei:

P.S.: leider habe ich keinen Kältespray mehr um die negativen zu zeigen 
...;)..

von Berti (Gast)


Lesenswert?

Richard S. schrieb:
> und hier bitte das Bild vom Versuchsaufbau

Und bitte schnell "Termometer" in Thermometer ändern.
Ist ja schon peinlich.

von Richard S. (richards)


Lesenswert?

ist gar kein Problem,
da ich zwischen 4 Sprachen "umschalten" muß, kommt manchmal dazu,
daß ein Buchstabe fehlt .....

von Volker U. (volkeru)


Lesenswert?

Richard S. schrieb:
> da ich zwischen 4 Sprachen "umschalten" muß, kommt manchmal dazu,
> daß ein Buchstabe fehlt .....

Und wenn man "Digital-Thermometer" schreibt, ist das Wort außerdem nicht 
mehr so schön zentriert, bei einem 20-Zeichen-Display :-p

von Frank m. (morphy)


Lesenswert?

@Richard S.

wie schaut denn deine main.c aus?
Ih versuche das gleiche Projekt zu verwirklichen

Grüße
Frank

von Lutz (Gast)


Lesenswert?

Hallo Zusammen,

erst mal recht herzlichen Dank, für die ganzen Codes zu diesem Thema.
Ich habe den Sensor nun endlich ausgelesen,dann jedoch feststellen 
müssen, dass er ab einer Temperatur über 53°C  nicht mehr erkannt wird. 
Komischerweise springt das Programm dann immer in die Anweisung:

    if( diff == PRESENCE_ERR ){
    lcd_clear();
    lcd_setcursor(0,2);
      lcd_string( "  Sensor fehlt!" );
      break;
    }

(Befindet sich in der tempmeas.c)

kann mir jmd sagen woran das liegt? Alles andere scheint zu 
funktionieren.

von Wolfgang (Gast)


Lesenswert?

Lutz schrieb:
> kann mir jmd sagen woran das liegt?

Am fehlenden Schaltplan und Angaben zum Aufbau? Parasitärer Betrieb und 
Leckströme vielleicht? Das Datenblatt spricht zwar erst ab 100°C von 
Problemen ("The use of parasite power is not recommended for 
temperatures above +100°C"), aber vielleicht liegt noch mehr im Argen.

von Conny G. (conny_g)


Lesenswert?

Vielleicht mag der uC einfach nicht in den Ofen oder in die Sauna 
gesteckt werden und kann die Pins nicht mehr auslesen? :-)

von Volker U. (volkeru)


Lesenswert?

Lutz schrieb:
>     if( diff == PRESENCE_ERR ){
> kann mir jmd sagen woran das liegt? Alles andere scheint zu
> funktionieren.

Falls der Sensor im Parasite-Power-Modus betrieben wird, hängt dies fast 
immer damit zusammen, dass das nötige "strong pullup" nicht schnell 
genug nach dem Absetzen des CONVERT_T Kommandos zugeschaltet wird. Dazu 
sind nur 10 Mikrosekunden Zeit. Siehe auch hier: 
Beitrag "Re: DS1820, DS18B20 in C"

von Richard S. (richards)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe das Projekt mit dem Tiny84 realisiert und jetzt für konkrete 
Aufgabe vorbereitet - unser Kühlschrank.
Das Gehäuse ist noch nicht ganz fertig, aber bald.
Die Anzeige funktioniert einwandfrei, wie man sehen kann.


@Volker
Dein Vorschlag ist natürlich auch drin....Danke!

Gruß,
Richard

von Volker U. (volkeru)


Lesenswert?

Wie schön! :-)

Wie hast du deine Messleitungen in den Kühlschrank geführt? Ich hatte 
auch mal ein Thermometer im Gefrierschrank. Da hatte ich eine ganz dünne 
Zwillingslitze zwischen Türrahmen und Dichtung entlang geführt. Das 
Problem war: An dieser Stelle kommt Luft von außen in den Schrank, auch 
wenn es nur sehr wenig ist. Im Laufe der Zeit hat sich die Dichtung an 
der Stelle zudem verformt, also dem Kabel angepasst und blieb auch 
undicht, wenn das Kabel entfernt war. Dort wo diese Undichtigkeit 
bestand, war der Gefrierschrank innen immer erheblich dicker mit Eis 
befroren, als im übrigen Innenraum. Das heißt, dass selbst so eine 
kleine Undichtigkeit nicht unerhebliche Auswirkungen auf das Innenleben 
eines Gefrierschranks und damit auch auf den Energieverbrauch hat.

Vermutlich müsste man ein kleines Loch in die Dichtung bohren, das Kabel 
dann dort durchführen und alles mit Silikon abdichten, um es perfekt zu 
machen.

Schöne Grüße, Volker

von Michael (Gast)


Lesenswert?

Volker U. schrieb:
> Vermutlich müsste man ein kleines Loch in die Dichtung bohren, das Kabel
> dann dort durchführen und alles mit Silikon abdichten, um es perfekt zu
> machen.

Das hat Conrad vielleicht ein passendes Kabel (943358). Die 0.1mm dürfte 
auch die Kühlschrankdichtung nicht zu sehr aus der Fassung bringen.

von Volker U. (volkeru)


Lesenswert?

Interessantes Kabel! Allerdings ist es mit 34 mm ganz schön breit. Und 
wie hoch der spezifische Widerstand ist, darüber schweigt sich das 
Datenblatt leider völlig aus. Für NF-Anwendungen ist es sicher gut 
geeignet, für Temperatursensoren auch. Im HF-Bereich dürfte es 
allerdings sehr schnell versagen, weil es eine große Fläche und keine 
Abschirmung bietet.

Es sieht aus wie ein Klebeband, daher wäre es eigentlich perfekt, wenn 
es auf der einen Seite eine Klebefläche hätte und auch wie ein Klebeband 
befestigt werden könnte. Aber das geht leider nicht, man muss es wohl 
mit Klebstoff festkleben.

Da fällt mir auf, dass es sowas noch gar nicht gibt: Eine ultraflache 
Zwillingslitze in Form eines Klebebandes, die man wie ein Tesa-Klebeband 
verarbeiten und überall aufkleben kann. Das wäre genial, um unsichtbare 
Kabel auf Fußleisten oder über Türrahmen zu verlegen. Scheint eine 
Marktlücke zu sein...

von T. A. (wambly)


Lesenswert?

Hi

Hauchdünner Kupferlackdraht auf Tixo kleben ginge auch.

Ich hab mal 0,01mm gekauft. Das muss ich teilweise unter der Lupe löten, 
sonst sehe ich den Draht nicht. Vor und nach der Dichtung kann man ja 
mit "normalem" Kabel weiterleiten.
Aber bei über 1KM könnte man auch lange Verbindungen herstellen.

Preis ist ja nicht ohne für 1m bei dem "Flachband" Kabel.

Ciao T.A.

von Volker U. (volkeru)


Lesenswert?

Ich wusste bis jetzt gar nicht, dass der Tesafilm in Österreich Tixo 
heißt :-).

Das ist aber eine ziemliche Fummelei, einen dünnen Kupferlackdraht 
manuell auf Klebefilm aufzutragen. Klar, für kleine Strecken ist es kein 
Problem. Das Problem ist dann eher der Übergang vom hochempfindlichen 
Lackdraht zum normalen Kabel. Da muss man den Draht auf jeden Fall 
irgendwie fixieren, z.B. mit einem Klebepad, weil er sonst schnell 
abreißt.

von Richard S. (richards)


Lesenswert?

Hallo,

ich habe ein ca. 10 cm-Stück  vom Flachbandstreifen (ca. 0.2 mmm dick) 
eines alten Tintenstrahlers genommen und zwischen zwei kleinen Stücken 
Epoxyplatinnen (durchkontaktierten) gelötet. Da dran ist dann normales 
dünnes kabel angelötet. Somit ist der Übergang an den Türen absolut 
akzeptabel, denke ich.

von Volker U. (volkeru)


Lesenswert?

Ja, das ist eine interessante und gute Idee! Allerdings würde ich trotz 
der geringen Dicke von nur 0,2 mm ab und zu mal die Türdichtung an der 
Durchführungsstelle beobachten.

von ds18b20 verzweifler (Gast)


Lesenswert?

Hallo


ich versuche vergebens diese Libs zu portieren.

habe jetzt defines geschrieben:
1
#define OW_PORT LPC_GPIO1
2
3
#define OW_DIR         OW_PORT->FIODIR
4
#define OW_SET         OW_PORT->FIOSET
5
#define OW_CLEAR       OW_PORT->FIOCLR
6
7
#define OW_PIN             (1 << 29)        //Change this to change the RS data pin
8
9
#define OW_SET_OUTPUT()    GPIO_SetDir(OW_PORT,OW_PIN,1)
10
#define OW_SET_INPUT()     GPIO_SetDir(OW_PORT,OW_PIN,0)
11
#define OW_HIGH()          GPIO_SetValue(OW_PORT,OW_PIN)
12
#define OW_LOW()           GPIO_ClearValue(OW_PORT,OW_PIN)
13
#define OW_GET_MASK(x)     x = GPIO_ReadValue(OW_PORT)
14
15
16
#define OW_IN    OW_PORT->FIOPIN
17
#define OW_PIN_NR 29
18
19
#ifndef W1_PIN
20
#define W1_PIN  OW_PIN_NR
21
#define W1_IN  OW_IN
22
#define W1_OUT  OW_SET
23
#define W1_DDR  OW_DIR
24
#endif



weiters habe ich noch die delayfunction portiert.. diese funktioniert...


als ergebnis für den DS18B20 bekomme ich immer
1
 BUS ERROR

leider weiß ich  nicht mehr weiter..
am Oszilloskop kann ich waveforms erkennen vom UC und auch vom Ds18b20 
also falsch verdrahtet ist es nicht. ich verwende 3v3 und den 4k7 
Widerstand..

mfg

von Felix T. (felix)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen

Nach etwas probieren kompiliert der Code von Peter nun bei mir mit 
AVR-Studio 4 und WinAVR problemlos und fehlerfrei. (Ich hatte teilweise 
die gleichen Compiler-Errors wie weiter oben beschrieben)
Der Code funktioniert wunderbar. Tolle Sache, Peter.
Damit andere sich andere das Gestolper sparen können anbei das gezippte 
Projekt für AVR-Studio, inkl. Quellcode.

Verwendet habe ich einen ATMega16 @8MHz (int. Oszillator), 19200 Baud am 
Uart und 2 DS18S20. Beide Sensoren werden automatisch erkannt und anhand 
ihrer Seriennummer ausgelesen. Beide Sensoren sind an der gleichen 
1Wire-Leitung, 4k7 Pullup nicht vergessen!

Viel Spaß damit.

von Philipp K. (philipp_k59)


Lesenswert?

Hallo, habe mich hier grob mal durchgelesen.. irgendwie zeigen bei mir 
alle DS18B20 ca 2-3° zuviel.. am arduino als Test waren diese alle 
gleich, soweit genau und identisch.

Habe ich hier vielleicht eine zu alte Vorlage genutzt ?

: Bearbeitet durch User
von Sebastian A. (xxlxx)


Lesenswert?

Hi

Das hatte ich auch so. Durch die permanente Spannung wird das 
eigenerwärmung sein. Meine Sensoren kleben aber an Flächen da war das 
dann egal. Diese Flächen Werden nicht warm.

von F. F. (foldi)


Lesenswert?

Philipp K. schrieb:
> irgendwie zeigen bei mir
> alle DS18B20 ca 2-3° zuviel.. am arduino als Test waren diese alle
> gleich, soweit genau und identisch.

Entweder zeigen die was an oder nicht, aber zu viel oder zu wenig geht 
nicht, da sie ab Werk kalibriert sind. Natürlich haben die Abweichungen, 
aber nicht mehrere Grad.
Schon mal überlegt, ob dein Vergleichsthermometer genau ist?
In meinem Raum hier sind zwei Uhren mit Thermometer, eines zeigt 22.9°C 
und das andere 23.3°C. Die üblichen Abweichungen liegen bei einem halben 
Grad im Maximum.
DS18..., die ich auch ausschließlich verwende, haben bei mir alle bis 
jetzt höchstens 0.3 Grad Abweichung gehabt.

: Bearbeitet durch User
von Philipp K. (philipp_k59)


Lesenswert?

dann muss ich nochmal schauen ..

Aber habe mehrere DS18B20 in mehreren Geräten über eine ArduinoLib in 
Benutzung und diese zeigen alle den gleichen Wert wie praktisch jedes 
andere Thermometer.. egal welchen ich nun in mein Avr-C Projekt mit dem 
Beispiel hier benutze zeigt der mindestens 2° mehr an..

Ich vermutete das ich vielleicht etwas wichtiges nicht beachtet habe.

Gruß,
Philipp

von F. F. (foldi)


Lesenswert?

Philipp K. schrieb:
> Ich vermutete das ich vielleicht etwas wichtiges nicht beachtet habe.

Vermutlich ne lib für den DS18  S  20 genommen?

von Julian (Gast)


Lesenswert?

Hallo
Ich versuche jetzt schon seit einer Ewigkeit den 1wire Code von Peter 
Dannegger zum Laufen zu bekommen. Da ich mich wahrscheinlich einfach nur 
dumm anstelle, hoffe ich auf eure Hilfe.
Ich will einfach ein integer bekommen und dann auf einem LCD anzeigen.
Wie mache ich das?

Noch eine schöne Woche!!!!
mfg

von Karsten W. (lsmod)


Lesenswert?

Ich möchte diesen alten Thread noch einmal aufwärmen, da ich nun leider 
auch das Problem habe mehrere (3 Stück) DS18B20 am 1Wire-Bus ausgelesen 
zu bekommen.

Vorweg: Ich benutze nun schon seit langer Zeit erfolgreich die Routinen 
mit CRC-Berechnung von Volker U., die wiederum auf dem Code von Peter 
Dannegger beruhen. Beitrag "Re: DS1820, DS18B20 in C"
Das Auslesen eines Temperatursensors läuft absolut stabil.

Nun möchte ich allerdings 3 (max. 5) Sensoren an dem gleichen 1Wire-Bus 
auslesen und ich habe dabei große Probleme.
Interessanterweise funktioniert das Auslesen von 3 Sensoren problemlos 
im Laborbetrieb auf dem Schreibtisch!

In eingebautem Zustand sind die Sensoren aber über ein ca. 5m langes 
CAT5 Kabel angeschlossen, von dem 3 Leitungen benutzt werden. 5V, Data 
und GND (Schirmung ist ebenfalls an GND).
Am Ende des CAT5 Kabel sind noch 300 nF Blockkondensatoren und von dort 
aus gehen jeweils 3 Leitungen mit ca. 1m zu jeweils einem Sensor.

Beim auslesen der Sensoren (read_meas()) werden immer nur max. 2 
Sensoren erkannt - ganz selten auch Mal alle 3 Sensoren.
Manchmal bekomme ich dabei den Fehler "DS1820: Bus Error" zurück.

Ich habe schon alles ausprobiert. Seitdem ich am Ende des CAT5 einen 
weiteren 4K7 Pullup installiert habe, werden zumindest recht stabil 2 
Sensoren erkannt.

Scheinbar ist es schwierig die Sensoren stabil ausgelesen zu bekommen.
Beitrag "Re: DS1820, DS18B20 in C"
TEMPMES.c : "Es treten gelegentlich Lesefehler auf (Detektor wird nicht 
gefunden)."
Mir ist nicht ganz klar warum hier die Funktion NameValid( char * name ) 
eingeführt worden ist?

Liegt es wirklich nur am Kabel (was kann man hier evtl. ändern)?

Oder kann es auch am Timing liegen?
Ich hatte damals die Warteroutinen in 1wire.c durch delay-Makros 
ersetzt:
1
bit w1_reset(void)
2
{
3
  bit err;
4
5
  W1_OUT &= ~(1<<W1_PIN);
6
  W1_DDR |= 1<<W1_PIN;
7
//   wait_x_075u( 216 );          // 599,5 us
8
  _delay_us(600);
9
  cli();
10
  W1_DDR &= ~(1<<W1_PIN);
11
//   wait_x_075u( 23 );          // 68,75 us
12
  _delay_us(69);
13
  err = W1_IN & (1<<W1_PIN);      // no presence detect
14
  sei();
15
//   wait_x_075u( 136 );          // 379,5 us
16
  _delay_us(380);
17
  if( (W1_IN & (1<<W1_PIN)) == 0 )    // short circuit
18
  err = 1;
19
  return err;
20
}
21
22
23
uchar w1_bit_io( bit b, bit pull )
24
{
25
  cli();
26
  W1_DDR |= (1<<W1_PIN);
27
//   wait_x_1u();            // 1 us
28
//   wait_x_1u();            // 1 us
29
  _delay_us(2);
30
  if( b )
31
  W1_DDR &= ~(1<<W1_PIN);
32
//   wait_x_075u( 0 );    // 7,5 us
33
  _delay_us(8);
34
  if( (W1_IN & (1<<W1_PIN)) == 0 )
35
  b = 0;
36
//   wait_x_075u( 17 );          // 52,25 us -> Gesamtzeit 61,75
37
  _delay_us(52);
38
  if( pull ) {
39
  W1_OUT |= (1<<W1_PIN);
40
  W1_DDR |= (1<<W1_PIN);
41
  } else
42
  W1_DDR &= ~(1<<W1_PIN);
43
  sei();
44
  return b;
45
}

: Bearbeitet durch User
von Karsten W. (lsmod)


Lesenswert?

Dann muss ich meine Frage selber beantworten.

Die hier veröffentlichte Firmware ist leider nur gut für die Ansteuerung 
von einem Sensor.
Beitrag "1Wire-Bus SEARCH ROM missverstanden?"

von Hans Peter (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
ich habe mich dazu entschlossen, nach früheren Gehversuchen in Bascom 
auf die C_ Schiene zu wechseln.
Ich habe es in C noch nicht ans laufen bekommen, hänge Gedanklich noch 
fest.
Wenn ich den Code im Anhang verwende, kann ich auf dem Scope den Reset, 
die Meldung des 1820, Presence-Impuls,und auch meine Anfrage nach hex33 
00110011 auf dem Datenbus sehen.
Nun mein Frage, sollte der 1820 nicht direkt darauf reagieren, und 
hinter meiner Anfrage den ROM Code im Telegramm darstellen??

Um einen Hardwaredefekt auszuschliessen, habe ich die Anwendung in 
Bascom geschrieben, und diese hex mit AVR Studio 4.19  geschossen, 
funktioniert.

Vielen Dank für eure Hilfe.

Schöne Ostertage
Hans Peter

von Hans Peter (Gast)


Lesenswert?

Sorry,
mein Fehler, im Code muss es natürlich (0x33) heissen..
Hans Peter

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.