Forum: Digitale Signalverarbeitung / DSP / Machine Learning gleitende Mittelwertbildung Filter funktioniert nicht


von Mark (Gast)


Lesenswert?

Hallo Gemeinde,

ich habe ein Problem mit meinem Filter Aufruf.

Der Code sieht folgendermaßen aus:
1
float Filter_UohneL(float Delta_Alpha)
2
{
3
  
4
  static unsigned long avgsum=0;   
5
  static short n = 0;
6
7
  if (n<15) {
8
    n++;
9
    avgsum += Delta_Alpha;
10
    return avgsum/n;
11
  }
12
  else {
13
    avgsum -= avgsum/15;
14
    avgsum += Delta_Alpha;
15
    return avgsum/15;
16
  }
17
}

Der Aufruf erfolgt folgermaßen in der Main:
1
Delta_Alpha_gefiltert = Filter_UohneL (Delta_Alpha);

Aber wieso wird immer Null zurückgegeben?
Vielen Dank an die Helfenden

von Roland E. (roland0815)


Lesenswert?

Ich kann falsch liegen, aber innerhalb einer Funktion funktioniert

static short n = 0;

nicht oder ist nicht Kompilerübergreifend.

Ersetze es mal (testweise) gegen die klassisce Variante, die Variable zu 
setzen bevor sie das erste mal verwendet wird.

An deiner Steller wäre ausserdem eine for(n=0;n>=15;N++){..} besser.

von Pandur S. (jetztnicht)


Lesenswert?

So ein Problem kann man doch in der IDE Single-Steppen.
Was kam dabei raus ?

von Andreas M. (amesser)


Lesenswert?

Du benutzt einen Integer um einen Float zu Mitteln?

von Clemens L. (c_l)


Lesenswert?

Und du liegst in der Tat falsch. Innerhalb einer Funktion funktioniert 
static genauso wie außerhalb; der einzige Unterschied ist, dass die 
Variable außerhalb nicht sichtbar ist.

Das Problem ist wahrscheinlich, dass Werte kleiner 1.0 abgerundet 
werden.

von Lattice User (Gast)


Lesenswert?

Mark schrieb:
>
> Aber wieso wird immer Null zurückgegeben?

Weil dein Delta_Alphaimmer < 15 ist?
Deklariere avgsum auch als float.


Davon abgesehen ist das kein gleitender Mittelwert (aka Mittelwert der 
letzten n Werte) sondern ein IIR Tiefpassfilter. (IIR = Infinit Impulse 
Response)

von Mark (Gast)


Lesenswert?

Vielen Dank, das Ändern von avgsum in float hat geholfen, danke danke.
Und danke für den Hinweis, dass es keine gleitende Mittelwertbildung 
ist!
DANKE

von Oberlehrer (Gast)


Lesenswert?

Und ausserdem dividerst du durch 0!
Boeser Fehler!

Oberlehrer

von Timo (Gast)


Lesenswert?

?! wieder was dazu gelernt..
Ich dachte in C ist static eine Konstante...
In Pascal kähme hier eine  Fehlermeldung, das die Konstante nicht 
verändert werden könnte..hmmm

von Karl H. (kbuchegg)


Lesenswert?

Oberlehrer schrieb:
> Und ausserdem dividerst du durch 0!

Wo genau soll das sein?

von Oberlehrer (Gast)


Lesenswert?

Da er n nicht zuruecksetzt, laeuft die Variable irgendwann
mal ueber, bzw. wird zu null.

Oberlehrer

von Relais Sucher (Gast)


Lesenswert?

Oberlehrer schrieb:
> Und ausserdem dividerst du durch 0!
> Boeser Fehler!

Nein, das macht er nicht...

von Abfallverwerter (Gast)


Lesenswert?

Oberlehrer schrieb:
> Und ausserdem dividerst du durch 0!

Wo? Zeig mal.

von Timo (Gast)


Lesenswert?

achne..const war eine Konstante :->)

von Relais Sucher (Gast)


Lesenswert?

Oberlehrer schrieb:
> Da er n nicht zuruecksetzt, laeuft die Variable irgendwann
> mal ueber, bzw. wird zu null.

Auch das nicht... ;)

von Karl H. (kbuchegg)


Lesenswert?

Oberlehrer schrieb:
> Da er n nicht zuruecksetzt, laeuft die Variable irgendwann
> mal ueber, bzw. wird zu null.

Auch das nicht.

>
> Oberlehrer

Sag mal, was genau unterrichtest du eigentlich?
Programmierung kanns ja wohl nicht sein

von Stefan (Gast)


Lesenswert?

> Sag mal, was genau unterrichtest du eigentlich?
> Programmierung kanns ja wohl nicht sein

Doch doch, das kann sehr wohl sein. Wenn ich mir anschaue, was meine 
Kinder im Informatikunterricht in der Schule so alles (nicht) gelehrt 
bekommen.

Gruß, Stefan

von Karl H. (kbuchegg)


Lesenswert?

Timo schrieb:
> achne..const war eine Konstante :->)

Vorsicht:
In C ist eine als 'const' markierte Variable nach wie vor eine Variable. 
Allerdings eine von der du die Zusicherung machst, dass du sie in deinem 
Programm nicht verändern wirst. Das 'const' bedeutet in C 'not 
modifiable'.
Es ist KEINE Konstante!

Der Unterschied ist subtil und tritt dann zu Tage, wenn du versuchst 
eine derartige vermeintliche 'Konstante' an Stellen zu verwenden, an 
denen von der Syntax her tatsächlich eine Konstante gefordert wird. Wie 
zb. bei einem 'case' in einem switch-case.

: Bearbeitet durch User
von Oberlehrer (Gast)


Lesenswert?

So wie die Funktion oben beschrieben ist macht sie
kein Mittelwert. Deshalb bin ich davon ausgegangen,
das sie irgendwo von ausserhalb in einer Schleife immer
wieder aufgerufen wird, um einen neuen Mittelwert zu
berechenen. (Warums sonst soll man in der Funktion
Variablen statisch halten?).

N wird bei jedem Aufruf um eins erhoeht, ergo irgendwann
laeuft N mal ueber.

Oberlehrer

von Paul B. (paul_baumann)


Lesenswert?

Karl Heinz schrieb:
> In C ist eine als 'const' markierte Variable nach wie vor eine Variable.
> Allerdings eine von der du die Zusicherung machst, dass du sie in deinem
> Programm nicht verändern wirst. Das 'const' bedeutet in C 'not
> modifiable'.
> Es ist KEINE Konstante!

