Forum: Compiler & IDEs Konstante durch Variable ersetzen, problem


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Jan S. (Firma: Eigenbau) (vox_equus)


Angehängte Dateien:

Lesenswert?

Guten Tag,
bin daran, die Firmware einer feldorientierten Motorsteuerung von
Microchip auf meine Bedürfnisse abzuändern.
Nun stecke ich an dieser Stelle fest und komme nicht mehr weiter:

#define MAX_PH_ADV_DEG 60
#define MAX_PH_ADV   (int)(((float)MAX_PH_ADV_DEG / 360.0) * 65536.0)

Um die Phasenverschiebung mit einem Poti zu verstellen, möchte diese
zwei Definitionen, also Konstanten als Variablen umdeklarieren, etwa so:

//1:
int MAX_PH_ADV_DEG = 60;

//2:
int MAX_PH_ADV = (int)(((float)MAX_PH_ADV_DEG / 360.0) * 65536.0);

Wenn ich nur die 2: als Variable deklariere, dann akzeptiert der
Compiler dies.
Sobald ich aber die 1: als Variable deklariere, verlangt der Compiler
eine Konstante.
Wie kann man die 2: ändern, so dass eine Variable akzeptiert wird?
Freundliche Grüsse Jan

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Jan S. schrieb:
> Wie kann man die 2: ändern, so dass eine Variable akzeptiert wird?

C++ benutzen 😉

von Jan S. (Firma: Eigenbau) (vox_equus)


Lesenswert?

Niklas G. schrieb:
> Jan S. schrieb:
>> Wie kann man die 2: ändern, so dass eine Variable akzeptiert wird?
>
> C++ benutzen 😉

Das geht nicht, der Compiler für die dsPics ist sehr 
Prozessorspezifisch.
MFG Jan

von Horst V. (hoschti)


Lesenswert?

Solange in der Deklaration gerechnet werden soll, geht das nur mit 
Konstanten. Das wird ja bei der Übersetzung vom Präprozessor/Compiler 
erledigt. Sollen "lebende Werte" verwurschtelt werden, muss das zur 
Laufzeit erfolgen, also per Codezeile(n) innerhalb deines Programms.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Dann wirst du wohl MAX_PH_ADV in einer Initialisierungs-Funktion oder am 
Anfang der main() manuell berechnen & initialisieren müssen.

Allerdings: Im Code wird MAX_PH_ADV_DEG überhaupt nur verwendet um 
MAX_PH_ADV zu initialisieren. Du könntest es auch einfach so machen (und 
MAX_PH_ADV_DEG ganz entfernen):
1
int MAX_PH_ADV = 65536 / 6;

Und dann MAX_PH_ADV direkt per Poti modifizieren. Braucht dann auch 
keine float-Berechnung.

: Bearbeitet durch User
von Jan S. (Firma: Eigenbau) (vox_equus)


Lesenswert?

Horst V. schrieb:
> Solange in der Deklaration gerechnet werden soll, geht das nur mit
> Konstanten. Das wird ja bei der Übersetzung vom Präprozessor/Compiler
> erledigt. Sollen "lebende Werte" verwurschtelt werden, muss das zur
> Laufzeit erfolgen, also per Codezeile(n) innerhalb deines Programms.
Danke für die Antwort, werde versuchen, den Codeschnipsel weiter unten 
einzufügen.
MFG Jan

@ Niklas: Danke, werde ich versuchen, float braucht es aber vermutlich, 
weil der ADC fraktional ausgelesen wird.
MFG Jan

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Jan S. schrieb:
> float braucht es aber vermutlich,
> weil der ADC fraktional ausgelesen wird.

Wäre das nicht eher Fixed-Point?

von Jan S. (Firma: Eigenbau) (vox_equus)


Lesenswert?

Niklas G. schrieb:
> Jan S. schrieb:
>> float braucht es aber vermutlich,
>> weil der ADC fraktional ausgelesen wird.
>
> Wäre das nicht eher Fixed-Point?

Das ADC Ergebnisregister liefert das Ergebnis "big endian" (sagt man, 
glaub ich), also linksseitig.
Später wird der Wert als "signed" gehandelt, um vorwärts- bzw. 
Rückwärtsbetrieb zu generieren, aber ich blicke da noch nicht ganz 
durch.

von Oliver S. (oliverso)


Lesenswert?

