Variablen-Nummerierung, komme hier nicht weiter

Hm, wie erklär ich das?
Also,
ich habe einen Messwert, den möchte ich in einer Variablen speichern.

Nennen wir den Messwert mal P, und die Variablen VP0 bis VP19

erster Schritt nun VP0 = P, klar

eine Stunde später messe ich P erneut und schreibe den Wert in VP1
usw.

Das mache ich, bis ich die 20. Messung in VP19 schreibe.

Die Zeit wird mit millis gemacht, das ist weiter kein Problem.

Die gemessenen Werte ergeben bei mir später über eine map Funktion immer Werte von 0 - 7
VPx kann also Werte von 0-7 enthalten, das ist hier aber nicht kritisch.

x hat Werte von 0-19, und da sind wir schon beim Thema.

Ist es möglich, die Numerierung der Variablen( hier VP) ebenfalls als Variable zu haben?

wenn ich x berechne, und dann sagen möchte b= VPx, geht das?

bei der 21. Messung möchte ich gerne den Wert von VP0 verwerfen.
VP0 bekommt nun den Wert von VP1, VP1 bekommt dann den von VP2 usw.
die 21. Messung wird dann VP19 zugeordnet.

Vor der 22. Mesung wiederholt sich das Spiel VPo wird VP1 usw und die 22. Messung wird VP19

ich stelle mir vor zu sagen
für a = 0 bis a<=18
VPa = VP(a+1)
VP19=P

Ist soetwas denkbar?

Die 20 Werte schreiben eine Zeile voll.
Die Zeile schreibe ich immer ganz
Wert 21 läßt dann alles einmal nach links rücken und steht an Pos 20 ( cursosor also 19, klar )

Funktionen wie z.B. scrollen führen bei mir immer zum ganz oder teilweisen Überschreiben anderer Displayzeilen.
Das wollte ich so um gehen.

Ausserdem könnte man die variablen so auch für die Cursorpositionierung benutzen.

Ich hoffe, ich hab meine Gedankengänge so ausgedrückt, dass der ein- oder andere das nachvollziehen kann.

Danke schon mal vorab

Habe hier mal den bisherigen sketch reingeschrieben.
Laufen tut er schon.
Es geht um den letzten Abschnitt.
Der läuft halt testweise nun, un macht die Zeile auch einmal voll, wurstelt sich aber dann natürlich durchs ganze Display.
Daran feile ich gerade, hoffentlich mit Hilfe von euch.

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#include <Sodaq_BMP085.h>


 /* 
 * Written by skyfox60, but also with some copy paste from the arduino examples
 * 
 * LCD RS pin to digital pin 7
 * LCD Enable pin to digital pin 2
 * LCD D4 pin to digital pin 3
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 5
 * LCD D7 pin to digital pin 6
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 10K resistor 1:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3) thats for the contrast 
 * 10K resistor 2:
 * ends to +5V and ground
 * wiper to pin (pin A1) thats to set the brightness
 * Backlight Anode brightness pin 11
 * GND to Kathode
 * D12 = DHT22 input
 */

#define brightnessPWM 10
#define DHTPIN 12
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

Sodaq_BMP085 bmp;
  float Druck;
  long D;

//Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);
const int rs = 7, en = 2, d4 = 3, d5 = 4, d6 = 5, d7 = 6;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


unsigned long interval = 1000 ;             // use will be named later
unsigned long interval2 = 2000 ;            // Time after which the actual Temp is measured and refresht on display
unsigned long currentMillis = millis() ;    // used to count the time to refresh the actual Temp on display
unsigned long previousMillis = 0 ;          // for the interval of refreshing the actual temp
unsigned long currentgraphMillis = millis() ;    // used to count the time to refresh the actual Temp on display
unsigned long previousgraphMillis = 0 ;          // for the interval of refreshing the actual temp


float tempC = 0.00;              
int Ledpin = 13;                            // not even necessary, used it during debug, but, set temp limit very near to actual temp and you´ll see it flash, but Relais is stable due to smoothing.
                                            // if you switch you Relais with the same condition, it will go on/off/on/off several times before heater is stably switched on. thats why the 1000/60000 Interval is given.
