avatar_Peter

DS1820 liefert falschen Wert

Begonnen von Peter, 16.03.2021, 21:19:34 CET

⏪ vorheriges - nächstes ⏩

Peter

16.03.2021, 21:19:34 CET Letzte Bearbeitung: 16.03.2021, 21:21:28 CET von Peter
Hallo Habe hier einen Temperatursensor (DS1820) der seit Jahren seinen Dienst draussen verrichtet. Nur ab und zu liefert er einen Wert von -0,5 Grad. Habe ihn auch schon esetzt aber immer noch manchmal diesen Fehler. Hänge das Programm mal an, vielleicht findet einer ja was, was da falsch ist.
Ow_Reset(PORTC, 0)                   ' Onewire reset signal
      Ow_Write(PORTC, 0, 0xCC)             ' Issue command SKIP_ROM
      Ow_Write(PORTC, 0, 0x44)             ' Issue command CONVERT_T
      Delay_ms(750)

      Ow_Reset(PORTC, 0)
      Ow_Write(PORTC, 0, 0xCC)             ' Issue command SKIP_ROM
      Ow_Write(PORTC, 0, 0xBE)             ' Issue command READ_SCRATCHPAD

      temp =  Ow_Read(PORTC, 0)
      temp = (Ow_Read(PORTC, 0) << 8) + temp

      Display_Temperature(temp)       
sub procedure Display_Temperature( dim temp2write as word )
const RES_SHIFT = TEMP_RESOLUTION - 8

dim temp_whole as byte
    temp_fraction as word

    text = ""
    ' Check if temperature is negative
    if (temp2write and 0x8000) then
      text[0] = "-"
      temp2write = not temp2write + 1
    end if

    ' Extract temp_whole
    temp_whole = word(temp2write >> RES_SHIFT)

    text[1] = (temp_whole div 10)mod 10 + 48               ' Extract tens digit
    text[2] =  temp_whole mod 10        + 48               ' Extract ones digit

    ' Extract temp_fraction and convert it to unsigned int
    temp_fraction  =  word(temp2write << (4-RES_SHIFT))
    temp_fraction  = temp_fraction and 0x000F
    temp_fraction  = temp_fraction * 625

    ' Convert temp_fraction to characters
    text[3] = word(temp_fraction div 1000)    + 48         ' Extract thousands digit
    'bytetostr (text ,cc)
     fff = text[1]
     fff = fff - 48

     uuu = text[2]
     uuu = uuu - 48

     ttt = text[3]
     ttt = ttt - 48

     vvv = text[0]
end sub

vloki

Der größte Unterschied zu meinem Programm, zu dem ich mich von Nico inspirieren ließ, scheint nur zu sein, dass ich immer alle 9 Bytes des Scratchpads auslese. RES_SHIFT verstehe ich nicht, bzw. scheint mir unnötig zu sein, weil das ist doch vermutlich immer 4, oder? Ich häng mal ein Schnipsel von meinem C-Programm zum Vergleich an:
    LCD_Init();
    LCD_ConstTextOut(0,0,"DS18B20");
    LCD_ConstTextOut(1,0,"   .  ");LCD_CharOut(0x27);LCD_CharOut('C');

//----------------------------------------------------------------------- main()
    while(ds18x20_res()){
        ds18x20_wr(SKIP_ROM);
        ds18x20_wr(CONV_T);
        __delay_ms(750);
        ds18x20_res();
        ds18x20_wr(SKIP_ROM);
        ds18x20_wr(RD_SCRATCH);
//        __delay_ms(1);
        ds18x20_rdTemp();
        if(ds18x20.t_int < 0)
            LCD_ValueOut_00(1,0,ds18x20.t_int,2);
        else
            LCD_ValueOut_00(1,0,ds18x20.t_int,3);
        LCD_ValueOut_00(1,4,ds18x20.t_dec,1);
    }
    LCD_ConstTextOut(1,0," ERROR  ");
    while(1){;}