"C" kommt mir vor, wie die Durchquerung eines Urwaldes voller Schlangen 
und Skorpione in einer mondlosen Nacht ohne Taschenlampe.

MfG Paul

von Karl H. (kbuchegg)


Lesenswert?

Oberlehrer schrieb:
> So wie die Funktion oben beschrieben ist macht sie
> kein Mittelwert. Deshalb bin ich davon ausgegangen,
> das sie irgendwo von ausserhalb in einer Schleife immer
> wieder aufgerufen wird, um einen neuen Mittelwert zu
> berechenen.

So weit so gut,
Zum Beispiel von der Hauptschleife, die den ADC ausliest und die 
sukzessive ermittelten Werte filtern lässt.

> (Warums sonst soll man in der Funktion
> Variablen statisch halten?).

Damit sie von ausserhalb der Funktion nicht zugreifbar sind. Die 
Variablen gehören konzeptionell zu der Funktion und sind nur innerhalb 
der Funktion relevant.
Das ist eigentlich der Standardfall, warum man Variablen static macht.

>
> N wird bei jedem Aufruf um eins erhoeht, ergo irgendwann
> laeuft N mal ueber.

Und das hier
1
  if (n<15) {

zählt gar nichts?

n wird bis 15 hochgezählt (bei jedem erneuten Funktionsaufruf um 1 mehr) 
und bleibt dann bei 15 stehen.

Und der Zweck besteht darin, dass er über die letzten 15 Werte Tiefpass 
filtern möchte, allerdings das Problem hat, dass der ganze Klaperatismus 
ja auch erst mal anlaufen muss. D.h. für die ersten 14 Messwerte kommt 
eine andere Berechnung zum Zug, weil sich ja die Summe der ersten 15 
Werte erst nach und nach mit jedem Funktionsaufruf aufbauen muss. Daher 
wird nicht 1/15 der Summe abgezogen und daher wird da auch noch nicht 
durch 15 dividiert.
Sobald die Funktion das 15.te mal (und folgende) aufgerufen wird ist die 
ganze Sache mit dem n vom Tisch: Ab dann wird von der bisherigen Summe 
1/15 abgezogen, der neue Messwert in die Summe eingerechnet und der 
Durschnitt geliefert.

Eigentlich eine ganz einfache Funktion.

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Oberlehrer schrieb:
> Und ausserdem dividerst du durch 0!
Zwar nicht, aber diese Division ist fast genauso /umständlich/:
Mark schrieb:
> return avgsum/15;

Man sollte sein Zielsystem kennen und wissen, dass so ein Rechenknecht 
im Zweiersystem arbeitet. Dann kommt man pfeilschnell auf die Idee, dass 
eine Filterweite von 16 und damit eine Division durch 16 wesentlich 
geschickter wäre...

Mark schrieb:
> float Filter_UohneL(float Delta_Alpha)
Worauf soll das Ganze nochmal laufen? Kann das Zielsystem mit float 
umgehen?
Falls ja:
> static unsigned long avgsum=0;
Ich würde wenigstens diese lokale Summe dann auch zu einem float 
machen...

Mark schrieb:
> Der Code sieht folgendermaßen aus:
Der kommt mir bekannt vor... ;-)
http://www.lothar-miller.de/s9y/archives/25-Filter-in-C.html

von Matthias L. (Gast)


Lesenswert?

> D.h. für die ersten 14 Messwerte kommt
>eine andere Berechnung zum Zug, weil sich ja die Summe der ersten 15
>Werte erst nach und nach mit jedem Funktionsaufruf aufbauen muss.

hier kann man sich fragen, ob das wichtig ist. Immerhin sinds nur die 
ersten x(15) Werte, wo sich das aufbaut. Evtl. kann man das auch 
ignorieren. So spart man sich einen Vergleich, der bis auf die ersten 
paar Mal nie erfüllt ist...
1
float Filter_UohneL(float NewValue)
2
{
3
  #define  FILTERLEN   15
4
5
  static float ArrayData[FILTERLEN];
6
  static float ArraySum = 0;
7
  static short ArrayIdx = 0;
8
9
  //-- letzten Wert entfernen -----------
10
  ArraySum -= ArrayData[ArrayIdx];
11
12
  //-- neuen Wert eintragen -------------
13
  ArrayIdx++;
14
  if ( ArrayIdx >= FILTERLEN ) ArrayIdx = 0;
15
  ArrayData[ArrayIdx] = NewValue;
16
17
  //-- neue Summe bilden ----------------
18
  ArraySum += ArrayData[ArrayIdx];
19
20
  //-- Wert zurückgeben -----------------
21
  return ( ArraySum / FILTERLEN );
22
}

von karadur (Gast)


Lesenswert?

Hallo

bin ein bisschen aus der Übung, aber beim Aufruf der Funktion wird n=0 
gesetzt. Im IF auf 1 gesetzt und die Funktion verlassen.

Wie soll n hochzählen ?

von Karl H. (kbuchegg)


Lesenswert?

karadur schrieb:
> Hallo
>
> bin ein bisschen aus der Übung, aber beim Aufruf der Funktion wird n=0
> gesetzt. Im IF auf 1 gesetzt und die Funktion verlassen.
>
> Wie soll n hochzählen ?

n ist static!

d.h. die Variable behält ihren Wert auch über mehrere Funktionsaufrufe 
hinweg. Das 0 setzen passiert nur beim ersten Aufruf.

: Bearbeitet durch User
von karadur (Gast)


Lesenswert?

danke

von Stefan (Gast)


Lesenswert?

static, siehe:
http://de.wikipedia.org/wiki/Static_%28Schl%C3%BCsselwort%29

Das kleine Problem dabei:
Die Variablen avgsum und n gibt es nur einmal. Solange die Funktion 
Filter_UohneL() nur an einer einzigen Stelle verwendet wird, gibt es 
kein Problem. Sobald Du aber Dein Programm erweiterst, hast Du ein 
Problem:
1
Delta_Alpha_gefiltert = Filter_UohneL (Delta_Alpha);
2
Delta_Beta_gefiltert  = Filter_UohneL (Delta_Beta);

In avgsum wird jetzt Delta_Alpha_gefiltert UND Delta_Beta_gefiltert 
aufaddiert - was zu falschen Ergebnissen führt.

Gruß, Stefan

von Martin K. (martinko)


Lesenswert?

Matthias Lipinsky schrieb:
>> …
>
>
1
> float Filter_UohneL(float NewValue)
2
> {
3
>   #define  FILTERLEN   15
4
> 
5
>   static float ArrayData[FILTERLEN];
6
>   static float ArraySum = 0;
7
>   static short ArrayIdx = 0;
8
> 
9
>   //-- letzten Wert entfernen -----------
10
>   ArraySum -= ArrayData[ArrayIdx];
11
> 
12
. . .
13
>

Läuft der Dir nicht wegen Rundungsproblemen (float) aus dem Ruder?

Gruß Martin

von Bernd K. (prof7bit)


Lesenswert?

Oberlehrer schrieb:
> N wird bei jedem Aufruf um eins erhoeht

nein.

von W.S. (Gast)


Lesenswert?

Karl Heinz schrieb:
> Es ist KEINE Konstante!

Aber, aber, Karlheinz.
Das kommt nämlich ganz auf die Umstände drauf an. Bei Zeugs, was auf 
deinem PC komplett im RAM läuft, hast du ja Recht, aber initialisierte 
Konstanten landen bei den µC, die ich vor der Nase habe, gnadenlos im 
Flash und bleiben dort auch. Da ist Neese mit Zuweisungen aller Art. 
Allenfalls kriegt man ne Data-Exception auf die Rübe.

Aber die Code-Kostproben, die hier kamen, sind schon grandios...

Eigentlich macht man's etwa so:

typ buf[zweierpotenz];
int zeiger;
typ summe;

void init_me(void)
{ summe = zeiger = 0; }

typ filtere (typ was)
{ typ tmp;

  tmp = summe - buf[zeiger] + was;
  buf[zeiger] = was;
  zeiger = (zeiger+1) & (zweierpotenz-1);
  return tmp>>zweierpotenz;
}

So. Hoffentlich nix vergessen...
Wer will, kann natürlich auch krumme Pufferlängen nehmen, dann ist eben 
ein if(zeiger>=buflenge) zeiger=0 und eine Division am Ende nötig.

W.S.

von W.S. (Gast)


Lesenswert?

Doch was vergessen... ;-)

W.S.

von eProfi (Gast)


Lesenswert?

Das Problem mit dem "ersten Einschwingen" kann man so elegant lösen:
man initialisiert die Summe auf den n-fachen Wert.
Entweder automatisch:
#define FS 64  //Filterstärke
firstTime=1;

im Filter:
if(firstTime){adcSum = FS * adc; firstTime = 0;}
else {adcSum += adc - adcSum / FS;}

Oder beim Initialisieren (z.B. wenn der Wert in etwa bekannt ist).
Oder man nimmt zuerst einen schwachen Filter:
#define FS1 8       //Filterstärke 1
#define FS2 8 * FS1 //Filterstärke 2
firstTimes=16;

if(firstTimes){
  if(firstTimes-- == 16) {adcSum = FS2 * adc;} //Filter setzen
  else {adcSum += FS2 / FS1 * adc - adcSum / FS2;} //schwach filtern
  }
else {adcSum += adc - adcSum / FS2;} //stark filtern

Code wie immer ungetestet, kam mir gerade so in den Sinn  ;-)

Oft ist es besser (genauer), am Ende des Filters adcSum nicht zu 
dividieren, um in den Werte-Bereich von adc zu kommen, sondern direkt 
mit der Summe weiterzurechnen.

> Vorsicht:
> In C ist eine als 'const' markierte Variable nach wie vor eine
> Variable. Allerdings eine von der du die Zusicherung machst,
> dass du sie in deinem Programm nicht verändern wirst. Das
> 'const' bedeutet in C 'not modifiable'. Es ist KEINE Konstante!
Daher ist es besser, Konstanten als Macros zu definieren.

von W.S. (Gast)


Lesenswert?

