Go Down

Topic: Optimieren einer Funktion mit einem Array?! (Read 264 times) previous topic - next topic

fckw

Hallo zusammen,

ich habe mir folgende Funktion zusammengebastelt die ich regelmäßig aufrufe um vier DHT22 Sensoren auszulesen und die Daten per MQTT zu verschicken.

Code: [Select]
void dht22_reading()
{
  //------------DHT22 Sensor 1-------------
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println(F("Failed to read from DHT sensor 1!"));
  }
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity h1: "));
  Serial.print(h);
  Serial.print(F("%, "));
  Serial.print(F("Temperature t1: "));
  Serial.print(t);
  Serial.print(F("°C, "));
  Serial.print(F("Heat index t1: "));
  Serial.print(hic);
  Serial.println(F("°C"));

  Serial.print(F("Senden der MQTT Nachrichten für Sensor 1: "));
  Serial.print(String(hic).c_str());
  client.publish("/SmartHome/Feldgeraet/Mega2560/DHT1/t/", String(hic).c_str());
  Serial.print(F(" "));
  Serial.println(String(h).c_str());
  client.publish("/SmartHome/Feldgeraet/Mega2560/DHT1/h/", String(h).c_str());


  //------------DHT22 Sensor 2-------------
  h = dht2.readHumidity();
  // Read temperature as Celsius (the default)
  t = dht2.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println(F("Failed to read from DHT sensor 2!"));
    return;
  }
  // Compute heat index in Celsius (isFahreheit = false)
  hic = dht2.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity h2: "));
  Serial.print(h);
  Serial.print(F("%, "));
  Serial.print(F("Temperature t2: "));
  Serial.print(t);
  Serial.print(F("°C, "));
  Serial.print(F("Heat index t2: "));
  Serial.print(hic);
  Serial.println(F("°C"));

  Serial.print(F("Senden der MQTT Nachrichten für Sensor 2: "));
  Serial.print(String(hic).c_str());
  client.publish("/SmartHome/Feldgeraet/Mega2560/DHT2/t/", String(hic).c_str());
  Serial.print(F(" "));
  Serial.println(String(h).c_str());
  client.publish("/SmartHome/Feldgeraet/Mega2560/DHT2/h/", String(h).c_str());

  //------------DHT22 Sensor 3-------------
  h = dht3.readHumidity();
  // Read temperature as Celsius (the default)
  t = dht3.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println(F("Failed to read from DHT sensor 3!"));
    return;
  }
  // Compute heat index in Celsius (isFahreheit = false)
  hic = dht3.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity h3: "));
  Serial.print(h);
  Serial.print(F("%, "));
  Serial.print(F("Temperature t3: "));
  Serial.print(t);
  Serial.print(F("°C, "));
  Serial.print(F("Heat index t3: "));
  Serial.print(hic);
  Serial.println(F("°C"));

  Serial.print(F("Senden der MQTT Nachrichten für Sensor 3: "));
  Serial.print(String(hic).c_str());
  client.publish("/SmartHome/Feldgeraet/Mega2560/DHT3/t/", String(hic).c_str());
  Serial.print(F(" "));
  Serial.println(String(h).c_str());
  client.publish("/SmartHome/Feldgeraet/Mega2560/DHT3/h/", String(h).c_str());
 
  //------------DHT22 Sensor 4-------------
  h = dht4.readHumidity();
  // Read temperature as Celsius (the default)
  t = dht4.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println(F("Failed to read from DHT sensor 4!"));
    return;
  }
  // Compute heat index in Celsius (isFahreheit = false)
  hic = dht4.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity h4: "));
  Serial.print(h);
  Serial.print(F("%, "));
  Serial.print(F("Temperature t4: "));
  Serial.print(t);
  Serial.print(F("°C, "));
  Serial.print(F("Heat index t4: "));
  Serial.print(hic);
  Serial.println(F("°C"));

  Serial.print(F("Senden der MQTT Nachrichten für Sensor 4: "));
  Serial.print(String(hic).c_str());
  client.publish("/SmartHome/Feldgeraet/Mega2560/DHT4/t/", String(hic).c_str());
  Serial.print(F(" "));
  Serial.println(String(h).c_str());
  client.publish("/SmartHome/Feldgeraet/Mega2560/DHT4/h/", String(h).c_str());
}


Es wird im Prinzip für jeden Sensor hintereinander das gleiche ausgeführt.
Nun habe ich überlegt, ob man das ganze nicht zusammenfassen könnte, mit einem Array in einer for-schleife. Ich bin Anfänger und weiß ga rnicht ob das ganze überhaupt Sinn macht und funktioniert.
Ich habe sowas probiert:
Code: [Select]
byte dhtS[] = {0, 1, 2, 3};
  for (byte i = 0; i < 4; i = i + 1) {
    Serial.print("Auslesen von Sensor ");
    Serial.println(dhtS[i]);
    float h = dht[i].readHumidity();

das geht natürlich nicht, aber es soll darstellen was ich gerne tun würde. liegt es an der deklaration von i? Ich sehe irgendwie den Wald vor lauter Bäumen nicht. Vielleicht kann mir einer helfen das ich weiter komme.

Serenifly

#1
Jun 16, 2019, 12:22 pm Last Edit: Jun 16, 2019, 12:24 pm by Serenifly
Was du brauchst ist ein Array aus DHT Objekten

Code: [Select]

DHT sensors[] = { { 2, DHT22}, { 3, DHT22}, .... };  //hier die Pins angeben

void loop()
{
    for { DHT& sensor : sensors }
    {
       float h = sensor.readHumidity();
       float t = sensor.readTemperature();

       ...
    }
}

noiasca

nö, du musst schon die Objekte (dht.) in ein Array packen.

Lies mal hier: https://forum.arduino.cc/index.php?topic=141908.0
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

fckw

Ich danke euch schonmal, weil ich einen großen Schritt weiter gekommen bin. Ich deklariere jetzt das ganze so:
Code: [Select]
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
const int maxDHT = 4;
int pins[maxDHT] = {46, 47, 48, 49};
DHT *dht[maxDHT]; // array of 4 pointers to DHTs

und im Setup so:
Code: [Select]

 for (int n = 0; n < maxDHT; n++)
  {
    dht[n] = new DHT(pins[n], DHTTYPE); // define a sensor at pin 'n' with sensor type DHT11
    dht[n]->begin();
  }

und meine Funktion "dht_reading();" sieht jetzt folgendermaßen aus:
Code: [Select]
void dht22_reading()
{
  //------------DHT22 Sensoren-------------
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  for (int n = 0; n < maxDHT; n++)
  {
    float h = dht[n]->readHumidity();
    float t = dht[n]->readTemperature();

    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t)) {
      Serial.println();
      Serial.print(F("Failed to read from DHT Sensor: "));
      Serial.print(n);
    }
    // Compute heat index in Celsius
    float hic = dht[n]->computeHeatIndex(t, h, false);

    Serial.println();
    Serial.print(F("Humidity h"));
    Serial.print(n);
    Serial.print(F(": "));
    Serial.print(h);
    Serial.print(F("%, "));
    Serial.print(F("Temperature t"));
    Serial.print(n);
    Serial.print(F(": "));
    Serial.print(t);
    Serial.print(F("°C, "));
    Serial.print(F("Heat index t"));
    Serial.print(n);
    Serial.print(F(": "));
    Serial.print(hic);
    Serial.println(F("°C"));

    Serial.print(F("Senden der MQTT Nachrichten für Sensor"));
    Serial.print(n);
    Serial.print(F(": "));
    Serial.print(String(h).c_str());
    //client.publish("/SmartHome/Feldgeraet/Mega2560/DHT1/h/", String(h).c_str());
    Serial.print(F(" "));
    Serial.print(String(hic).c_str());
    //client.publish("/SmartHome/Feldgeraet/Mega2560/DHT1/t/", String(hic).c_str());
  }
}


das funktioniert schonmal sehr gut  :D .
Was mir aber nicht klar ist wie ich dem Aufruf
Code: [Select]
client.publish("/SmartHome/Feldgeraet/Mega2560/DHT*/t/", String(hic).c_str());
dem String da wo ich das * gemacht habe die variable n übergebe.

noiasca

ich kenne nicht was dein .publish erwartet.

Aber mitteles itoa bekommst du aus einem integer einen string http://www.cplusplus.com/reference/cstdlib/itoa/

apropos Integer: deine for (int n = 0 kannst kürzen auf for (byte n = 0
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

fckw

ich kenne nicht was dein .publish erwartet.

Aber mitteles itoa bekommst du aus einem integer einen string http://www.cplusplus.com/reference/cstdlib/itoa/

apropos Integer: deine for (int n = 0 kannst kürzen auf for (byte n = 0
Also soweit ich rausgefunden habe erwartet es ein char?!?

ein Serial.print habe ich z.B so hinbekommen:
Code: [Select]
Serial.print("/SmartHome/Feldgeraet/Mega2560/DHT/t" + String(n, DEC) + "/ ");

wenn ich jetzt versuche das auf client.publish zu übertragen, mein Versuch
Code: [Select]
client.publish(("/SmartHome/Feldgeraet/Mega2560/DHT/t" + String(n, DEC) + "/"), String(t).c_str());

Dann meckert der Compiler mit no matching function for call to 'PubSubClient::publish(StringSumHelper&, const char*)'

muss ich jetzt ein char array anlegen?

noiasca

#6
Jun 16, 2019, 05:59 pm Last Edit: Jun 16, 2019, 06:15 pm by noiasca
so könntest ein char array zusammenbasteln:

Code: [Select]

//gegeben sei
const char header[] = {"/SmartHome/Feldgeraet/Mega2560/DHT/t"};
const byte bufferLength = 40;
char myBuffer [bufferLength];
char temp[4]; // 3 stellen + \0
byte i = 0;

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

void loop()
{
  itoa(i, temp, 10);
  strcpy(myBuffer, header);
  strcat(myBuffer, temp);
  Serial.println(myBuffer);
  i++;
}



oder du schaust dir mal PString an http://arduiniana.org/libraries/pstring/
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

Tommy56

Code: [Select]
const char header[] = "/SmartHome/Feldgeraet/Mega2560/DHT/t"; // ist auch mit Nullterminator

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

noiasca

how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

fckw

Ihr seid echt super! Meine Funktion sieht jetzt so aus und alles scheint auch zu funktionieren.
Code: [Select]
void dht22_reading()
{
  //------------DHT22 Sensoren-------------
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  for (byte n = 0; n < maxDHT; n++)
  {
    float h = dht[n]->readHumidity();
    float t = dht[n]->readTemperature();

    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t)) {
      Serial.println();
      Serial.print(F("Failed to read from DHT Sensor: "));
      Serial.print(n);
    }
    // Compute heat index in Celsius
    float hic = dht[n]->computeHeatIndex(t, h, false);

    Serial.println();
    Serial.print(F("Humidity h"));
    Serial.print(n);
    Serial.print(F(": "));
    Serial.print(h);
    Serial.print(F("%, "));
    Serial.print(F("Temperature t"));
    Serial.print(n);
    Serial.print(F(": "));
    Serial.print(t);
    Serial.print(F("°C, "));
    Serial.print(F("Heat index t"));
    Serial.print(n);
    Serial.print(F(": "));
    Serial.print(hic);
    Serial.println(F("°C"));

    const char header[] = {"/SmartHome/Feldgeraet/Mega2560/DHT/t\0"}; // mit Nullterminator
    const byte bufferLength = 40;
    char myBuffer [bufferLength];
    char temp[4]; // 3 stellen + \0
    Serial.print(F("Senden der MQTT Nachrichten für Sensor "));
    Serial.print(n);
    Serial.println(F(": "));
    itoa(n, temp, 10);
    strcpy(myBuffer, header);
    strcat(myBuffer, temp);
    Serial.print(myBuffer);
    Serial.print(F(" "));
    Serial.println(String(hic).c_str());
    client.publish(myBuffer, String(hic).c_str());

    const char header2[] = {"/SmartHome/Feldgeraet/Mega2560/DHT/h\0"}; // mit Nullterminator
    char hum[4]; // 3 stellen + \0
    itoa(n, hum, 10);
    strcpy(myBuffer, header2);
    strcat(myBuffer, hum);
    Serial.print(myBuffer);
    Serial.print(F(" "));
    Serial.println(String(h).c_str());
    client.publish(myBuffer, String(h).c_str());
  }
}


ich weiß nicht ob ich das mit der "Doppelverwendung" von myBuffer richtig gemacht habe, ich benötige es für zwei Werte die jeder Sensor leifert. Es funktioniert, aber vielleicht mag sich das nochmal jemand anschauen.

noiasca

#10
Jun 16, 2019, 06:56 pm Last Edit: Jun 16, 2019, 07:01 pm by noiasca
die Wiederverwendung des buffers ist schon ok.
Pass auf die Feuchtigkeit hum auf, wie viele Stellen kann diese erreichen? hab mich vertan, dachte gerade an einen vierstelligen Luftdruck... ^^
aber wenn die 4 Stellen eh reichen, könntest das auch mit einem buffer für n, temp, hum machen.

und beachte Tommys Hinweis, du musst nicht extra den const header nullterminisieren.
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

fckw

Danke für den Hinweis.

ich habe jetzt folgendes angepasst:
Code: [Select]
const byte bufferLength = 42;
itoa(n, temp, 7);
itoa(n, hum, 6);


temp hat ja noch ein Vorzeichen und hum geht von 0-100.00, ist meine Änderung richtig?

Serenifly

#12
Jun 16, 2019, 08:58 pm Last Edit: Jun 16, 2019, 09:00 pm by Serenifly
Der 3. Parameter hat nichts mit Stellen zu tun, sondern ist die Basis des Zahlensystems. Das ist hier immer 10 für Dezimal. Lies dir die Doku der Funktion durch!

Wenn du Nachkommastellen willst brauchst du dtostrf():
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42

Das mit dem Array aus Zeigern auf Objekten ist übrigens unnötig kompliziert. Es geht ja, aber man kann auch die Objekte direkt in ein Array packen

fckw

Danke,

jetzt habe ich es so umgebaut:

Code: [Select]
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
const int maxDHT =4;
int pins[maxDHT] = {46, 47, 48, 49};
DHT dht[maxDHT] = {DHT(pins[0], DHTTYPE),DHT(pins[1], DHTTYPE ),DHT(pins[2], DHTTYPE),DHT(pins[3], DHTTYPE)};


Im Setup dann so:
Code: [Select]
for (byte n = 0; n < maxDHT; n++)
  {
    dht[n].begin();
  }


und meine Funktion zum auslesen so:
Code: [Select]
void dht22_reading()
{
  //------------DHT22 Sensoren-------------
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  for (byte n = 0; n < maxDHT; n++)
  {
    float h = dht[n].readHumidity();
    float t = dht[n].readTemperature();

    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t)) {
      Serial.println();
      Serial.print(F("Failed to read from DHT Sensor: "));
      Serial.print(n);
    }
    // Compute heat index in Celsius
    float hic = dht[n].computeHeatIndex(t, h, false);

    Serial.println();
    Serial.print(F("Humidity h"));
    Serial.print(n);
    Serial.print(F(": "));
    Serial.print(h);
    Serial.print(F("%, "));
    Serial.print(F("Temperature t"));
    Serial.print(n);
    Serial.print(F(": "));
    Serial.print(t);
    Serial.print(F("°C, "));
    Serial.print(F("Heat index t"));
    Serial.print(n);
    Serial.print(F(": "));
    Serial.print(hic);
    Serial.println(F("°C"));

    const char header[] = {"/SmartHome/Feldgeraet/Mega2560/DHT/t"};
    const byte bufferLength = 40;
    char myBuffer [bufferLength];
    char temp[4]; // 3 stellen + \0
    Serial.print(F("Senden der MQTT Nachrichten für Sensor "));
    Serial.print(n);
    Serial.println(F(": "));
    itoa(n, temp, 10);
    strcpy(myBuffer, header);
    strcat(myBuffer, temp);
    Serial.print(myBuffer);
    Serial.print(F(" "));
    Serial.println(String(hic).c_str());
    client.publish(myBuffer, String(hic).c_str());

    const char header2[] = {"/SmartHome/Feldgeraet/Mega2560/DHT/h"};
    char hum[4]; // 3 stellen + \0
    itoa(n, hum, 10);
    strcpy(myBuffer, header2);
    strcat(myBuffer, hum);
    Serial.print(myBuffer);
    Serial.print(F(" "));
    Serial.println(String(h).c_str());
    client.publish(myBuffer, String(h).c_str());
  }
}


Jetzt habe ich ein Array direkt aus dem Objekt(Class?) "DHT"? Und "dht" nennt man eine Instanz? Voher bestand das array aus pointer/zeiger auf das Objekt, richtig? :smiley-confuse:
Dem Compiler ist es ziemlich egal, gleiche größe, ist wahrscheinlich auch logisch ::)

Danke für den hilfreichen Input.

Go Up