int HUM;
int brightness;
int CP = 0; // cursorposition
int VP; // maps actual pressure to values of 1 to 8 for the grahic display characters
unsigned char valtable[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
int counter //

                                            
// make some custom characters: out of the examples, I just coy/paste it, not all needed here.
byte eight[8] = {
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111
};

byte seven[8] = {
  0b00000,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111
};

byte six[8] = {
  0b00000,
  0b00000,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111
};

byte five[8] = {
  0b00000,
  0b00000,
  0b00000,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111
};

byte four[8] = {
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b11111,
  0b11111,
  0b11111,
  0b11111
};

byte three[8] = {
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b11111,
  0b11111,
  0b11111
};

byte two[8] = {
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b11111,
  0b11111
};

byte one[8] = {
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b11111
};
void setup() 
{
 
  pinMode (Ledpin, OUTPUT);
  pinMode (A1, INPUT);
  analogWrite (brightnessPWM,255);
 
  lcd.begin(20, 4);
  Serial.begin(9600);             //necessary only for debug
  dht.begin();
  bmp.begin();
  
  
  
  lcd.createChar(0, one);       // create a new character    
 
  lcd.createChar(1, two);      // create a new character
 
  lcd.createChar(2, three);     // create a new character
  
  lcd.createChar(3, four);    // create a new character    
  
  lcd.createChar(4, five);      // create a new character   
   
  lcd.createChar(5, six);     // create a new character 

  lcd.createChar(6, seven);     // create a new character

  lcd.createChar(7, eight);     // create a new character
  
  delay(10);                    
  
 
  lcd.clear();
    
 lcd.setCursor(0,0);

 int HUM = dht.readHumidity();
 
 delay(3000);
 //lcd.clear();     
}

//finally getting started
  
  void loop() 
  {

  int B = analogRead (A1);   
  //Serial.println(B);
  brightness=map(B,0,1024,3,255);
  analogWrite (brightnessPWM,brightness);
        
// time to refresh the display an to do the real work ( switching the relais )
//Zeit, mal das Display zu aktualisieren und die eigentliche Arbeit zu erledigen, das Schalten des Relais
  
  currentMillis = millis();
 // Serial.println( currentMillis - previousMillis);
  //Serial.println( currentsmoothMillis - previoussmoothMillis);
  if (currentMillis - previousMillis >= interval2){   
      previousMillis = currentMillis ;
      tempC = dht.readTemperature();
      HUM = dht.readHumidity();
    //Serial.print("Temperature = ");
    
    // Serial.print("Pressure = ");
    D = bmp.readPressure();
    //Serial.println (D);

  lcd.setCursor(0, 0);
  lcd.print("T = ");
  lcd.print(tempC,1);
  lcd.write(0xDF),lcd.print("C "),lcd.print(millis());

  lcd.setCursor(0,1);
  //lcd.print("Rel. Luftfeuchte");
  //lcd.setCursor(0,1);
  //lcd.print(" betr\xE1"); lcd.print("gt ");
  lcd.print("F = "),lcd.print(HUM);
  lcd.print("%");
    
    Druck = D/100.0;
    lcd.setCursor(0,2);
    lcd.print("D = ");
    lcd.print(Druck,2);
    lcd.print(" hPa");            

//HIER GEHT MEINE FRAGE LOS; DAS HIER UNTERHALB MÖCHTE ICH OPTIMIEREN

 currentgraphMillis = millis();
 // Serial.println( currentMillis - previousMillis);
  //Serial.println( currentsmoothMillis - previoussmoothMillis);
  if (currentgraphMillis - previousgraphMillis >= interval){   
      previousgraphMillis = currentgraphMillis ;
      VP = map(Druck,990,1040,0,7);
      lcd.setCursor(CP,3);
      lcd.write((byte)VP);
      CP++;
      Serial.println(CP);
      Serial.println(VP);

  }    
    lcd.setCursor(0,0);
 
  
  }   }

Hallo,

das wa Du suchst nennt sich Array link

Heinz

ja, dann habe ich ein mit 20 Daten befülltes Array.
kann ich printen, so weit so gut.

Und dann?

Dann kommt der 21. Messwert und ich weiß nicht, wohin damit.Von Anbeginn neu beschreiben ist nicht, dann dann stünde Wert 21 vor Wert 2, das wäre ja einfach. Das kann man auch ohne Array leicht lösen.
Soweit war ich auch schon.

1 Wert aus Array raus, alle weiteren eins nach links, und den 21. hinten dran hängen.
Klingt einfach, überfordert mich aber heftig.
Da liegt mein Problem.

suche mal nach "Ringbuffer",

Grund-Idee ist, dass man nicht Werte shiftet, sondern jeweils eine Lese- und eine Schreibe-Position hat.

außerdem hatten wir das Thema in den letzten 10 Tagen. Daher such mal ein paar Tage zurück, findest du hier.

Soweit war ich auch schon.
Nein, nicht wirklich!

Da liegt mein Problem.
Nein, nicht wirklich.

Natürlich ist die einzige wirkliche C und auch C++ Antwort auf die Frage, "Wie kann ich die völlig unpraktikable Durchnummerierung meiner Variablen los werden?", das Array.
Moderner in C++ auch Vector, Map, List usw...
Der allgemeine Begriff: Container!

Das Array:
Der reservierte Speicherbereich, für gleichartige Daten.

Eigentlich gibts auch die Möglichkeit mit malloc() oder seinen Brüdern Speicher zu reservieren, und darin mit Zeigern rum zu zeigen.

Im Grunde, sind beide Verfahren gleichwertig und voll umfänglich kombinierbar. (wobei man auf kleinen µC die dynamische Speicherverwaltung, mit Vorsicht genießen sollte)

Gleichwertig, weil es die in C und C++ festgeschriebene Äquivalenz von Zeigern und Indexierten Zugriffen gibt.


Ringbuffer(FiFo), Stack(LiFo) und eine paar andere, wie Listen, Bäume, zählen zu den Grundlegenden Datenstrukturen!
Ich rate dazu, sich diese mal in den Kopf zu schütten!

skyfox60:
Von Anbeginn neu beschreiben ist nicht, dann dann stünde Wert 21 vor Wert 2

Doch, genau das macht man. Wo die Werte im Array stehen ist völlig egal. Man muss sich nur merken wo der Anfang ist

1 Wert aus Array raus, alle weiteren eins nach links, und den 21. hinten dran hängen.
Klingt einfach, überfordert mich aber heftig.

Das wäre nicht optimal, solltest du aber eigentlich hinkriegen, sonst überfordern dich die anderen Vorschläge wohl auch. :frowning:

Falls es dir hilft:
Ob du da fertige Ringpuffer-Objekte nimmst, oder das Prinzip selber (mit Arrays) nachbaust, ist natürlich deine Sache. Die Sende- und Empfangs-Puffer (z.B. von HardwareSerial) arbeiten übrigens so.

Wobei du den Unterschied hast, dass dein Puffer (nach der Anfangsphase) immer voll ist. Brauchst also eigentlich nur einen Schreibzeiger mit dem du einen relativen Index in einen Lesezeiger umrechnen kannst.

Hallo,

es ist ja bereits angedeutet worden. Du benötigst ein Array mit 20 Elementen, Zugriff darauf hast du mit dem Index 0-19.Wenn dein Array noch leer ist dann schreibst Du deine Messert zunächst in das Array mit dem Index 0 , den nächsten in den Index 1 usw. das ist der Schreibzeiger. Wenn Du mit dem Schreibzeiger beim letzten Index=19 angekommen bist must Du erst etwas anderes machen. In einer for Schleife von i=1-19 schreibst den Arryawert mit dem index i in den Arraywert mit dem Index i-1. Dadurch ist der Älteste rausgefallen, alle Position nach unten gerückt und du kannst den aktuellen neuen Messwert an die Position mit dem Index 19 schreiben.

Bei der Ausgabe auf die Anzeige benutzt du eine for schleife von i=0 bis Schreibzeiger. Damit gibst du nur soviele Werte aus wie in dem Ringpuffer enthalten sind.

Heinz

Wieso die Werte im Array verschieben? Wenn du das machst ist es kein Ringpuffer mehr. In einem Ringpuffer geht es nach 19 direkt mit 0 weiter

Serenifly:
Wieso die Werte im Array verschieben? Wenn du das machst ist es kein Ringpuffer mehr. In einem Ringpuffer geht es nach 19 direkt mit 0 weiter

Stimmt , ich habe FIFO im Kopf gehabt, scheint mir aber auch ehr das was er haben will.

Gruß Heinz

, ich habe FIFO im Kopf gehabt,

FiFo heißt "First in, First out"

Das hat nichts damit zu tun, ob man das als Ringbuffer ausbildet, oder die Daten unnötig durch die Gegend kopiert.

Tipp:
Daten werden weder schöner, noch korrekter vom kopieren.

@ serenifly

genau das will ich ja nicht.

wenn 19 geschrieben ist, dann soll der nächste Wert ja nicht in 0 im array geschrieben werden, sondern der Array-Inhalt stelle 0 übernimmt den Wert aus Stelle 1 usw. Der Vorherige in Stelle 0 war der älteste Wert, der soll verschwinden, dann bleiben von den "alten " Werten ( 20 Stck. ) noch 19 über, und die stehen idealerweise jetzt an den Stellen 0-18.
der 21.ste, der kommt dann als "neuer" Wert an die Stelle 19.
Das macht die Sache fortlaufend.

Ich habe gefunden in den Erklärungen:

int myArray[10]={9, 3, 2, 4, 3, 2, 7, 8, 9, 11};

Das ist jetzt eine Vorgabe fester Werte.

Die ist auch leicht abzufragen.

Das konnte ich nicht finden:

Kann die Zahlenreihe auch eine Reihe Variablen sein? int myArray[10]={VP1, VP2, VP3usw. };
Passt sich der Wert dann an, wenn irgendwo im Programm VPx aufgerufen wird?

kann man dann sagen, myVP =VP (myArray,2) und das gibt myVP en Wert der Variablen VP2?

Bin ich da auf dem richtigen Pfad, oder gehr das so auf keinen Fall?

dann könnte ich ja beim messen einencounter mitlaufen lassen, und sagen

counter=0
hole Druck
VP[counter] = mapx,x,x,x also gibt den gewünschten Wert 0-7

wenn counter hierbei gerade 14 ist müsste sich im array an entsprechender Stelle eben jetzt der Wert 7 hinter der Variablen VP14 verbergen.

Ach ja und VPcounter, wie würde man das richtig schreiben an der stelle?
VP8counter), oder VP[counter] oder wie. Das müsste nach meinem Verständnis der index sein, bin mir aber nicht sicher.

