Forum: Mikrocontroller und Digitale Elektronik ESP32 - IDF: 1-wire DS18B20


von Markus _. (markush)


Lesenswert?

Hi,

ich versuche mich momentan mit einem ESP32 am Auslesen von 1-wire 
Temperatur Sensoren (DS18B20). Das ganze aber nicht mit dem Arduino 
Ökosystem sondern auf Basis der ESO-IDF mit Eclipse als IDE. Ich nutze 
die aktuelle IDF 4.x und das (relativ) neue Eclipse Plugin. Das ganze 
funktioniert soweit wirklich gut und ich habe andere Sachen bereits 
problemlos damit umsetzen können (z.B. wifi, mqtt Verbindung mit tls 
etc.).
Ich möchte mehrere Sensoren an einem Bus (parasitär) betreiben, bin 
aktuell soweit, dass ich die Roms der verschiedenen Sensoren auslesen 
kann. Der bisherige Code dazu (in Ausschnitten):

Romsearch:
1
bool ow_search(){
2
  uint UIbit = 1;
3
  uint UIlastzero = 0;
4
  uint UIrom_byte = 0;
5
  UIrom_byte_mask = 1;
6
7
  if (ow_reset()){
8
    ow_write_byte(ow_SEARCHROM);
9
      do {
10
        Bit1 = ow_read_bit();
11
        Bit2 = ow_read_bit();
12
        printf("" BIT_TO_BINARY_PATTERN, BIT_TO_BINARY(Bit1));    //show bits
13
14
        if ((Bit1 == 1) && (Bit2 == 1)){
15
          return false;    //no device detected
16
          break;
17
        } else {
18
          if (Bit1 != Bit2) {  //devices detect with 0 and 1 in Bit1
19
            UIsearchDirection = Bit1;
20
          } else {      //?
21
          if (UIbit < UIlastDiscrepancy) {
22
            UIsearchDirection = ((rom_id[UIrom_byte] & UIrom_byte_mask) > 0);
23
          } else {
24
            UIsearchDirection = (UIbit == UIlastDiscrepancy);
25
          }
26
          if (UIsearchDirection == 0) {
27
            UIlastzero = UIbit;
28
            if (UIlastzero < 9) {
29
              UIlastfam = UIlastzero;
30
            }
31
          }
32
          }
33
          if (UIsearchDirection == 1) {
34
            rom_id[UIrom_byte] |= UIrom_byte_mask;
35
          } else {
36
            rom_id[UIrom_byte] &= ~(UIrom_byte_mask);
37
          }
38
          ow_write_bit(UIsearchDirection);
39
          UIbit++;
40
          UIrom_byte_mask <<= 1;
41
          if (UIrom_byte_mask == 0) {
42
            UIrom_byte++;
43
            UIrom_byte_mask = 1;
44
          }
45
        }
46
        } while (UIrom_byte < 8);
47
        if (UIbit > 64) {
48
          UIlastDiscrepancy = UIlastzero;
49
          if (UIlastDiscrepancy == 0) {
50
            UIlastDevice = 1;
51
          }
52
          return true;
53
        }
54
    }
55
  return false;
56
}

Das liefert z.B. bei drei Sensoren folgende Ausgabe in der Konsole:
1
 85.0° c0 00 00 00 08 e4 b0 28 
2
 85.0° 07 00 00 00 08 c8 51 28 
3
 85.0° ea 00 00 00 08 cc 05 28
Erstes Byte zeigt 0x28 also korrekte Familie.

Problem nun: Ich bekomme nur eine Temperatur mit einem Sensor angezeigt, 
sobald ein weiterer Sensor dran hängt bekomm ich dauerend die 85.0°.