eProfi schrieb:
> if(firstTimes){

Naja.. meine Meinung dazu ist, den Filterkernel so klein wie möglich zu 
halten. Da ist es eigentlich egal, ob bei den ersten 16 oder 32 Werten 
Murks rauskommt und später läuft das Ganze ja sowieso, da ist dann ne 
Fallabfrage nicht mehr nützlich.

W.S.

von Karl H. (kbuchegg)


Lesenswert?

W.S. schrieb:
> Karl Heinz schrieb:
>> Es ist KEINE Konstante!
>
> Aber, aber, Karlheinz.
> Das kommt nämlich ganz auf die Umstände drauf an.


Du solltest dir endlich mal angewöhnen zu akzeptieren, dass nicht deine 
Compiler Implementierungen definieren, wie C zu funktionieren hat, 
sondern einzig und allein der Standard.

> Bei Zeugs, was auf
> deinem PC komplett im RAM läuft, hast du ja Recht, aber initialisierte
> Konstanten landen bei den µC, die ich vor der Nase habe, gnadenlos im
> Flash und bleiben dort auch.

Und? Ist komplett irrelevant

> Da ist Neese mit Zuweisungen aller Art.
> Allenfalls kriegt man ne Data-Exception auf die Rübe.

Und auch das ist korrekt.
Beim Versuch der Veränderung einer const Variablen landet man in 
'undefined behaviour land'. Hat nur leider nichts damit zu tun, das 
const markierte Variablen in C keine Konstanten sind (im Gegensatz zu 
C++)

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Hat nur leider nichts damit zu tun, das
> const markierte Variablen in C keine Konstanten sind (im Gegensatz zu
> C++)

Vielleicht wird dir der Unterschied (und das wovon ich eigentlich 
spreche) bewusst, wenn du dieses 'Programm' einmal durch den C Compiler 
und einmal durch den C++ Compiler jagst und dir die Fehlermeldungen mal 
ansiehst
1
const int size = 5;
2
3
int data[size];
4
5
int main(int argc, char* argv[])
6
{
7
}

C: illegal. size ist keine Konstante
C++: legal. size ist eine Konstante

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Mich würde da echt brennend interessieren, wie groß der Wert von float 
Delta_Alpha ist. Wenn nämlich die Ganzzahl-Filtersumme kleiner als 15 
ist, dann kommt bei avgsum/15 immer etwas kleineres als 1 und damit 0 
raus.

Ich hatte das schon mal erwähnt, es scheint mir aber ein wenig 
untergegangen zu sein...

: Bearbeitet durch Moderator
von Mark (Gast)


Angehängte Dateien:

Lesenswert?

Ja, Delta_Alpha ist immer kleiner 1.

Der Filter scheint im Betrieb zu funktionieren, nur beim allerersten 
Anschalten werden erst n Werte gesammelt...
Siehe Foto (sorry wegen der Quali).
Das war aber nicht Sinn der Sache..
Jemand Rat?

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:

> Der Filter

Welcher?
In diesem Thread wurden mindestens 3 verschiedene Implementierungen 
gezeigt mit durchaus unterschiedlichen Charakteristiken.

von Mark (Gast)


Lesenswert?

Der aus meinem ersten Beitrag.
Mit avgsum in float geändert.

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:
> Der aus meinem ersten Beitrag.
> Mit avgsum in float geändert.


Nö.
Der sammelt nicht, bis er das erste mal irgendein sinnvolles Resultat 
kriegt. Der tut sein bestes um mit den n Werten, die er vorliegen hat 
einen gefilterten Wert zu kriegen.

Hast du schon mal die Delta Werte numerisch verfolgt?

von Mark (Gast)


Lesenswert?

Numerisch verfolgen ist schlecht.
Aber verdoppele ich "n" so verdoppelt sich auch die "Totzeit" zu Beginn 
des vorherigen Fotos.
Anscheinend ist Delta_alpha zu Beginn, solange n nicht seinen Max Wert 
erreicht hat, wirklich null. Wüsste aber nicht wieso..
komisch..

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:
> Numerisch verfolgen ist schlecht.

Das wiederrum ist ganz schlecht.
Einer der schlimmsten Fehler, den man meiner Meinung nach machen kann, 
ist es sich von Anfang an keine Debugmöglichkeit zu verschaffen, an der 
man auch mal Zahlenwerte rauskriegt. Die Methode 'Stochern im Nebel' war 
zum Debuggen noch nie sehr effektiv.

Kannst du dir die ersten sagen wir mal 20 Werte nicht zb in ein EEPROM 
schreiben lassen und dann später vom EEPROM auslesen? (Benutzt du 
überhaupt einen AVR?)

> Anscheinend ist Delta_alpha zu Beginn, solange n nicht seinen Max Wert
> erreicht hat, wirklich null. Wüsste aber nicht wieso..

Wo kommen die her und was passiert mit dem gefilterten Wert weiter?

: Bearbeitet durch User
von Lattice User (Gast)


Lesenswert?

Karl Heinz schrieb:

> man auch mal Zahlenwerte rauskriegt. Die Methode 'Stochern im Nebel' war
> zum Debuggen noch nie sehr effektiv.
>

1. Versuch im Nebel zu stochern:
1
    return avgsum/((float)n);

von Mark (Gast)


Lesenswert?

Erst mal Danke für den ersten "Nebelstocherer". Leider ohne Erfolg.

Also was ich in etwa mache ist folgendes:

Der Aufruf sieht in der main so aus:
1
Delta_Alpha = PI_ohneL(Id_neu, Id_alt, Imax);
2
Delta_Alpha_gefiltert = Filter_UohneL (Delta_Alpha, Stromregelung);
3
ALPHA_radiant = ALPHA_radiant - Delta_Alpha_gefiltert;
4
ALPHA_ohneL = ALPHA_radiant * 6366.197717;

Ich mache eine Phasenanschnittssteuerung, aber sobald ich n , wie 
gesagt, höher setze, wird zu Beginn mit dem größten Alpha angeschnitten.

PI_ohneL sieht so aus:
1
float PI_ohneL(float Id_neu, float Id_alt, float Imax)    //Für ohne Linearisierung
2
{
3
  
4
  xd = (Imax - Id_neu);
5
  xd_1 = (Imax - Id_alt);
6
  /*
7
  if (PIdurchlauf == 1)   //Um beim ersten Durchlauf P-Anteil nicht zu vernachlässigen
8
  {
9
    xd_1 = 0;
10
    PIdurchlauf = 0;
11
  }  
12
  else  xd_1 = (Imax - Id_alt);
13
*/
14
  TermA = (xd - xd_1);
15
  TermB = k_Ri * TermA;
16
  TermC = T_AB/T_Ri;
17
  TermD = k_Ri * TermC;
18
  TermE = TermC * xd_1;
19
  TermF = TermB + TermE;   
20
  new_u_ist = TermF;
21
        //new_u_ist = (new_u_ist + k_Ri_lin * (xd - xd_1) + k_Ri_lin * T_AB_lin / T_Ri_lin * xd_1) ;
22
23
  u_ohneL = new_u_ist;
24
  
25
  return u_ohneL;    //Übergabe Stellgröße
26
}

Im Grunde funktioniert ja alles, nur eben dass der Start in Abhängigkeit 
von "n" verzögert wird

von Mark (Gast)


Lesenswert?

Okay sorry, vergessen wir das mit dem "n"
Funktioniert jetzt doch, sorry.
Lag wohl doch daran, dass n int war.

von Mark (Gast)


Lesenswert?

Zu früh gefreut.
Nach dem Bespielen (sprich Reset) des uC und starten des Programms läuft 
alles wie es soll.
Nur nach dem erneuten Starten des Programms durch einen Taster steigt 
und fällt die anfängliche Totzeit mit n!?

Was muss ich denn wo nullsetzen?
Mir würde es ja einleuchten, wenn die vorherigen Werte noch gespeichert 
wären, aber wieso die ersten n Werte nach dem fortsetzen des Programms 
mit Null initialisiert werden das verstehe ich nicht.

von Mark (Gast)


Lesenswert?

Wie kann man denn eine static zurücksetzen wenn man möchte?

von Mark (Gast)


Lesenswert?

Und entschuldigung falls ich nerve, aber eine Frage noch:

Funktioniert die Funktion PI_ohneL so wie sie soll?
Weil ich new_u_ist einfach ganz normal als float innerhalb der header 
Datei in der die Funktion geschrieben ist, definiert habe, nicht als 
static..

von Tom (Gast)


Lesenswert?

Karl Heinz schrieb:
> Einer der schlimmsten Fehler, den man meiner Meinung nach machen kann,
> ist es sich von Anfang an keine Debugmöglichkeit zu verschaffen, an der
> man auch mal Zahlenwerte rauskriegt. Die Methode 'Stochern im Nebel' war
> zum Debuggen noch nie sehr effektiv.


Der einzig vernünftige Weg, so etwas komplexes (1) zum Laufen zu 
bekommen, ist, es erst in C auf dem PC zu implementieren, die Funktion 
mit reichlich Testszenarien zu füttern und Diagramme der Ausgabe zu 
malen a la meintest.exe > zahlen.csv und Excel.

Wenn das vernünftige Werte liefert, schiebt man tiefpass.c und 
tiefpass.h einfach in uc-Projekt.


(1) relativ zum Kenntnisstand

von Lattice User (Gast)


Lesenswert?

Mark schrieb:
> Zu früh gefreut.
> Nach dem Bespielen (sprich Reset) des uC und starten des Programms läuft
> alles wie es soll.
> Nur nach dem erneuten Starten des Programms durch einen Taster steigt
> und fällt die anfängliche Totzeit mit n!?
>
> Was muss ich denn wo nullsetzen?
> Mir würde es ja einleuchten, wenn die vorherigen Werte noch gespeichert
> wären, aber wieso die ersten n Werte nach dem fortsetzen des Programms
> mit Null initialisiert werden das verstehe ich nicht.

Sind sie auch. n und avgsum werden nur beim laden des Programms auf 0 
gesetzt. Das ist die schonmal oben angesprochene Falle von static 
Variabblen.

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:
> Wie kann man denn eine static zurücksetzen wenn man möchte?

Gar nicht.
Genau das ist der Sinn der Sache mit 'static', dass du ausserhalb der 
Funktion an diese Variable nicht ran kommst.

Also entweder verpasst du der Funktion ein Argument, mit dem du ihr 
mitteilst: "jetzt gehts von vorne los" oder du machst dir dieses 'n' 
(nenn die Variable aber dann anders) global um in der 
Programmstartsequenz es auf 0 setzen zu können.

> Lag wohl doch daran, dass n int war.

In dem Fall hätte es nur eine einzige Lösung gegeben:
Wenn dein Compiler so verkorkst ist, dass er so etwas einfaches wie eine 
Datentypanpassung (die genau geregelt ist) nicht hinkriegt, dann will 
ich gar nicht wissen, was dieser Compiler noch alles nicht hinkriegt. 
Dann gibt es nur eine Lösung: Diesen Haufen Schrott entsorgen und einen 
wenigstens halbwegs vernünftigen Compiler nehmen.

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:

> Funktioniert die Funktion PI_ohneL so wie sie soll?

Was wird das jetzt eigentlich schon wieder mal?
Schon wieder eine Nachhilfestunde in elementaren C Kentnissen? Denkst du 
nicht, dass du derartige Dinge schon längst beherrschen solltest, ehe du 
dich an dein erstes reales Projekt wagst?

Ich kann immer nur immer wieder den Kopf schütteln. Was waren wir doch 
für Trottel damals, als wir unsere Programmiersprache von der Pieke auf 
gelernt haben. Offenbar braucht mann das ja gar nicht. Seltsam ist immer 
nur, dass es genau wir sind, die dann immer aushelfen müssen. Hmm. Ob da 
wohl ein Zusammenhang besteht?

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Karl Heinz schrieb:
> Du solltest dir endlich mal angewöhnen zu akzeptieren, dass nicht deine
> Compiler Implementierungen definieren, wie C zu funktionieren hat,
> sondern einzig und allein der Standard.

Ach Karlheinz, mir scheint, daß dir mal wieder nach etwas Zoff oder 
zumindest nach etwas Reibung zumute ist. Halte ich für völlig 
überflüssig, aber was soll man machen, wenn ein Mod sich daneben 
benimmt...

Also, das Einzige, was ICH akzeptiere, ist die blutige Praxis. 
Theoretisierendes Geschwafel und Scholastik mag ich nicht. Eher schon 
echte und vorzugsweise mathematische Logik. Deshalb sind die real in 
dieser Welt existierenden Compiler-Implementierungen wichtiger als das 
Wälzen irgend eines Standards - der zumindest für mich in einigen Teilen 
höchst zweifelhaft ist. Und letztendlich sieht es eben genau so aus, 
wie ich das geschrieben habe.

So. Wo const draufsteht, ist auch const drin - und du darfst dich nun 
freuen (oder eher nicht), wenn dir dein Compiler beim Beschreiben einer 
const Entity nicht auf die Finger haut. Du darfst also dir das Nötige 
dafür angewöhnen.

Uff!

Aber mal zum grundsätzlichen Prinzip beim gleitenden Mittelwert als dem 
zweitsimpelsten aller Filter:
1. es ist das am schnellsten berechenbare Filter
2. es ist das einzige, was wirklich formgetreu arbeitet, also keinerlei 
Ripple und keinen Phasengang besitzt
3. es hat wie alle Filter eine konstante Signalverzögerung von 
Taps/FSample. Da kommt man grundsätzlich nicht drum herum.
4. es ist der Sauberkeit zuliebe sicherlich eine gute Idee, den 
Samplepuffer vor Erstverwendung zu nullen, aber wirklich notwendig ist 
es nicht

Ähem.. das simpelste wäre ein IIR Filter:
Meßwert = (AlterMeßwert + AktuellerMeßwert)/2;


W.S.

von Karl H. (kbuchegg)


Lesenswert?

W.S. schrieb:

> So. Wo const draufsteht, ist auch const drin - und du darfst dich nun
> freuen (oder eher nicht), wenn dir dein Compiler beim Beschreiben einer
> const Entity nicht auf die Finger haut.

Ich stelle fest: Du hast kein Wort verstanden.
Wieder mal Halbwissen. Allerdings diesmal gepaart mit 
Selbstüberschätzung.

Du treibst gerade eine tote Sau durchs Dorf. Denn das ...
> wenn dir dein Compiler beim Beschreiben einer const Entity nicht
> auf die Finger haut.
... ist nicht der Unterschied den C zwischen einer 'non modifable 
variable' und einer 'compile-time constant' macht. Auch Flash, ROM, 
EEPROM, PROM, etc. haben damit aus Sicht der Sprache genau gar nichts zu 
tun. Wenn dein Compiler const markierte Variablen ins Flash legt - schön 
für ihn. Genau darum gehts aber nicht.
Es geht darum, dass der Begriff 'Konstante' eine definierte Bedeutung 
hat. Und eine als const markierte Variable, qualifiziert sich nicht für 
diese Bedeutung. Das wiederrum hat Konsequenzen, weil an einigen Stellen 
in der C-Syntax explizit eine Konstante gefordert wird.

: Bearbeitet durch User
von Paul B. (paul_baumann)


Lesenswert?

Nur mal eine kurze Anmerkung, weil ich stutzig geworden bin: Wenn man so 
ein Filter nicht mittels Programm sondern mit Bauelementen realisiert, 
dann muß doch nach dem ersten Einschalten auch erst mal einen Moment 
gewartet werden, bis "hinten raus" brauchbare Sachen kommen.
Warum wollt ihr in dem Programm offenbar mit Gewalt diesen Moment, bis 
15 oder 16 "Stützstellen" eingelaufen sind, nicht abwarten?

(Bitte die Frage in Klartext beantworten, ich kann kein "C" und will 
(und muß) es auch nicht mehr lernen.)

MfG Paul

von Karl H. (kbuchegg)


Lesenswert?

Paul Baumann schrieb:

> gewartet werden, bis "hinten raus" brauchbare Sachen kommen.

'brauchbar' ist aber nicht 'es kommt zuerst mal nur 0 raus'.

> Warum wollt ihr in dem Programm offenbar mit Gewalt diesen Moment, bis
> 15 oder 16 "Stützstellen" eingelaufen sind, nicht abwarten?

jedes Filter muss sich erst mal einschwingen.
Seines tut das offenbar nicht. Und das sollte eigentlich nicht so sein. 
D.h. da gibt es irgendetwas im Programm, was entweder
* fehlerhaft
* oder nicht komplett verstanden
ist. Und das ist kein gutes Zeichen. Dem muss man nachgehen.

> (Bitte die Frage in Klartext beantworten, ich kann kein "C" und will
> (und muß) es auch nicht mehr lernen.)

Das wär in BASCOM auch nicht anders.
Wenn du eine Berechnung hast, von der du weisst, dass sie nicht 0 
ergeben kann und es kommt trotzdem 0 raus, dann ist irgendwo etwas faul.
Das können natürlich auch Eingangsdaten sein, die nicht die Werte haben, 
die man annimmt das sie haben. Im Laufe der Jahre hab ich gelernt, genau 
da als erstes Nachzuhaken: Sind die Werte, die ich in ein System 
reingebe auch wirklich die, die ich die ganze Zeit einfach annehme ohne 
sie gesehen zu haben? Öfter als mir lieb ist, stellt sich nämlich raus: 
Ooops, sie sind es nicht.
Würde hier bedeuten: Der Filter ist vollkommen in Ordnung, aber die 
ersten Datenwerte sind tatsächlich 0.

: Bearbeitet durch User
von $OS (Gast)


Lesenswert?

W.S. schrieb:
> Das kommt nämlich ganz auf die Umstände drauf an. Bei Zeugs, was auf
> deinem PC komplett im RAM läuft, hast du ja Recht, aber initialisierte
> Konstanten landen bei den µC, die ich vor der Nase habe, gnadenlos im
> Flash und bleiben dort auch. Da ist Neese mit Zuweisungen aller Art.
> Allenfalls kriegt man ne Data-Exception auf die Rübe.

$OS kann Const in Readonly Pages tun.

von Mark (Gast)


Lesenswert?

Also an alle sich Beteiligenden schon ein Mal ein recht herzliches 
Dankeschön.
Mir ist bewusst, dass man einfache Sachen von der Programmierumgebung 
simulieren kann (AVR Studio 6). Aber eben nur einfache Sachen, das 
setzen von Bits für INTs oder ADCs geht auch, macht mir aber schon 
wieder keinen Spaß mehr.
Und Formeln habe ich natürlich vorher auch in Exel eingegeben und was 
als Ergebnis rauskommt überprüft.
Eine RS232 Schnittstelle und Ausgabe auf HTerm etc. habe ich in meinem 
Leben auch schon gemacht und halte ich für ziemlich wichtig, aber wenn 
es die Platine nicht zulässt, ist es doof..

C Programmierung habe ich schon das ein oder andere Mal gemacht, aber 
anscheinend zuvor nie mit static Variablen. Zugegeben habe ich den 
Filter aus dem Netz, von dem sich hier auch bereits gemeldeten Person ;)
Trotzdem geht ja anscheinend auch alles mit globalen Variablen, die 
behalten ja ihren Wert auch.. also mein Programm läuft, static war da 
einfach der für mich unnötige Zusatz..
Gebe ich jedem Recht, dass man sich selber mit dem Thema und den 
Grundlagen auseinander setzen muss. Und diese simplen Fragen zu 
Grundlagen tuen mir Leid.
Ich bin beim Durchspielen im Kopf allerdings immer noch nicht ganz 
darauf gekommen, wieso man avgsum und n auf null setzen muss.. Aber es 
geht jetzt so, indem ich sie in der Tasterfunktion nulle.