ds18x20_t ds18x20;
uint8_t ds18x20_data[9];

uint8_t ds18x20_res(void)
{
    uint8_t rec;
    
    DS18X20_OUT = 0;    // set the (I)O to low level
    DS18X20_DIR = 0;    // config as output (-> low)
    __delay_us(480);    // reset pulse >=480 us
    DS18X20_DIR = 1;    // config as input (high-z -> pull up)
    __delay_us(80);
    rec = ~DS18X20_IN;  // read the level (if low, slave available)
    __delay_us(400);    // wait for end of slot
    return (rec);
}

void ds18x20_wr(uint8_t value)
{
    for(uint8_t i = 0; i < 8; i++){
        DS18X20_DIR = 0;
        __delay_us(1);
        if(value & 0x01){ DS18X20_DIR = 1; }
        __delay_us(60);
        DS18X20_DIR = 1;
        value = value >> 1;
    }
}

uint8_t ds18x20_rd(void)
{
    uint8_t value = 0;
    
    for(uint8_t i = 0; i < 8; i++){
        DS18X20_DIR = 0;
        __delay_us(1);
        DS18X20_DIR = 1;
        __delay_us(9);
        value |= DS18X20_IN << i;
        __delay_us(51);             // 60+1 us minimum
    }
    return value;
}

int8_t ds18x20_rdTemp(void)
{
        for(uint8_t i = 0; i < 9; i++){
            ds18x20_data[i] = ds18x20_rd();
        }
        ds18x20.t_int = *(int16_t *)&ds18x20_data[0] >> 4;  
        ds18x20.t_dec = ((ds18x20_data[0] & 0x0F)*10) >> 4;
        if(ds18x20.t_int < 0)
            ds18x20.t_dec = 9 - ds18x20.t_dec;
        return ds18x20.t_int;
}
typedef enum {
    CONV_T          = 0x44,
    RD_SCRATCH      = 0xBE,
    WR_SCRATCH      = 0x4E,
    COPY_SCRATCH    = 0x48,
    RECALL_EE       = 0xB8,
    RD_PWR_SUPLY    = 0xB4,
    SKIP_ROM        = 0xCC,
    FIND_ROM        = 0xF0,
    RD_ROM          = 0x33,
    MATCH_ROM       = 0x55,
    FIND_ALRM       = 0xEC
}DS18x20_Command_t;

typedef struct{
    uint8_t  t_dec;
    int8_t t_int;
}ds18x20_t;

pic18

18.03.2021, 12:52:09 CET #2 Letzte Bearbeitung: 18.03.2021, 12:59:57 CET von pic18
Stimmt das Timing in der Abfrage? Ich meine -0,5°C sind lauter 1er im Datenbyte. Ich finde __delay_us() ist wahrscheinlich zu ungenau

vloki

18.03.2021, 14:22:43 CET #3 Letzte Bearbeitung: 18.03.2021, 14:27:31 CET von vloki
Zitat von: pic18 am 18.03.2021, 12:52:09 CETStimmt das Timing in der Abfrage? Ich meine -0,5°C sind lauter 1er im Datenbyte.
Da könntest du recht habent. Auf jeden Fall ein guter Hinweis!

Die Delay Makros sind eigentlich recht genau. Der Takt sollte natürlich nicht zu niedrig sein und es darf auch kein IR rein funken können.
Zudem tauchen die us Delays nur in meinem Code auf.

pic18


Peter

Hallo
Also der Befehl RES_SHIFT = TEMP_RESOLUTION - 8 ist ein interner Befehl vom
Compiler. Damit wird festgelegt welcher DS18x20 es ist.
Laut Datenblatt braucht der DS18x20 750ms Zeit um die Werte ab zu fragen.
Auf der Platine sitzt noch ein RFM12 B Sender. Ob der den DS18x20 durcheinander
bringt ? Muss ich mal überprüfen.

Peter

