INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Wetterstation mal anders - Funktionsaufrufe werden nicht „abgearbeitet“
02.12.2020, 16:24 (Dieser Beitrag wurde zuletzt bearbeitet: 12.12.2020 16:15 von Bitklopfer.)
Beitrag #1
Wetterstation mal anders - Funktionsaufrufe werden nicht „abgearbeitet“
Hallo zusammen,
ich habe vor, eine „ambiente“ Wetterstation zu bauen. Hierbei sollen Temperatur und Luftfeuchtigkeit über Farbänderungen und sich bewegende Teile dargestellt werden.
Für die Farbänderung nutze ich ein LED Stripe und für die bewegende Teile nutze ich u.a. einen Servo (später sollen noch 2 Schrittmotoren genutzt werden; damit das Ganze hier nicht zu kompliziert wird, habe ich den Teil mit den Schrittmotoren aus dem scetch herausgelassen).
Zur Übertragung von Temperatur und Luftfeuchtigkeit nutze ich eine drahtlose Übertragung auf Basis 433Mhz (Sendehäufigkeit erfolgt Testzwecken alle 3sec; gelöst über „millis“. Das Sende Scetch habe ich nicht mit angehängt; ich denke das hat mit dem Problem nichts zu tun...).
Der aktuelle Stand des Projekts ist, dass Temperatur und Luftfeuchtigkeit erfolgreich empfangen werden und dass Temperaturbereiche mittels einer case Struktur im LED Stripe durch entsprechende Farben auch „wunschgemäß“ dargestellt werden.
Nun soll ebenfalls in einer case Struktur auch ein Servo angesteuert werden.
Hierzu wird in der case Struktur eine Funktion aufgerufen: „Servo90reli()“ bzw „Servo180reli()“ .
Nun das Problem: Sobald eine der beiden Servo-Funktionen „Servo90reli() oder Servo180reli“ im scetch auskommentiert wird, wird zwar die entsprechende Servo Funktion ausgeführt, aber ansonsten „stoppt“ das Programm. Genauer: Nachdem sich der Servo um z.B. 180° gedreht hat, passiert „nichts“. Meine Erwartung wäre, dass wieder in die loop zurückgesprungen wird und der nächste Befehl in der loop abgearbeitet wird. In meinem Fall: "FeuchtigkeitAnzeigen“ . Das ist aber nicht der Fall: Es passiert nichts weiter.
Zu debugging Zwecken hatte ich die Servofunktion wie folgt geändert: Statt der eigentlichen servo Ansteuerung habe ich das LED Stripe leuchten lassen. Das hatte funktioniert. D.h. es wurde in die Funktion Servo180reli gesprungen und das LED stripe wurde korrekt angesteuert. Von da aus erfolgte dann auch ein Sprunk zurück in die loop und die nächste Funktion „FeuchtigkeitAnzeigen“ wurde ausgeführt.
Was ich auch getestet hatte, ist die Ansteuerung der Schrittmotoren anstelle des Servos aus der case Struktur heraus; aber auch hier zeigt sich der gleiche Effekt: D.h. nachdem die Schrittmotoren einmal erfolgreich angesteuert wurden, „stoppt“ das Programm und weitere Befehle z.B. Funktionsaufrufe aus der loop wurden nicht weiter ausgeführt.

Warum führt die Ausführung der Servo oder Schrittmotorenbefehle zu einem „Anhalten“ in der loop ? Und: Was sollte ich also ändern ?
Könnt ihr mir Tipps geben ?
Das wäre echt Klasse. Danke schon mal.

Hier noch Infos zu Komponenten:
Stepper Motor NEMA 17
Arduino UNO mit zusätzlichem Adafruit Motorshield
LED stripe WS2812
Servo SUNFOUNDER
Receiver: WINGONEER RXB6 433Mhz
Sender: Aukru 433Mhz
Netzteil: BTF 100W

Code:
/*
   ================================================================================​============================
   =================================          Ambiente Wetterstation       ====================================
   ================================================================================​============================
*/
#include <PWMServo.h> //library für Servo einbinden
#include <Wire.h> // library für Schrittmotoren einbinden
#include <Adafruit_MotorShield.h> // library für das Motorshield (Schrittmotoren) einbinden
#include <RH_ASK.h>                      // Einbinden von RadioHead Amplitude Shift Keying Library; wird für das Senden/Empfangen von Daten über 433Mhz benötigt
#include <SPI.h>                         // Einbinden von  SPI Library
#include <Adafruit_NeoPixel.h>               // Library für LED Stripe einbinden
#ifdef __AVR__
#include <avr/power.h>
#endif

String str_humid;                       // Definieren der output strings (die dann gesendet werden sollen)
String str_temp;
String str_out;

RH_ASK rf_driver;                         // Erstellung eines Amplitude Shift Keying Object; wird für Senden und Empfangen von Daten benötigt (Funkverbindung)

#define delayval 5                      // Variable "delayval" wird global definiert als allgemeine delayvariable in msec
#define PIN           6                    // festlegen, an welchem digitalen Ausgang, das LED Stripe verbunden ist
#define NUMPIXELS     240                 // festlegen, wieviele LED´s (welches stripe) angeschlossen wurden

PWMServo myservo;  // Servo Objekt erstellen; Servo muss an digital PIN 9 angeschlossen werden
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); // LED stripe wird entsprechend vorbereitet
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); // motorshield object erzeugen


////////////////////////////////////////////// SETUP ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  rf_driver.init();                         // Amplitude Shift Key Objekt wird initialisiert; wird für Senden und Empfangen von Daten benötigt
  Serial.begin(9600);                       // Serial Kommunikation wird initialisiert
  pixels.begin();                           // NeoPixel Library wird initialisiert
  Serial.println("======================= Wetterstation startet  ===========================");
  LEDstripeWeiss();
}

// Variablen für die späteren CASE Strkturen definieren
const int temperaturMin = -5;             // geringster Wert, den der Temperatursensor liefern kann; beim DHT22: -40°C;  Wert für Projekt: -5°C
const int temperaturMax = 30;             // größter Wert, den der Temperatursensor liefern kann; beim DHT22: 125°C; Wert für Projekt: 30°C
const int feuchtigkeitMin = 10;           // geringster Wert, den der Feuchtigkeitssensor liefern kann; beim DHT22: 0 %; Wert für Projekt: 10%
const int feuchtigkeitMax = 100;          // größter Wert, den der Feuchtigkeitssensor liefern kann; beim DHT22: 100 %; Wert für Projekt 100%

////////////////////////////////////////////// LOOP ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {
  TemperaturAnzeigen();                // die Funktionen TemperaturAnzeigen wird aufgerufen
  FeuchtigkeitAnzeigen();              // die Funktionen FeuchtigkeitAnzeigen wird aufgerufen
}

// ===================================  FUNKTIONEN  ===========================================================================​============================================

void TemperaturAnzeigen() {

  uint8_t buf[11];                        //string Puffergröße für den Datenempfang auf die erwartete Größe (Sendepaket) einstellen
  uint8_t buflen = sizeof(buf);           // Prüfen ob die das empfangenen Datenpacket die richtige Größe hat (also vollständig ist)

  if (rf_driver.recv(buf, &buflen))      // wenn das Datenpacket die gültige Größe (Checksumme) hat, dann sollen die Werte ausgelesen bzw. in ein String in ein string gewandelt werden
  {
    str_out = String((char*)buf);
    for (int i = 0; i < str_out.length(); i++) {   // mit der for Schleife soll der strin in 2 Werte geteilt werden
      if (str_out.substring(i, i + 1) == ",") {
        str_humid = str_out.substring(0, i);
        str_temp = str_out.substring(i + 1);
        break;
      }
    }

    int temperatur = atoi(str_temp.c_str());                                  // der string "temp" soll in einen integer "temperatur" gewandelt werden
    Serial.print("Temperatur: ");
    Serial.println(temperatur);

    int rangeTemperatur = map(temperatur, temperaturMin, temperaturMax, 1, 4);    // den Temperaturbereich zwischen 0 und 30 auf cases von 1 bis 4 mappen
    switch (rangeTemperatur) {                                               // case Struktur für das Steuern des LED Stripe
      case 1:
        LEDstripeBlau();
        break;

      case 2:
        LEDstripeTuerkis();
        //Servo90reli();
        /*werden die Zeilen "Servo180reli()" und "Servo90reli" auskommentiert, dann wird der Servo zwar erfolgreich angesteuert.
          Allerdings "stoppt" der scetch in  der Servo Funktion. D,h, es werden keine weiteren Funktionen mehr ausgeführt.
          Das Ziel wäre: Nach Ausführung der Servo Funktion sollte in die loop zurückgesprungen werden, um dann den nächsten Befehl aus der loop auszuführen.
          In dem Fall sollte das die Funktion "FeuchtigkeitAnzeigen" sein. Das ist aber nicht der Fall.
          Was muss geändert werden, sodass nach Ausführung der Servo Funktion weitere Befehle der "loop" ausgeführt werden ? (D.h.in meinem Fall, dass die nächste Funktion aufgerufen wird)
        */
        break;

      case 3:
        LEDstripeOrange();
        //Servo180reli();
        /*werden die Zeilen "Servo180reli()" und "Servo90reli" auskommentiert, dann wird der Servo zwar erfolgreich angesteuert.
          Allerdings "stoppt" der scetch in  der Servo Funktion. D,h, es werden keine weiteren Funktionen mehr ausgeführt.
          Das Ziel wäre: Nach Ausführung der Servo Funktion sollte in die loop zurückgesprungen werden, um dann den nächsten Befehl aus der loop auszuführen.
          In dem Fall sollte das die Funktion "FeuchtigkeitAnzeigen" sein. Das ist aber nicht der Fall.
          Was muss geändert werden, sodass nach Ausführung der Servo Funktion weitere Befehle der "loop" ausgeführt werden ? (D.h.in meinem Fall, dass die nächste Funktion aufgerufen wird)
        */
        break;

      case 4:
        LEDstripeRot();
        break;
    }
  }
}

void FeuchtigkeitAnzeigen() {

  uint8_t buf[11];                        //string Puffergröße für den Datenempfang auf die erwartete Größe (Sendepaket) einstellen
  uint8_t buflen = sizeof(buf);           // Prüfen ob die das empfangenen Datenpacket die richtige Größe hat (also vollständig ist)

  if (rf_driver.recv(buf, &buflen))      // wenn das Datenpacket die gültige Größe (Checksumme) hat, dann sollen die Werte ausgelesen bzw. in ein String in ein string gewandelt werden
  {
    str_out = String((char*)buf);
    for (int i = 0; i < str_out.length(); i++) {   // mit der for Schleife soll der string in 2 Werte geteilt werden
      if (str_out.substring(i, i + 1) == ",") {
        str_humid = str_out.substring(0, i);
        str_temp = str_out.substring(i + 1);
        break;
      }
    }

    int feuchtigkeit = atoi(str_humid.c_str());                               // der string "humid" soll in einen integer "fuechtigkeit" gewandelt werden
    Serial.print(" Feuchtigkeit: ");
    Serial.println(feuchtigkeit);

    int rangeFeuchtigkeit = map(feuchtigkeit, feuchtigkeitMin, feuchtigkeitMax, 1, 4);    // den Feuchtebereich zu cases von 1 bis 4 mappen

    switch (rangeFeuchtigkeit) {    // case Struktur für das Steuern des LED Stripe
      case 1:
        LEDstripeWeiss(); // testweise
        break;

      case 2:
        LEDstripeGruen(); // testweise
        break;

      case 3:
        LEDstripeWeiss();      // testweise
        break;

      case 4:
        LEDstripeWeiss();      // testweise
        break;
    }
  }
}

////////////////////////////////////////////////////////// FUNKTIONEN FÜR DAS LED STRIPE VERHALTEN  /////////////////////////////////////////////////////////////////

void LEDstripeWeiss() {                                       //Funktion um das LED stripe weiss leuchten zu lassen
  pixels.clear();                                             // alle Pixel dunkel schalten
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {                       // steuert alle 240 Pixel an
    pixels.setPixelColor(i, pixels.Color(50, 50, 50));        // RGB Wert
    pixels.show();                                            // sendet die aktualiserten Farbwerte an das LED Stripe
    delay(delayval);
  }
}

void LEDstripeGruen() {
  pixels.clear();
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(10, 110, 10));
    pixels.show();
    delay(delayval);
  }
}

void LEDstripeBlau() {
  pixels.clear();
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 30, 120));
    pixels.show();
    delay(delayval);
  }
}

void LEDstripeTuerkis() {
  pixels.clear();
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 60, 60));
    pixels.show();
    delay(delayval);
  }
}

void LEDstripeOrange() {
  pixels.clear();
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(63, 22, 0));
    pixels.show();
    delay(delayval);
  }
}

void LEDstripeRot() {
  pixels.clear();
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(120, 0, 0));
    pixels.show();
    delay(delayval);
  }
}

////////////////////////////////////////////////////////// FUNKTIONEN FÜR DAS SERVO VERHALTEN  /////////////////////////////////////////////////////////////////

void Servo180reli() {                     // dreht den servo nach rechts um 180° und danach nach links 180°
  Serial.println("servo180reli");
  int servopos = 0;                        // lokale Variable für das Abspeichern der Servoposition
  myservo.attach(SERVO_PIN_A);

  for (servopos = 0; servopos < 180; servopos += 1) {            // dreht den Servo von 0 bis 180° in 1 Grad Schritten
    myservo.write(servopos);              // sagt dem Servo die Position aus Varible servopos anzusteuern
    delay(20);                       // servo "Stell-Geschwindigkeit"
  }
  for (servopos = 180; servopos >= 1; servopos -= 1) { // Servo läuft zurück
    myservo.write(servopos);
    delay(20);
  }
  myservo.detach(); // soll den Servo vom Digital PIN "lösen", damit dieser nicht mehr "wackelt"
}

void Servo90reli() {                     // dreht den servo nach rechts um 90° und danach nach links 90°
  Serial.println("servo90reli");
  int servopos = 0;                        // lokale Variable für das Abspeichern der Servoposition
  myservo.attach(SERVO_PIN_A);

  for (servopos = 0; servopos < 90; servopos += 1) {            // dreht den Servo von 0 bis 90° in 1 Grad Schritten
    myservo.write(servopos);              // sagt dem Servo die Position aus Varible servopos anzusteuern
    delay(20);                       // servo "Stell-Geschwindigkeit"
  }
  for (servopos = 90; servopos >= 1; servopos -= 1) { // Servo läuft zurück
    myservo.write(servopos);
    delay(20);
  }
  myservo.detach(); // soll den Servo vom Digital PIN "lösen", damit dieser nicht mehr "wackelt"
}
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
02.12.2020, 16:57
Beitrag #2
RE: Wetterstation mal anders - Funktionsaufrufe werden nicht „abgearbeitet“
Ich vermute da mal einen Timer-Konflikt. Das PWMServo benutzt einen Timer und RH_ASK auch. Vermutlich benutzen beide Timer 1. Bei der RH_ASK kann man das wohl ändern:
Code:
/// The RH_ASK driver uses a timer-driven interrupt to generate 8 interrupts per bit period. RH_ASK
/// takes over a timer on Arduino-like platforms. By default it takes over Timer 1. You can force it
/// to use Timer 2 instead by enabling the define RH_ASK_ARDUINO_USE_TIMER2 near the top of RH_ASK.cpp