Jan S. schrieb:
> Guten Tag,
> bin daran, die Firmware einer feldorientierten Motorsteuerung von
> Microchip auf meine Bedürfnisse abzuändern.
> Nun stecke ich an dieser Stelle fest und komme nicht mehr weiter:
>
> #define MAX_PH_ADV_DEG 60
> #define MAX_PH_ADV   (int)(((float)MAX_PH_ADV_DEG / 360.0) * 65536.0)

Warum?

Oliver

von Monk (roehrmond)


Lesenswert?

Ich würde beides durch eine Funktion ersetzten. Etwa so:
1
int max_ph_adv(float max_ph_adv_deg) {
2
  return max_ph_adv_deg/360.0*65536.0
3
}

Dann ist auch transparent, dass die Berechnung für jeden Wert von 
max_ph_adv_deg erneut stattfinden muss.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Jan S. schrieb:
> Das ADC Ergebnisregister liefert das Ergebnis "big endian" (sagt man,
> glaub ich), also linksseitig.

Das kann dem Prozessor ziemlich wurscht sein, weil der ja wohl 
hoffentlich die gleiche Byte-Reihenfolge wie die Peripherie nutzt.

Jan S. schrieb:
> Später wird der Wert als "signed" gehandelt, um vorwärts- bzw.
> Rückwärtsbetrieb zu generieren,

Das hat dann aber immer noch nichts mit Float zu tun.

Steve van de Grens schrieb:
> Ich würde beides durch eine Funktion ersetzten.

Ich würde mir die wiederholte float-Berechnung ganz sparen. Lieber das 
MAX_PH_ADV mittels Poti um Integer-Werte inkrementieren / 
dekrementieren.

von Jan S. (Firma: Eigenbau) (vox_equus)


Lesenswert?

Steve van de Grens schrieb:
> Ich würde beides durch eine Funktion ersetzten. Etwa so:
> int max_ph_adv(float max_ph_adv_deg) {
>   return max_ph_adv_deg/360.0*65536.0
> }
>
> Dann ist auch transparent, dass die Berechnung für jeden Wert von
> max_ph_adv_deg erneut stattfinden muss.

Danke für Deinen Vorschlag, auch das werde ich probieren. MFG Jan

von Jan S. (Firma: Eigenbau) (vox_equus)


Lesenswert?

Sodele, jetzt wird regelmässig eine Funktion per polling aufgerufen und 
es funzt. Vielen Dank für die inputs.
Mfg Jan

von Adam P. (adamap)


Lesenswert?

Jan S. schrieb:
> Sodele, jetzt wird regelmässig eine Funktion per polling aufgerufen und
> es funzt.

Und wir haben grad erst MO...

Ja, wenn dein Controller sonst nix zu tun hat, kann man das gern so 
machen.
Aber überleg dir lieber mal ob du es nicht durch Interrupt oder PDC / 
DMA oder sonst was lösen möchtest.

Also ich könnte da net ruhig schlafen, wenn das so "dirty" gelöst ist.

Jeder Function-Call kostet zeit. Kann man sich sparen.

edit:
Im besten Fall machst dir ein klein Scheduler der Events von Interrupts 
entgegennimmt und dann die dazugehörige Funktion aufruft.

Nur so mal als Idee.

Klar, für kleine Systeme voll Overplay, aber wenn man es einmal hat, 
will man net mehr drauf verzichten. (eigene Erfahrung)

: Bearbeitet durch User
von Jan S. (Firma: Eigenbau) (vox_equus)


Lesenswert?

Adam P. schrieb:
> Ja, wenn dein Controller sonst nix zu tun hat, kann man das gern so
> machen.
> Aber überleg dir lieber mal ob du es nicht durch Interrupt oder PDC /
> DMA oder sonst was lösen möchtest.
Vielen Dank für den Input.
Das mit dem Interrupt habe ich mir schon überlegt, da aber die von mir 
veränderte Originalfirmware sowieso in einer Endlosschlaufe eine Taste 
zum ein/ausschalten pollt, polle ich als Minimalist gleich noch einen 
anderen Pin. In erster Linie gehts mir darum, den Unterschied der 
Drehzahl des Motors zu ermitteln, wenn Phaseadvance auf dem Maximum ist. 
Die ganze Schaltung habe ich mit der Absicht aufgebaut, einen Einblick 
in die feldorientierte Motorsteuerung zu erhalten.

Freundliche Grüsse Jan

: Bearbeitet durch User
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.