Forum: Mikrocontroller und Digitale Elektronik Ds18B20 Zeigt zu höhe Werte


von Dennis T. (dennist92)


Lesenswert?

Ich habe einen mega328p mit einem DS18B20 Programmiert, die 
Temperaturausgabe geschieht über ein LCD Display. Anfangs habe ich es 
nicht hinbekommen, dass die Temperatur ausgegeben wird, der Sensor hat 
aber reale Werte geliefert, ca. 0x16B. Nun habe ich es hinbekommen, dass 
die Temperatur ausgegeben wird, aber nun gibt der Sensor mir einen Welt 
von 0x6D2 also über 100 Grad. Wo liegt der Fehler?
DS.c Datei
1
int ds_readtemp(){  
2
  ds_masterreset();
3
  ds_command(DS_SKIPROMCOMMAND);
4
  ds_command(DS_CONVERTTEMP);
5
  _delay_ms(DS_WAIT_MS);
6
  ds_masterreset();
7
  ds_command(DS_SKIPROMCOMMAND);
8
  ds_command(DS_READSCRATCH);
9
  uint8_t temp1 = ds_readbyte();
10
  uint8_t temp2 = ds_readbyte();
11
  int out = ((temp2) * 256) + temp1;
12
  return out;
13
}
14
int ds_readbit(){
15
  ds_out();
16
  DS_PORT &= ~(1 << DS_PIN);
17
  ds_in();
18
  _delay_us(1);
19
  if (PINC & (1 << DS_PIN)){
20
    return 1;
21
  }
22
  return 0;
23
} 
24
int ds_readbyte(){
25
  int i;
26
  int i_byte = 0;
27
  for (i = 0; i < 8; i++){
28
    i_byte += (ds_readbit() << i);
29
  }
30
  return i_byte;
31
}
hier habe ich eigentlich nur die letzten 2 Zeilen in ds_readtemp 
geändert, diese haben aber mit dem auslesen an sich eigentlich nichts 
zutun.

von (prx) A. K. (prx)


Lesenswert?

Das Timing stimmt nicht.

von (prx) A. K. (prx)


Lesenswert?

Ist hier wohl kein Problem, aber generell zum Umgang mit dem I/O-Pin bei 
separat versorgtem Sensor, also nicht parasitär über die Datenleitung: 
Bit im Output-Register einmalig auf 0 setzten und dann dabei belassen. 
Danach nur noch mit dem Bit in im Direction-Register spielen.

von Dennis T. (dennist92)


Angehängte Dateien:

Lesenswert?

Timings habe ich mit einem Logicanalyzer gecheckt, funktioniert 
eigentlich.

von Dennis T. (dennist92)


Lesenswert?

I/O Funktionen sehen so aus.
1
void ds_out(){
2
  DS_DDR |= (1 << DS_PIN);
3
  DS_PORT |= (1 << DS_PIN);
4
}
5
void ds_in(){
6
  DS_DDR &= ~(1 << DS_PIN);
7
  DS_PORT |= (1 << DS_PIN);
8
}

von (prx) A. K. (prx)


Lesenswert?

Lesen: Pin kurz aktiv auf Low ziehen, min 1µs max wenige µs, und nach 
15µs auslesen. Die 15µs sehe ich im Code nicht.

von (prx) A. K. (prx)


Lesenswert?

Dennis T. schrieb:
> I/O Funktionen sehen so aus.

Ausser bei parasitärer Versorgung darf der Portpin nie auf High 
gezogen werden. Das macht der externe Pullup-Widerstand. Der interne 
Pullup ist zu hochohmig.

von Dennis T. (dennist92)


Lesenswert?

das Auslesen klappt auch bei 1us, aber man sieht auch im Logicanalyzer, 
dass der falsche Werte gibt.

von (prx) A. K. (prx)


Lesenswert?

Mit einem LA-Shot ohne Zeitachse kann ich nichts anfangen. Und wenn der 
Hersteller 15µs dranschreibt, dann verwendet man auch 15µs. Allerdings 
insgesamt, d.h. die unbekannte Laufzeit vom Code ist mit im Spiel.

von Dennis T. (dennist92)


Lesenswert?

(prx) A. K. schrieb:
> Der interne
> Pullup ist zu hochohmig.
Also bei in und out die 2th Zeile entfernen?

von (prx) A. K. (prx)


Lesenswert?

In dieser Phase ist übrigens ein Oszi besser als ein LA. Erst einmal 
sollten Timing und Pegel stimmen. Daten kommen später.

Was liest du, wenn nach Powerup des Sensors keine Messung erfolgt? Da 
müssen 85°C rauskommen.

von (prx) A. K. (prx)


Lesenswert?