Gruß, Franz-Peter
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
04.12.2020, 16:35
Beitrag #3
RE: Wetterstation mal anders - Funktionsaufrufe werden nicht „abgearbeitet“
(02.12.2020 16:57)MicroBahner schrieb:  Ich vermute da mal einen Timer-Konflikt. Das PWMServo benutzt einen Timer und RH_ASK auch. Vermutlich benutzen beide Timer 1. Bei der RH_ASK kann man das wohl ändern:
Code:
/// The RH_ASK driver uses a timer-driven interrupt to generate 8 interrupts per bit period. RH_ASK
/// takes over a timer on Arduino-like platforms. By default it takes over Timer 1. You can force it
/// to use Timer 2 instead by enabling the define RH_ASK_ARDUINO_USE_TIMER2 near the top of RH_ASK.cpp

SUPER ! Das war die Ursache. Problem ist behoben, nachdem ich die Library entsprechend angepasst hatte.
Tausend Dank! Das war ein toller Hinweis.Smile
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
04.12.2020, 17:10
Beitrag #4
RE: Wetterstation mal anders - Funktionsaufrufe werden nicht „abgearbeitet“: Programm
Freut mich, wenn's jetzt klappt. Und danke für die Rückmeldung.

Gruß, Franz-Peter
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
10.12.2020, 17:16
Beitrag #5
RE: Wetterstation mal anders - Funktionsaufrufe werden nicht „abgearbeitet“: Programm
(04.12.2020 17:10)MicroBahner schrieb:  Freut mich, wenn's jetzt klappt. Und danke für die Rückmeldung.

Hallo Franz-Peter,

nach Änderung der RH_ASK.h Library (Timer 2 verwenden lassen) führte der sketch nun zunächst auch die entsprechenden Funktionen aus. D.h. es wurden Temperatur und Feuchtigkeit über eine 433Mhz Funkverbindung korrekt empfangen und dann in Abhängigkeit einer case Struktur, Farben eines LED stripes geändert, sowie Servo und Schrittmotoren angesteuert. Alles prima also.
Leider zeigt sich nun ein nicht vollziehbares Programmverhalten, nachdem ich weitere Schrittmotorfunktionen hinzugefügt hatte. Diese sollen aus einer case Struktur heraus ausgeführt werden (z.B. die Funktion „ ganzInnen“; siehe sketch).
Folgendes Fehlerbild zeigt sich: Es werden keine plausiblen Messwerte mehr empfangen (Temp 0° und Feuchtigkeit 0%) , sobald im Sketch die Schrittmotoren über entsprechende Funktionen angesteuert werden sollen.
Zur Fehlereingrenzung habe ich nun verschiedene sketch Varianten durch Auskommentieren von Funktionen mit folgendem Ergebnis erzeugt:
1. Variante: „Nur Messwerte darstellen“. Ziel: Um zu prüfen ob Messerte korrekt empfangen werden, sollen Temp. und Feuchtigkeit empfangen und per seriellem Monitor ausgegeben werden Ergebnis: Funktioniert. D.h. Korrektes Empfangen und Darstellen der beiden Messwerte alle 3 sec.
2. Variante: Messwerte empfangen UND LED stripe ansteuern. Ergebnis: Funktioniert. D.h. korrektes Empfangen der Messwerte UND erwartungsgemäßes LED stripe Verhalten. Allerdings: Die Messwerte werden nicht alle 3sec sondern alle 6sec empfangen. Nicht tragisch, aber ein Hinweis auf eine Fehlerquelle ?
3. Variante: Messwerte empfangen UND LED Stripe ansteuern UND zusätzlich Servo ansteuern. Ergebnis: Funktioniert. D.h. D.h. korrektes Empfangen der Messwerte UND erwartungsgemäßes LED stripe Verhalten UND erwartungsgemäßes Ansteuern vom Servo; auch hier werden nur alle 6sec Messwerte empfangen
4. Variante: Wie Variante 3 UND zusätzlich Schrittmotoren ansteuern. Ergebnis: Funktioniert NICHT. D.h. das Kalibrieren der Schrittmotoren im setup funktioniert zwar, aber die Messwerte werden nicht korrekt empfangen (0° Temp und 0% Luftfeuchtigkeit). Die case Struktur wird ausgeführt (für den case 0°...; case 0
5. Variante: Messwerte empfangen und per seriellem Monitor darstellen UND nur die Schrittmotoren ansteuern. Ergebnis: Funktioniert NICHT. D.h. auch hier werden die Messwerte werden nicht korrekt empfangen (0° Temp und 0% Feuchtigkeit).
Alles andere wie Brettaufbau und Komponenten sind gleich geblieben.
Ich kann das Fehlerbild systematisch erzeugen. D.h. jedes Mal wenn ich eine der Varianten neu kompiliere und auf den UNO lade, dann zeigt sich zuverlässig genau das gleiche Verhalten (mit den gleichen Fehlern bzw. mit dem fehlerfreien Funktionieren).
Für mich sieht es so aus, dass das Einbinden der Schrittmotoren zu „irgendeinem“ Problem führt.

Was könnte ich zur Fehlerbehebung probieren ?
Für jeden Tipp bin ich dankbar. Und sorry für das längliche post...

Das angehängte sketch entspricht der (nicht funktionierenden) Variante 4.

Grüße
Guido


Code:
/*
   ================================================================================​============================
   =================================          Ambiente Wetterstation    3_02   ====================================
   ================================================================================​============================
*/
#include <PWMServo.h> //library für Servo einbinden
#include <Wire.h> // library für Schrittmotoren einbinden
#include <Adafruit_MotorShield.h> // library für das Motorshield (Schrittmotoren) einbinden
#include <RH_ASK.h>                      // Einbinden von RadioHead Amplitude Shift Keying Library; wird für das Senden/Empfangen von Daten über 433Mhz benötigt
#include <SPI.h>                         // Einbinden von  SPI Library
#include <Adafruit_NeoPixel.h>               // Library für LED Stripe einbinden
#ifdef __AVR__
#include <avr/power.h>
#endif

String str_humid;                       // Definieren der output strings (die dann gesendet werden sollen)
String str_temp;
String str_out;

RH_ASK rf_driver;                         // Erstellung eines Amplitude Shift Keying Object; wird für Senden und Empfangen von Daten benötigt (Funkverbindung)

#define delayval 5                      // Variable "delayval" wird global definiert als allgemeine delayvariable in msec
#define PIN           6                    // festlegen, an welchem digitalen Ausgang, das LED Stripe verbunden ist
#define NUMPIXELS     240                 // festlegen, wieviele LED´s (welches stripe) angeschlossen wurden

PWMServo myservo;  // Servo Objekt erstellen; Servo muss an digital PIN 9 angeschlossen werden
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); // LED stripe wird entsprechend vorbereitet
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); // motorshield object erzeugen
Adafruit_StepperMotor *myMotor1 = AFMS.getStepper(200, 1); // verbinde Steppermotor 1 mit 200 steps and port 1; d.h. auf dem Arduino shield an M1 und M2;
Adafruit_StepperMotor *myMotor2 = AFMS.getStepper(200, 2); // verbinde Steppermotor 2 mit 200 steps and port 2; d.h. auf dem Arduino shield an M3 und M4;

//int servopos = 0;    // variable to store the servo position
int motor1zaehler; // Variable für Schrittmotor 1 für eine while schleife
int lichtschranke1 = A0; // Gabellichtschranke für Motor 1 an analog Pin 0
int lichtschrankeWert1 = 0; // Variable für Lichtschranke 1 anlegen um den Helligkeitswert für die Gabellichtschranke zu vergleichen
int motor2zaehler; // Variable für Motor 2 für eine  while schleife
int lichtschranke2 = A1; // Gabellichtschranke für Motor 2 an analog Pin 1
int lichtschrankeWert2 = 0; // Variable für Lichtschranke 2 anlegen um den Helligkeitswert für die Gabellichtschranke zu vergleichen

////////////////////////////////////////////// SETUP ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  rf_driver.init();                         // Amplitude Shift Key Objekt wird initialisiert; wird für Senden und Empfangen von Daten benötigt
  Serial.begin(9600);                       // Serial Kommunikation wird initialisiert
  pixels.begin();                           // NeoPixel Library wird initialisiert
  Serial.println("======================= Wetterstation startet  ===========================");
  LEDstripeWeiss();
  AFMS.begin();  // erzeugt eine "Verbindung/Kommunikation" mit dem motorshield mit der default Frequenz von 1.6KHz

  myMotor1->setSpeed(50);  // 50 rpm als Defaultgeschwindigkeit für Schrittmotor 1
  myMotor2->setSpeed(50);  // 50 rpm als Defaultgeschwindigkeit für Schrittmotor 2

  Motorenkalibrieren();
}

// Variablen für die späteren CASE Strkturen definieren
const int temperaturMin = -5;             // geringster Wert, den der Temperatursensor liefern kann; beim DHT22: -40°C;  Wert für Projekt: -5°C
const int temperaturMax = 30;             // größter Wert, den der Temperatursensor liefern kann; beim DHT22: 125°C; Wert für Projekt: 30°C
const int feuchtigkeitMin = 10;           // geringster Wert, den der Feuchtigkeitssensor liefern kann; beim DHT22: 0 %; Wert für Projekt: 10%
const int feuchtigkeitMax = 100;          // größter Wert, den der Feuchtigkeitssensor liefern kann; beim DHT22: 100 %; Wert für Projekt 100%

////////////////////////////////////////////// LOOP ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {
  TemperaturAnzeigen();                // die Funktionen TemperaturAnzeigen wird aufgerufen
  FeuchtigkeitAnzeigen();              // die Funktionen FeuchtigkeitAnzeigen wird aufgerufen
}

// ===================================  FUNKTIONEN  ===========================================================================​============================================

