Suche 1-Wire Treiber fürs Auslesen von DS18B20 Sensoren

DS18B20 Treiber

  • 1
  • 2
  • 3
  • Page 2 of 3
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2123
Registered: 03 / 2003
Subject:

Re: Suche 1-Wire Treiber fürs Auslesen von DS18B20 Sensoren

 · 
Posted: 21.08.2024 - 14:59  ·  #9
Ich denke mal Roy möchte mehrere an einem Portpin haben?

Gruss
Harry
Roy
Benutzer
Avatar
Gender:
Age: 68
Posts: 24
Registered: 07 / 2024
Subject:

Re: Suche 1-Wire Treiber fürs Auslesen von DS18B20 Sensoren

 · 
Posted: 22.08.2024 - 10:22  ·  #10
Hallo Golf, Harry,
so isses, ich möchte die - momentan 3 - DS18B20 als 1-Wire auf einen Pin verschalten, bei mir mit Spannungsversorgung - also 3 Leitungen, +5V, GND und Daten.
Dank Golfs Code weiss ich nun aber erstmal, wie ich die Hex-Befehle CC, 55 etc. (siehe Datasheet DS18B20) an die Sensoren schicke.
Zum Thema 1-Wire Implementierung gibt es einen sehr ausführlichen Beitrag unter
https://www.kampis-elektroecke…r-den-avr/
mit dem kompletten Code unter
https://github.com/Kampi/AVR/c…3c6036b0f6
( "source/Interfaces/OneWire/OneWire.c" suchen )
leider in "C" geschrieben - kann ich nicht :-(
Wenn das ein Kundiger mal in Pascal übersetzen würde...

Im Moment versuche ich erstmal, die einfachsten Behehlssequenzen (Impulsfolgen), Reset u.s.w., nachzubilden...
Das gemeine ist, das es für z.B. "BASCOM" und für den Arduino fertig implantierte Protokolle gibt, da kann man sich nur nichts abschauen.

Grüße
Roy
wilbo
Benutzer
Avatar
Gender:
Age: 68
Posts: 34
Registered: 11 / 2023
Subject:

Re: Suche 1-Wire Treiber fürs Auslesen von DS18B20 Sensoren

 · 
Posted: 22.08.2024 - 13:51  ·  #11
Hallo Roy (Harry,Golf),

Ich habe mich damit auch schon mal befasst. Sollte mal eine Heizungssteuerung werden hat sich dann aber erledigt.
Ich würde mir bei drei mal DS18B20 das mit einem Pin noch einmal überlegen, denn dann gibt es nur die Möglichkeit das über die ID des jeweiligen Sensors eine Zuordung zur Meßstelle zu machen. Das geht nur z.b. über ein Array im Flash/EEPROM und im falle eines Sensordefekts wärst du vermutlich der einzige der diesen wechseln könnte. Im Anhang mal meine damaligen Versuche evtl. ist die CRC - Prüfung da ganz nützlich (entstamt aber nicht von mir aber ist korrekt).

Gruß wilbo

Code
Program Heizung;

{.$NOSHADOW}
{ .$WG}                     {global Warnings off} 

Device = mega328, VCC = 5; 
{ $BOOTRST $00C00}         {Reset Jump to $00C00} 

Import SysTick, I2CPort, LCDport;

From System Import Float; 


Define
  ProcClock      = 8000000;       {Hertz} 
  SysTick        = 10;             {msec} 
  StackSize      = $0032, iData; 
  FrameSize      = $0032, iData; 
  LCDport        = LcdUserPort; 
  LCDtype        = 44780;             {66712} 
  LCDrows        = 4;                 {2 rows}
  LCDcolumns     = 20;                {20 chars per line} 
  I2Cport        = PortC;{use port C} 
  I2Cclk         = 1;{clock-pin = port C bit 1} 
  I2Cdat         = 2;{data-pin = port C bit 2} 

Uses PCF8574_I2C_LCDIOS; // Oder je nach Anschluss PCF8574_TWI_LCDIOS (nicht getestet!!!) 
Implementation

{$IDATA}

{--------------------------------------------------------------} 
{ Type Declarations } 

Type
  
  
{--------------------------------------------------------------} 
{ Const Declarations } 
Const
  //dwArr        : array[0..6] of string[2]= 
  //('Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'); 
  
  DS1            : Table[0..7] Of Byte = ($10, $8F, $12, $24, $01, $08, $00, $69); 
  SP             : Byte                = 1; 
  SP2            : Byte                = 1;
  RWSlot         : Byte                = 80; 
  LP             : Byte                = 55; 
{--------------------------------------------------------------} 
{ Var Declarations } 
{$IDATA}
Var
  Y, X : Byte; 
  crc1, crc2, nc1, nc2, MC : Longint; 
  DSTimer : Byte; 
  KSTemp : Float;                    // Kesseltemperatur 
  SPTemp : Float;                    // Speichertemperatur 
  get  : Array[0..8] Of Byte; 
  Convblock : Boolean;               // Convert in OneSecond Blocken 
  DS1PORT[@Portb, 0] : Bit; 
  DDS1PORT[@DDRB, 0] : Bit; 
  DS1INP[@PINB, 0] : Bit; 
  DS2PORT[@Portb, 1] : Bit; 
  DDS2PORT[@DDRB, 1] : Bit; 
  DS2INP[@PINB, 1] : Bit; 
  LED[@Portc, 5] : Bit; 
  DDLED[@DDRc, 5] : Bit; 
  TS[@Portd, 2] : Bit; 
  DDTS[@DDRd, 2] : Bit; 
  TSINP[@PINd, 2] : Bit; 
  MyTemp : Float; 
  tf   : Float; 
  TB   : int8; 
  Oldsecond : Byte; 
  
{--------------------------------------------------------------} 
{ functions } 
//------------------------------------------------------------------------------ 
Function OneWireReset(DSPORT : Byte) : Boolean; 
Begin
  DisableInts; 
  Case DSPORT Of 
    1 : 
        DDS1PORT := 1; //port is output 
        DS1PORT := 1;    //port is high 
      |
    2 : 
        DDS2PORT := 1; //port is output 
        DS2PORT := 1;    //port is high 
      |
  Endcase; 
  uDelay_1(RWSlot);   // wait 60us 
  Case DSPORT Of 
    1 : 
        DS1PORT := 0;    //port is low 
      |
    2 : 
        DS2PORT := 0;    //port is low 
      |
  Endcase; 
  uDelay(LP);     //wait 480 us 
  Case DSPORT Of 
    1 : 
        DDS1PORT := 0;   // port is input 
        DS1PORT := 1;    // pullup on 
      |
    2 : 
        DDS2PORT := 0;   // port is input 
        DS2PORT := 1;    // pullup on 
      |
  Endcase; 
  uDelay_1(RWSlot);   // wait 60us 
  Case DSPORT Of 
    1 : 
        Return(Not DS1INP); 
      |
    2 : 
        Return(Not DS2INP); 
      |
  Endcase; 
  ENABLEINTS; 
End; 
//------------------------------------------------------------------------------ 
Procedure OneWireWrite_1_Bit(DSPORT : Byte); 
Begin
  DisableInts; 
  Case DSPORT Of 
    1 : 
        DS1PORT := 0; 
        DDS1PORT := 1; 
        uDelay_1(SP); 
      |
    2 : 
        DS2PORT := 0; 
        DDS2PORT := 1; 
        uDelay_1(SP2); 
      |
  Endcase; 
  Case DSPORT Of 
    1 : 
        DDS1PORT := 0; 
        DS1PORT := 1; 
      |
    2 : 
        DDS2PORT := 0; 
        DS2PORT := 1; 
      |
  Endcase; 
  uDelay_1(RWSlot);  //timeslot = 60us 
  ENABLEINTS; 
End; 
//------------------------------------------------------------------------------ 
Procedure OneWireWrite_0_Bit(DSPORT : Byte); 
Begin
  DisableInts; 
  Case DSPORT Of 
    1 : 
        DS1PORT := 0; 
        DDS1PORT := 1; 
      |
    2 : 
        DS2PORT := 0; 
        DDS2PORT := 1; 
      |
  Endcase; 
  uDelay_1(RWSlot);  //timeslot = 60us 
  Case DSPORT Of 
    1 : 
        DDS1PORT := 0; 
        DS1PORT := 1; 
      |
    2 : 
        DDS2PORT := 0; 
        DS2PORT := 1; 
      |
  Endcase; 
  ENABLEINTS; 
End; 
//------------------------------------------------------------------------------ 
Function OneWireReadBit(DSPORT : Byte) : Boolean;
Begin
  DisableInts; 
  Case DSPORT Of 
    1 : 
        DS1PORT := 0; 
        DDS1PORT := 1; 
        uDelay_1(SP); 
      |
    2 : 
        DS2PORT := 0; 
        DDS2PORT := 1; 
        uDelay_1(SP2); 
      |
  Endcase; 
  Case DSPORT Of 
    1 : 
        DDS1PORT := 0; 
        DS1PORT := 1; 
        uDelay_1(SP); 
      |
    2 : 
        DDS2PORT := 0; 
        DS2PORT := 1; 
        uDelay_1(SP2); 
      |
  Endcase; 
  ENABLEINTS; 
  Case DSPORT Of 
    1 : 
        Return(DS1INP); 
      |
    2 : 
        Return(DS2INP); 
      |
  Endcase; 
End; 
//------------------------------------------------------------------------------
Procedure OneWireWriteByte(DSPORT : Byte; C : Byte); 
Var
  X   : Byte; 
Begin
  For X := 0 To 7 Do 
    If Bit(C, X) Then 
      OneWireWrite_1_Bit(DSPORT); 
    Else 
      OneWireWrite_0_Bit(DSPORT); 
    Endif; 
    uDelay_1(2); 
  Endfor; 
End; 
//------------------------------------------------------------------------------ 
Function OneWireReadByte(DSPORT : Byte) : Byte; 
Var
  X, D   : Byte; 
Begin
  For X := 0 To 7 Do 
    If OneWireReadBit(DSPORT) Then 
      INCL(D, X); 
    Else 
      EXCL(D, X); 
    Endif; 
    uDelay_1(RWSlot);  //timeslot = 60us 
  Endfor; 
  Return(D); 
End; 
//------------------------------------------------------------------------------ 
Function ReadTemperature : Byte; 
Var
  temp_lsb, temp_msb   : Byte; 
  k                    : Byte; 
  Temp                 : Word; 
Begin
  temp_msb := get[1];// Sign byte + lsbit 
  temp_lsb := get[0];// Temp data plus lsb 
  Hi(Temp) := temp_msb; 
  Lo(Temp) := temp_lsb; 
  Temp := Temp Shr 4; // 1C Auflösung 
  Return(Lo(Temp)); 
End ReadTemperature; 
//------------------------------------------------------------------------------ 
Procedure ReadScratchpad(DSPORT : Byte); 
Var
  k              : Byte; 
Begin
  OneWireReset(DSPORT); 
  uDelay(5); 
  OneWireWriteByte(DSPORT, $CC);  //Skip ROM 
  OneWireWriteByte(DSPORT, $BE);  // Read Scratch Pad 
  For k := 0 To 8 Do 
    get[k] := OneWireReadByte(DSPORT); 
  Endfor; 
End ReadScratchpad; 
//------------------------------------------------------------------------------ 
Procedure ReadRom(DSPORT : Byte); 
Var
  k              : Byte; 
Begin
  OneWireWriteByte(DSPORT, $33);  // Read Rom 
  For k := 0 To 7 Do 
    get[k] := OneWireReadByte(DSPORT); 
  Endfor; 
End ReadRom; 
//------------------------------------------------------------------------------ 
Function Calccrc : Byte; 
Const
  Poly           : Byte      = $8C; 
  
Var
  CRC            : Byte; 
  I, j           : Integer; 
  Result         : Byte; 
Begin
  CRC := 0; 
  For I := 0 To 7 Do 
    CRC := CRC Xor get[I]; 
    For j := 1 To 8 Do 
      If odd(CRC) Then 
        CRC := (CRC Shr 1) Xor Poly; 
      Else CRC := CRC Shr 1; 
      Endif; 
    Endfor; 
  Endfor; 
  Return(CRC); 
End; 

//------------------------------------------------------------------------------ 
Procedure Onsystick(SaveAllRegs); 
Begin
  If DSTimer > 0 Then 
    Dec(DSTimer); 
  Else 
    Convblock := False; 
  Endif; 
End; 
//------------------------------------------------------------------------------ 
Procedure ReadDS;
Begin
  ReadScratchpad(1); 
  If Calccrc = get[8] Then 
    TB := Int8(ReadTemperature); 
    tf := Float(get[7] - get[6]); 
    KSTemp := Float(TB - 0.25) + (tf / Float(get[7])); 
  Else 
    INC(crc1); 
  Endif; 
  
  ReadScratchpad(2); 
  If Calccrc = get[8] Then 
    TB := Int8(ReadTemperature); 
    tf := Float(get[7] - get[6]); 
    SpTemp := Float(TB - 0.25) + (tf / Float(get[7])); 
  Else 
    INC(crc2); 
  Endif; 
End; 
//------------------------------------------------------------------------------
Procedure Startconv;
Begin
  If OneWireReset(1) Then 
    uDelay_1(RWSlot); 
    OneWireWriteByte(1, $CC);    // Skip ROM 
    OneWireWriteByte(1, $44);    // Start Convert 
  Else 
    INC(nc1); 
  Endif; 
  
  If OneWireReset(2) Then 
    uDelay_1(RWSlot); 
    OneWireWriteByte(2, $CC);    // Skip ROM 
    OneWireWriteByte(2, $44);    // Start Convert 
  Else 
    INC(nc2); 
  Endif; 
  DSTimer := 85;            // at 10ms Systick 800 mS for Convert 
  Convblock := True; 
  Inc(MC); 
End; 

{--------------------------------------------------------------} 
{ Main Program } 
{$IDATA}

Begin
  ENABLEINTS; 
  init_lcd($27); 
  BL_On;
  lcdcursor(False, False); 
  lcdclr; 
  LCDCharSet(#2, $00, $08, $03, $04, $04, $04, $03, $00); 
  lcdxy(0, 0); 
  Convblock := True;
  crc1 := 0; 
  crc2 := 0; 
  nc1 := 0; 
  nc2 := 0; 
  MC := 0; 
  DDLED := 1; 
  KSTemp := 0;
  Convblock := True; 
  DSTimer := 0; 
  
  OneWireReset(1);
  uDelay_1(RWSlot); 
  OneWireWriteByte(1, $CC);  // Skip ROM 
  OneWireWriteByte(1, $44);  // Start Conversion 
  OneWireReset(2); 
  OneWireWriteByte(2, $CC);  // Skip ROM
  OneWireWriteByte(2, $44);  // Start Conversion 
  MDelay(255); 
  lcdclr; 
  DSTimer := 85;
  Loop
      lcdxy(2, 0);
      Write(LCDOUT, LongToStr(MC : 6)); 

    If Convblock = False Then 
      Readds; 
      Led := False;
    Endif; 
    mDelay(100);
    If ((DSTimer = 0)) Then
      lcdxy(0, 1);
      Write(LCDOUT, 'TK:' + IntToStr(Round(KSTemp) : 5));
      LCDOUT(#2);
      lcdxy(10, 1);
      Write(LCDOUT, 'TS:' + IntToStr(Round(SPTemp) : 5));
      LCDOUT(#2);
      lcdxy(0, 2);
      Write(LCDOUT, 'CRC: '); // CRC Fehler
      Write(LCDOUT, LongToStr(crc1 : 6));
      Write(LCDOUT, LongToStr(crc2 : 6));
      lcdxy(0, 3);
      Write(LCDOUT, 'NC : '); // No Connect Fehler
      Write(LCDOUT, LongToStr(nc1 : 6));
      Write(LCDOUT, LongToStr(nc2 : 6));
    Endif;

    If ((Convblock = False)) Then
      Startconv
      ; 
      LED := True;
    Endif; 
    
  Endloop;
End Heizung.

You must be logged in or your permissions are to low to see this Attachment(s).
Roy
Benutzer
Avatar
Gender:
Age: 68
Posts: 24
Registered: 07 / 2024
Subject:

Re: Suche 1-Wire Treiber fürs Auslesen von DS18B20 Sensoren

 · 
Posted: 22.08.2024 - 20:09  ·  #12
Hallo Wilbo,
ihr (Golf und Du) habt ja einiges an Code gebaut - alle Achtung.
Zwei Fragen sind gleich am Anfang aufgetaucht:
- ist die Temperaturumrechnung für den DS18B20 oder DS1820? - wie ich mitbekommen habe müssen die unterschiedlich ausgewertet werde)n
- und 2. (schäme mich) - kannst Du mir mal das get[irgendwas] z.B. in
For k := 0 To 7 Do
get[k] := OneWireReadByte(DSPORT);
Endfor;
erklären?

Grüsse
Roy
golf
Benutzer
Avatar
Gender:
Location: Donauwörth
Age: 71
Posts: 256
Registered: 11 / 2009
Subject:

Re: Suche 1-Wire Treiber fürs Auslesen von DS18B20 Sensoren

 · 
Posted: 23.08.2024 - 07:38  ·  #13
Hallo Roy,
ich meine, das war bei mir der 18B20.
Aber ich hab das damals auf die Schnelle für jemanden gemacht und das Alles weitergegeben.
Ich hab momentan keine Sensoren mehr hier und kann im Moment nicht viel weiter beitragen.

Gruß

golf

übrigens:
dieses get ist ein array im source von wilbo: get : Array[0..8] Of Byte;
Roy
Benutzer
Avatar
Gender:
Age: 68
Posts: 24
Registered: 07 / 2024
Subject:

Re: Suche 1-Wire Treiber fürs Auslesen von DS18B20 Sensoren

 · 
Posted: 23.08.2024 - 19:47  ·  #14
Quote
übrigens:
dieses get ist ein array im source von wilbo: get : Array[0..8] Of Byte;


Da ist es wieder: "Wer lesen kann ist klar im Vorteil" ;-)
Danke.

Grüsse
Roy
wilbo
Benutzer
Avatar
Gender:
Age: 68
Posts: 34
Registered: 11 / 2023
Subject:

Re: Suche 1-Wire Treiber fürs Auslesen von DS18B20 Sensoren

 · 
Posted: 27.08.2024 - 19:57  ·  #15
Hallo Roy,
leider komme ich durch einen Arbeitsurlaub erst jetzt dazu mich zu melden. Wie Golf schon geschrieben hat ist Get ein Array in dem die Antworten des Sensor zur weiteren verabeitung gespeichert werden. Bei mir sind es auch "DS18B20" gewesen. Wenn du noch Fragen hast melde dich und ich werde versuchen etwas zeitnäher zu antworten.

Gruß wilbo
Roy
Benutzer
Avatar
Gender:
Age: 68
Posts: 24
Registered: 07 / 2024
Subject:

Re: Suche 1-Wire Treiber fürs Auslesen von DS18B20 Sensoren

 · 
Posted: 29.08.2024 - 19:45  ·  #16
Hallo Wilbo, Golf,
kein Problem Wilbo, ich bin seit Tagen (immer mal 1 Stunde abends, u.a. wegen Gartenarbeit) dabei, mir die Programmteile zur Kommunikation mit dem DS18B20 auf "1-Wire Art" zusammenzubauen.
Stand jetzt: Ich kann mich mit einem einzelnen Sensor "unterhalten", d.h. ROM-ID ,Scratchpad und Temperatur auslesen - auch dank Eurem Code.
Die Suche und Identifikation aller am Bus beteiligten Sensoren und das abspeichern der einzelnenen ROM-IDs ist aber noch ein "dickeres Brett", mit dem ich jetzt kämpfe.
Wenn ich zählbares habe zeige ich's hier.

Grüsse
Roy
  • 1
  • 2
  • 3
  • Page 2 of 3
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 15 · Cache Hits: 14   140   154 · Page-Gen-Time: 0.032341s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI