Forum: Mikrocontroller und Digitale Elektronik #define Makrogrosse begrenzt


von Ma B. (drumstick)


Lesenswert?

Guten Tag!

Ich habe eine Frage, ich arbeite mit dem uVision von Keil.
1
#define MAXVALCUR   700000
2
float   save_currCW[MAXVALCUR] = {0};

Error: L6406E: No space in execution regions with .ANY selector 
matching.
Error: L6407E: Sections of aggregate size 0xaae600 bytes could not fit 
into .ANY selector(s).

Wo ist die Grenze derPräprozessormakrogrösse. Oder bezieht sich der 
Fehler auf das Array? Der Wertebereich reicht doch aus??

Vielen Dank!

M.B.

von Peter II (Gast)


Lesenswert?

M. B. schrieb:
> Wo ist die Grenze derPräprozessormakrogrösse.
nirgends

> Oder bezieht sich der Fehler auf das Array?
richtig erkannt.

> Der Wertebereich reicht doch aus??
welcher Wertebereich? Du hast einfach nciht genug RAM für
700000 * sizof(float)

von Ma B. (drumstick)


Lesenswert?

Ah, ok!

Vielen Dank!

Gruss

von Oliver (Gast)


Lesenswert?

Und du bist dir wirklich sicher, daß du ein Array mit 700.000 (in 
Worten: Siebenhunderttausend) float-Werten anlegen willst, und das auch 
benötigst?

Oliver

von Peter S. (psavr)


Lesenswert?

Der Fehler bezieht sich sehr wahrscheinlich auf die Arraygrösse. Typisch 
der Index ein int sein, je nach Compiler und CPU ist das dann Maximal 
32768.

Etwas seltsam: 700'000 = 0x00A'AE60, Der Compiler/Linker meckert aber 
über einen 16 x höheren Wert:  Sections of aggregate size 0x00AA'E600 
bytes

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wenn `int' ein 16-bit-Typ ist, dann ist der größtmögliche
Array-Index 32767, da die Indizierung in C immer mit dem Typ `int'
erfolgt (und auch immer vorzeichenbehaftet ist, denn ptr[-1] ist
eine gültige Operation).

("Keil uVision" allein genügt nicht um festzustellen, welche
Datentypen die Zielplattform wirklich hat.)

Selbst für eine 32-bit-Plattform sind 700000 floats aber schon
heftig viel.  Internen SRAM von mehr als 2 MiB dürfte kaum ein
Controller haben.  Die Benutzung externen RAMs muss man dem Compiler
(bzw. Linker) sicher irgendwo anzeigen.

von Ma B. (drumstick)


Lesenswert?

Ich mach eine Strommessung auf einer Länge von 3600mm, der Task wird 
alle 70us durchlaufen. ergibt 680000 Messungen. Jetzt mach ich halt alle 
150 zyklen eine Messung. Die Messung sollte einfach möglichst genau 
sein.

von Ma B. (drumstick)


Lesenswert?

Ich verwende den STM32F103VCT.

von Yalu X. (yalu) (Moderator)


Lesenswert?

M. B. schrieb:
> Error: L6407E: Sections of aggregate size 0xaae600 bytes could not fit
> into .ANY selector(s).

Die Zahl 0xaae600 (=4·700000·sizeof(float)) deutet darauf hin, dass du
nicht nur ein Float-Array mit 700000 Elementen angelegt hast, sondern
gleich vier davon. Wieviel RAM hast du denn insgesamt?

von Andreas D. (rackandboneman)


Lesenswert?

@Jörg sicher dass es nicht size_t ist?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Andy D. schrieb:
> @Jörg sicher dass es nicht size_t ist?

Ja, da size_t unsigned ist, die Array-Indizierung aber (wie oben
erläutert) vorzeichenbehaftet ist, bin ich mir da sehr sicher.

von Purzel H. (hacky)


Lesenswert?

Weshalb float? Ein ADC gibt sicher nicht Float raus. Allenfalls Word, 
und dann benoetigt man nur noch die Haelfte Speicher.

von Peter D. (peda)


Lesenswert?

M. B. schrieb:
> Ich mach eine Strommessung auf einer Länge von 3600mm, der Task wird
> alle 70us durchlaufen. ergibt 680000 Messungen.