void TemperaturAnzeigen() {

  uint8_t buf[11];                        //string Puffergröße für den Datenempfang auf die erwartete Größe (Sendepaket) einstellen
  uint8_t buflen = sizeof(buf);           // Prüfen ob die das empfangenen Datenpacket die richtige Größe hat (also vollständig ist)

  if (rf_driver.recv(buf, &buflen))      // wenn das Datenpacket die gültige Größe (Checksumme) hat, dann sollen die Werte ausgelesen bzw. in ein String in ein string gewandelt werden
  {
    str_out = String((char*)buf);
    for (int i = 0; i < str_out.length(); i++) {   // mit der for Schleife soll der strin in 2 Werte geteilt werden
      if (str_out.substring(i, i + 1) == ",") {
        str_humid = str_out.substring(0, i);
        str_temp = str_out.substring(i + 1);
        break;
      }
    }

    int temperatur = atoi(str_temp.c_str());                                  // der string "temp" soll in einen integer "temperatur" gewandelt werden
    Serial.print("Temperatur: ");
    Serial.println(temperatur);

    int rangeTemperatur = map(temperatur, temperaturMin, temperaturMax, 1, 4);    // den Temperaturbereich zwischen 0 und 30 auf cases von 1 bis 4 mappen
    switch (rangeTemperatur) {                                               // case Struktur für das Steuern des LED Stripe
      case 1:
        LEDstripeBlau();
        Servo180reli();
        break;

      case 2:
        LEDstripeTuerkis();
        Servo180reli();
        break;

      case 3:
        LEDstripeOrange();
        Servo90reli();
        break;

      case 4:
        LEDstripeRot();
        Servo90reli();
        break;
    }
  }
}

void FeuchtigkeitAnzeigen() {

  uint8_t buf[11];                        //string Puffergröße für den Datenempfang auf die erwartete Größe (Sendepaket) einstellen
  uint8_t buflen = sizeof(buf);           // Prüfen ob die das empfangenen Datenpacket die richtige Größe hat (also vollständig ist)

  if (rf_driver.recv(buf, &buflen))      // wenn das Datenpacket die gültige Größe (Checksumme) hat, dann sollen die Werte ausgelesen bzw. in ein String in ein string gewandelt werden
  {
    str_out = String((char*)buf);
    for (int i = 0; i < str_out.length(); i++) {   // mit der for Schleife soll der string in 2 Werte geteilt werden
      if (str_out.substring(i, i + 1) == ",") {
        str_humid = str_out.substring(0, i);
        str_temp = str_out.substring(i + 1);
        break;
      }
    }

    int feuchtigkeit = atoi(str_humid.c_str());                               // der string "humid" soll in einen integer "fuechtigkeit" gewandelt werden
    Serial.print(" Feuchtigkeit: ");
    Serial.println(feuchtigkeit);

    int rangeFeuchtigkeit = map(feuchtigkeit, feuchtigkeitMin, feuchtigkeitMax, 1, 4);    // den Feuchtebereich zu cases von 1 bis 4 mappen

    switch (rangeFeuchtigkeit) {    // case Struktur für das Steuern des LED Stripe
      case 1:
        LEDstripeWeiss(); // testweise
        ganzInnen();
        break;

      case 2:
        LEDstripeGruen(); // testweise
        Innen();
        break;

      case 3:
        LEDstripeWeiss();      // testweise
        Aussen();
        break;

      case 4:
        LEDstripeWeiss();      // testweise
        ganzAussen();
        break;
    }
  }
}

////////////////////////////////////////////////////////// FUNKTIONEN FÜR DAS LED STRIPE VERHALTEN  /////////////////////////////////////////////////////////////////

void LEDstripeWeiss() {                                       //Funktion um das LED stripe weiss leuchten zu lassen
  pixels.clear();                                             // alle Pixel dunkel schalten
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {                       // steuert alle 240 Pixel an
    pixels.setPixelColor(i, pixels.Color(50, 50, 50));        // RGB Wert
    pixels.show();                                            // sendet die aktualiserten Farbwerte an das LED Stripe
    delay(delayval);
  }
}

void LEDstripeGruen() {
  pixels.clear();
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(10, 110, 10));
    pixels.show();
    delay(delayval);
  }
}

void LEDstripeBlau() {
  pixels.clear();
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 30, 120));
    pixels.show();
    delay(delayval);
  }
}

void LEDstripeTuerkis() {
  pixels.clear();
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 60, 60));
    pixels.show();
    delay(delayval);
  }
}

void LEDstripeOrange() {
  pixels.clear();
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(63, 22, 0));
    pixels.show();
    delay(delayval);
  }
}

void LEDstripeRot() {
  pixels.clear();
  pixels.show();
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(120, 0, 0));
    pixels.show();
    delay(delayval);
  }
}

////////////////////////////////////////////////////////// FUNKTIONEN FÜR DAS STEPPERMOTOREN UND SERVO VERHALTEN  /////////////////////////////////////////////////////////////////

/*void steppermotors() {                     // dreht den servo nach rechts um 180° und danach nach links 180°
  Serial.println("Motoren ansteuern: Microsschritte rechts und links"); //Motor1 wird testweise angesteuert
  myMotor1->step(20, FORWARD, MICROSTEP); //Anzahl der Steps bestimmt die Dauer
  myMotor1->step(20, BACKWARD, MICROSTEP);
  myMotor2->step(20, FORWARD, MICROSTEP);
  myMotor2->step(20, BACKWARD, MICROSTEP);
  }

*/

