array mit variablen

Hi,
muss in einem array, dass vor den voids definiert wird, konstante werte enthalten?
Ich habe ien array folgend angelegt:

const int PWMchannel[15] [24] = { { m[0][0], m[0][1], m[0][2], m[0][3], m[0][4], m[0][5], sd[0], 3500, 1500,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, ss[0], m[0][21], m[0][22], m[0][23] }, 
                                  { m[1][0], m[1][1], m[1][2], m[1][3], m[1][4], m[1][5], sd[1], 3500, 1500,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, ss[1], m[1][21], m[1][22], m[1][23] },  
....

jetzt teste ich grad und merke, dass zB ss[0] nicht verändert wird, bzw. kein wert erkannt wird (also immer =0)

ist das richtig so? Wie kann ich das dann machen?

Sind denn die Werte von m[0][0] oder ss[0] schon vorher definiert? Dann sollten auch in PWMchannel[][] die gleichen Werte drin stehen.
Falls Du aber willst, das m[0][0] oder ss[0] in der Definition von PWMchannel[][] quasi Verweise auf Werte sind, die an einer anderen Stelle definiert sind, funktioniert das so nicht.

Du hast zwei Möglichkeiten. Entweder Du verwendest im Array PWMchannel[][] Zeiger die auf die tatsächlichen Werte zeigen, dann musst Du aber anders auf die Werte zugreifen (Stichwort dereferenzieren), oder Du kopierst die Werte bei jeder Änderung im Deinen Arrays m[][] und s[] auch gleichzeitig wieder an die passende Stelle in PWMchannel[][].
Mario.

Hi,

die Werte m[0][0] etc. verändern sich im Laufe einer Stunde. Also es sind nicht die gleichen Werte.

Was meinst du mit kopieren? Mach ich das nicht indirekt indem ich irgendwo im code m[0][0] = 12345 definiere?
Werde mal nach dereferenzieren googlen.

VG

currymuetze:
die Werte m[0][0] etc. verändern sich im Laufe einer Stunde. Also es sind nicht die gleichen Werte.
Was meinst du mit kopieren? Mach ich das nicht indirekt indem ich irgendwo im code m[0][0] = 12345 definiere?

Nein, machst Du nicht. Bei der Zuweisung der Daten in Dein Array PWMchannel[][] werden die aktuellen Werte aus m[][] und s[] an die Stellen kopiert. Der Wert existiert dann zwei Mal im Speicher. Einmal an der Stelle wo z.B. das Array s[] ihn speichert und einmal an der Stelle wo das Array PWMchannel[][] ihn speichert. Änderst Du nun einen der Werte, hat das keinen Einfluss auf den anderen Wert.

Mit Kopieren meine ich folgendes. Du definierst Dir eine Funktion "void fillPWMchannel()" der Du die beiden aktuellen Arrays s[] und m[][] übergibst (am besten als Zeiger oder Referenz, wegen des Speicherverbrauchs) und das dann Deine bisher "statische" Zuweisung entsprechend ausführt und die Werte von s[] und m[][] an die passenden Stellen von PWMchannel[][] schreibt.

Ich rate mal, du willst mit einem Array von Pointern auf andere Stellen (anderen Arrays) zeigen, so dass, wenn sich dort was ändert ( Beispiel m[0][0] ) ,
auch der Wert PWMChannel[0][0] ändert ???

Das mit dem Array von Zeigern ist machbar, aber so wie du fragst, lass lieber die Finger davon ( oder du wirst in den nächsten Wochen c-Guru :wink:

Wenn PWMChannel Zeiger sind, musst du sie als int* definieren und mit *PWMChannel[ i ][ j ] den Wert abfragen. ( Das meint mkl mit "dereferenzieren" )

Umkopieren, wenn sich ein Wert ändert, macht nicht viel Sinn, finde ich.
Aber für jede Zahl einen Zeiger definieren, braucht den doppelten Speicher... und Konstanten ( 3500 ) wären dann auch Zeiger auf Konstanten.

Warum willst / kanst du nicht die Original-Variablen-Namen ( ss[0] ) nehmen ?

Und, was meinst du mit > "vor den voids definiert " in deinem ersten Post ???
Vielleicht erzählst du, was das Ganze soll :slight_smile: ?

edit: [ i ] braucht Leerzeichen, wenn's als solches gemeint ist ; )

Vor den voids bedeutet vermutlich vor der Definition von "void setup()" und "void loop()".

Hi,
ok, ist wohl doch etwas komplexer, also kurz ein paar mehr Details:

Mein code funktioniert so, dass ich RTC gesteuert stündlich 2 Dimmwerte abfrage: z.B. pwmchannel[0][hour] und pwmchannel[0][hour+1].
Dahinter liegt dann eine Methode, die meine LED uhrzeitgesteuert hoch/runterdimmt, indem die beiden Werte verglichen werden:
Sieht so aus:

void fadeLight() {
  for (pinCount=0; pinCount<15; pinCount++) {
    if (hour<23) bruch[pinCount] = (float)3600 / (PWMchannel[pinCount][hour+1] - PWMchannel[pinCount][hour]);
    if (hour==23) bruch[pinCount] = (float)3600 / (PWMchannel[pinCount][0] - PWMchannel[pinCount][hour]);
    i[pinCount] = PWMchannel[pinCount][hour] + ((3600 - (3600 - ((mins * 60) + (sec * 1)))) / bruch[pinCount]);
  } 
}

Was damit allerdings nicht geht, ist dass ich quasi auf minutenbasis dimme, sprich ich möcht zu bestimmten Stunden noch etwas genauer dimmen, also in 10 Minuten Abständen bestimmte Werte angeben können.
Dazu habe ich mir eine neue FUnktion und entsprehcendes Array gebaut:

                                //  0   | 10  | 20  | 30  | 40  | 50
const int SunSetValues[5] [6] = { { 3500, 3600, 4095, 4095, 4095, 4095 },
                                  { 3500, 3600, 3700, 4095, 4095, 4095 },
                                  { 3500, 3600, 3700, 3800, 4095, 4095 },
                                  { 3500, 3600, 3700, 3800, 3900, 4095 },
                                  { 3500, 3600, 3700, 3800, 3900, 3950 } };

void SunSet() {
  if (mins<50) {
    for (pinCount=0; pinCount<5; pinCount++) {
      if (mins==0 || mins%10==0) {
        bruchss[pinCount] = (float)600 / (SunSetValues[pinCount][(mins/10)+1] - SunSetValues[pinCount][(mins/10)]);
        valuess[pinCount] = SunSetValues[pinCount][(mins/10)]; /// Zwischenlagerung des Wertes für mins/10
      }
      ss[pinCount] = valuess[pinCount] + ((600 - (600 - (((mins%10) * 60) + (sec * 1)))) / bruchss[pinCount]); //mins%10 => was bei mins = 0?? oder 1???
    }
  }
  if (mins>=50) {
    for (pinCount=0; pinCount<5; pinCount++) {
      if (pinCount<4) ss[pinCount] = 4095;
      if (pinCount==4) {
        if (mins%10==0) {
          bruchss[pinCount] = (float)600 / (m[4][hour] - SunSetValues[pinCount][(mins/10)]);
          valuess[pinCount] = SunSetValues[pinCount][(mins/10)]; 
        }
        ss[pinCount] = valuess[pinCount] + ((600 - (600 - (((mins%10) * 60) + (sec * 1)))) / bruchss[pinCount]);
      }
    }
  }
}

Die ganze Berechnung und soweiter funktioniert perfekt. Nur halt nicht dass die Werte in meine Hauptarray übergeben werden. Daran scheitert es.

VG

wohl doch etwas komplexer

Meine volle Zustimmung :wink:
Was ich verstanden hab:

  • PWMchannel enthält Stundenwerte, lineares Interpolieren ist dir aber zu grob.

Was ich nicht verstanden habe:

  • bruch ist nur eine temporäre Variable, warum ein array, warum global, warum float ?
  • das Ergebnis von fadeLight wird in einem globalen Array namens i abgelegt. Das glaub ich nicht ?!
  • was ist dein "Hauptarray"
  • Damit du eine feinere Auflösung kriegst, willst du dynamisch diese Stundenwerte ändern ?

Funktionen heissen Funktionen, weil sie aus Eingangswerten etwas berechnen und das als Ergebnis zurückliefern.

Ich könnte mir gut eine Funktion
** ** int fadeLight(const int * PWMHours, int hour, int minute)** **
vorstellen, die du für jeden Channel einmal aufrufst und die gar keine globalen Variablen braucht, weil sie die benötigten Stundenwerte gleich mitgeliefert bekommt und dadurch für jeden Channel verwendbar ist.

Hi,
also was mir wichtig war bei der Funktion: Wenn der arduino mal ausfällt und wieder angeht, soll er direkt mit dem korrekten PWM Wert starten. Darum hab ich das in Abhängigkeit von der RTC gemacht. Das nur am Rande, das funktioniert super.

Im Array PWM Channel habe ich die Start/Endzeiten pro Stunde gespeichert. SO kann der Arduino um 17:11:25 sich den korrekten Wert ziehen, der zwischen 17 und 18h errechnet wird. Das wird hier linear interpoliert, das ist richtig.

allerdings möchte ich gerne zu bestimmten Uhrzeiten den Fade etwas feiner gestalten. Daher habe ich da ne Variable eingefügt, die dann widerrum über eine 2te FUnktion errechnet wird.

Zu deinen Fragen:

  • bruch ist in der tat temporär. Ich definiere irgendwie immer alle variablen global. Ist das kontraproduktiv? Float musste sein, da die zwischenergebnisse auch nachkommastellen liefern. Hatte da hin und her probiert und nur mit float klappte es.

  • was meinst du mit "glaub ich nicht"? Ist das nicht sinnvoll? i[] ist der Wert, der dann an den TLC weitergegeben wird.

  • das Hauptarray ist das PWM Channel

  • genau - an bestimmten Zeiten will ich nen feineren Sonnenauf/untergang simulieren. (das ganze ist für ne Aquariumbeleuchtung)

VG

michael_x:
Funktionen heissen Funktionen, weil sie aus Eingangswerten etwas berechnen und das als Ergebnis zurückliefern.

Ich könnte mir gut eine Funktion
** ** int fadeLight(const int * PWMHours, int hour, int minute)** **
vorstellen, die du für jeden Channel einmal aufrufst und die gar keine globalen Variablen braucht, weil sie die benötigten Stundenwerte gleich mitgeliefert bekommt und dadurch für jeden Channel verwendbar ist.

so ganz seh ich den vorteil noch nicht... das array bleibt doch dann inkl. der arrays/variablen im array?

Wie ist der Ansatz hier?

void PWMvalue() {
  for (pinCount=0; pinCount<15; pinCount++) {
    i[pinCount] = fadeLight(mins, sec, PWMchannel[pinCount][hour+1], PWMchannel[pinCount][hour]);
  }
} 
 
int fadeLight(int minute, int sekunde, const int* PWMvaluebald, const int* PWMvaluejetzt) {
  float bruch = (float)3600 / WMvaluebald - PWMvaluejetzt;
  int result;
  result = PWMvaluejetzt + ((3600 - (3600 - ((minuten * 60) + (sekunden * 1)))) / bruch);
  return result;
}

so ganz seh ich den vorteil noch nicht

Der Vorteil liegt im Verständnis des Ganzen.

Ich definiere irgendwie immer alle variablen global. Ist das kontraproduktiv?

Du hast natürlich recht, in der Arduino Umgebung ist es strenggenommen egal. Die Funktionen werden nur nacheinander aufgerufen, und können daher auch mit globalen Variablen arbeiten.

Üblich ist das nicht :wink:
Puristen kommen (fast) ganz ohne globale Variable aus, andere verwenden sie für Sachen, die globale Bedeutung haben.
i ist ein schöner Name für einen Schleifenzähler, dessen Wert man nach 3 Zeilen Code nicht mehr braucht, und der danach auch nicht mehr definiert ist.
Generell sollten Variable nur dort sichtbar sein, wo sie gebraucht werden. Das hilft, das Programm verständlicher zu halten und vermeidet manchmal schwer zu findende Fehler.

Einer Funktion y = f(x); sieht man sofort an, dass sie - abhängig von dem Wert von x, einen Ergebnis-Wert für y ermittelt, der danach dort drin steht.
Dass in Wirklichkeit f() irgendwas geheimes macht - in einer globalen Variablen mit dem sehr aussagekräftigen Namen i , etwas abspeichert, kann man nicht so leicht erraten.

Wenn der arduino mal ausfällt und wieder angeht, soll er direkt mit dem korrekten PWM Wert starten

Das ist schon der richtige Ansatz.
Aber eigentlich ist die Aufgabe doch einfach, dann sollte man auch versuchen, eine einfache Lösung zu finden...
Ich finde, fadeLight() sieht schon einfacher aus als vorher :wink:
Wenn ich jetzt noch verstehe, wofür du PWMvalue() brauchst ( bzw. das i[] Array ) ?
Wann werden denn die 5 Channels miteinander verknüpft ?

Hi,

also i[] ist dann die Ausgabe an den TLC, ein array, da ich 14 Kanäle nutze.

void setLight() {
  for (pinCount=0; pinCount<14; pinCount++) {
      Tlc.set(LED[pinCount], i[pinCount]);
      Tlc.update();
      brightness[pinCount]=map(i[pinCount], 0, 4095, 100, 0);
  }
}

Ich habe das bewusst in eine eigene void (und nicht mit in fadeLight) geschrieben. Wenn ich zB manuell alle blauen LEDs einschalten möchte, dann soll trotzdem im Hintergrund noch die normale fadeLight weiterlaufen.

PWMvalue wäre jetzt der PWM Wert, der aus meinem großem array übergeben werden soll an die FUnktion. Also der PWMwert der aktuellen Stunde und der Stunde+1.

Ganz genau habe ich das mit dem int* noch nicht verstanden - ist das hier notwendig? (const int* PWMvaluebald)

Ganz genau habe ich das mit dem int* noch nicht verstanden

Du übergibst ein Array aus mehreren int, das ist für die aufgerufene Funktion das gleiche ein Zeiger auf das erste Element.

const ist nur ein Hinweis, dass die Adresse nicht verwendet wird, um dort etwas zu überschreiben. Das kann dann schon der Compiler überwachen.

Wenn ich zB manuell alle blauen LEDs einschalten möchte, dann soll trotzdem im Hintergrund noch die normale fadeLight weiterlaufen.

Dann ist i also der zentrale Speicher, in dem der jeweilige Zustand pro Pin abgelegt wird, egal wer es gerade ändert?!

Da ist eine globale Variable nicht schlecht ( wenn man kein Purist ist ; ).
Das "Hauptarray", das du mal erwähnt hast, ich aber nicht so ganz verstanden hab ?

Ein toller Name ! Nur noch von einer Variable namens _ zu toppen --- Hoffe du bist nicht eingeschnappt :wink:

Eine Funktion, die diesen Wert ändert, kann trotzdem als

const int pinCount=15;
...
for (pin=0; pin<pinCount; pin++) 
   i[pin] = PMValue(pin);

geschrieben werden. Aber - wie schon vorher erwähnt - in der Arduino Umgebung ist es strenggenommen egal.

Ein toller Name ! Nur noch von einer Variable namens _ zu toppen --- Hoffe du bist nicht eingeschnappt

Du meinst PWMchannel[][] ?? Was ist daran so schlimm als variable namen?
Eingeschnappt? Nö - ich freu mich ja eher über TIpps und Lösungsvorschläge, dann gerne auch Verbesserungen :wink:

Ich glaube aber, dass ich mit der Funktion mehr oder weniger klar komme (int fadelight)....
Allerdings im VOrfeld eine Frage dazu:
Kann ich in einem FUnktionsaufruf, wo ich die Variablen übergebe (zB int funktion (a,b,c,d) ) bereits eine weitere FUnktion aufrufen, um den Wert zu bekommen? Also:
int funktion (a,b,funktion2(a,b,c,d), d) ???
Gruß

ich meinte [b] i[pinCount][/b]

Kann ich in einem FUnktionsaufruf, wo ich die Variablen übergebe (zB int funktion (a,b,c,d) ) bereits eine weitere FUnktion aufrufen, um den Wert zu bekommen? Also:
int funktion (a,b,funktion2(a,b,c,d), d) ???

Ja, wenn's keine void funktion2 ist und der Ergebnis-Typ passt

alles klar, rest teste ich erst mal, bei weitern fragen werd ich mich bestimmt wieder melden :wink:
danke schon mal

Hi Michael,

hab alles hinbekommen, läuft alles. Super und vielen Dank.
Werd jetzt mal meinen Code aufräumen, schauen wo ich weitere FUnktionen nutzen kann, globale Variblen besser benennen (als nur ''i") und minimieren.

Gruß