Aus negativer Zahl wird 4,294,967,295.

Hallo Zusammen,

ich habe das seltsame Problem, dass in meinem Sketch aufeinmal aus einer negativen Zahl eine 4,294,967,295-x wird. Laut Wikipedia ist 4,294,967,295 genau 2^32 (1 Integer). Gibt es eine Erklärung dafür? Dynamischer Speicher voll?

Hi

Deine Variable ist als UNSIGNED (vorzeichenlos) definiert - deshalb gibt es Da KEINE negativen Zahlen.
10 ist 10
0 ist 0
-1 ist 2^Bitbreite**-1**
-2 ist 2^Bitbreite -2
...
Edit Korrigiert nach #10, danke :slight_smile:

Das ist wirklich sehr verwirrend. Die Variable stammt aus einem Encoder-Interrupt vom Due:

void setup() {

//Due Encoder Definieren
  REG_PMC_PCER0 = PMC_PCER0_PID27;   // activate clock for TC0
  REG_TC0_CMR0 = TC_CMR_TCCLKS_XC0;  // select XC0 as clock source

  // activate quadrature encoder and position measure mode, no filters
  REG_TC0_BMR = TC_BMR_QDEN
              | TC_BMR_POSEN
              | TC_BMR_EDGPHA;

  // enable the clock (CLKEN=1) and reset the counter (SWTRG=1)
  REG_TC0_CCR0 = TC_CCR_CLKEN | TC_CCR_SWTRG;
}

Die Variable REG_TC0_CV0 ist dann meine Motorposition, bei der auch der Fehler auftritt.

Merkwürdigerweise funktioniert der Code in einem externen Beispielprogramm. Sobald ich diese Encoder-Funktion in mein Hauptprogramm einfüge, wird dann aus der negativen Zahl die besagte Int. Zahl obwohl ich in die Variablen in keinster Weise eingreife.

Das ist wirklich sehr verwirrend.

Ja!
Da du dich vermutlich noch nie mit den Datentypen beschäftigt hast, welche du verwendest.

Nachweis, um diese Vermutung zu bestätigen:
Dein publizierter Code enthält keinerlei Bezug zu den Datentypen, über du dich mokierst.

combie:
Dein publizierter Code enthält keinerlei Bezug zu den Datentypen, über du dich mokierst.

Das ist ja das verwirrende, ich habe keinerlei Datentypen definiert, also konnte ich auch keine Datentypen falsch verwenden :wink: Diese stammen nämlich aus dem Register soweit ich das verstanden habe. Außerdem funktioniert der Code 1:1 in einem Beispielprogramm. Ich vermute die Ursache also stark an anderer Stelle.

Hi

Vll. verwendet das Beispiel-Programm den Rückgabewert nur richtig?
Also so, wie Sich Das der Progger damals gedacht hat?

Vll. verrätst Du uns, welches Beispiel Du von Wo mit welcher Lib auf welcher Hardware benutzt?

MfG

Hallo,

Überlauf Du bist einmal rund, d.h genau genommen unterlauf fängt jetzt wieder von oben an.

der Wert stammt doch aus einen Motorposition, da gibts halt irgendwann einen Überlauf wenn es nur in eine Richtung geht.

ItsUnreal:
Das ist ja das verwirrende, ich habe keinerlei Datentypen definiert, also konnte ich auch keine Datentypen falsch verwenden :wink: Diese stammen nämlich aus dem Register soweit ich das verstanden habe. Außerdem funktioniert der Code 1:1 in einem Beispielprogramm. Ich vermute die Ursache also stark an anderer Stelle.

Naja...

Da du offensichtlich Ausgaben hast, welche dir nicht passen, arbeitest du zwangsläufig mit Daten.
Und diese Daten sind natürlich Type gebunden. Was anderes lässt C/C++ nicht zu.
Das ist ein "Muss" ein "es ist so", unabhängig davon, ob du das weißt, willst, oder ignorierst.

Ich vermute die Ursache also stark an anderer Stelle

Ja. Dort wo REG_TC0_CV0 deklariert ist.

Hallo,

@ TO , was ist denn aus deinen verlorenen Impulsen von gestern geworden, da hatten wir noch ein paar Fragen die du uns noch nicht beantwortet hast.

Gruß

Heinz

postmaster-ino:
Deine Variable ist als UNSIGNED (vorzeichenlos) definiert - deshalb gibt es Da KEINE negativen Zahlen.
-1 ist 2^Bitbreite
-2 ist 2^Bitbreite -1
...

Nein, das ist falsch.

2Bitbreite ist nicht darstellbar.

-1 = 2Bitbreite - 1

Also nochmal, da ja einige der Meinung sind ich hätte einen ungeeigneten Datentypen gewählt. Das ist der vollständige Code:

