Go Down

Topic: Frage zur Array Nutzung (Read 777 times) previous topic - next topic

Loschder

Hallo,

bräuchte eure Hilfe bei der Array Verwendung:

Für eine Bewässerungssteuerung möchte ich die 7 Wochentage über ein graphisches Display (7 Buttons So-Sa) ak/deaktivieren. Hierfür wird ein touchTFT mit der UTFT von Rinky verwendet.
Die eigentliche graphische Einstelloberfläche ist immer gleich, jedoch muss das ganze für 6 unterschiedlichen Zonen sepparat einstellbar sein - hierfür verwende ich "byte currentZone" für die jeweiligen Zonen 0-5.
Eine RTC stellt das byte dow zur Verfügung.
Da auch mehrere Tage pro Zone aktivierbar sein sollen bräuchte ich ein array...richtig?

                            So  Mo  Di  Mi  Do  Fr  Sa
Zone 0            / 0 / 0 / 0 / 0 / 0 / 0 / 0 /
Zone 1             / 0 / 0 / 0 / 0 / 0 / 0 / 0 /
Zone 2            / 0 / 0 / 0 / 0 / 0 / 0 / 0 /
Zone 3            / 0 / 0 / 0 / 0 / 0 / 0 / 0 /
Zone 4            / 0 / 0 / 0 / 0 / 0 / 0 / 0 /
Zone 5            / 0 / 0 / 0 / 0 / 0 / 0 / 0 /

0 = deaktiviert
1 = aktiviert

Es soll NICHT auf TFT angezeigt werden, nur für die Programmlogik.

Wie lege ich das array an, wie greife ich auf die jeweiligen Zellen zum schreiben/lesen zu?


Und wie würde ich zum Schluss den heutigen Wert (dow der RTC) vergleichen ob in der zugehörigen Registerspalte etwas aktiv (auf 1) steht?

Hmm...
....

Serenifly

Du kannst entweder für jede Zone oder für jeden Tag ein Bit eines einzelnen Bytes verwenden. Dann brauchst du nur ein Array aus Bytes

Schuppeste

#2
Mar 25, 2018, 05:30 pm Last Edit: Mar 25, 2018, 05:31 pm by Schuppeste
Kommt drauf an ob das Zonen Byte ein Int mit Wochentagnummer oder ein Byte mit nur einem Bit ist.

Code: [Select]
byte zonen[7];

int DOW=1 //Montag=1

byte DOWbyte= Dowbyte (1 << (7-DOW)) //setzt Bit 6 auf 1 B0100000

for(int z=0; z<6;z++)
{
if(DOWbyte & zonen[z])
Serial.print("EinTreffer, Zone:");
Serial.println(z);
}

Loschder

Hallo Serenifly,

Deine Idee gefällt mir....aber:

Nehmen wir an ich mache mir 7 bytes für die Wochentage

byte SoRegister[5] = {0,0,0,0,0,0}
byte MoRegister[5] = {0,0,0,0,0,0}
byte DiRegister[5] = {0,0,0,0,0,0}
byte MiRegister[5] = {0,0,0,0,0,0}
byte DoRegister[5] = {0,0,0,0,0,0}
byte FrRegister[5] = {0,0,0,0,0,0}
byte SaRegister[5] = {0,0,0,0,0,0}

ich komme mit folgendem Abschnitt an die Programmstelle

Code: [Select]

