Konstanten für Flash in einer Schleife während Kompilierens

Hi,

ich weis das es möglich ist aber noch nicht genau wie.
Während des kompilierens Konstanten für PROGMEM in einer For-Schleife berechnen lassen, wie geht das?

Vielen Dank im Voraus

MfG
Andi

Haribo68:
ich weis das es möglich ist aber noch nicht genau wie.
Während des kompilierens Konstanten für PROGMEM in einer For-Schleife berechnen lassen, wie geht das?

Da der Compiler beim Compilieren keine der C-Programmzeilen ausführt, muss es sich nach meinem Verständnis um einen Befehl des Präprozessors handeln, also um irgendein Ding, das wie

#ifdef

aussieht. Eine hilfreiche Seite zu Präprozessorbefehlen konnte ich auf die Schnelle nicht finden. Aber vielleicht kennt ja jemand eine gute Seite und postet einen Link.

Gruß

Gregor

Die Doku zum C-Präprozessor ist hier.

Gruß Tommy

Mit C++14 und den erweiterten constexpr Ausdrücken wäre es leicht möglich. Je nachdem was man genau berechnen will. Aber dieses Feature braucht so wie es aussieht ggc 5 und die Arduino IDE hat höchstens 4.9

Serenifly:
Mit C++14 und den erweiterten constexpr Ausdrücken wäre es leicht möglich. Je nachdem was man genau berechnen will. Aber dieses Feature braucht so wie es aussieht ggc 5 und die Arduino IDE hat höchstens 4.9

D. h., dass das, was Haribo möchte, nicht möglich ist, wenn man ausschließlich die Arduino-IDE benutzt?

Als Workaround fällt mir gerade nur ein, dass man den zu berechnenden Teil als separates Programm schreibt und dessen Ausgabe (irgendein *.txt) per #include einbindet.

Gruß

Gregor

Haribo68:
Hi,

ich weis das es möglich ist aber noch nicht genau wie.
Während des kompilierens Konstanten für PROGMEM in einer For-Schleife berechnen lassen, wie geht das?

Vielen Dank im Voraus

MfG
Andi

Haribo68:
Hi,

ich weis das es möglich ist aber noch nicht genau wie.
Während des kompilierens Konstanten für PROGMEM in einer For-Schleife berechnen lassen, wie geht das?

Diese Fragestellung hört sich für mich nach völligem Bullshit an.

"Konstanten für PROGMEM " sind Bestandteil des Programms, und wenn diese als solche ins Programm eingebunden und in den Programmspeicher hochgeladen werden sollen, müssen diese VOR dem Kompilieren feststehen.

Außerdem zeichnen sich "Konstanten" von der Begrifflichkeit her dadurch aus, daß sie konstant sind. Und als Konstenten haben sie VOR, WÄHREND und NACH dem Kompilieren immer denselben wert. Wenn irgendwas berechnet wird und im Rahmen einer Berechnung den Wert ändert, ist es von meinem Sprachverständnis her eine Variable und keine Konstante.

Was Du im PROGMEM haben könntest, wären "berechnete Konstanten", aber in dem Fall können diese berechneten Konstanten nur auf anderen Konstanten beruhen, die im Programm stehen, und sie können auch nicht "in einer for-Schleife" berechnet werden, sondern nur von Fall zu Fall mit Anweisungen für den Präprozessor, z.B. mittels #define.

Viellicht kannst Du noch mal ausführlicher erklären, was Du eigentlich machen möchtest.
Und vielleicht fällt dann jemandem etwas dazu ein.
In vielen Fällen dürfte es in diesem Forum einfach nur die abseitige und verquere Fragestellung sein, die qualifizierte und zielführende Antworten unterbindet.

jurs:
FDiese Fragestellung hört sich für mich nach völligem Bullshit an.

Wundert Dich das etwa?! Wenn man etwas nicht weiß, ist es nicht unüblich, dass man Fragen stellt, die sich für einen Wissenden als Bullshit anhören.

Gruß :wink:

Gregor

jurs:
Diese Fragestellung hört sich für mich nach völligem Bullshit an.

Ist es überhaupt nicht. Es gibt Anwendungen wo man eine Tabelle berechnen möchte weil man die Werte nicht so einfach weiß. Wieso also nicht dem Compiler mitteilen das auszurechnen und dann direkt in das Programm einzutragen

Und es gibt in modernen C++ Mittel um Dinge wirklich vom Compiler ausrechnen zu lassen. Templates machen auch nichts anderes.

gregorss:
D. h., dass das, was Haribo möchte, nicht möglich ist, wenn man ausschließlich die Arduino-IDE benutzt?

Kommt drauf an welches Board man benutzt. Der Teensy benutzt mittlerweile schon g++ 5.4, da sollte man durch Ändern der boards.txt mit C++14 arbeiten können.

OK,

wenn man nicht weis wie das Ergebnis ist weis man auch nicht immer wie man fragen soll, aber egal.

Ich meinte sowas wie das hier:

const float rad=Pi/1800;

const PROGMEM uint16_t sinusTab[901] = sin(rad*???[???])*32768;

Im Prinzip ein Auffüllen der Variable sinusTab die im Flash ist.
Keine Ahnung wie das gehen soll.
In jedem Index muss ein anderer Wert rein aber automatisch.
Es sollen umgerechnete Winkel-Werte in 1/10 Grad sein.
Im RAM hab ich es schon getestet und im Setup mit einer For-Schleife aufgefüllt.

MfG
Andi

So einfach nicht, weil normale Berechnungen eben zur Laufzeit ausgeführt werden. Du kannst dir aber recht einfach ein Programm schreiben, dass die Werte berechnet und als Text ausgibt und zwar so formatiert dass du Liste direkt kopieren und in dein eigentliches Programm einfügen kannst.

Serenifly:
Ist es überhaupt nicht. Es gibt Anwendungen wo man eine Tabelle berechnen möchte weil man die Werte nicht so einfach weiß. Wieso also nicht dem Compiler mitteilen das auszurechnen und dann direkt in das Programm einzutragen

Und es gibt in modernen C++ Mittel um Dinge wirklich vom Compiler ausrechnen zu lassen

Sowas würde ich eher ganz klassisch machen: Zuerst mache ich mir eine Rechenfunktion mit serieller Ausgabe, die mir die zu berechnenden Daten auf Serial ausgibt. Serielle Ausgabe dann beispielsweise:

byte konstanten[] PROGMEM = {128, 
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 
};

Das Programm mit der Rechenfunktion im setup() lasse ich dann einmal laufen während der serielle Monitor geöffnet ist.

Danach kopiere ich mit den Inhalt aus dem seriellen Monitor in eine neue Tab-Datei in der IDE, die ich beispielsweise "konstanten.h" nenne.

Und in die eigentliche .ino-Sketchdatei inkludiere ich diese Datendatei vom Editor-Tab dann mit
#include "konstanten.h"
und dann habe ich nach dem Kompilieren die Daten im PROGMEM.
Und ein kleines Berchnungsprogramm als Zwischenschritt, das den Code für ein PROGMEM-Array auf Serial ausgibt, sollte ja nun wirklich keine Hürde sein.

Haribo68:
Ich meinte sowas wie das hier:

const float rad=Pi/1800;

const PROGMEM uint16_t sinusTab[901] = sin(rad*???[???])*32768;

Kommt drauf an, ob der Compiler sin() ausführen kann. Nur Schleifen kann er sicher nicht, man müßte also den Ausdruck für jedes Element des Arrays hinschreiben. Dazu ggf. was #definieren, was das Argument nach jeder Berechnung automatisch erhöht.

Mit dem Umweg über eine berechnete Header-Datei funktioniert es jedenfalls immer, und die berechneten Werte können dann auch noch überprüft werden.

Hallo zusammen!

Zwei Zusatzfragen von mir: Sind Schleifenkonstrukte in Form von Präprozessorbefehlen tatsächlich erst seit C++14 standardmäßig möglich? Wieso hat man eine derart allgemeine Sache nicht schon viel früher möglich gemacht?

Gruß

Gregor

Wie sollten solche Schleifenkonstrukte aussehen?

Der normale C Präprozessor sind nur Text-Ersetzungen. Wenn da was zur Compile-Zeit ausgerechnet wird ist das nicht viel oder normale Compiler Optimierungen

constexpr gibt es seit C++11, aber da nur recht eingeschränkt weil die verwendeten Ausdrücke selbst alle konstant sein müssen. Und es geht nur ein einziges return Statement. Man kann z.B. einfache Serien machen wenn man eine Funktion rekursiv aufruft.
C++14 hat das erweitert und erlaubt sehr viel mehr Sprachelemente in den Ausdrücken. Damit kann man dann sowas machen:

template<int N>
struct Data
{
 constexpr Data() : arr()
 {
   for (auto i = 0; i < N; i++)
     arr[i] = i;
 }
 int arr[N];
};

constexpr Data<10> data;

int main()
{
 for (auto x : data.arr)
   cout << x << endl;
}

Geht wie gesagt leider nicht auf dem Arduino und ich bin mir nicht 100%ig sicher ob das dann mit PROGMEM geht. Aber theoretisch schon.

Das hat aber nichts mit dem Präprozessor zu tun, sondern ist ein Feature des Compilers. Der versucht ja schon lange, konstante Ausdrücke zur Compilezeit zu berechnen.

Diese strikte Unterscheidung zwischen Präprozessor und Compiler ist eher ein Relikt aus C Urzeiten. Klar kann man damit vieles machen aber er wird auch missbraucht und der Code ist bei komplexen Sachen oft kryptisch. Außerdem resultiert er in oft völlig unverständlichen Fehlermeldungen. Das heute noch zu erweitern wäre völlig unsinnig.

Viele der neueren Features in C++ zielen ja gerade darauf ab, den Präprozessor immer mehr unnötig zu machen.

DrDiettrich:
Wie sollten solche Schleifenkonstrukte aussehen?

Evtl. verstehe ich Dich falsch oder Deine Frage richtet sich einen Anderen.

Was oder wen meinst Du?

Gruß

Gregor