Bin ich da auf dem richtigen Pfad, oder gehr das so auf keinen Fall?

Ganz daneben!

Du möchtest einen RingBuffer!
Ob du das weißt, oder ablehnst, oder wie auch immer, ist mir völlig egal.

wenn 19 geschrieben ist, dann soll der nächste Wert ja nicht in 0 im array geschrieben werden, sondern der Array-Inhalt stelle 0 übernimmt den Wert aus Stelle 1 usw. Der Vorherige in Stelle 0 war der älteste Wert, der soll verschwinden, dann bleiben von den "alten " Werten ( 20 Stck. ) noch 19 über, und die stehen idealerweise jetzt an den Stellen 0-18.
der 21.ste, der kommt dann als "neuer" Wert an die Stelle 19.
Das macht die Sache fortlaufend.

Ein irriger Ansatz!

Natürlich würde das auch gehen, ist aber voll daneben.
Alleine schon wegen der Rechenzeitverplemperung.

Tipp:
Je länger du darauf beharrst, desto öfter wird dir das gesagt werden, von um so mehr Leuten.

skyfox60:
Der Vorherige in Stelle 0 war der älteste Wert, der soll verschwinden,

Der verschwindet doch wenn du ihn mit dem neuesten Wert überschreibst

und die stehen idealerweise jetzt an den Stellen 0-18.