Dennis T. schrieb:
> Also bei in und out die 2th Zeile entfernen?

Korrekt.

von Dennis T. (dennist92)


Lesenswert?

Habe ich noch nicht getestet, ohne Messung

von (prx) A. K. (prx)


Lesenswert?

Dennis T. schrieb:
> das Auslesen klappt auch bei 1us, aber man sieht auch im Logicanalyzer,
> dass der falsche Werte gibt.

Findest du nicht, dass der Satz sich selbst widerspricht?

von Dennis T. (dennist92)


Angehängte Dateien:

Lesenswert?

Die Auslesezeit ist ja in erster Linie nicht wichtig, da ob ich auslese, 
oder nicht der DS die Werte überträgt, nun habe ich den internen Pullup 
weg gelassen, und der DS sendet keine ganzen Pakete mehr?

von Dennis T. (dennist92)


Angehängte Dateien:

Lesenswert?

Rot sind die Timings des DS

von Wolfgang (Gast)


Lesenswert?

Dennis T. schrieb:
> Screenshot_2021-08-27_194122.png
> Rot sind die Timings des DS

Kannst du vielleicht mal eine ganz normale Zeitachse an das Zeitdiagramm 
vom LA packen oder die Daten wenigsten in nutzbarer Form anhängen?

Wer soll sich denn durch den Pixelsalat durchfummeln?

von Dennis T. (dennist92)


Angehängte Dateien:

Lesenswert?

Leider kann ich nicht alle Zeiten anzeigen lassen, sorry bin noch 
relativ neu in der Materie.

von Jack V. (jackv)


Lesenswert?

Statt die Leute immer wieder mit unhandlichen und unnötigen Bildern zu 
beglücken, könntest du einfach die Aufnahme des LA in einem der dafür 
üblichen Formate speichern, und diese Datei mit den Daten hier anhängen. 
Da sind dann alle Informationen drin, und jeder kann sie sich so 
anschauen, wie er es braucht.

von Dennis T. (dennist92)


Angehängte Dateien:

Lesenswert?

Hier im CSV format

von (prx) A. K. (prx)


Lesenswert?

Jack V. schrieb:
> Statt die Leute immer wieder mit unhandlichen und unnötigen Bildern zu
> beglücken

Was hast du gegen die linke Seite? Etwas zu viel Photoshop vielleicht.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Screenshots von einzelnen Fenstern macht man mit Strg-Druck. Oder mit 
dem Snipping Tool.

von MaWin (Gast)


Lesenswert?

Dennis T. schrieb:
> ich eigentlich nur die letzten 2 Zeilen in ds_readtemp geändert

Du hast also das Programm aus einer anderen Quelle geholt, und dort 
funktioniert es (angeblich).
Dieselbe Taktfrequenz ?

Auf der einen Seite gibt es DS_PORT, auf der anderen PINC, ist DS_PORT 
auch PORTC, oder geändert ? (scheiss Definitionen).

von Dennis T. (dennist92)


Lesenswert?

ne, die Lib habe ich selber erstellt, habe da keine gefunden.
1
// PIN
2
#define DS_DDR      DDRC
3
#define DS_PORT      PORTC
4
#define DS_PIN      0

von (prx) A. K. (prx)


Lesenswert?

Dennis T. schrieb:
> ne, die Lib habe ich selber erstellt, habe da keine gefunden.

Beitrag "DS1820, DS18B20 in C"

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

Dennis T. schrieb:
> Leider kann ich nicht alle Zeiten anzeigen lassen, sorry bin noch
> relativ neu in der Materie.

Und in der Pupertät hängen geblieben ;-)

von Falk B. (falk)


Lesenswert?

Dennis T. schrieb:
> ne, die Lib habe ich selber erstellt, habe da keine gefunden.

Ja klar, es hat ja auch noch niemals eine Onewire Bibliothek ins 
Internet gestellt. OMG!

Beitrag "Re: Onewire + DS18x20 Library"

Profitipp: Wenn man die CRC-Prüfung der Daten macht, erkennt man 
Übertragungsfehler.

von Dennis T. (dennist92)


Lesenswert?

Falk B. schrieb:
> Und in der Pupertät hängen geblieben ;-)

und warum dies?

von Lutz (Gast)


Lesenswert?

Weil du nebenbei ein Foto deiner viel älteren Schwester mitgeschickt 
hast...

von Lutz (Gast)


Lesenswert?

Und nun schau dir endlich das 1Wire-Protokoll an. Wie ist ein 1 codiert, 
wie eine 0.

von Dennis T. (dennist92)


Lesenswert?

Das Schaue ich mir später an, habe erst heute Abend wieder Zeit. Nein 
das ist nicht meine Schwester ;) Seltsamer Weise läuft der DS18 nun 
wieder.

von Wolfgang (Gast)


Lesenswert?

Dennis T. schrieb:
> Seltsamer Weise läuft der DS18 nun wieder.

Steckbrettaufbau?

von Lutz (Gast)


Lesenswert?

Dann macht _delay_us(1); definitiv nicht das, was man vermutet!

von Dennis T. (dennist92)


Angehängte Dateien:

Lesenswert?

Ich habe mal mein komplettes Projekt hier hoch geladen. es läuft Aktuell 
und zeigt die Temperatur an. Nicht über die F_CPU und die Delaywerte 
wundern, diese sind alle Kalibriert, klar wären Korrekte werte besser, 
habe aber irgendwelche Probleme mit den Fuses. Hier sind meine Fuses 
E:07, H:D9, L:57

von Falk B. (falk)


Lesenswert?

Dennis T. schrieb:
> Ich habe mal mein komplettes Projekt hier hoch geladen. es läuft Aktuell
> und zeigt die Temperatur an. Nicht über die F_CPU und die Delaywerte
> wundern, diese sind alle Kalibriert, klar wären Korrekte werte besser,
> habe aber irgendwelche Probleme mit den Fuses. Hier sind meine Fuses
> E:07, H:D9, L:57

Naja, da gibt es "einiges" an Verbesserungspotential.
1
void ds_command(uint8_t command){
2
  int i;
3
  for (i = 0; i < 8; i++){
4
    ((command >> i) % 2) == 0 ? ds_writezero() : ds_writeone();
5
  }
6
}

Was soll das? Erstens ist eine variable Verschiebung  >> i relativ 
aufwändig und 2. sinnlos. Ein Modulo 2 ist es umso mehr. Akademischer 
und weltfremder geht es kaum. Das Ganze garniert mit dem ? Operator, den 
man so eher sparsam nutzen sollte. Ein schnödes if() tut es auch und ist 
besser lesbar.

Solche Sachen man man besser mit einer Maske und Bitmanipulation. 
Deutlich einfacher lesbar und deutlich performanter.

Deine Funktionen void ds_writezero(), void ds_writeone() ds_out() und 
ds_in() sind auch vollkommen akademisch aufgeblasen.

>Nicht über die F_CPU und die Delaywerte
>wundern, diese sind alle Kalibriert, klar wären Korrekte werte besser,
>habe aber irgendwelche Probleme mit den Fuses. Hier sind meine Fuses
>:07, H:D9, L:57

Dann löse zuerst diese Probleme, denn sonst wird dein Chaos noch größer!
Schreib ein Programm mit einem definierten Puls, z.B. 1ms, schau ihn dir 
mit dem Oszi oder Logikanaylsator an und stell deinen Fuses bzw. den 
RC-Oszillator so ein, daß er ausreichend genau 1ms erzeugt.
Hast du die Optimierung beim Compiler eingeschaltet? Ohne diese 
funktionieren diese Funktionen nicht!

: Bearbeitet durch User
von Dennis T. (dennist92)


Lesenswert?

1
 for (i = 0; i < 8; i++){
2
    if((command >> i) % 2) == 0){
3
      ds_writezero();
4
    }else{
5
      ds_writeone();
6
    }
7
  }
und wie kann ich nun eine Maske und Bitmanipulation anwenden? habe nicht 
viel C Erfahrung, dazu kommt, dass die Digitaltechnik noch sehr neu ist. 
Es würde auch guter Lesestoff, oder Videos helfen. Dieses Thema schweift 
ja nun eigentlich sehr vom Topic ab :)

Danke euch übrigens sehr für eure Hilfe :)

von Stefan F. (Gast)


Lesenswert?

Falk hat Recht. Zumindest bei AVR Mikrocontrollern sind Shift 
Operationen mit einer Variablen Anzahl von Schritten ziemlich 
ineffizient.

Vorher:
1
void ds_command(uint8_t command){
2
  int i;
3
  for (i = 0; i < 8; i++){
4
    ((command >> i) % 2) == 0 ? ds_writezero() : ds_writeone();
5
  }
6
}

Verbesserung:
1
void ds_command(uint8_t command){
2
  int i;
3
  for (i = 0; i < 8; i++){
4
    if (command & 1) {
5
      ds_writeone();
6
    }
7
    else {
8
      ds_writezero();
9
    }
10
    command = command >> 1;
11
  }
12
}

von Falk B. (falk)


Lesenswert?

Dennis T. schrieb:
> und wie kann ich nun eine Maske und Bitmanipulation anwenden? habe nicht
> viel C Erfahrung, dazu kommt, dass die Digitaltechnik noch sehr neu ist.
> Es würde auch guter Lesestoff,