Kannst Du mal den Rechenweg erläutern, wie du Darauf kommst?

Auch wenn man aus der PC-Welt kommt, sollte man wissen, daß nicht jeder 
MC mindestens 4GB RAM hat.


M. B. schrieb:
> Die Messung sollte einfach möglichst genau
> sein.

Durch Umwandeln in float bläht sich der Wert nur auf, die Genauigkeit 
bleibt gleich. Wieviel Bit liefert denn Dein AD-Wandler.


Peter

von Andreas D. (rackandboneman)


Lesenswert?

Wahrscheinlich haben wir beide unrecht, es sieht so aus als sei ein 
Index als solcher nicht typisiert.

von Ma B. (drumstick)


Lesenswert?

1
float       current = 0.0;
2
3
float Current_Measure(void)                  //ToDo//                    
4
{                                            
5
  const float resistor = 0.22;
6
  const int   Bits = 4095;
7
  const float voltage = 3.3;
8
  float res = 0.0;
9
  ADC_MotI_Mes =  ADCin.AN_IN;               //Get the measured ADC value
10
  ADC_Value = PWMaverage (ADC_MotI_Mes);
11
  current = ((voltage/Bits*ADC_Value)/resistor);
12
13
  res = current;
14
  return(res);
15
}

1
float currcal = 0;
2
3
tSM_functions SM_UIcal_exe(tSM_functions ms)
4
{
5
  
6
  if(!iStopp)
7
  {
8
    do
9
    {
10
      Motor_CW();
11
      func_ramp_mot(eSMrmpmot_run);
12
      currcal = Current_Measure();
13
      {
14
          static unsigned int i = 0;
15
    
16
          save_currCW[i] = currcal;
17
          i = ++i % MAXVALCUR;
18
      }  
19
    }while(!iStopp);
20
21
 
22
  res.main = eSMUImain_run;
23
  
24
  return(res);
25
}

12 Bit ADC

von Ma B. (drumstick)


Lesenswert?

IRAM1 = 0xC000

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ja, und warum erfolgt die Umrechnung vom 12-Bit-Ergebnis in float 
bereits während der Messung? Wie schon mehrfach angedeutet, ist das 
nicht sinnvoll. Speichere direkt das ADC-Ergebnis (in einem Array aus 
int16_t) und wandle das erst bei der abschließenden Auswertung in 
float um.

von Ma B. (drumstick)


Lesenswert?

ich bilde den Mittelwert direkt vom ADC Wert und übergebe einen int 
Wert. Dann rechne ich das ganze in den Stromwert (float) um. Aber dann 
lege ich ja wieder ein floatwert in ein Array?! einfach nur noch einmal 
statt 2 mal! Das sehe ich ein. Aber dann speichere ich ja trotzdem ein 
float in das Array!?

Das Ziel des ganzen ist ja, wenn der Strom ein gewisses Level erreicht 
hat, muss ich den Motor abschalten. Ich habe den ADC Wert in ein 
Stromwert umgerechnet, um es besser zu visualisieren. Du meinst jetzt 
ich soll den ADC Wert nicht in einen Stromwert umrechnen und ihn mit 
einem int Wert begrenzen? Das gebe viel weniger zu rechnen, es wäre aber 
nicht auf einen Blick ersichtlich, also unübersichtlicher!?

von Oliver (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Speichere direkt das ADC-Ergebnis (in einem Array aus
> int16_t)

700000*2 byte sind 1,3MB. Das braucht immer noch einen ziemlich dicken 
MC.

Oliver

von Peter II (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Wenn `int' ein 16-bit-Typ ist, dann ist der größtmögliche
> Array-Index 32767, da die Indizierung in C immer mit dem Typ `int'
> erfolgt (und auch immer vorzeichenbehaftet ist, denn ptr[-1] ist
> eine gültige Operation).
welcher index ist damit gemeint, der absolute oder der relative.

int 16bit

int a[32001];

a[32000] = 0;

dann muss er ja intern a + 32000*sizoof(int) rechen. damit ist das 
zwischenergebniss aber größer als int. Das ganze wird ja noch schlimmer 
wenn das array nicht int sondern ein noch größere Datentype ist.

von Ma B. (drumstick)


Lesenswert?

Ok, das mit 700000 Messungen in einem Array ablegen kann ich vergessen, 
egal int oder float.!?

von Peter D. (peda)


Lesenswert?

Oliver schrieb:
> 700000*2 byte sind 1,3MB. Das braucht immer noch einen ziemlich dicken
> MC.

Laut Datenblatt hat der STM32F103VC stolze 48kB RAM. Damit ist er schon 
ein Bolide unter den MCs.

Da fehlen also noch einige Byte an 1,3MB.


Peter

von Karl H. (kbuchegg)


Lesenswert?

M. B. schrieb:

> Wert. Dann rechne ich das ganze in den Stromwert (float) um. Aber dann
> lege ich ja wieder ein floatwert in ein Array?!

Wozu?


> Das Ziel des ganzen ist ja, wenn der Strom ein gewisses Level erreicht
> hat, muss ich den Motor abschalten.

Dazu musst du aber nicht den ADC Wert in einen Strom umrechnen. Du 
kannst ja auch diesen gewissen Level in den zugehörigen ADC Wert 
umrechnen und damit den Vergleich machen.

> Ich habe den ADC Wert in ein
> Stromwert umgerechnet, um es besser zu visualisieren.

Du du sowieso eine lineare Funktion hast, ist das doch im Grunde nichts 
anderes als eine entsprechende Achsbeschriftung, wenn du die ADC Werte 
hinmalst. Die Kurve ist ja vollständig identisch, egal ob du sie als 
direkte ADC Werte oder als umgerechnete Stromwerte ausgibst. D.h. 'Ich 
muss visualisieren' ist kein Grund für unnötige Speicherverschwendung.

> einem int Wert begrenzen? Das gebe viel weniger zu rechnen, es wäre aber
> nicht auf einen Blick ersichtlich, also unübersichtlicher!?

Warum soll das unübersichtlich sein?
Alles nur eine Frage der Doku bzw. vernünftiger Variablennamen.

von Oliver (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Laut Datenblatt hat der STM32F103VC stolze 48kB RAM.

Um das ganze dann mal umzudrehen: 48kB Ram sind ausreichen für um die 
24000 16-bit-Werte, oder 12000 32-bit-Werte.

Das liegt nun doch um einiges unter den ursprüglichen 700000 Werten. Da 
sollte man nochmals über das Konzept nachdenken.

Oliver

von Ma B. (drumstick)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Warum soll das unübersichtlich sein?
> Alles nur eine Frage der Doku bzw. vernünftiger Variablennamen.

ja ich weiss jetzt wie ich es mache. Die Vorgabe ist, das auch die 
Hardwareentwickler und Projektleiter auf einen Blick die Software 
verstehen. Aber die sind ja auch nicht auf den Kopf gefallen. Wie Du 
sagtest, eine Sache der richtigen Doku und Darstellung.

Danke für eure Antworten! Wieder etwas gelernt!

Gruss!

M.B.

von Karl H. (kbuchegg)


Lesenswert?

M. B. schrieb:

> ja ich weiss jetzt wie ich es mache. Die Vorgabe ist, das auch die
> Hardwareentwickler und Projektleiter auf einen Blick die Software
> verstehen.

Verpass allen Variablen einen postFix

   current_adc       ist der Messwert Strom-Messwert vom ADC
   current_cur       ist der zugehörige Messwert umgerechnet in einen
                     Strom

   limit_adc         ist der Grenzwert, ausgedrückt in ADC Einheiten
   limit_cur         dasselbe in Strom-Einheiten


Ein Code von
1
   if( current_cur > limit_adc )
kann daher schon mal nicht richtig sein, weil hier falsche Einheiten 
miteinander verrechnet werden. Das eine sind Milliampere, das andere 
sind ADC Werte.

Wohingegen
1
   if( current_cur > limit_cur )
oder
1
   if( current_adc > limit_adc )
richtig sein kann. Links und rechts sind die gleichen 'Einheiten'.

Noch dokumentieren, dass im Variablennamen die 'Einheit' des Messwertes 
enthalten sind, und schon versteht das jeder Techniker oder Ingenieur.

von Purzel H. (hacky)


Lesenswert?

Vieleicht sollte man etwas weiter schauen. 680k Messwerte reinziehen ist 
eine Sache. Und dadann ? alle Sekunden neu anzeigen ? Als Graph, als 
Tabelle ? Auswerten ? Weitergeben ?

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.