Aber dazu eine Frage: wieso sollte ich nicht "n" als Variable benutzen?
Das tu ich nämlich. Man benutzt doch auch "i" zB..

Und eine weitere Frage: ist es jetzt ein IIR oder doch ein gleitender 
Mittelwert Filter?

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:

> Aber dazu eine Frage: wieso sollte ich nicht "n" als Variable benutzen?
> Das tu ich nämlich. Man benutzt doch auch "i" zB..

Das kommt drauf an.
In einer Funktion mit optisch überschaubarem Geltungsbereich sind 
einbuchstabige Variablennamen, besonders wenn es sich um Zähler handelt, 
absolut kein Problem.

Wenn aber eine Variable global wird, dann läuft man schnell Gefahr, dass 
in einem anderen Modul es auch eine Variable namens n gibt. Und dann 
kollidiert das ganze. Je größer der Sichtbarkeitsbereich einer Variablen 
ist, desto aussagekräftiger sollte ihr Name sein. Das heisst jetzt 
nicht, dass da Wortmonster entstehen müssen. Aber mit einem 
"nrFilterSamples" kann man auch in einem halben Jahr noch eruieren, was 
der Zweck der Variablen war, und das das mit einem 'n' in der LCD 
Ansteuerung nichts zu tun hat.

EInbuchstabige Variablen benutzt man gerne an Stellen, an denen man eine 
Variable braucht, weil man etwas braucht was sich verändern kann aber 
der genaue Name nicht so wichtig ist. Typischerweise sind das zb die 
Laufvariablen in for-Schleifen; zb bei der Abarbeitung eines Arrays
1
   for( i = 0; i < irgendwas; i++ )