Ja, siehe Bitmanipulation bzw. mein Projekt.

https://www.mikrocontroller.net/topic/goto_post/4890827

> oder Videos helfen.

Nö. Du bist ein Millenial, welcher glaubt, die Welt kann vor allem mit 
"Tutorials" und Youtube-Videos erklärt werden. Dem ist nicht so. In 
vielen Fällen sind einfache Texte, sei es auf Papier oder elektronisch 
einem Video überlegen.

> Danke euch übrigens sehr für eure Hilfe :)

Was hast du gelernt? Wo lag der Fehler? Wie hast du ihn erkannt? Wie 
hast du ihn behoben?

von Vorn N. (eprofi)


Lesenswert?

>for (i = 0; i < 8; i++){
>    if((command >> i) % 2) == 0){
>      ds_writezero();
>    }else{
>      ds_writeone();
>    }
>  }
Das geht eleganter (mask ist zugleich Bitmaske und Zähler):
1
mask = 0x80;do{
2
  if(command & mask) ds_writeone(); else ds:writezero();}
3
  while(mask/=2);
4
5
oder gleich:
6
mask = 0x80; do ds_write(command & mask) while(mask/=2);

> Es würde auch guter Lesestoff, oder Videos helfen.
Das Internet enthält genug gute Beispiele, aus denen man viel lernen 
kann.
Die Kunst ist, die Qualität der Beiträge zu bestimmen.

von Falk B. (falk)


Lesenswert?

Vorn N. schrieb:
> Das geht eleganter (mask ist zugleich Bitmaske und Zähler):mask =
> 0x80;do{
>   if(command & mask) ds_writeone(); else ds:writezero();}
>   while(mask/=2);
> oder gleich:
> mask = 0x80; do ds_write(command & mask) while(mask/=2);

FAIL! OneWire sendet LSB first ;-)
Außerdem ist eine einfache UND-Verknüpfung und Auswertung kaum 
optimierbar, denn da kommt auf den meisten CPUs nur 1 ASM Befehl zum 
Bittesten raus.

"Ich bin dafür, die Dinge so weit wie möglich zu vereinfachen, aber 
nicht weiter."

Albert Einstein

von Stefan F. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> if (command & 1)

Das ist die Maske, die Falk meint. Durch die UND-Verknüpfung wird nur 
das niedrigste Bit verwendet. Und wenn das 1 ist, dann wird der if-Block 
ausgeführt.

(Alle Ausdrücke die nicht 0 ergeben sind wahr)

> command = command >> 1;

Hier wird das Kommando bei jedem Schleifendurchlauf um eine Position 
nach rechts verschoben. Deswegen brauchen wir wir immer nur das gleiche 
Bit 0 mit if abzufragen. Die Verschiebung um 1 führt der Mikrocontroller 
besonders schnell aus, nämlich in nur einem einzigen Takt.
1
    if (command & 1) {
2
      ds_writeone();
3
    }
4
    else {
5
      ds_writezero();
6
    }

Alternative Schreibweise mit dem ternären Operator:
1
    (command & 1) ? ds_writeone() : ds_writezero();

Gefällt mir persönlich weniger gut, ist auch nicht effizienter.

von (prx) A. K. (prx)


Lesenswert?

Vorn N. schrieb:
> mask/=2

Wenn man Bits schieben will, sollte man das auch tun, statt per 
Multiplikation oder Division um die Ecke zu denken. Zumal man dann je 
nach Datentypen und Intelligenz des Compilers Überraschungen erleben 
kann, nämlich wenn der Compiler mit Vorzeichen dividiert.

: Bearbeitet durch User
von Dennis T. (dennist92)


Lesenswert?

1
/*
2
 * DS18B20.c
3
 *
4
 * Created: 27.07.2021 21:12:53
5
 *  Author: User
6
 */ 