Wo die Werte stehen ist egal. Du merkst dir in separaten Variablen wo es mit dem Schreiben und/oder Lesen weitergeht. Im Detail gibt es da unterschiedliche Implementierungen. Aber das Prinzip ist das gleiche

Stelle dir das wirklich wortwörtlich als Ring vor:

Dein erster Wert kann mitten im Array stehen, aber die Reihenfolge passt da sich der Array-Index anpasst. Kann man z.B. einfach (wenn auch etwas ineffizient) mit einer Modulo-Division machen:

0 % 4 = 0
1 % 4 = 1
2 % 4 = 2
3 % 4 = 3
4 % 4 = 0
...

Projektion:

Die zu speichernden Daten sind Murmeln!
Der Datenspeicher ist eine Röhre.

Der Ringbuffer ist ein runde Röhre, ääähh...
Eine Röhre in Kreisform.
Also so ein Kreis, wo sich Anfang und Ende berühren.
Darum heißt es auch Ring.
Eine ringförmige Röhre, mit nur einem Loch, wo man was rein tun kann.

Jetzt gibt es 2 Möglichkeiten:

  1. Du schiebst die Murmeln durch die Röhre
  2. Du schiebst die Röhre über die Murmeln.

Die Nummer 2 hört sich vielleicht komplizierter an, ist es aber nicht.
Die Nummer 2 ist das Mittel der Wahl!

Hallo,
Selbst auf die Gefahr hin das ich jetzt einen vor den Bug bekomme, schau dir das mal an. Es soll dir zeigen wie man Zugriff auf die einzelnen Elemente hat.

Es ist nicht die optimale Lösung aber leichter zu verstehen. Rechenzeit hin oder her. ich denke in dem Fall ist der Aufwand kleiner.

Heinz

