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