7
8
#include <avr/io.h>
9
#include "../header/DS18B20.h"
10
#include <util/delay.h>
11
12
void ds_out(){
13
  DS_DDR |= (1 << DS_PIN);
14
}
15
void ds_in(){
16
  DS_DDR &= ~(1 << DS_PIN);
17
}
18
19
void ds_masterreset(){
20
  ds_out();
21
  DS_PORT &= ~(1 << DS_PIN);
22
  _delay_us(DS_MASTERRESET_US);
23
  ds_in();
24
  _delay_us(DS_WAIT_US);
25
}
26
void ds_command(uint8_t command){
27
  int i;
28
  
29
  for (i = 0; i < 8; i++){
30
    if (command & 1) {
31
      ds_writeone();
32
    }
33
    else {
34
      ds_writezero();
35
    }
36
    command = command >> 1;
37
  }
38
}
39
void ds_writezero(){
40
  ds_out();
41
  DS_PORT &= ~(1 << DS_PIN);
42
  _delay_us(DS_WRITEZERO_US);
43
  ds_in();
44
}
45
void ds_writeone(){
46
  ds_out();
47
  DS_PORT &= ~(1 << DS_PIN);
48
  ds_in();  
49
  _delay_us(DS_WRITEONE_US);
50
}
51
int ds_check(){
52
  ds_masterreset();
53
  ds_command(DS_SKIPROMCOMMAND);
54
  ds_command(DS_READSCRATCH);
55
  uint8_t temp1 = ds_readbyte();
56
  uint8_t temp2 = ds_readbyte();
57
  int out = ((temp2) * 256) + temp1;
58
  return out;
59
}
60
int ds_readtemp(){  
61
  ds_masterreset();
62
  ds_command(DS_SKIPROMCOMMAND);
63
  ds_command(DS_CONVERTTEMP);
64
  _delay_ms(DS_WAIT_MS);
65
  ds_masterreset();
66
  ds_command(DS_SKIPROMCOMMAND);
67
  ds_command(DS_READSCRATCH);
68
  uint8_t temp1 = ds_readbyte();
69
  uint8_t temp2 = ds_readbyte();
70
  int out = ((temp2) * 256) + temp1;
71
  return out;
72
}
73
int ds_readbit(){
74
  ds_out();
75
  DS_PORT &= ~(1 << DS_PIN);
76
  ds_in();
77
  _delay_us(30);
78
  if (PINC & (1 << DS_PIN)){
79
    return 1;
80
  }
81
  return 0;
82
} 
83
int ds_readbyte(){
84
  int i;
85
  int i_byte = 0;
86
  for (i = 0; i < 8; i++){
87
    i_byte += (ds_readbit() << i);
88
  }
89
  return i_byte;
90
}
Ich hab nun ein wenig bearbeitet, setze den internen Pullup nicht mehr 
auf high, sondern stelle den Port wieder auf Eingang. Das Timing passt 
nun auch, allerdings bei
#define F_CPU 2000000L obwohl ich ein 16mhz Quarz habe?
Zu der Frage woran der Fehler lag kann ich nichts sagen, denn ich habe 
zu der Zeit nur Code auskommentiert, hochgeladen und dann wieder zurück, 
ging dann irgendwie obwohl nichts anders war als vorher auch.

von Stefan F. (Gast)


Lesenswert?

Dennis T. schrieb:
> for (i = 0; i < 8; i++){
>     i_byte += (ds_readbit() << i);
>   }

Hatten wir nicht gerade Shift Operationen mit variabler Schrittweite 
besprochen?

von Dennis T. (dennist92)


Lesenswert?

Sehe ich als Verbesserungwürdig, mache ich gleich. Mal ne andere Frage 
habe einen usbasp für 10€ nutze atmel Studio und Abtdude. Atmel Studio 
läuft aber nur auf windoof, gibt es gute Alternativen?

von Dennis T. (dennist92)


Lesenswert?

1
for (i = 0; i < 8; i++){ 
2
i_byte &= ds_readbit();
3
i_byte = i_byte >> 1;
4
 }

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Dennis T. schrieb:
> Atmel Studio läuft aber nur auf windoof, gibt es gute Alternativen?

http://stefanfrings.de/avr_tools/index.html#ide

von Stefan F. (Gast)


Lesenswert?

Dennis T. schrieb:
> for (i = 0; i < 8; i++){
>     i_byte &= ds_readbit();
>     i_byte = i_byte >> 1;
>  }

Ich würde mit i_byte=0 anfangen und dann |= anstelle von &= benutzen.

von Wolfgang (Gast)


Lesenswert?

Dennis T. schrieb:
> #define F_CPU 2000000L obwohl ich ein 16mhz Quarz habe?

Und wird der externe Quarz auch benutzt (Fuses)?

von Stefan F. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich würde mit i_byte=0 anfangen und dann |= anstelle von &= benutzen.

Und nach links schieben! Nach rechts ist falsch.

von Dennis T. (dennist92)


Lesenswert?

Dennis T. schrieb:
> Hier sind meine Fuses E:07, H:D9, L:57

Ist auf 16MHZ gestellt

Stefan ⛄ F. schrieb:
> Und nach links schieben! Nach rechts ist falsch.

Ja fiel mir auch nach dem Post ein, dass ich falschherum einlese. 
Momentan klagt aber ein anderes Problem, der DS antwortet mit FF.

von neuer PIC Freund (Gast)


Lesenswert?