2
     data[i] = ....
hier kommt es nicht wirklich auf den Namen an. Der 'Einsatzbereich' 
dieser Variablen ist überschaubar eng. Ein längerer Name würde keinen 
Lesevorteil bieten. Die Variable i hat keine spezielle spezifische 
Bedeutung.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:

> Eine RS232 Schnittstelle und Ausgabe auf HTerm etc. habe ich in meinem
> Leben auch schon gemacht und halte ich für ziemlich wichtig, aber wenn
> es die Platine nicht zulässt, ist es doof..

Auch nicht, indem du die beiden Pins für die UART kurzerhand und mit 
einem Messer von ihrer jetzigen Aussenbeschaltun befreist und einen 
UARTzugang mit ein paar Drahtstücken und einem auf einem STück 
Lochraster gelötetem MAX232 herstellst?

Ich würde das ins Auge fassen, ehe ich da jetzt Stunden in Rätselraten 
investiere.
Da oben hast du sowieso noch sowas wie einen  PID Regler, wenn ich das 
richtig sehe. Auch bei dem wird sich so eine Ausgabemöglichkeit noch als 
nützlich erweisen um mal zu sehen, wie sich eigentlich die PID Werte 
zeitlich  entwickeln.

: Bearbeitet durch User
von Mark (Gast)