int messwert[10]; // Array anlegen

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  for (int i = 0; i < 10; i++) {
    messwert[i] = 100 + i; // Array beschreiben
  }

  Serial.println("zehn messwerte ausgeben");
  for (int i = 0; i < 10; i++) {
    Serial.println(messwert[i]);// alle Ausgabe
  }
  for (int i = 1; i < 10; i++) { // schieben
    messwert[i-1] = messwert[i];
  }
  
  messwert[9] = 110; // letzten ändern
  Serial.print("geschoben und letzen geändert auf:");
  Serial.println(messwert[9]);
  
  Serial.println("nochmal alle ausgeben");
  for (int i = 0; i < 10; i++) {
    Serial.println(messwert[i]);// alle Ausgabe
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

Ja, in diesem Fall wird das wohl einfacher sein.

int messwert[10]; // Array anlegen

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  for (int i = 0; i < 10; i++) {
    messwert[i] = 100 + i; // Array beschreiben
  }

  Serial.println("zehn messwerte ausgeben");
  for (int i = 0; i < 10; i++) {
    Serial.println(messwert[i]);// alle Ausgabe
  }
  for (int i = 1; i < 10; i++) { // schieben
    messwert[i-1] = messwert[i];
  }
  
  messwert[9] = 110; // letzten ändern
  Serial.print("geschoben und letzen geändert auf:");
  Serial.println(messwert[9]);
  
  Serial.println("nochmal alle ausgeben");
  for (int i = 0; i < 10; i++) {
    Serial.println(messwert[i]);// alle Ausgabe
  }
}

@ Rentner DU BIST DER GRÖßTE

das ist genau das , was ich gesucht habe.
und in selbst für mich verständlichem Code.

es gibt nicht nur eine Variable messwert, sondern messwert
Wenn i 0-10 ist, habe ich also abrufbar 11 Variable Werte und mit "i" habe ich auch die Stellen
Das mit dem "for" krieg ich da raus,soweit kann ich das, denke ich.
Ich frag ja über millis() nur einmal die Stunde einen Messwert ab, und möchte nicht 20 Stunden in der for-Schleife hängen.
Ist aber kein Problem.
Das werde ich jetzt umsetzen.
Zumal, Rechenleistung, davon ist genug über.
Alle 2 Sekunden mal die Sensoren abfragen, und einmal in der Stunde den aktuellen Wert über diesen Weg graphisch anzeigen, so das die letzten 20 Stunden als Graphik-Balkendiagram sichtbar sind, das ist soviel Zeit über.
Bis dahin fährt die Lok so oft im Kreis, und langweilt sich.
Das ganze ist ja kein Zeitkritischer Verlauf.
Deine Lösung trifft meine Idee auf den Punkt.
D A N KE !!!!! :smiley:

Hallo,

danke für die Blumen , aber das sind hier ganz andere Spezi´s unterwegs , da muss ich ganz schnell irgendwo im Loch verschwinden.

Aber es hat mich dann schon gereizt das mal zu Ende zu spinnen , herausgekommen ist das dabei.

Heinz

/*Simuliert eine Messwerterfassung mit einer festen
   Zykluszeit. Die Messwerte werden in einem Fifo
   gespeichert. Der Inhalt des Fifo wird zeilenweise
   ausgegeben.
   Hardware UNO             Vers.03.20
*/

uint32_t altzeit;           // Hilfsgrösse Messzyklus
uint32_t messzyklus = 1000; // Messzykluus
const int puffermax = 20;   // Grösse des FIFO
int puffer[puffermax];      // Array anlegen
int anzahl = 0;             // Anzahl im FIFO
int messwert = 0;           // Messwert

void setup() {
  Serial.begin(9600);
}

void loop() {

  if (millis() - altzeit >= messzyklus) {
    altzeit = millis();

    messwert = 100 + random(10); // zur Simulation
    Serial.print("neuer Messwert "); Serial.println(messwert);

    anzahl = fifo(); // Fifo aufrufen
    // Anzeige
    for ( byte i = 0; i <= anzahl; i++) {
      Serial.print(puffer[i]); Serial.print(" ");
    }
    Serial.println();// neue Zeile
  }
}

int fifo() {
  static int zeiger = -1; // Schreibzeiger initialisieren
  // die folgende 3 zeilen sind ein bischen doof , aber so hats
  // geklappt.
  zeiger++;  // schreibzeiger erhöhen
  if (zeiger > puffermax - 1) {   // wenn oben angekommen
    zeiger = puffermax - 1 ;      // begrenzen

    for (byte i = 1; i <= puffermax - 1; i++) { // schieben
      puffer[i - 1] = puffer[i];
    }
  }
  puffer[zeiger] = messwert;  // neuen Messwert speichern
  return zeiger;

}

Nachtrag : globalen Variablennemen zeiger geändert ist jetzt anzahl