if (ZonenEinstellung[currentZone] == 3) { 
          //******Abfrage der DOW Tasten******
          if ((x>=10) && (x<=100) && (y>=240) && (y<=290))  {  //wenn Sonntag gedrückt...
          drawFrame(10,240,100,290);
         ->hier soll die So-Zelle der jeweiligen DOWregister umgeschrieben/gemerkt werden
          }
          if ((x>=124) && (x<=214) && (y>=240) && (y<=290))  {  //wenn Montag gedrückt...
          drawFrame(124,240,214,290);
         ->hier soll die Mo-Zelle der jeweiligen DOWregister umgeschrieben/gemerkt werden
          }
          ..........
       


Wie weise ich dann "currentZone" zu?
....

Serenifly

#4
Mar 25, 2018, 05:40 pm Last Edit: Mar 25, 2018, 05:42 pm by Serenifly
Das ist nicht was ich gemeint habe...

Bei deiner Variante kann man einen Zeiger auf das aktuelle Array anlegen. Aber generell ist das einfach schrecklich. Das ist wieder so eine Sache wo krampfhaft versucht wird etwas in Arrays zu zwingen, weil das scheinbar die einzige Datenstruktur ist die man kennt

Loschder

#5
Mar 25, 2018, 05:54 pm Last Edit: Mar 25, 2018, 05:55 pm by Loschder
Das ist nicht was ich gemeint habe...
Dann sag doch mal...
....

Schuppeste

Ich meinte nicht zonenbyte sondern ob dow ein Wochentagnummer oder ein byte mit gesetzten Bit ist.

Loschder

Ich meinte nicht zonenbyte sondern ob dow ein Wochentagnummer oder ein byte mit gesetzten Bit ist.
byte dow gibt 0-6 zurück, 0=So
....

michael_x

#8
Mar 25, 2018, 06:29 pm Last Edit: Mar 25, 2018, 06:34 pm by michael_x
Quote
Hallo Serenifly,
Deine Idee gefällt mir....aber:
... du verstehst es nicht, leider.

Serenifly meinte sowas
byte aktiv [6] ; // Index 0..5 = Zone, je Byte 1 Bit / Wochentag (dow) : 0 = So, 6 = Sa

Für Dummies gibt es dazu bei Arduino die Komfort-Funktion bitRead / bitWrite.

Serenifly hat angedeutet, dass man es auch andersrum machen könnte. Aber das vereinfacht es vermutlich nicht wirklich:

byte aktiv [7] ; // Index 0..6 = dow(0 = So, 6 = Sa ), je Byte 1 Bit/Zone (0..5)

Serenifly


Schuppeste

#10
Mar 25, 2018, 06:51 pm Last Edit: Mar 25, 2018, 07:01 pm by Schuppeste
Mein Beispiel ist doch das gleiche..

da die Bits im Zone Byte sowieso nach Wochentagen angeordnet sind wandelt man den Wochentag in eine Bitstelle im Byte um.

byte DOWbyte= 0;

Dowbyte |= (1 << DOW) // DOWbyte =B0000010; für Montag

in einem Zonenbyte in dem auch Montag aktiv ist steht ja z.B. B00101010


also steppt man die Zonen durch mit

if(DOWbyte & zonenbyte[z]) //prüft ob die Einsen aus dem Zonenbyte auch in DOWbyte vorhanden sind.

Vergleichbar mit:
if (B00101010 & B00000010) //es gelten nur die Einsen im Vergleich & ist Prüf Operator für 1.

Mit 4 Zonen könnte man sogar noch Spielchen mit nem uint32_t machen.

Setzen kann man das auch.. ich würde da ein AVR-Bitmanipulation Tutorial verschlagen.

Ausserdem kann es bis auf den Ram keinen unterschied machen ob man ein Byte oder ein Bit setzt.
Wenn man die 7x7 Bytes Platz hat kann man auch gleich ein byte für 0 und 1 benutzen.







michael_x

Quote
Mein Beispiel ist doch das gleiche..
Das wollte ich nicht abstreiten. Und deine zusätzliche Erläuterung ist auch hilfreich, denke ich.

Quote
Wenn man die 7x7 Bytes Platz hat kann man auch gleich ein byte für 0 und 1 benutzen.
Gern macht man sich einen Knoten ins Hirn mit zweidimensionalen Arrays, wo man mit der Reihenfolge der Indizes durcheinanderkommt. Weiss aber nicht, ob der größere Speicherplatz irgend etwas an Vereinfachung bringt.


Schuppeste

Weiss aber nicht, ob der größere Speicherplatz irgend etwas an Vereinfachung bringt.
Der unterschied ist halt, belegter Ram stört nicht wenn viel Frei ist.

Ausserdem ist es einfacher.

Code: [Select]
int zonentage [7] [7] {
{0, 0, 0, 0, 0, 0, 0},      
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0}};

void setZone(uint8_t zone, uint8_t day)
{
zonentage[zone][day]=1;
}

void rmZone(uint8_t zone, uint8_t day)
{
zonentage[zone][day]=0;
}

boolean testzone(uint8_t zone,uint8_t DOW)
{
if(zonentage[zone][DOW]==1)
return true;
}

michael_x

Du meinst sicher
Code: [Select]
boolean testzone(uint8_t zone,uint8_t DOW)
{
    return zonentage[zone][DOW];
}


Quote
Ausserdem ist es einfacher.
Code: [Select]
bool testzone(uint8_t zone,uint8_t DOW)
{
    return aktiv[zone] & bit(DOW);
}
Kann man jetzt diskutieren, was einfacher ist. Der Compiler hält deins für komplizierter ;)

Ist evtl. auch meine persönliche Abneigung gegen die Überlegung, was nun richtig ist:
  int zonentage[6][7]; // 6 Zeilen mit je 7 Elementen ?
oder umgekehrt?

Dein Argument "Vorhandenen RAM kann man auch nutzen" gilt auch für deinen größeren Flash-Bedarf, da gebe ich dir Recht.



Schuppeste

#14
Mar 26, 2018, 02:30 pm Last Edit: Mar 26, 2018, 02:32 pm by Schuppeste
Nene, der mit dem Multiarray ist nur fürs Anfängerverständnis.

Wie ich ja selbst als erstes vorgeschlagen habe würde ich die Bitvariante nutzen..

Ich meinte halt nur wer sich die Mühe als Anfänger nicht geben will machts so wenn die Ressourcen da sind.


Denke es wäre einfacher die Tage als Bit zu haben, das gilt solange DOW das Suchkriterium ist und nicht immer alle Zonen aktiv sind.. Außerdem sind Zonen erweiterbar, Wochentage müssen nie erweitert werden :D


Go Up