So habe nun den Fehler gefunden, warum falsche Werte geliefert werden.
Es liegt wahrhaftig an der Störung des Senders. Der stört nämlich den Controller und
bringt ihn wohl aus dem Takt. Nachdem ich den Controller abgeschirmt hatte, trat das Problem
nicht mehr auf. Dachte nicht das die Pic Controller so empfindlich sind. Aber nun
läuft es so wie es sein soll.
 

picass

Zitat von: Peter am 29.05.2021, 21:47:36 CESTDachte nicht das die Pic Controller so empfindlich sind.
Deine Problemschilderung erinnert mich an ein irgendwie ähnliches Erlebnis beim Experimentieren mit meiner Rollladenschaltung. Die Prototyp-Anlage aus drei Platinen - zwei davon enthalten je einen PIC - funktionierte, will sagen, der Datentransport via Kabel klappte. Aber gelegentlich startete eine Datenübermittlung vom sendenden PIC, obwohl keine Startbedingung (Taste / Portänderung) vorlag. Dann fand ich raus, dass manchmal schon die Annäherung eines Fingers an den Sende-PIC reichte, um den zur Arbeit zu bewegen. Es half da auch nur wenig, mit einer Hand in der Steckdose - also am Erdungsbügel - zu sein, und dieserart "eigentlich" die Elektrostatik ausgebremst zu haben. Dieses Phänomen habe ich noch nicht im Griff, mag sein, dass der nun bevorstehende Einbau in ein Alugehäuse da weiterhilft.
Grüße, picass

vloki

Zitat von: picass am 31.05.2021, 09:19:13 CEST
Zitat von: Peter am 29.05.2021, 21:47:36 CESTDachte nicht das die Pic Controller so empfindlich sind.
... Dann fand ich raus, dass manchmal schon die Annäherung eines Fingers an den Sende-PIC reichte, um den zur Arbeit zu bewegen.
Die MCLR Pins sind aber schon ordentlich beschaltet, bzw. deaktiviert?

Peter

Der MCLR Pin ist über einen Widerstand an Plus verbunden.
Ich glaub auch nicht das der Controller einen Reset macht.

picass

Zitat von: vloki am 01.06.2021, 14:41:50 CESTDie MCLR Pins sind aber schon ordentlich beschaltet, bzw. deaktiviert?
Hoffe, wir kommen hier nicht vom Fredthema ab....wäre wohl besser, einen eigenständigen Fred über Empfindlichkeit zu erstellen. Bis dahin...
Grundsätzliches über die Beschaltung von Port-Pinnen fand ich hier, Zitat aus dem PIC18F14k22-Databook:
-"Each of the PORTA pins has an individually controlled weak internal pull-up. When set, each bit of the WPUA register enables the corresponding pin pull-up. When cleared, the RABPU bit of the INTCON2 register enables pull-ups on all pins which also have their corresponding WPUA bit set. When set, the RABPU bit disables all weak pull-ups. The weak pull-up is automatically turned off when the port pin is configured as an output. The pull-ups are disabled on a Power-on Reset."
und
-"MCLR : Active low Master Clear with internal pull-up"

Dazu gibts noch einen Ausschnitt - Text und Bild - aus dem Microchip MPLAB X PICkit 3 User's Guide, in welcher ein extra montierter R zu sehen ist. Der ist in nachfolgender Beschreibung noch mal erwähnt als "Irgendwas in der Größe um 10 kO".
---------------
In meiner Schaltung hatte ich diesen extra-(pull-up)Widerstand an der Vpp/MCLR-Leitung noch nicht installiert. Zudem sind im Programm die Pull-Ups (WPUA-Register) alle abgeschaltet.
Grüße, picass

Schnellantwort

Name:
E-Mail:
Verifizierung:
Bitte lassen Sie dieses Feld leer:
Geben Sie die Buchstaben aus dem Bild ein
Buchstaben anhören / Neues Bild laden

Geben Sie die Buchstaben aus dem Bild ein:

Shortcuts: mit Alt+S Beitrag schreiben oder Alt+P für Vorschau

------------

Impressum Datenschutz