Fang erstmal ganz unten an. Deine ds_readbit() sind suboptimal. Sie 
verstoßen gegen die "Time Slot" Spezifikation des DS18B20, welche 
zwischen 60us und 120us liegen sollte. Du wartest nur bis zum 
Rückgabewert und brichst dann ab. Im rar 15us, oben 30us. Lass die 15 
und füge vor jedem return noch ein delay_us(70) ein.

von Stefan F. (Gast)


Lesenswert?

Dennis T. schrieb:
> der DS antwortet mit FF.

Bzw. er antwortet gar nicht. Denn HIGH ist ja der Ruhepegel der Leitung.

von Joachim B. (jar)


Lesenswert?

Falk B. schrieb:
> Das Ganze garniert mit dem ? Operator, den
> man so eher sparsam nutzen sollte. Ein schnödes if() tut es auch und ist
> besser lesbar.

da hast du Recht, aber da Monitore eher breit als hoch sind habe ich dem 
? Einzeiler mehr sichtbaren Quellcode, deswegen nutze ich den gerne.

von Stefan F. (Gast)


Lesenswert?

1
(command & 1) ? ds_writeone() : ds_writezero();

Joachim B. schrieb:
> da Monitore eher breit als hoch sind habe ich dem
> ? Einzeiler mehr sichtbaren Quellcode, deswegen nutze ich den gerne.

Das:
1
if (command & 1) ds_writeone() else ds_writezero();

ist nicht verboten. Nur mal so als alternativen Vorschlag.

Ich benutze den ternären Operator gerne, wenn er einen Wert zurück 
liefert, wie in:
1
puts( (httpStatus>=400) ? "error" : "success" );

von Joachim B. (jar)


Lesenswert?

Stefan ⛄ F. schrieb:
> if (command & 1) ds_writeone() else ds_writezero();

wetten da meckert der Compiler.

Stefan ⛄ F. schrieb:
> Ich benutze den ternären Operator gerne, wenn er einen Wert zurück
> liefert, wie in:puts( (httpStatus>=400) ? "error" : "success" );

me too

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

>> if (command & 1) ds_writeone() else ds_writezero();

Joachim B. schrieb:
> wetten da meckert der Compiler.

Sorry, da fehlt ein Semikolon hinter ds_writeone().

von Wolfgang (Gast)


Lesenswert?

Dennis T. schrieb:
> Dennis T. schrieb:
>> Hier sind meine Fuses E:07, H:D9, L:57
>
> Ist auf 16MHZ gestellt

Ist er nicht. Mit den Einstellungen bekommt der uC einen Takt von 2MHz.
Guck dir mal das CKDIV8-Bit an.
https://eleccelerator.com/fusecalc/fusecalc.php?chip=atmega328p

von Stefan F. (Gast)


Lesenswert?

Wolfgang schrieb:
> Ist er nicht. Mit den Einstellungen bekommt der uC einen Takt von 2MHz.

Es sei denn, sein Program setzt das CLKPR Register passend.

von Dennis T. (dennist92)


Lesenswert?

Huch, oh man der hacken bei dividiere durch 8 ist ja drin 🤔. Dann passt 
ja doch alles :D

von Wolfgang (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Es sei denn, sein Program setzt das CLKPR Register passend.

Unwahrscheinlich ;-)

Dennis T. schrieb:
> Studio_C.rar (75 KB)

Dennis T. schrieb:
> Das Timing passt nun auch, allerdings bei
> #define F_CPU 2000000L obwohl ich ein 16mhz Quarz habe?

von Dennis T. (dennist92)


Lesenswert?

Hm, der DS gibt ein Presentpulse, aber ich kann ihn nicht mehr auslesen.
1
void ds_readscratch(){
2
  ds_masterreset();
3
  ds_command(DS_SKIPROMCOMMAND);
4
  ds_command(DS_READSCRATCH);
5
  for(int i = 0; i < 9; i++){
6
    scratch[i] = ds_readbyte();
7
  }
8
}
9
10
void ds_converttemp(){  
11
  ds_masterreset();
12
  ds_command(DS_SKIPROMCOMMAND);
13
  ds_command(DS_CONVERTTEMP);
14
  _delay_ms(DS_WAIT_MS);
15
}
16
17
int ds_readbit(){
18
  ds_out();
19
  DS_PORT &= ~(1 << DS_PIN);
20
  ds_in();
21
  if (PINC & (1 << DS_PIN)){
22
    _delay_us(60);
23
    return 1;
24
  }
25
  _delay_us(60);
26
  return 0;
27
} 
28
uint8_t ds_readbyte(){
29
  uint8_t i_byte = 0;
30
  for (int i = 0; i <  8; i++){
31
    i_byte |= ds_readbit();
32
    i_byte =  i_byte << 1;
33
  }
34
  return i_byte;
35
}

von Falk B. (falk)


Lesenswert?

Dennis T. schrieb:
> Hm, der DS gibt ein Presentpulse, aber ich kann ihn nicht mehr auslesen.

Dein Quick & Dirty Hack ist Mist. Nicht rumstochern und "probieren", 
sondern ma nachdenken und auch MESSEN! Dein Lesen des Bits funktioniert 
so nicht. Man sollte schon die Zeiten einhalten. Und lass die Finger von 
dem PORT-Bit, das muss nur EINMAL auf 0 gesetzt werden, das macht 
eigentlich schon der Reset. Man muss nur die Richtung Eingang/Ausgang 
umschalten, denn es ist ein Open Drain Signal.

https://www.mikrocontroller.net/articles/Ausgangsstufen_Logik-ICs#Open_Collector
1
uint8_t ds_readbit(){
2
  uint8_t tmp=0;
3
4
  DS_DDR |= (1 << DS_PIN);   // LOW
5
  _delay_us(5);
6
  DS_DDR &= ~(1 << DS_PIN);  // Eingang/Tristate
7
  _delay_us(15);             // warten auf Reaktion
8
  if (PINC & (1 << DS_PIN)){ // lesen
9
    tmp = 1;
10
  }
11
  _delay_us(60);             // volle Bitzeit
12
  return tmp;
13
}

von Falk B. (falk)


Lesenswert?

Dennis T. schrieb:
> uint8_t ds_readbyte(){
>   uint8_t i_byte = 0;
>   for (int i = 0; i <  8; i++){
>     i_byte |= ds_readbit();
>     i_byte =  i_byte << 1;
>   }
>   return i_byte;
> }

Und du hast es immer noch nicht verstanden, daß man das sinnvollerweise 
anders macht? Außerdem schiebst du falsch! OneWire überträgt LSB first, 
du machst aber aus dem 1. Bit das MSB durch dein nach links schieben! 
Außerdem schiebst du NACH der letzten Bitspeicherung, womit die Daten 
erst recht im Eimer sind! Eher so!
1
uint8_t ds_readbyte(){
2
  uint8_t i_byte = 0;
3
4
  for (int i = 0; i <  8; i++) {
5
    i_byte >>= 1;   // Platz schaffen für nächstes Bit ganz links
6
    if (ds_readbit()) i_byte |= (1<<7);
7
  }
8
  return i_byte;
9
}

von Dennis T. (dennist92)


Angehängte Dateien:

Lesenswert?

Falk B. schrieb:
> Dein Lesen des Bits funktioniert
> so nicht. Man sollte schon die Zeiten einhalten. Und lass die Finger von
> dem PORT-Bit, das muss nur EINMAL auf 0 gesetzt werden, das macht
> eigentlich schon der Reset

Das mit den Zeiten habe ich auch schon geregelt, habe ins Datenblatt und 
im Logic geschaut, dann fiel mir ein dass ich falsches Timing habe, 
würde vorher von geredet, nur vergessen umzusetzen.
Das einlesen habe ich nun auch geregelt, danke für eure Geduld :D mein 
Problem ist wirklich dass ich mehrere Fehler habe welche ich behebe, 
dadurch kommt anderes unter, ich aber selber auch suche, dadurch lerne 
ich es aber auch.
Ihr seit mir aber auch eine große Hilfe bin euch da sehr Dankbar :)

Das Thema des Topics ist nun eigentlich erfüllt, es läuft wie es soll.
alles weitere ist somit eigentlich nur noch Optimierung
Folglich Poste ich noch einmal die momentan endgültige Version.

Dann geht es erstmal zum nächsten Sensor dem DHT22 mal sehen was hier 
auf mich wartet :)

Nochmals großen Dank für die große Hilfsbereitschaft.

: Bearbeitet durch User
Beitrag #6803529 wurde vom Autor gelöscht.
von Lutz (Gast)


Lesenswert?

Falk B. schrieb:
> Was soll das? Erstens ist eine variable Verschiebung  >> i relativ
> aufwändig und 2. sinnlos.

Falk B. schrieb:
> Deine Funktionen void ds_writezero(), void ds_writeone() ds_out() und
> ds_in() sind auch vollkommen akademisch aufgeblasen.

Falk B. schrieb:
> uint8_t ds_readbyte(){
>   uint8_t i_byte = 0;
>   for (int i = 0; i <  8; i++) {
>     i_byte >>= 1;   // Platz schaffen für nächstes Bit ganz links
>     if (ds_readbit()) i_byte |= (1<<7);
>   }
>   return i_byte;
> }

Da predigt er von ganz weit oben (wo übrigens ziemlich wenig Sauerstoff 
ist...) einen runter, erwähnt Effizienz, zitiert sogar Onkel Albert usw. 
und kommt dann mit einer Schleife um die Ecke, die in jedem Durchlauf 
7 unnötige Shifts macht???

von Stefan F. (Gast)


Lesenswert?

Lutz schrieb:
> und kommt dann mit einer Schleife um die Ecke, die in jedem Durchlauf
> 7 unnötige Shifts macht???

Jetzt bin ich aber sehr gespannt, wie du die 8 Bits ohne 8 
Shift-Operationen in ein Byte einliest.

An alle: Achtung, ich bitte um Aufmerksamkeit. Der Lutz zeigt uns allen 
jetzt einen genialen Trick den jeder Programmierer drauf haben sollte. 
Trommelwirbel bitte: taraa taraa taratatatataa

von (prx) A. K. (prx)


Lesenswert?

Stefan ⛄ F. schrieb:
> Jetzt bin ich aber sehr gespannt, wie du die 8 Bits ohne 8
> Shift-Operationen in ein Byte einliest.

Überhaupt kein Problem und oben schon gezeigt. Man muss nur die Shifts 
durch Multiplikation und Division ersetzen. :-)

von Dennis T. (dennist92)


Lesenswert?

Stefan ⛄ F. schrieb:
> Jetzt bin ich aber sehr gespannt, wie du die 8 Bits ohne 8
> Shift-Operationen in ein Byte einliest.

Die 7 durch i ersetzen
1
uint8_t ds_readbyte(){
2
  uint8_t i_byte = 0;
3
  for (int i = 0; i <  8; i++) {
4
    if (ds_readbit()) i_byte |= (1<<i);
5
  }
6
  return i_byte;
7
}

von STK500-Besitzer (Gast)


Lesenswert?

Dennis T. schrieb:
> Die 7 durch i ersetzen

LOL
Was macht der Compiler wohl aus "1<<i"?

Es gibt Dinge, die man nicht besser machen kann.

von (prx) A. K. (prx)


Lesenswert?

STK500-Besitzer schrieb:
> Was macht der Compiler wohl aus "1<<i"?

Eine Konstante, wenn du ihn dazu kriegst, die Schleife zu unrollen. :-)

Wobei man das auch selber machen kann. 8x der gleiche Code statt 
Schleife, und weg ist der Shift.

: Bearbeitet durch User
von STK500-Besitzer (Gast)


Lesenswert?

(prx) A. K. schrieb:
> Wobei man das auch selber machen kann. 8x der gleiche Code statt
> Schleife, und weg ist der Shift.

OK...

von Dennis T. (dennist92)


Lesenswert?

(prx) A. K. schrieb:
> Wobei man das auch selber machen kann. 8x der gleiche Code statt
> Schleife, und weg ist der Shift.

Ist wohl längerer Code, aber nicht zu viel und nach dem compilieren 
wahrscheinlich sogar effektiver und kleiner, als mit Schleife und 
variable?

von Lutz (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Lutz schrieb:
>> und kommt dann mit einer Schleife um die Ecke, die in jedem Durchlauf
>> 7 unnötige Shifts macht???
>
> Jetzt bin ich aber sehr gespannt, wie du die 8 Bits ohne 8
> Shift-Operationen in ein Byte einliest.

Oh man, mal wieder der Beweis, daß es der Original-Stefan (nicht 
gehackter Account) ist...

Ich schrieb etwas von 7, du etwas von 8. Komm; das schaffst du im 
zweiten Versuch...
Ich muß jetzt leider mit dem Kochen anfangen und kann dich daher erstmal 
nicht weiter beaufsichtigen.

von Lutz (Gast)


Lesenswert?

Nun gut, Kommando zurück: 1<<7 ist ja eine Konstante zum verODERn. Das 
wird ja nicht zur Laufzeit geshiftet.

von Stefan F. (Gast)


Lesenswert?

Lutz schrieb:
> Nun gut, Kommando zurück: 1<<7 ist ja eine Konstante zum verODERn.
> Das wird ja nicht zur Laufzeit geshiftet.

Na also, geht doch. Ich hoffe du schämst dich jetzt ein bisschen für 
deine persönlichen Angriffe gegen Falk und mich.

Lutz schrieb:
> Ich schrieb etwas von 7, du etwas von 8.

Aus gutem Grund, denn die Beispiele von Falk und mir nutzen 8 
Schiebe-Operationen (einer mehr als nötig, OK). Du hast geschrieben, 
dass davon 7 Shifts unnötig seien. Man hätte demnach also alle 8 Bits 
mit nur einer Shift Operation einlesen müssen.

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.