void setup() {
  // Setup the quadrature encoder
  // For more information see http://forum.arduino.cc/index.php?topic=140205.30
  REG_PMC_PCER0 = PMC_PCER0_PID27;   // activate clock for TC0
  REG_TC0_CMR0 = TC_CMR_TCCLKS_XC0;  // select XC0 as clock source

  // activate quadrature encoder and position measure mode, no filters
  REG_TC0_BMR = TC_BMR_QDEN
              | TC_BMR_POSEN
              | TC_BMR_EDGPHA;

  // enable the clock (CLKEN=1) and reset the counter (SWTRG=1)
  REG_TC0_CCR0 = TC_CCR_CLKEN | TC_CCR_SWTRG;
}

// The encoder position is then accessed from
void loop() {
  Serial.println(REG_TC0_CV0); // Read the encoder position from register
}

REG_TC0_CV0 ist nicht von mir definiert. Es handelt sich um eine Systemvariable (nennt man das so?) Jedenfals ist sie Read-Only und im Atmel-Core definiert. Dazu habe ich folgendes im Datenblatt gefunden, fals es jemandem hilft:

#define REG_TC0_CV0 REG_ACCESS(RoReg, 0xF8008010U) /**< \brief (TC0) Counter Value (channel = 0) */

Das oben gezeigte Beispielprogramm funktioniert wie es soll. Bei negativer Drehrichtung wird mir im SerialMonitor bspw. "-1432" angezeigt. Jetzt habe ich exakt den Teil kopiert und bei mir eingefügt. Dazu kommen also noch jede Menge Zeilen Code um einen Schrittmotor anzusteuern, einen AD-Wandler auszulesen etc. Aufjedenfall nichts was in irgendeiner Art EG_TC0_CV0 verändern könnte.
Da man EG_TC0_CV0 garnicht beschreiben kann, ist es ausgeschlossen, dass ich falsch damit umgegangen bin. Fakt ist, dass jetzt plötzlich (sobald EG_TC0_CV0 negativ werden müsste), mir 4,294,967,295-x (x: Schrittzahl) ausgegeben wird. Da ich also keinerlei Veränderungen am Code vorgenommen habe, und auch nichts im Code habe, was einen Einfluss darauf haben könnte, kann ich mir den Umstand nicht erklären.

#define REG_TC0_CV0            REG_ACCESS(RoReg, 0xF8008010U) Jetzt musst du noch die Definition von REG_ACCESS und evtl. RoReg rauskriegen.
Immerhin hat das ganze was mit uint32_t zu tun, wie man an der Konstanten erkennen kann.

(Hab nicht gemeint, dass du selbst irgendwo was falsch machst)

Dazu habe ich folgendes im Datenblatt gefunden, fals es jemandem hilft:

#define REG_TC0_CV0 REG_ACCESS(RoReg, 0xF8008010U) /**< \brief (TC0) Counter Value (channel = 0) */

Nur falls man den Keil Kompiler nutzt.
Das tust du aber nicht.

Also nochmal, da ja einige der Meinung sind ich hätte einen ungeeigneten Datentypen gewählt.

Deine falschen Annahmen steht dir im Weg rum.

Niemand hat gesagt, dass du den falschen Datentype gewählt hast.
Nur hast du offensichtlich den Datentype, welchen du verwendest, nicht verstanden.

So sieht die Definition von RoReg für deinen Kompiler aus:

typedef volatile const uint32_t RoReg; /**< Read only 32-bit register (volatile const unsigned int) */

Daraus ergibt sich ganz klar:
Der Datentype, welchen du verwendest, ist uint32_t.

Merke:
Ein unsigned int KANN niemals negativ werden.
Das von dir beobachtete Verhalten entspricht also vollkommen dem zu erwartendem Verhalten.

Sie müssen TC_CV0 zuerst in ein int32_t kopieren, bevor Sie es verwenden können. Vor 0 gibt es die Position - 1, die gleich ist und eine vorzeichenbehaftete Variable mit 0xFFFFFFFF ist.

void setup() {

Serial.begin(250000);

// int 32_t var = TC_CV0; // TC_CV0 = 0xFFFFFFFF 
int32_t var = 0XFFFFFFFF; // 2 exp 32  - 1

printf(" var = %d\n", var);
delay(1);

// var = -1

}

void loop() {

}

Um das Vorzeichen auf der einen oder anderen Seite umzukehren, verwenden Sie TC_BMR_SWAP.

An dieser Stelle erstmal danke für eure Antworten.

Ich hatte im Code: int current_Position_e = REG_TC0_CV0 / 2.5 - endlage; stehen.
Mit einer "Zwichenvariable":

int current_Position_e_r = REG_TC0_CV0;
int current_Position_e = current_Position_e_r / 2.5 - endlage;

funktioniert es jetzt.

Aber Sie müssen jedoch wissen, wann Sie durch 0 gehen, um zu den Negativen zu gelangen, da ansonsten TC_CV0 = 0xFFFFFFFFFF eine positive Zahl ist, wenn ein Überlauf vorliegt:

https://community.atmel.com/forum/quadrature-decoder

Ich hatte im Code

Du hast da noch implizite Konvertierung, von einem Integer Type, zu float.
Und wieder zurück.
Ich befürchte, dass dir das auch Streiche spielen wird.