Neuling benötigt Unterstützung mit Code

Hallo zusammen

Mein Name ist Stefano und bin ganz neu in der Makerszene bezw. habe vor 2 Wochen mit meinem kleinen ersten Arduino-Projekt angefangen. Das ganze soll ein kleines automatisiertes Gewächshaus werden (anfangs nicht grad das schwerste heraussuchen, habe ich mir sagen lassen).

Ich habe mir dazu das Eleegoo Starterkit auf Amazon besorgt mit einem Arduino Uno R3.
Folgende Hardware ist an diesem Projekt angedacht:

Arduino Uno R3 (Starterkit)

Bewässerung:

  • Relaismodul mit Optokoppler-Eingang
  • kleine 5V Wasserpumpe (Speisung sep. Netzteil)
  • Bodenfeuchtesensor: Capacitive Soil Moisture Sensor 2.0

Belüftung:
Messung der Luftfeuchtigkeit und Temperatur DHT22
Ansteuerung eines kleinen Servos in 3 Stufen für eine Lüftungsklappe

Anzeige der Sensorwerte und Status Pumpe/ Servo auf einem 4*20Zeilen LCD

Nun habe ich mich codemässig glaub ich ein bisschen verrannt und wäre über Tipps und Ratschläge sehr dankbar. Folgende Themen stehen momentan bezüglich Display an und ich komme nicht weiter:

-da ich verschiedenste Werte anzeigen lassen möchte, habe ich mich an den Displaywechsel gewagt. Grob funktioniert es habe aber noch folgende Fehler: Auf dem ersten Display wird in der ersten Zeile Growduino ausgeschrieben und beim zweiten Display fehlt das G und das r von Growduino.

  • das zweite Thema die Bodenfeuchte wird nur mit 00% ausgegeben.

Anbei der Code dazu:

[code]
//===========================================================Projekt Growduino================================================//
//erstellt/angepasst von Stefano Scarpelli
//Vorlage basiert auf der Grundlage Youtube-Video von Bastelbruder: https://www.youtube.com/watch?v=DaSagesHyGM



//====================================== Bibliotheken

#include <Servo.h> 
Servo myservo;                      // Objekt myservo anlegen

#include "DHT.h"
#define DHTTYPE DHT22
#define DHTPIN 13
DHT dht(DHTPIN, DHTTYPE);           // Objekt dht anlegen und Zuweisung Typ und PIN13

#include "LiquidCrystal_I2C.h"    
LiquidCrystal_I2C lcd(0x27,20,4);   // Objekt lcd anlegen und Typenbeschreibung (4Zeilen, 20Zeichen)                     

//====================================== Temperatureinstellungen

#define solltemp 22                 // Solltemperatur 22°C
#define stufe1 solltemp+2           // Stufe 1 sind 2°C mehr als Soll
#define stufe2 solltemp+4           // Stufe 2 sind 4°C mehr als Soll
#define stufe3 solltemp+6           // Stufe 3 sind 6°C mehr als Soll

//====================================== Datentyp- und Wertzuweisung

const int trocken = 624;            // Wert für trockene Erde vom Bodenfeuchtesensor
const int nass = 246;               // dito für nasse Erde
int FeuchtigkeitProzent;
float temp;
String status;                      // das Wort status wird einem String zugewiesen

#define RELAIS 12                   // Zuweisung RELAIS an Pin 12
boolean Relaiszustand = false;      // Relaiszustand wird boolscher Wert zugewiesen

//====================================== Setup (wird einmalig beim Start ausgeführt)

void setup() {
  
      myservo.attach(11);           // myservo wird an PIN11 zugewiesen
      lcd.init();                   // LCD-Display wird initialisiert
      lcd.backlight();              // LCD-Hintergrundbeleuchtung wird eingeschaltet
      dht.begin();                  // Temp- und Luftfeuchtesensor wird initialisiert
      pinMode(RELAIS, OUTPUT);      // der Pin 12 wird als Output deklariert
}

void AnzeigenEins() 
{
      lcd,clear()
      lcd.setCursor(0,0);
      lcd.print("Growduino by Scarpi");
      lcd.setCursor(0,1);
      lcd.print("Temp SOLL: ");
      lcd.print(solltemp);
      lcd.print("\337C  ");
      lcd.setCursor(0,2);
      lcd.print("Temp IST: ");
      lcd.print(temp);
      lcd.print("\337C");
      lcd.setCursor(0,3);
      lcd.print("Frischluft: ");
      lcd.print(status);
}

void AnzeigenZwei()
{
      lcd.clear()
      lcd.setCursor(0,0);
      lcd.print("Growduino by Scarpi");
      lcd.setCursor(0,1);
      lcd.print("Bodenfeuchte: ");
      
            if(FeuchtigkeitProzent < 10)
                lcd.print("0");
                
      lcd.print(FeuchtigkeitProzent);
      lcd.print("%");  
      lcd.setCursor(0,2);
      lcd.print("Pumpenstatus: "); 
            
            if(Relaiszustand = false)
                lcd.print("Ein");
            else 
                lcd.print("Aus");
}

void Wechselanzeige()
{
  switch ((millis()/8000)%2)
  {
    case 0: AnzeigenEins();break;
    case 1: AnzeigenZwei();break;
    //default: Serial.println("Error");
  }  
}
//====================================== Loop (wird zyklisch abgearbeitet / analog SPS)

void loop()
{
// Messungen
      
delay(2000);                                                            // 2sek warten bevor erste Messung
int WertCSMS = analogRead(A0);                                          // Analogeingang A0 wird gemessen und an WertCSMS zuweisen
int FeuchtigkeitProzent = map(WertCSMS, nass, trocken, 100, 0);         // der WertCSMS wird in 0-100% umgerechnet und Zuweisung an FeuchtigkeitProzent
FeuchtigkeitProzent = constrain(FeuchtigkeitProzent, 1, 100);           // den Wert FeuchtigkeitProzent auf 1 bis 100% begrenzen 
      
temp = dht.readTemperature();                                     // DHT22 Temperatur auslesen und dem Wert temp zuweisen

// Aktionen
      
      if (temp <= solltemp) { myservo.write(0); status = "AUS       "; }else
      if (temp >= stufe2) {  myservo.write(150); status = "Stufe 3"; }else
      if (temp >= stufe1) {  myservo.write(90); status = "Stufe 2"; }else
      if (temp >= solltemp) {  myservo.write(40); status = "Stufe 1"; }
      if (FeuchtigkeitProzent < 15)
         Relaiszustand = false;
      if (FeuchtigkeitProzent > 30)
         Relaiszustand = true;
digitalWrite(RELAIS, Relaiszustand);

Wechselanzeige();

}
[/code]

Bitte seht mir allfällige Fehler noch ein bisschen nach und ich bin froh um wertvolle Ansätze zur Verbesserung.

Vielen Dank im voraus
Stefano

Hallo
und herzlichen Willkommen.
Bitte poste den Sketch im IDE formatiert mit STRG T und dann hier in Code Tags "</>".
Dann wird das Ganze ein bißchen leserlicher.

Hallo paulpaulson
wurde angepasst. Ist das so besser?

1 Like

Dann will ich mal anfangen...
Im Code steht:

  delay(2000);                  // 2sek warten bevor erste Messung

Das passiert aber bei jedem Umlöauf, weil es im loop steht. Der Kommentar passt somit nicht zur Funktion. Was willst Du tatsächlich?

Hier:

void AnzeigenEins()
{
  lcd, clear()

ist ein ganz wirres , drin.

Das:

void Wechselanzeige()
{
  switch ((millis() / 8000) % 2)

könnte Dir auf die Füsse fallen.
Ja, hab ich früher auch mal gemacht.... aber davon bin ich weg.
Das geht auch ganz einfach auf Basis des blinkwithoutdelay Examples in der IDE :wink:

Na mal schaun, was sich sonst noch findet....

mit dem Delay möchte ich abwarten bis der DHT22 bereit ist um einen Wert auszugeben. Dies habe ich bei jemandem abgeschaut... Das der Kommentar nicht mehr stimmt ist korrekt. Aber alle 2sek eine Messung machen wird auch mehr als genügend sein für meine Anwendung.

Das lcd, clear() war mein Versuch die LCD Anzeige zu löschen bevor wieder neu geschrieben wird um diesen Anzeigefehler auf der zweiten Anzeige zu umgehen.

das blinkwithoutdelay versuche ich mal in meinen code zu integrieren.

Vielen Dank für deine Tipps.

1 Like

Na, dann hab ich mal noch was:

  if (Relaiszustand = false)
    lcd.print("Ein");

Das haut richtig weg.

Hast Du Deinen Code mal warnungs- und fehlerfrei compiliert?
Denn auch hier:

lcd.clear()

fehlt ja noch ein ; Oben auch.

Kompiliert erstmal - ob es das macht, was Du willst, weiss ich nicht....

//===========================================================Projekt Growduino================================================//
//erstellt/angepasst von Stefano Scarpelli
//Vorlage basiert auf der Grundlage Youtube-Video von Bastelbruder: https://www.youtube.com/watch?v=DaSagesHyGM



//====================================== Bibliotheken

#include <Servo.h>
Servo myservo;                      // Objekt myservo anlegen

#include "DHT.h"
#define DHTTYPE DHT22
#define DHTPIN 13
DHT dht(DHTPIN, DHTTYPE);           // Objekt dht anlegen und Zuweisung Typ und PIN13

#include "LiquidCrystal_I2C.h"
LiquidCrystal_I2C lcd(0x27, 20, 4); // Objekt lcd anlegen und Typenbeschreibung (4Zeilen, 20Zeichen)

//====================================== Temperatureinstellungen

#define solltemp 22                 // Solltemperatur 22°C
#define stufe1 solltemp+2           // Stufe 1 sind 2°C mehr als Soll
#define stufe2 solltemp+4           // Stufe 2 sind 4°C mehr als Soll
#define stufe3 solltemp+6           // Stufe 3 sind 6°C mehr als Soll

//====================================== Datentyp- und Wertzuweisung

const int trocken = 624;            // Wert für trockene Erde vom Bodenfeuchtesensor
const int nass = 246;               // dito für nasse Erde
int FeuchtigkeitProzent;
float temp;
String status;                      // das Wort status wird einem String zugewiesen

#define RELAIS 12                   // Zuweisung RELAIS an Pin 12
boolean Relaiszustand = false;      // Relaiszustand wird boolscher Wert zugewiesen

//====================================== Setup (wird einmalig beim Start ausgeführt)

void setup()
{
  myservo.attach(11);           // myservo wird an PIN11 zugewiesen
  // lcd.init();                   // LCD-Display wird initialisiert
  lcd.backlight();              // LCD-Hintergrundbeleuchtung wird eingeschaltet
  dht.begin();                  // Temp- und Luftfeuchtesensor wird initialisiert
  pinMode(RELAIS, OUTPUT);      // der Pin 12 wird als Output deklariert
}

void AnzeigenEins()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Growduino by Scarpi");
  lcd.setCursor(0, 1);
  lcd.print("Temp SOLL: ");
  lcd.print(solltemp);
  lcd.print("\337C  ");
  lcd.setCursor(0, 2);
  lcd.print("Temp IST: ");
  lcd.print(temp);
  lcd.print("\337C");
  lcd.setCursor(0, 3);
  lcd.print("Frischluft: ");
  lcd.print(status);
}

void AnzeigenZwei()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Growduino by Scarpi");
  lcd.setCursor(0, 1);
  lcd.print("Bodenfeuchte: ");
  if (FeuchtigkeitProzent < 10)
    lcd.print("0");
  lcd.print(FeuchtigkeitProzent);
  lcd.print("%");
  lcd.setCursor(0, 2);
  lcd.print("Pumpenstatus: ");
  if (Relaiszustand == false)
    lcd.print("Ein");
  else
    lcd.print("Aus");
}

void Wechselanzeige()
{
  switch ((millis() / 8000) % 2)
  {
    case 0: AnzeigenEins(); break;
    case 1: AnzeigenZwei(); break;
      //default: Serial.println("Error");
  }
}
//====================================== Loop (wird zyklisch abgearbeitet / analog SPS)
void dhtMessen()
{
  const unsigned long interval = 2000;
  static unsigned long lastMessung = 0;
  if (millis() - lastMessung >= interval)
  {
    int WertCSMS = analogRead(A0);                                          // Analogeingang A0 wird gemessen und an WertCSMS zuweisen
    int FeuchtigkeitProzent = map(WertCSMS, nass, trocken, 100, 0);         // der WertCSMS wird in 0-100% umgerechnet und Zuweisung an FeuchtigkeitProzent
    FeuchtigkeitProzent = constrain(FeuchtigkeitProzent, 1, 100);           // den Wert FeuchtigkeitProzent auf 1 bis 100% begrenzen
    temp = dht.readTemperature();                                     // DHT22 Temperatur auslesen und dem Wert temp zuweisen
    lastMessung = millis();
  }
}

void servoAktion()
{
  // Aktionen
  if (temp <= solltemp)
  {
    myservo.write(0); status = "AUS       ";
  }
  else if (temp >= stufe2)
  {
    myservo.write(150); status = "Stufe 3";
  }
  else if (temp >= stufe1)
  {
    myservo.write(90); status = "Stufe 2";
  }
  else if (temp >= solltemp)
  {
    myservo.write(40); status = "Stufe 1";
  }
}
void relaisAktion()
{
  if (FeuchtigkeitProzent < 15)
    Relaiszustand = false;
  if (FeuchtigkeitProzent > 30)
    Relaiszustand = true;
  digitalWrite(RELAIS, Relaiszustand);
}

void loop()
{
  dhtMessen();
  servoAktion();
  relaisAktion();
  Wechselanzeige();
}

Hallo,
Mach den clear raus lass dir anzeigen lcd 1 un 2 danach alle "Leichen" mit " " Löschen
Ich mach sowas mit blat Papier danach entscheide ich ob was und wie wird angezeigt

Musst Du nicht wiederholen ist ja statisch
bei lcd clear ist Wurm drin :wink:

Hi. Deine Inputs haben mir schon einiges weitergeholfen. Vielen Dank dafür.

lcd.clear habe ich draussen
alle fehlenden ; wurden gesetzt
kompiliert habe ich auch und das ganze mal intensiv ausgetestet.
Die Funktionen bewirken das gewünschte.

nach wie vor fehlen aber auf der zweiten Anzeige die ersten 2 Buchstaben von Growduino.
konnte das ganze soweit eingrenzen, dass wenn ich die aktionServo auskommentiere funktionierts. Wieso erschliesst sich mir nicht ganz...

Gib mal Deinen aktuellen Code.

//===========================================================Projekt Growduino================================================//
//erstellt/angepasst von Stefano Scarpelli
//Vorlage basiert auf der Grundlage Youtube-Video von Bastelbruder: https://www.youtube.com/watch?v=DaSagesHyGM



//====================================== Bibliotheken

#include <Servo.h>
Servo myservo;                      // Objekt myservo anlegen

#include "DHT.h"
#define DHTTYPE DHT22
#define DHTPIN 13
DHT dht(DHTPIN, DHTTYPE);           // Objekt dht anlegen und Zuweisung Typ und PIN13

#include "LiquidCrystal_I2C.h"
LiquidCrystal_I2C lcd(0x27, 20, 4); // Objekt lcd anlegen und Typenbeschreibung (4Zeilen, 20Zeichen)

//====================================== Temperatureinstellungen

#define solltemp 22                 // Solltemperatur 22°C
#define stufe1 solltemp+2           // Stufe 1 sind 2°C mehr als Soll
#define stufe2 solltemp+4           // Stufe 2 sind 4°C mehr als Soll
#define stufe3 solltemp+6           // Stufe 3 sind 6°C mehr als Soll

//====================================== Datentyp- und Wertzuweisung

int FeuchtigkeitProzent;
int csmsWert;
const int trocken = 416;                                              // Wert für trockene Erde vom Bodenfeuchtesensor
const int nass = 249;                                                 // dito für nasse Erde
float temp;
String status;                      // das Wort status wird einem String zugewiesen

#define RELAIS 12                   // Zuweisung RELAIS an Pin 12
boolean Relaiszustand = false;      // Relaiszustand wird boolscher Wert zugewiesen

//====================================== Setup (wird einmalig beim Start ausgeführt)

void setup() {

  myservo.attach(3);            // myservo wird an PIN11 zugewiesen
  lcd.init();                   // LCD-Display wird initialisiert
  lcd.backlight();              // LCD-Hintergrundbeleuchtung wird eingeschaltet
  dht.begin();                  // Temp- und Luftfeuchtesensor wird initialisiert
  pinMode(RELAIS, OUTPUT);      // der Pin 12 wird als Output deklariert
}

//===================================== Funktionen definieren

void csmsMessen()
{
  const unsigned long interval1 = 5000;                                   // Intervall für Temperaturmessung
  static unsigned long lastMessung1 = 0;                                  // Zwischenspeicher für Zeitstempel letzte Messung
  if (millis() - lastMessung1 >= interval1) {                           // wenn der Zähler millis minus Wert letzte Messung grösser gleich interval ist
    csmsWert = analogRead(A0);                                          // Messung und Zuweisung an csmsWert
    FeuchtigkeitProzent = map(csmsWert, nass, trocken, 99, 10);         // der csmsWert wird in 0-100% umgerechnet und Zuweisung an FeuchtigkeitProzent
    FeuchtigkeitProzent = constrain(FeuchtigkeitProzent, 10, 99);       // den Wert FeuchtigkeitProzent auf 10 bis 99% begrenzen
    lastMessung1 = millis();
  }
}

void dhtMessen()
{
  const unsigned long interval2 = 2000;                                   // Intervall für Temperaturmessung
  static unsigned long lastMessung2 = 0;                                  // Zwischenspeicher für Zeitstempel letzte Messung
  if (millis() - lastMessung2 >= interval2)                             // wenn der Zähler millis minus Wert letzte Messung grösser gleich interval ist
  {
    temp = dht.readTemperature();                                          // DHT22 Temperatur auslesen und dem Wert temp zuweisen
    lastMessung2 = millis();                                               // Wert von millis wird in letzte Messung geschrieben
  }
}

void servoAktion()
{
  if (temp <= solltemp) {
    myservo.write(0);
    status = "AUS       ";
  } else if (temp >= stufe2) {
    myservo.write(150);
    status = "Stufe 3";
  } else if (temp >= stufe1) {
    myservo.write(90);
    status = "Stufe 2";
  } else if (temp >= solltemp) {
    myservo.write(40);
    status = "Stufe 1";
  }
}

void relaisAktion()
{
  if (FeuchtigkeitProzent < 15)
    Relaiszustand = false;
  if (FeuchtigkeitProzent > 30)
    Relaiszustand = true;
  digitalWrite(RELAIS, Relaiszustand);
}

void AnzeigenEins()
{
  lcd.setCursor(0, 0);
  lcd.print("Growduino by Scarpi");
  lcd.setCursor(0, 1);
  lcd.print("Temp SOLL: ");
  lcd.print(solltemp);
  lcd.print("\337C  ");
  lcd.setCursor(0, 2);
  lcd.print("Temp IST: ");
  lcd.print(temp);
  lcd.print("\337C");
  lcd.setCursor(0, 3);
  lcd.print("Frischluft: ");
  lcd.print(status);
}

void AnzeigenZwei()
{
  lcd.setCursor(0, 0);
  lcd.print("Growduino by Scarpi");
  lcd.setCursor(0, 1);
  lcd.print("Bodenfeuchte: ");

  //if (FeuchtigkeitProzent < 10)
  //lcd.print("0");

  lcd.print(FeuchtigkeitProzent);
  lcd.print("%");
  lcd.setCursor(0, 2);
  lcd.print("Pumpenstatus: ");

  if (Relaiszustand == false)
    lcd.print("Ein");
  else
    lcd.print("Aus");
}

