Konstante durch Variable ersetzen, problem

(Firma: Eigenbau) #7662004
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

Angehängte Dateien:
Persönliche Seite #7662021
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.

(Firma: Eigenbau) #7662034
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

(Firma: Eigenbau) #7662068
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.

Persönliche Seite #7662078
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.

(Firma: Eigenbau) #7662081
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

#7664440
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)

(Firma: Eigenbau) #7665074
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

#7768510
Lesenswert?

So könnte man alle glücklich machen :

1
//0:
2
#define MY_MAX_PH_ADV_DEG 60
3
//1:
4
int MAX_PH_ADV_DEG = MY_MAX_PH_ADV_DEG;
5
//2:
6
int MAX_PH_ADV = (int)(((float)MY_MAX_PH_ADV_DEG / 360.0) * 65536.0);

Der gewünschte Startwert müsste dann bei 0 eingetragen werden. Wenn man eine Variable davon im Laufe der Programmausführung ändert, sollte man die andere am Besten mit anpassen, sonst kommt man aus dem Staunen über die Ergebnisse vermutlich nicht heraus. :-P

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren