Rechenoperationen und rundung ausführen

Hallo,

leider kann ich den Trick nicht für meinen Frequenzgenerator übernehmen. Da der float Wert von "frequenz" variabel einstellbar ist mit Kommastelle. Ich kann keinen konstanten Bruch bilden. Hauptsache man hat wieder was gelernt und kann sich das hoffentlich merken. :)

new_TOP = (long) ((CPU_Takt/used_Prescaler[i]/frequenz)+0.5);  // TOP Berechnung und runden

Abgesehen davon ist eine Division durch 32 auch für Floats keine Division sondern nur eine Exponenten Subtraction.

Habe ich nicht bedacht, danke für den Hinweis. Macht der Compiler das so? Oder wandelt er erstmal die 32 in eine float Zahl, um dann float/float zu rechnen? Für die reine Exponenten-Subtraktion ist es etwas langsam, für die volle Software-Gleitkomma-Arithmetik gar nicht schlecht.

Die eigentliche "Aufgabe" war übrigens:

Diese möchte ich durch 32 teilen, mit einer Rundungsfunktion auf eine Ganzzahl bringen und dann in Hi Pegel umwandeln.

Da finde ich die Umstellung schon sinnvoll: erst auf Integer und aufrunden, dann /32, also den Compiler daraus >>5 machen lassen.

Ich glaube dass der Kompiler aus der Division durch 32 eine Operation auf dem Exponenten des Floats erzeugt.

Aber wir sind uns ja alle einig, dass bei der Aufgabenstellung Floats wenig sinnvoll sind.

Diese möchte ich durch 32 teilen, mit einer Rundungsfunktion auf eine Ganzzahl bringen und dann in Hi Pegel umwandeln.

Da bleibt die Frage offen, wie wandelt man einen Integer in Hi Pegel?

Hallo,

letzteres hatte ich nun wiederum herausgelesen. Das Ergebnis gibt für ihn die Anzahl der High-Low Wechsel zurück die er dann machen muss. Natürlich in einer neuen Funktion.

Macht der Compiler das so?

Falls es jemanden interessiert: Hab es mir mal mit objdump -dangesehen

float f = 12345.67;
void setup() {
int i = f / 32;  // nimmt eine 4 byte Konstante 0x3D000000 = 0.03125 =  1/32 für eine float Multiplikation und wandelt das Ergebnis nach int
...
}

Whandall: Aber wir sind uns ja alle einig, dass bei der Aufgabenstellung Floats wenig sinnvoll sind.

Doc_Arduino:
leider kann ich den Trick nicht für meinen Frequenzgenerator übernehmen. Da der float Wert von “frequenz” variabel einstellbar ist mit Kommastelle. Ich kann keinen konstanten Bruch bilden.

Du benötigst keinen konstanten Bruch, nur das Equivalent zu 0,5 vor der Division (Mathematiker können das sicher besser ausdrücken). Mein Testsketch

uint32_t CPU_Takt = 16000000;
uint32_t used_Prescaler[] = {16};
float f_frequenz = 1000.0;
uint16_t i_frequenz = 1000;
byte j = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println("Anfang");
  for (byte i = 0; i < 10; i++) {
    long long_TOP = (long) ((CPU_Takt / used_Prescaler[j] / f_frequenz) + 0.5); // TOP Berechnung und runden
    long int_TOP =  (long) ((CPU_Takt / used_Prescaler[j]) + (i_frequenz / 2)) / i_frequenz;
    f_frequenz += 111.0;
    i_frequenz += 111;
    Serial.print(long_TOP);
    Serial.print('\t');
    Serial.println(int_TOP);
  }
}

void loop() {}

hat diese Ausgabe:

Anfang
1000 1000
900 900
818 818
750 750
693 693
643 643
600 600
563 563
530 530
500 500

Ich behaupte nicht, dies oder das wäre besser. Siehe es bitte als Anregung, Deine Gehirnwindungen arbeiten ja bestens :slight_smile:

Hallo,

mir ist schon klar das nur der benötigte Bruch immer 1/2 sein muss, egal wie, ob 2/4 oder 6/12 usw. Nur ist der übergebene Frequenzwert eben nie vorhersehbar und float, kann jederzeit live eingestellt werden. Ich müsste demzufolge vorher immer erstmal den passenden Zähler zum float! Nenner berechnen um dann den Trick anzuwenden. Und da denke ich macht der zusätzliche Code und Rechenaufwand alles wieder zu nichte was es am Ende bringt. Ich belasse das so. Und wenn ich mit irgendwelchen Konstanten rechne, dann kann ich das gut anwenden. Es ist ja nicht so das ich aus dem Thread nichts mitnehmen kann. :)