void Wechselanzeige()
{
  switch ((millis() / 8000) % 2)
  {
    case 0: AnzeigenEins(); break;
    case 1: AnzeigenZwei(); break;
    default: lcd.print("Error");
  }
}
//====================================== Loop (wird zyklisch abgearbeitet / analog SPS)

void loop()
{
  csmsMessen();
  relaisAktion();
  dhtMessen();
  servoAktion();
  Wechselanzeige();


}

Frage:
Deine Fehler treten hier auf?

a) Dann wäre "Gr" weg (dafür Leerzeichen?) und danach alles richtig ODER
b) "owduino" fängt an der ersten Stelle an.
Welches ist richtig?

Hallo @stefs26
Das LCD ist so aufgebaut, wen Du in der Zeile 0.2 hast ein Überlauf zB. hast sich vertan und stat 20 Zeichen willst 25 Zeichen anzeigen " 20 cols, 4 rows + LCD " Dan werden die 5 letze Zeichen in der Zeile 0.0 geschrieben also stat Hello werden wird "+LCD llo, friends!" angezeigt. Da aber die loop läuft wird abwechselnd mal Hello mal +LCD angezeigt.
Hofe Du verstehst was ich meine

Und noch was wen DU zB. schreibst
LCD.setCursor(0,0);
LCD.print(" Hello, friends! 20 cols, 4 rows");

wird das vernünftig angezeigt wie auf dem Bild obwohl du zu lange Zeile schreibst.
Es gibt Leute was schreiben
LCD.setCursor(20,0);
um in die(der) 2 Zeile schreiben, ohne das der Kompiler das anmeckert

hi. Variante a ist richtig.

Nur der erste und der zweite Buchstabe fehlt in der AnzeigeZwei. An der Stelle sind 2 Leerzeichen. Der Rest wird korrekt geschrieben.

Kannst Du mal die Funktiopn ersetzen:

void Wechselanzeige()
{
  static unsigned int tik = 0;
  static unsigned long lastmillis = 0;
  if (millis() - lastmillis > 5000)
  {
    tik++; if (tik>=2) tik=0;lastmillis = millis();
    switch (tik)
    {
      case 0: AnzeigenEins(); break;
      case 1: AnzeigenZwei(); break;
      default: lcd.print("Error");
    }
  }
}

Hi fony

Gut zu wissen, dass bei einem überlauf auf eine andere Zeile geschrieben wird.
Aber das ist es leider auch nicht. Die Zeile (0, 2) habe ich mal auskommentiert und das Fehlerbild bleibt das gleiche.
In der Zeile 0, 2 habe ich in der AnzeigeEins noch 3 zeichen frei und bei der AnzeigeZwei auch 3 Zeichen frei. Die Anzeigen dieser dritten Zeile sind korrekt und generieren keinen überlauf.

Leider immer noch nicht... :frowning: ist aber ein hartnäckiger.
mit deiner void Wechselanzeige() gehts ca. 8sek bis das LCD überhaupt mal was anzeigt und die ersten zwei Buchstaben fehlen.
Habe auch probiert die erste Zeile nur in einer Anzeige zu schreiben, da sich diese ja nicht ändert.

Das einzige was tatsächlich hilft ist die servoAktion im Loop auszukommentieren.

nützen Fotos von der LCD-Anzeige etwas? Glaube die sind im Forum nicht so gerne gesehen...

Ja, das ist richtig - es sind 5 Sekunden :wink: Die Zeit kannst verkürzen.
Für den ersten Start rufe AnzeigenZwei() einfach im Setup als letzte Zeile auf.

Dann sollte in der Anzeige auch wenigstens einmal alles drin stehen.

Hm...
Das wäre aber komisch, wenn da auch die ersten zwei Zeichen weg bleiben.

Folgendes Verhalten:

Zeile (0, 0) in beiden Anzeigen schreiben --> AnzeigeEins fehlt Gr
Zeile (0, 0) in AnzeigeEins auskommentiert --> gleiches Verhalten
Zeile (0, 0) in AnzeigeZwei auskommentiert --> Gr fehlt auf beiden Anzeigen

MOOMENT!

Kommentiere mal in in AnzeigenEins die Zeile lcd.print(status) aus.