Lesenswert?

Ok, danke für die ausführliche Antwort.

Evtl. werde ich das morgen in Angriff nehmen.
Aber da es ein wirklich winziger SMD uC ist, wird kein Kabel lange daran 
halten..
Na mal sehen.

Und den Filter würde ich einfach VZ1 Filter nennen?
Mit gleitender Mittelwertbildung?

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:
> Ok, danke für die ausführliche Antwort.
>
> Evtl. werde ich das morgen in Angriff nehmen.
> Aber da es ein wirklich winziger SMD uC ist, wird kein Kabel lange daran
> halten..

Es muss nur lang genug halten :-)

> Und den Filter würde ich einfach VZ1 Filter nennen?
> Mit gleitender Mittelwertbildung?

es ist ein IIR Filter. Aber häng dich da jetzt nicht am Namen auf.

von Mark (Gast)


Lesenswert?

Ok, vielen Dank!

von W.S. (Gast)


Lesenswert?

Karl Heinz schrieb:
> Ich stelle fest: Du hast kein Wort verstanden.
> Wieder mal Halbwissen. Allerdings diesmal gepaart mit
> Selbstüberschätzung.

Du agierst nach dem Motto "Haltet den Dieb!.."
Tja, das Halbwissen und die Selbstüberschätzung gebe ich dir postwendend 
zurück. Werde entweder konkret oder laß das Diskutieren mit mir sein.

Manchmal sehe ich bei dir einen Hang zur böswilligen Unterstellung, 
insbesondere bei:
Karl Heinz schrieb:
> ... ist nicht der Unterschied den C zwischen einer 'non modifable
> variable' und einer 'compile-time constant' macht. Auch Flash, ROM..

Ganz konkret, du meinst wohl:
#define Karl  123
im Gegensatz zu
const int Heinz = 456;

Bei letzterem haben sehr wohl Flash, Rom und Konsorten was zu sagen, 
denn dort landet Heinz, vorausgesetzt, es handelt sich um ne Firmware, 
die dort gespeichert wird.

Jaja - beim alten Borland Pascal war das anders, da stand ganz fett in 
der Doku, daß initialisierte Variablen eben nur initialisiert sind und 
man dennoch schreibend drauf zugreifen kann. Also:
const
  Karl = 123;
  Heinz : integer = 456;

Aber das galt für einen Betrieb des Programmes im RAM ohne Schutz für 
das Code- und Konstanten-Segment. Vielleicht ist das bei deinem Free-BSD 
anders, daß man da lustig im Code oder den Konstanten herumschreiben 
kann, ohne vom OS dabei erwischt zu werden.

W.S.

von Yalu X. (yalu) (Moderator)


Lesenswert?

W.S. schrieb:
> Ganz konkret, du meinst wohl:
> #define Karl  123
> im Gegensatz zu
> const int Heinz = 456;

Karl Heinz hat das doch oben anhand eines Beispiel erläutert:
1
const int size = 5;
2
3
int data[size];

Das geht in C nicht (in C++ schon). C erwartet als Größenangabe eines
Arrays einen konstanten Ausdruck.

Eine Variable (in diesem Fall size), auch wenn sie als const deklariert
wurde, ist aber kein konstanter Ausdruck im Sinne von C.

Sie ist es auch nicht, wenn sie vom Compiler/Linker ins Flash gelegt
wurde.

Sie ist es auch nicht, wenn statt des Flash maskenprogrammiertes ROM
verwendet wird.

Sie ist es auch nicht, wenn sie in Granit gemeißelt wurde.

Nicht einmal Diamant wäre hart genug, um aus der Variable einen
konstanten Ausdruck gemäß C-Standard zu machen.

Du kannst es drehen und wenden wie du willst: Obiges Code-Schnipsel ist
einfach kein korrektes C und wird von jedem C-Compiler zurecht angemahnt
werden.

Deswegen sollte man den Unterschied zwischen einer const-deklarierten
Variablen und einem konstanten Ausdruck kennen, egal, auf welcher
Architektur man programmiert.

Man kann jetzt beliebig lange darüber diskutieren, warum das Ganze
unlogisch ist. Ja, es ist unlogisch und wurde deswegen in C++ geändert.
Und es steht jedem, den das stört, frei, von C auf C++ umzusteigen. Der
Umstellungsaufwand ist nicht sehr groß.

: Bearbeitet durch Moderator
von Paul B. (paul_baumann)


Lesenswert?

Yalu X. schrieb:
> Nicht einmal Diamant wäre hart genug, um aus der Variable einen
> konstanten Ausdruck gemäß C-Standard zu machen.

Ich habe immer geahnt, daß C eine harte Sprache ist. Aber/so/ hart 
-nein, das geht über alle Befürchtungen hinaus.
;-)

MfG Paul

von W.S. (Gast)


Lesenswert?

Yalu X. schrieb:
> Das geht in C nicht (in C++ schon). C erwartet als Größenangabe eines
> Arrays einen konstanten Ausdruck.

Ach Yalu, erstmal Dank an dich für Sachlichkeit.

MIR ist das alles durchaus klar. ICH weiß durchaus zu unterscheiden 
zwischen Ausdrücken (inc. konstanten Ausdrücken) einerseits und 
Variablen, die gelegentlich als const Variablen deklariert sind und 
deshalb eben ne Konstante sind bzw. gefälligst sein sollen, wodurch das 
Wort "Variable" eigentlich sachlich falsch ist und besser "Konstante" 
genannt werden sollte.

Karl Heinz schrieb:
> Vorsicht:
> In C ist eine als 'const' markierte Variable nach wie vor eine Variable.
> Allerdings eine von der du die Zusicherung machst, dass du sie in deinem
> Programm nicht verändern wirst. Das 'const' bedeutet in C 'not
> modifiable'.
> Es ist KEINE Konstante!

Da habe wir's: Karl Heinz verwechselt "Konstante" mit "konstanter 
Ausdruck".

Genau DAS DAS DAS ist der elende Aufhänger:

Eine const Variable IST eine Konstante und ihr wurde in ihrer 
Deklaration der Wert eines "konstanten Ausdruckes" zugewiesen. Das hat 
nix mit gemachten Zusicherungen zu tun.