void ganzInnen() {
  Serial.println("Schrittmotoren ganzInnen");
  myMotor1->step(150, FORWARD, MICROSTEP); //Anzahl der Steps bestimmt die Dauer
  myMotor2->step(150, BACKWARD, MICROSTEP);
}

void Innen() {
  Serial.println("Schrittmotoren Innen");
  myMotor1->step(50, FORWARD, MICROSTEP); //Anzahl der Steps bestimmt die Dauer
  myMotor2->step(50, BACKWARD, MICROSTEP);
}


void Aussen() {
  Serial.println("Schrittmotoren Aussen");
  myMotor1->step(50, BACKWARD, MICROSTEP); //Anzahl der Steps bestimmt die Dauer
  myMotor2->step(50, FORWARD, MICROSTEP);
}

void ganzAussen() {
  Serial.println("Schrittmotoren ganzAussen");
  myMotor1->step(150, BACKWARD, MICROSTEP); //Anzahl der Steps bestimmt die Dauer
  myMotor2->step(150, FORWARD, MICROSTEP);
}


void Servo180reli() {                     // dreht den servo nach rechts um 180° und danach nach links 180°
  Serial.println("servo180reli");
  int servopos = 0;                        // lokale Variable für das Abspeichern der Servoposition
  myservo.attach(SERVO_PIN_A);

  for (servopos = 0; servopos < 180; servopos += 1) {            // dreht den Servo von 0 bis 180° in 1 Grad Schritten
    myservo.write(servopos);              // sagt dem Servo die Position aus Varible servopos anzusteuern
    delay(20);                       // servo "Stell-Geschwindigkeit"
  }
  for (servopos = 180; servopos >= 1; servopos -= 1) { // Servo läuft zurück
    myservo.write(servopos);
    delay(20);
  }
  myservo.detach(); // soll den Servo vom Digital PIN "lösen", damit dieser nicht mehr "wackelt"
}

void Servo90reli() {                     // dreht den servo nach rechts um 90° und danach nach links 90°
  Serial.println("servo90reli");
  int servopos = 0;                        // lokale Variable für das Abspeichern der Servoposition
  myservo.attach(SERVO_PIN_A);

  for (servopos = 0; servopos < 90; servopos += 1) {            // dreht den Servo von 0 bis 90° in 1 Grad Schritten
    myservo.write(servopos);              // sagt dem Servo die Position aus Varible servopos anzusteuern
    delay(20);                       // servo "Stell-Geschwindigkeit"
  }
  for (servopos = 90; servopos >= 1; servopos -= 1) { // Servo läuft zurück
    myservo.write(servopos);
    delay(20);
  }
  myservo.detach(); // soll den Servo vom Digital PIN "lösen", damit dieser nicht mehr "wackelt"
}

void Motorenkalibrieren() {
  /////////////////////////////////////////// SCHRITTMOTOR 1 wird kalibriert //////////////////////////////////
  while (lichtschrankeWert1 < 512) { //d.h. solange die Gabellichtschranke nicht unterbrochen wird
    lichtschrankeWert1 = analogRead(lichtschranke1); // lese den aktuellen Lichtschrankenwert aus und
    myMotor1->step(1, BACKWARD, MICROSTEP); // und lass den Motor 1 nach links drehen, solange bis die Gabellichtschranke nicht unterbrochen wird
    delay(15); // gebe dem Schrittmotor etwas Zeit den jeweiligen Microstep anzufahren/umzusetzen
  }
  /// wenn die Bedingung in der while Schleife nicht mehr erfüllt ist, d.h. die Werte kleiner als 512 sind, dann wurde die Schranke unterbrochen
  myMotor1->step(0, BACKWARD, MICROSTEP); //Motor1 anhalten
  delay(15);
  myMotor1->step(20, FORWARD, MICROSTEP); // Motor 1 soll etwas nach rechts gedreht werden.
  // Grund für das Rechtsdrehen: Damit ist gewährleistet dass die Scheiben/Motoren immer etwas Platz nach links zur Lichtschranke haben für die Kalibrierungsfahrt
  motor1zaehler = 0; // wird für die case Schleifen benötigt
  delay(15);

  /////////////////////////////////////////// SCHRITTMOTOR 2 wird kalibriert //////////////////////////////////
  while (lichtschrankeWert2 < 512) { //d.h. solange die Gabellichtschranke nicht unterbrochen wird
    lichtschrankeWert2 = analogRead(lichtschranke2); // lese den aktuellen Lichtschrankenwert aus und
    myMotor2->step(1, BACKWARD, MICROSTEP); // und lass den Motor 1 nach links drehen, solange bis die Gabellichtschranke nicht unterbrochen wird
    delay(15); // gebe dem Schrittmotor etwas Zeit den jeweiligen Microstep anzufahren/umzusetzen
  }
  myMotor2->step(0, BACKWARD, MICROSTEP); //Motor2 anhalten
  delay(15);
  myMotor2->step(20, FORWARD, MICROSTEP); // Motor 2 soll etwas nach rechts gedreht werden.
  motor2zaehler = 0;
  delay(15);
}
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
11.12.2020, 22:29
Beitrag #6
RE: Wetterstation mal anders - Funktionsaufrufe werden nicht „abgearbeitet“
Leider habe ich keine eigene Erfahrungen mit den von Dir verwendeten Bibliotheken und der HW. Was ich aber weis, dass die Stepper-Lib blockierend ist. D.h. während sich die Motore drehen läuft dein Sketch nicht weiter. Ich vermute, dass in dem Fall die Empfangsroutinen nicht oft genung aufgerufen werden, und deshalb der Empfang nicht funktioniert.
Es gibt zwar nicht blockierende Stepper Libs. Du hast aber ein sehr spezielles MotorShield, was wohl nur von der Adafruit Lib unterstützt wird. Ob es da eine nicht blockierende Lib gibt, weis ich nicht.

Gruß, Franz-Peter
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
12.12.2020, 09:37 (Dieser Beitrag wurde zuletzt bearbeitet: 12.12.2020 09:47 von MicroBahner.)
Beitrag #7
RE: Wetterstation mal anders - Funktionsaufrufe werden nicht „abgearbeitet“
Du solltest auch mal Links zu deinen verwendeten Bauteilen posten. So ist das immer nur mehr Vermutung, was Du tatsächlich einsetzt. Und passt dein Stepper zum Treiberboard?

Gruß, Franz-Peter
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
12.12.2020, 11:27
Beitrag #8
RE: Wetterstation mal anders - Funktionsaufrufe werden nicht „abgearbeitet“
(12.12.2020 09:37)MicroBahner schrieb:  Du solltest auch mal Links zu deinen verwendeten Bauteilen posten. So ist das immer nur mehr Vermutung, was Du tatsächlich einsetzt. Und passt dein Stepper zum Treiberboard?

Danke schon mal für den Hinweis auf die "blockierenden Schrittmotoren" im Zusammenhang mit den Messwerten die dann auch nicht mehr empfangen werden können. Hier werde ich auch schon mal Alternativen probieren (z.B. andere library, anderes sketch...).

Und ja: Das Adafruit motorshield sollte zu meinen Schrittmotoren passen (ich kann die steppers ja auch grundsätzlich in Betrieb nehmen und ansteuern...)

Hättest du eine Empfehlung für ein anderes Motorshield (mit dem dann auch nicht blockierende Ansteuerungen ausgeführt werden können) ?

Anbei aber auch noch der link zu meinen Komponenten:

Adafruit MotorShield v2.3:
https://www.amazon.de/gp/product/B00TDN8...UTF8&psc=1

2 mal: Usongshine Schrittmotor, 48NCM Nema 17 1.8° :
https://www.amazon.de/gp/product/B07X2WS...UTF8&psc=1

ELEGOO UNO R3 Mikrocontroller Board ATmega328P ATMEGA16U2 :
https://www.amazon.de/gp/product/B01EWOE...UTF8&psc=1

WS2812B / SK6812 Strip 4m 240 LED´s :
https://www.amazon.de/gp/product/B00GX9L...UTF8&psc=1

SUNFOUNDER 20KG Servomotor :
https://www.amazon.de/gp/product/B07VJG5...UTF8&psc=1

Netzteil: BTF-LIGHTING DC5V 20A 100W Aluminium Netzteil für WS2812B APA102 LED8806 WS2801 SK6812 LED-Streifenmodule Licht
BTF-LIGHTING (Produktt ist nicht mehr im Sortiment; daher kein link)


Grüße
Guido
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  Nano. Sketch kann nicht hochgeladen werden 4heiner 4 246 02.04.2021 17:21
Letzter Beitrag: 4heiner
  Programm startet bei Neustart nicht Moritzzz 18 560 02.04.2021 14:06
Letzter Beitrag: Tommy56
  Arduino Ampelschaltung Taster funktioniert nicht fatihakan36 9 655 13.03.2021 22:06
Letzter Beitrag: N1d45
  Library Ethernet: Nicht zu compilieren GuaAck 5 426 22.02.2021 17:31
Letzter Beitrag: Tommy56
  von delay auf millis umgestellt, klappt nur nicht. Servo Geschwindigkeit einstellen. gutschy 8 667 21.02.2021 15:22
Letzter Beitrag: gutschy
  Mehrere If-Schleifen werden grundlos immer wieder durchlaufen LK2567 3 343 18.02.2021 15:41
Letzter Beitrag: LK2567
  MMega2560-Clone läßt sich nicht programmieren kpc 8 586 08.02.2021 09:50
Letzter Beitrag: hotsystems
  If-Schleife wird nicht mehr durchlaufen LK2567 2 376 05.02.2021 21:20
Letzter Beitrag: LK2567
  Tasterabfrage funktioniert nicht Moehn 4 514 05.02.2021 15:23
Letzter Beitrag: Moehn
  Kompiler beschwert sich nicht, LC-Display macht aber nicht, was es soll. generic_user492 3 402 26.01.2021 14:11
Letzter Beitrag: MicroBahner

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste