Ressourcen-Icon

Entfernungsmessung mit dem I2C Bus und SRF02 1

Register 2 und 3
Diese beiden Register geben zusammen die Entfernung in cm, Inch oder uS zurück, je nachdem welche Maßeinheit über das Befehlsregister festgelegt wurde. Aus den beiden Byte-Registern bildet man den Entfernungswert durch die übliche Umrechnung:
Entfernung = (Register2 + 256) + Register3
Wäre sehr ungewöhnlich, insbesondere im Zusammenhang mit der Tabelle darüber.
 
Sorry, habe die Angaben noch mal kontrolliert. Die Register stimmen doch. R2 ist high und R3 ist low, oder meinst du die 256?
 
???
Du schreibst Register2 sei das HighByte, Register3 das LowByte, und daß beide zusammen die Entfernung in cm, Zoll oder Mikrosekunden enthalten.
Folglich solltest Du gar nicht rechnen müssen...
 
Jetzt bringst du mich ganz durcheinander. Das Regsiter2 ist high, das Register3 ist low. Es können mit dem I2C Bus nur 8 Bit Zahlen übertragen werden. Beide Register sind 8 Bit. Da ich erst Register2 lade und es um 256 (!) nach links schiebe und danach erst Regsiter3 lade und die übertragung zum Bus beende, bilde ich eine Binär Zahl mit 16 Bit und diese wird in eine Dezimalzahl umgerechnet.
Im Datenblatt des Herstellers ist angegeben:
Entfernung = (Register2 + 256) + Register 3
Bei Heinrich ist allerdings angeben: Entfernung = (256 X Register2)+Register3
Wenn ich die Formel von Heinrich ausrechne komme ich auf Werte die jenseitz von gut und böse sind. Damit ist die Formel von Heinrich verkehrt.
Habe noch mal auf den Seiten von AVRFreak nachgeschaut. Die machen es genau so wie ich:

messung_high = i2c_readAck(); // Register 2 (high) lesen
messung_low = i2c_readNak(); // Register 3 (low) lesen und stop
messung = (( messung_high << 8) + messung_low);

Da ich auf meinem Display die Binär Zahl nicht darstellen möchte bzw. mit lcd_printlc darstellen kann rechne ich das Ergebnis damit um:

utoa(messung,wert,10);
lcd_printlc(3,2,"Abstand:");
lcd_printlc(3,12,wert); // Anzeige in Zeile 3

Die Zahl 255 entspricht 11111111. Das sind 8 Stellen. Nutze ich 256 sind das 9 Stellen. Im DB des Herstellers ist 256 angegeben.
Im Moment versteh ich nicht was du meinst.
 
Muss noch mal nachfragen.

messung = (( messung_high << 8) + messung_low);

Damit verschiebe ich higt um 8 Stellen nach links. Die Binärzahl 8 ist 11 11 11 11. In der Formel ist doch 256 angegeben. Das entspricht der Binärzahl 1 00 00 00 00.
Was ist korrekt?
 
Es können mit dem I2C Bus nur 8 Bit Zahlen übertragen werden.
Genauer: I²C arbeitet byteweise, es können aber beliebig viele Bytes in einem Rutsch übertragen werden. Wie übrigens auch bei SPI. Beim Standard-U(S)ART hingegen lassen sich 5..9 Datenbits konfigurieren.
Beide Register sind 8 Bit.
Wie auch die meisten Registers der von Dir verwendeten Mikrocontroller (selbst der Zugriff auf Register der 16bit-Timer und des 10Bit-ADC laufen über 8-Bit-Bytes.
erst Register2 lade und es um 256 (!) nach links schiebe
Nein, Du willst vielleicht schieben, allerdings nicht um 256, und schieben ist hier eh nicht nötig (siehe eben) - Aber Du schiebst nicht, Du addierst einen Konstanten Offset drauf. Erst 256, dann 255.

Was bedeutet denn "Schieben"?
Wie ist 'ne Zahl aufgebaut?

Du hast 'nen Vorrat an Symbolen - Ziffern. Beim Dezimalsystem sind es Zehn, beim Binärsystem Zwei.
Entsprechend ist die Basis des Dezimalsystems die Zehn, die des Binärsystems ist die Zwei.

Wenn Du aus den Ziffern jetzt 'ne Zahl bildest, ist der Wert jeder Stelle "Ziffer * BasisStelle"
Für die letzte Stelle also "Ziffer * Basis0"
Die Stelle davor "Ziffer * Basis1"
...
Die siebte davor "Ziffer * Basis7"

Im Dezimalsystem ergeben sich damit also...
Letztes Stelle -> "Ziffer * 100 = Ziffer * 1" -> Einer
Stelle davor -> ""Ziffer * 101 = Ziffer * 10" -> Zehner
...
Die siebte davor -> "Ziffer * 107 = Ziffer * 10000000" -> ähm... Zentimilliarden?
(Die Ziffern können die Werte 0..9 annehmen)

Beim Binärsystem hast Du nur zwei mögliche Ziffern - "0" und "1".
Für die Letzte Stelle gilt "Ziffer * 20 = Ziffer * 1"
Für die davor "Ziffer * 21 = Ziffer * 2"
davor "Ziffer * 22 = Ziffer * 4"
...
Für die siebte davor "Ziffer * 27 = Ziffer * 128"

Was bedeutet jetzt "Schieben"?
 
Wenn ich mich richtig erinnere wird es in der Literatur als "Schieben" bezeichnet. Nach deinen Text wird aber nur der Wert von 255 (oder 256) dazu addiert. Da geb ich dir vollkommen Recht. Die Umrechnung des Binärsystems kenne ich. Mache es allerdings nicht einzeln, da es ja den Befehl utoa(messung,wert,10); gibt. Der übernimmt für mich die Arbeit.
Was hat das ganze jetzt aber mit der Ursprungsfrage zu tun?
 
Habe mir mein C-Buch vorgenommen. Dort werden verschiedene Zeichen für mathematische Opperationen dargestellt und erklärt. Wenn ich mir das vornehme:

messung = (( messung_high << 8) + messung_low);

sagt das Buch das << bedeutet das nach links verschoben wird um die Angabe des Wertes (8). Von einer Addition steht dort nichts.
Was im Hintergrund passiert wird nicht erklärt.
Sorry bin jetzt ziemlich Ratlos was wirklich gemeint oder gemacht wird.
Könnte mich jemand dazu aufklären?
 
Wenn ich mich richtig erinnere wird es in der Literatur als "Schieben" bezeichnet. Nach deinen Text wird aber nur der Wert von 255 (oder 256) dazu addiert.
Nein!
In Deiner Anleitung hast Du(!) addiert, was überhaupt keinen Sinn ergibt
WAS wird als schieben bezeichnet, genau das hatte ich Dich ja gerade gefragt.

Schieben verschiebt die Ziffern gegenüber den Potenzen der jeweiligen Basis.
Wenn die Ziffern (eine Stelle) nach links geschoben werden, erhöhen sich die Potenzen (um eins), es wird also effektiv (einmal) mit der Basis multipliziert.
Wenn die Ziffern (eine Stelle) nach rechts geschoben werden, reduzieren sich die Potenzen (je um eins), es wird also effektiv (einmal) durch die Basis dividiert.

(Einmal) Linksschieben einer Dezimalzahl entspricht einer Multiplikation mit Zehn, (einmal) Rechtsschieben einer Dezimalzahl entspricht einer Division durch Zehn (Das Komma wird quasi in die andere Richtung verschoben).
(Einmal) Linksschieben einer Binärzahl entspricht einer Multiplikation mit Zwei, (einmal) Rechtsschieben einer Binärzahl entspricht einer Division durch Zwei (Das Komma wird quasi in die andere Richtung verschoben).

Achtmal Linksschieben entspricht also acht aufeinanderfolgenden Multiplikationen mit Zwei, bzw einer Multiplikation mit 28=256.
Entfernung = (256 X Register2)+Register3
...liefert also genau dasselbe wie...
messung = (( messung_high << 8) + messung_low);
Wenn Der Controller "zu Fuß" multiplizieren muß (quasi alle Tinies), ist schieben wesentlich schneller und Codesparender, wenn er über Multiplikationsroutinen verfügt (quasi jeder Mega), könnte die Multiplikation etwas(!) schneller sein).

Und jetzt einfach mal etwas Praxis:
Nehmen wir einfach mal folgende Werte an...
Register2 liefert 00001111 und Register3 01010101
Die Multiplikationen exerzier ich jetzt nicht durch - zuviel Aufwand
aber das Schieben der Freaks...

"messung" soll sechzehn Bit aufnehmen können, muß also 'ne 16-Bit-Variable sein.
"( messung_high << 8)" muß (wenn es so umgesetzt wird) auch auf 16Bit operieren können, aus 00001111 wird nach acht Schiebezyklen 0000111100000000
( 00001111 ist übrigens dezimal 15, 00001111 0000111100000000 dezimal 3840. 15 * 256 = ??)
Da Dein Controller mit 8Bit rechnet, besteht jeder dieser Schiebezyklen in Wirklichkeit aus zwei Schiebeoperationen.
Erst wird das Lowbyte einmal linksgeschoben, dabei wird das Höchstwertigste Bit aus dem Byte rausgeschoben und landet im Carrybit ("Überlauf"); das neue niederwertigste Bit wird Null (es wird 'ne Null reingeschoben).
Danach wird das Highbyte einmal linksgeschoben, wobei das niederwertisgte Bit das Bit aus dem Carry übernimmt. Diese Schiebeinstruktion heißt "Rollen".

Anschließend wird Messung_low draufaddiert.
0000111100000000 + 01010101 liefert 0000111101010101.
Dein Controller rechnet mit 8Bit, es werden also in Wirklichkeit zweimal zwei Bytes addiert (und dabei einmal ein eventueller Überlauf berücksichtigt).

Gehts besser?
na klar... statt erstmal Nullen in messung_high reinzuschieben und anschließend messung_low draufzuaddieren, kann man auch gleich messung_low über das Carry in Messung_high reinschieben; dann ist man nach acht Schiebezyklen (je einmal schieben und rollen) fertig, die zwei Additionen sind unnötig.

Möglicherweise optimiert Dein Compiler das sogar so.

Als Ergebnis hast Du also "messung" den Wert 0000111101010101 zugewiesen, irgendwo im SRAM steht also 0000111101010101.
Du hast aber 'n 8Bit-Controller, auch Dein SRAM ist in Bytes organisiert.
Wenn "messung" als 16Bit-Variable (Word, UINT16 oder wie auch immer das bei Euch heißt) dimensioniert wird, werden zwei (wahrscheinlich aufeinanderfolgende) SRAM-Zellen allokiert. Eine nimmt das HighByte von Messung auf, die andere das LowByte.
In einer landet nach Deiner ganzen Rechnerei also 00001111 in einer anderen 01010101.
Statt der ganzen Rechnerei kannst Du also auch einfach Deine beiden Bytes direkt in die beiden SRAM-Zellen schreiben...
 
  • Like
Reaktionen: alecxs
Morgen,
Wau, du machst dir viel Arbeit gemacht um es zu erklären. Vieles kenne ich dazu, einiges ist neu oder eben die Erklärung dazu. Besonders die Sichtweise zu einigen Sachen werde ich mir genau ansehen. Wie weit muss man das alles wissen um es anwenden zu können? Gehen einige Sachen nicht schon ans Eingemachte oder wie der Prozessor im Hintergrund was macht? Das Rechnen mit Binär habe ich auch mal gelernt dann aber Jahre nicht mehr genommen (einzelne Schritte) sondern alles mit utoa gemacht, ist halt einfacher.
Lassen wir das rechnen erst mal sacken (verstehen). Was ist aber mit der Anzeige?

Zitat:
Statt der ganzen Rechnerei kannst Du also auch einfach Deine beiden Bytes direkt in die beiden SRAM-Zellen schreiben...

Wie kann ich die beiden SRAM Zeilen den als dezimalzahl Zahl darstellen? Muss dabei nicht immer eine Umrechnung erfolgen?

Falls du Zeit oder Lust hast kannst du mir bei einem anderen Problem helfen. Versuche mit dem Attiny 841 ein bischen SPI zu machen. Dabeu ghet es besonders um den MCP23S17 und einer SPI Anzeige von EA DOG163. Habe ja den MCP23017 (I2C) bereits vorgestellt, aber mit SPI ist es doch was ganz anderes.
 
Ja das gibt es bereits, aber mit Bascom und RN-Control. Habe selber mit RN-Control angefangen. Das Board ist etwas anders und in einigen Sachen auch eigen. Da es in der Software nicht zu meinem Board passt ist es doch anders. Du schreibst "wesentlicher ausführlicher", wieso? Auch dieser Artikel bezieht sich nur auf das Datenblatt des Herstellers und es sind die gleichen Bilder, Der Vorgänger zu mikrocontroller-elektronik war robotikhardware der auch der Hersteller des RN-Controllers und einiger anderer war. Wir verwenden beide das gleiche Datenblatt, nur die Software ist total anders.
 
1.) Bei Deinem Tut ist die Berechnung der Entfernung falsch - muss sein "Entfernung = (Register2 <<8) + Register3 und nicht Entfernung = (Register2 + 255) + Register3; Register 2 muss um 8 nach links geschoben werden (Grundlagen "Schiebeoperationen", shift left; shift right).

2.) Unter dem angegebenen webpage "www.Heinrichs.de" erscheint eine Firma mit Schrauben und Verschlussteilen

3.) Welche Versionsnummer hat denn nun das aktuelle Tut? Warum gibst Du keine Versionshistorie an (gilt bei all Deinen Tuts) "was wurde wann wie geändert" - ist doch Standart normalerweise

4.) wenn Angabe von Quellen (Internetseiten etc) bitte genaue Internetadresse, nicht nur die allgemeine wie z.B. "www.avrfreaks.net", sondern z.B. "https://www.avrfreaks.net/forum/i2c-issues-getting-values-srf02-range-finder?skey=srf02"!
 
Du verweist darauf das Berechnung falsch ist. Komisch. Diese Angabe stammt aus dem Datenblatt des Herstellers. Falls das wirklich falsch ist, musst du das Hersteller mitteilen. Hast du mal die restlichen Beiträge zu dieser Berechnung auf dieser Seite gelesen? LotadaC hat eigentlich schon genug dazu geschrieben und er ist mit seinen Erklärungen sehr tief gegangen. Hast du dir schon mal die Software zu diesem Tut angesehen? Scheint nicht so zu sein. In der Berechnund der Entfernung mache ich es genau so wie du es gern möchtest. Das selbe habe ich auch weiter ober mitgeteilt.
Bei den Tuts handelt es sich um private Veröffentlichungen. Vielleicht kannst du mir die entsprechenden Gesetz zur Angabe der Quellen, Versionen und Histori mitteilen. Ob die Seite von "Heinrich" noch exestiert oder sich anders nennt, weiss ich nicht. Habe vor ca. 5 Jahren das PDF mit Angabe der Adresse gefunden und angegeben. Nach seinen Angaben berechnet Heinrich den Wert falsch. Er gibt als Formel an: Entfernung = Register2 X (mal) 256 + Register 3 an.
Irgend wie habe ich das Gefühl, du willst mir sagen, ich soll das lassen und keine Tuts mehr reinstellen weil sie sowieso alle falsch sind. Warum beteiligst du dich an einer konstruktiven Diskussion um Fehler zu vermeiden und es für alle klar darzustellen.
Würdest du dich bitte an einen achtungsvollen Ton halten. Auf anderen Seiten ist es üblich das Fragende von Wissenden niedergemacht, beschimpft oder beleidigt werden. Das möchte ich auf dieser Seite nicht erleben. Meine Tuts sind Beispiele für Hardware und Software für Anfänger und Bastler. Ich erhebe keinerlei Ansprüche auf absolut korrekte Angaben und immer Fehlerfrei zu sein.
 
Deinen Beitrag 18 kann ich nicht unkommentiert stehen lassen

LotadaC hat eigentlich schon genug dazu geschrieben und er ist mit seinen Erklärungen sehr tief gegangen.
Hast Du seine Erklärungen auch verstanden ?
Hast du dir schon mal die Software zu diesem Tut angesehen?
Wo ist diese denn in Deinem Tut??
Bei den Tuts handelt es sich um private Veröffentlichungen. Vielleicht kannst du mir die entsprechenden Gesetz zur Angabe der Quellen, Versionen und Histori mitteilen. Ob die Seite von "Heinrich" noch exestiert oder sich anders nennt, weiss ich nicht. Habe vor ca. 5 Jahren das PDF mit Angabe der Adresse gefunden und angegeben.
Deine Tuts sind mir egal, da zu oberflächlich (und teilweise nicht korrekt). Wenn Du Quellenangaben machst, solltest Du auch verifizieren, dass die Quelle noch existiert und somit korrekt ist. Und wie schon erwähnt es ist Standart, dass man
1.) Quellen korrekt zitiert
2.) Änderungen in einem "Tut" als solche markiert ( nennt man "Versionierung") - siehe z.B Dein geändertes "Tut"- Seite 5: zuerst war es 256, dann 255, dann (jetzt) wieder 256 - ohne Hinweis, dass etwas geändert wurde.
3.) die Versionsnummer des "Tut" hochzählt
4.) so wie sich mir das darstellt, hast Du alles aus dem von mir in Beitrag 14 angegebenen Quellen zusammenkopiert.
Würdest du dich bitte an einen achtungsvollen Ton halten.
Was willst Du mir damit sagen? Was an meinem Beiträgen 14 und 16 in diesem Thread war NICHT achtungsvoll???

Ich erhebe keinerlei Ansprüche auf absolut korrekte Angaben und immer Fehlerfrei zu sein.
DAS ist mir klar und das bezweifle ich auch nicht, dennoch sollte Dein Bestreben sein, fehlerfreie "Tuts" anzufertigen.
 
Zuletzt bearbeitet:
In der oberen Leiste steht "Ressourcen", dort gibt es zwei Beiträge zum SRF02. Der eine ist die Hardware und die andere ist die Software und beide haben ein Nr. Es steht immer nur die letzte gültige Version im Netz.
LotadaC hat viel geschrieben. Wenn ich mir mein C Buch dazu nehme "C von A-Z" von Wolf wird das genau beschrieben. In den Seiten von Mikrocontroller wird es auch genau beschrieben. In der Software schiebe ich mit << 8 nach links, genau wie du es schreibst.
Im Netz habe ich nur ein Datenblatt zum SRF02 vom Hersteller gefunden. Dann noch die Sache von "Heinrich". Bei AVRfreaks und google habe ich so ca. 500 Beiträge zum SRF02 gefunden. Viele sind vom Raspi oder ähnliches, einige wollen mehr Bündeln, andere vergleichen mit SRF05 oder SRF10. Manche Software ist in Basic. Bei der Menge der Infos besteht das Tut aus der Überschrift und den Infos zu den Seiten, ist zu wenig für mich.
Deine Sachen waren verantwortungsvoll. Man sollte aber erst meckern wenn man alles gelesen hat. In meinen Tuts erhebe ich keinerlei Ansprüche auf Vollständigkeit. Es ist von Bastlern für Bastlern geschrieben. Menschen die sich mit der Sache auskennen brauchen so was nicht. Aus eigener Erfahrung kann ich dir sagen, es motiviert nichts besser als ein funktionierendes Programm. Wenn man das Programm nimmt und Stück für Stück zerlegen muss, jeden Befehl nachschlagen muss und die DB des Herstellers nimmt um rauszubekommen welche Adresse verwendet wird, welcher Adressrahmen verwendet wird oder welche Register für die Befehle sind und in welchem Register das Ergebnis steht und wie. Ist wahrscheinlich nicht so trocken wie ein C-Buch auswendig zu lernen und es vielleicht nicht so anwenden zu können wie man es gern möchte. Die "alten Hasen" bei C haben Tricks auf Lager dir mir absolut unbekannt sind. Es gibt genügend Beispile für scheinbar einfache Hardware und kaum beschaffbare Software oder Libs dazu, z.B. HT16K33 oder das TFT32 von EA mit 64 Busadressen.
Auf einigen anderen Seiten ist es üblich andere zu beleidigen und zu beschimpfen. Hoffe das hier nicht vorkommt. Lass unss bei einem freundlichen Ton bleiben.
Ansonsten lade ich dich gern ein mir bei den Tuts zu helfen. Sage einfach was ich besser machen kann oder sogar falsch ist. Es ist nicht leicht ein Tut zu schreiben, den richtigen Ton zu treffen und es so zu schreiben das auch Anfänger es verstehen.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)