Abfrage läuft so ab:
1
void ow_print_rom(void){
2
  uint8_t temp[3];
3
  int8_t digit;
4
  int8_t decimal;
5
  UIlastDiscrepancy = 0;
6
  UIlastDevice = 0;
7
  UIlastfam = 0;
8
  UIsearchDirection = 0;
9
10
    if (ow_reset()) {                    //init
11
          ow_write_byte(ow_SKIPROM);            //address all devices
12
          ow_write_byte(ow_CONVERTTEMP);          //temperature measurement
13
              gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);  //strong
14
              gpio_set_level(DS_GPIO, 1);            //pullup
15
              //vTaskDelay(94 / portTICK_RATE_MS);      //conversion time for 9bit
16
              vTaskDelay(750 / portTICK_RATE_MS);        //conversion time for 12bit
17
              //gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT);  //release strong pullup
18
              //ow_reset();                    //init
19
    } else {
20
      printf("Cancel...");
21
    }
22
    //printf("\nTemperaturen: ");
23
24
25
     do {
26
      if (ow_search()) {
27
28
          ow_write_byte(ow_RSCRATCHPAD);
29
          temp[0] = ow_read_byte();
30
          temp[1] = ow_read_byte();
31
32
          digit = temp[0] >> 4;
33
          digit |= (temp[1] & 0x7) << 4;
34
          if (temp[1] & 8){  //negative bit set?
35
              digit = (~(digit - 1)) / 16;
36
          }
37
          if (temp[0] & 8){  //0.5° set?
38
            decimal = 5;
39
          } else{
40
            decimal = 0;
41
          }
42
          printf(" %d.%01u° ", digit, decimal);
43
          //ow_read_temp();
44
45
        printf("%02x ", rom_id[7]);
46
        printf("%02x ", rom_id[6]);
47
        printf("%02x ", rom_id[5]);
48
        printf("%02x ", rom_id[4]);
49
        printf("%02x ", rom_id[3]);
50
        printf("%02x ", rom_id[2]);
51
        printf("%02x ", rom_id[1]);
52
        printf("%02x ", rom_id[0]);  
53
        printf("\n");
54
      } else {
55
        break;
56
      }
57
    } while (UIlastDevice == 0);
58
    /*if (UIlastDevice == 1) {
59
      printf("Last Device!\n");
60
    }*/
61
  printf("\nFertig!\n");
62
}

Wie gesagt, mit einem Sensor passt es. Ich gehe mal von einem 
Timing-Problem aus, ist aber eine reine Vermutung.Verschiedene Werte bei 
den jeweiligen Funktionen (reset, write bit, read bit usw.) habe ich 
schon getestet...

 Hat jemand ne Idee dazu?

Gruß - Markus

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Ändere mal die Reihenfolge für parasite Power, also erst auf high und 
dann auf Ausgang setzen. Sonst hast Du ein kurzes starkes Low auf der 
Leitung.

Kann auch sein, Dein Port ist zu schwach für mehrere Sensoren, 3,3V ist 
ja eh recht knapp. Starte also die Messungen nacheinander mit Wartezeit 
dazwischen.

von Markus _. (markush)


Lesenswert?

Peter D. schrieb:
> Ändere mal die Reihenfolge für parasite Power, also erst auf high und
> dann auf Ausgang setzen. Sonst hast Du ein kurzes starkes Low auf der
> Leitung.

Hallo Peter, also du siehst mich (nicht) mit offener Kinnlade vor dem PC 
sitzen! Das wars in der Tat, getauscht und sofort sind stabile Werte da:
1
23.5° 28 b0 e4 08 00 00 00 c0 
2
22.5° 28 51 c8 08 00 00 00 07 
3
23.0° 28 05 cc 08 00 00 00 ea 
4
22.5° 28 7b 90 08 00 00 00 d5

Eine Frage noch: Kann man sowas am Oszi sehen? Also wenn der 
Signalverlauf da nicht so ist wie es laut Datenblatt sein sollte? Bin am 
überlegen mir was zuzulegen, ich war schon das ein- oder andere Mal in 
so Situationen wo ich den Signalverlauf gern gesehen hätte!?! Und 
vermutlich viel Zeit gespart hätte!

VIELEN DANK!

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.