Uff. Ich hoffe, wir haben's jetzt endlich.

Es gibt bei vielen heutigen C-Compilern in dieser Hinsicht ein ganz 
anderes Problem, nämlich, daß man const Variablen ohne typecast (sofern 
technisch möglich) nicht als Argumente für Funktionen verwenden kann, 
ohne vom Compiler angemosert zu werden, "warning: argument xyz looses 
'const' property" oder so ähnlich. Das hat ja bei Harvard-Architekturen 
durchaus seinen Sinn, weil dort ja ein Pointer, der in den Datenbereich 
zeigt, etwas ganz anderes ist als einer, der in den Programm- und 
Konstantenbereich zeigt. AVR's oder PIC's sind da typische Vertreter. 
Aber bei nem ARM nervt sowas.

W.S.

von Yalu X. (yalu) (Moderator)


Lesenswert?

W.S. schrieb:
> Es gibt bei vielen heutigen C-Compilern in dieser Hinsicht ein ganz
> anderes Problem, nämlich, daß man const Variablen ohne typecast (sofern
> technisch möglich) nicht als Argumente für Funktionen verwenden kann,
> ohne vom Compiler angemosert zu werden, "warning: argument xyz looses
> 'const' property" oder so ähnlich.

Das liegt üblicherweise nicht am Compiler, sondern am Programmierer.

In folgendem Beispiel ist my_array als const deklariert, der Formalpara-
meter array von func aber nicht:
1
void func(int array[]);
2
3
int main(void) {
4
  const int my_array[3] = { 0, 1, 2 };
5
6
  func(my_array);
7
8
  return 0;
9
}

Beim Aufruf von func mit my_array könnte nun func die Elemente von
my_array überschreiben, was aber wegen der const-Deklaration von
my_array nicht sein darf. Das meckert der Compiler zurecht an.

Das Problem lässt sich dadurch beheben, dass der Formalparameter von
func ebenfalls als const deklariert wird:
1
void func(const int array[]);

Damit verschwindet die Fehlermeldung, es sei denn, func versucht
trotzdem, die Array-Elemente zu ändern. In diesem Fall wird eine
Fehlermeldung beim Kompilieren von func ausgegeben.

Man ist in C aber nicht gezwungen, const-Deklarationen zu verwenden. Nur
wenn man es tut, muss man es konsequent überall im gesamten Code tun.

> Das hat ja bei Harvard-Architekturen durchaus seinen Sinn

Auch hier: Das hat nicht primär etwas mit der Hardwarearchitektur zu
tun. Indem ich eine Variable als const deklariere, teile ich dem
Compiler mit, dass er davon ausgehen kann, dass sie bei jedem Zugriff
denselben Inhalt hat. Der Compiler kann dadurch ggf. Variablenzugriffe
wegoptimieren.

Mit der const-Deklaration bitte ich den Compiler aber auch nachzusehen,
ob in meinem Code die Variable nicht versehentlich doch irgendwo
beschrieben wird. Das wäre dann ein Programmierfehler, und es freut
mich, wenn er bereits zur Compile-Zeit aufgedeckt wird.

Ein const in der Variablendeklaration bedeutet übrigens nicht unbedingt,
dass der Variableninhalt bereits zur Compile-Zeit bekannt ist und die
Variable deswegen im nichtflüchtigen Speicher angelegt werden kann. Es
bedeutet lediglich, dass die Variable, nach dem sie einmal initialisiert
worden ist, für den Rest ihrer Lebensdauer nicht mehr geändert wird. Der
Initialisierungswert muss auch nicht unbedingt ein konstanter Ausdruck
sein.

Beispiel:
1
void func(int n) {
2
  const int n2 = n * n;
3
    .
4
    .
5
}

Hier kann n2 bei jedem Aufruf von func einen anderen Wert annehmen
(abhängig vom Argument n). Bis zum Ende von func kann n2 aber kein neuer
Wert zugewiesen werden.

von M.O. (Gast)


Lesenswert?

Mark schrieb:
> Nur nach dem erneuten Starten des Programms durch einen Taster steigt
> und fällt die anfängliche Totzeit mit n!?

Wie bekommst du da ein n Fakultät in deine Rechnung? Das solltest du 
noch mal genau prüfen.

von W.S. (Gast)


Lesenswert?

Yalu X. schrieb:
> Das Problem lässt sich dadurch beheben, dass der Formalparameter von
> func ebenfalls als const deklariert wird:
> void func(const int array[]);

Na klasse.

So, und nun schreib mal, wie du dir einen Treiber vorstellst, der 
beides ohne Warnung verträgt, z.B. sowas:

bool String_Out(char* P, int UART) {....}

also einen Peripherietreiber, der sowohl den Inhalt von Pufferarrays als 
auch konstante Strings ausgeben kann.

Nee, ich meine hier NICHT NUR sowas:
String_Out("YALU", COM1); //(das geht immer)
sondern eben auch
const char yalu[] = { 'Y','A','L','U',0 };
char buf[120];
...
String_Out(buf, COM2);
und
String_Out(yalu, COM3);

Egal wie du es drehst und wendest, entweder plazierst du bei wenigstens 
einem Aufruf nen Cast oder du mußt mit der Warnung leben. Das war der 
Punkt den ich angesprochen hatte.

W.S.

von Bernd K. (prof7bit)


Lesenswert?

W.S. schrieb:
> So, und nun schreib mal, wie du dir einen Treiber vorstellst, der
> beides ohne Warnung verträgt

Bitteschön:
1
const char fooc[2] = {1, 2};
2
char foov[2] = {1, 2};
3
4
void foofunc(const char* blub) {
5
6
}
7
8
void foobar() {
9
    foofunc(fooc);
10
    foofunc(foov);
11
    foofunc("foo");
12
}

von Yalu X. (yalu) (Moderator)


Lesenswert?

W.S. schrieb:
> Egal wie du es drehst und wendest, entweder plazierst du bei wenigstens
> einem Aufruf nen Cast oder du mußt mit der Warnung leben. Das war der
> Punkt den ich angesprochen hatte.

Wieso hast du das const vor dem char *P nicht einfach mal ausprobiert?
Dann wäre dir vielleicht ein Licht aufgegangen.

Natürlich kannst du jederzeit eine Nicht-Const-Variable in einem
Const-Kontext verwenden, nur umgekehrt nicht.

Oder anders ausgedrückt:

Es ist zwar verboten, eine Const-Variable zu verändern, es ist aber
nicht verboten, eine Nicht-Const-Variable unverändert zu lassen.

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.