mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zeitberechnung Arduino funtkioniert nicht und ich finde den Fehler nicht


Autor: Jonny H. (jonny123) Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich möchte eine Jalousiesteuerung per Web Interface aufbauen.
Auf einer HTML Seite soll man dann zwischen "Vollständig offen", "1/4", 
"1/2", "3/4", "Nur Schlitze" und "Vollständig geschlossen" wählen 
können. Dazu passe ich dann einfach den Sollwert an. Dieser Teil 
funktioniert bisher auch.

Um in der Testphase alles etwas übersichtlicher zu halten, habe ich die 
Steuerung erstmal in einem eigenen Sketch geschrieben und ich passe zum 
Simulieren einfach vor dem Hochladen die SollWerte für die Jalousie an.

Ich will die Position durch Zeitberechnung bestimmen und leider bekomme 
ich das nicht hin. Die 20.000 millisekunden, die ich als soll eingegeben 
habe, laufen in ca einer Sekunde durch.

Der Rest des Programms funktioniert bisher.

Da dies nur ein kleiner Teil von einer kleinen Hausautomatiesierung ist, 
kommt später alles auf einen Arduino Mega.

Kann mir bitte jemand helfen? Ich kann den Fehler einfach nicht finden.
Ich muss dazu auch sagen, dass ich noch kaum Erfahrung mit Programmieren 
und Arduinos habe.


Es handelt sich um 2 Wechsel Relais:
- Relais 1 Schaltet die Phase
- Relais 2 Schaltet Auffahren oder Zufahren

Ich hoffe ich habe es ausreichend Dokumentiert.
Danke im voraus.

Gruß
Jonny
int JalEA1 = 30;                            // Jalousie 1 Relais Ein/Aus an Pin 30
int JalR1 = 31;                             // Jalousie 1 Relais Richtung an Pin 31
unsigned long previousMillisAuf1 = 0;       // Startwert für Jalousie 1 Auffahren
unsigned long previousMillisZu1 = 0;        // Startwert für Jalousie 1 Zufahren
unsigned long MaxJal1 = 30000;              // Maximale Laufzeit Jalousie 1
unsigned long IstJal1M = 0;                 // Merker Ist-Wert
boolean Jal1Auf = false;                    // Jalousie 1 auffahren
boolean Jal1Zu = false;                     // Jalousie 1 zufahren
boolean Timer1An = false;                   // Status, ob Zeit für Jalousie 1 berechnet wird
unsigned long SollJal1 (20000);             // Sollwert Jalousie 1 (NUR ZUM TESTEN AUF 20000 GESETZT)
unsigned long IstJal1 (0);                  // Istwert Jalousie 1

void setup()
{
  Serial.begin(9600);
  pinMode(JalEA1, OUTPUT);                   // Relais als Ausgänge deklarieren
  pinMode(JalR1, OUTPUT);                    // Relais als Ausgänge deklarieren
  digitalWrite (JalEA1, HIGH);
  digitalWrite (JalR1, HIGH);

}

void loop()
{
  unsigned long currentMillisJal = millis();             // Millis für Jalousie

  if (SollJal1 < IstJal1)                                // Auffahren wenn Soll kleiner als Ist ist
  {
    Jal1Auf = true;
    Jal1Zu = false;
    //Serial.println("Auffahren gesetzt");               //Nur zum Testen
  }

  else if (IstJal1 < SollJal1)                           // Zufahren wenn Soll größer als Ist ist
  {
    Jal1Auf = false;
    Jal1Zu = true;
    //Serial.println("Zufahren gesetzt");                 //Nur zum Testen
  }

  if (Jal1Auf == true && Jal1Zu == false)                 // Auffahren
  {
    digitalWrite (JalEA1, LOW);                           // Relais Schalten
    digitalWrite (JalR1, HIGH);

    if (Timer1An == false)                                 // Startzeit Speichern
    {
      previousMillisAuf1 = currentMillisJal;
      Timer1An = true;
      Serial.println("previousMillisAuf1 gesetzt");         //Nur zum Testen
    }
    IstJal1M = IstJal1;                                   // Merker IstZeit setzen
    IstJal1 = IstJal1M - currentMillisJal - previousMillisAuf1;   // IstZeit berechnen


    if (IstJal1 < SollJal1)                               // Falls Istzeit kleiner als Sollzeit wird, wird die IstZeit gleichgesetzt wie die SollZeit
    {
      Jal1Auf = false;
      IstJal1 = SollJal1;
    }
    
    if (IstJal1 < 0 || IstJal1 > 100000)                  // Es trat oft ein >Fehler auf, wo IstJal1 auf einen sehr großen Wert gesetzt wurde. Hiermit wird dem entegen gewirkt
    {
      IstJal1 = 0;
      Jal1Auf = false;
    }

    Serial.println("Auffahren");   //Nur zum Testen
    Serial.print("Soll: ");        //Nur zum Testen
    Serial.println(SollJal1);      //Nur zum Testen
    Serial.print("Ist: ");         //Nur zum Testen
    Serial.println(IstJal1);       //Nur zum Testen
  }


  if (Jal1Zu == true && Jal1Auf == false)
  {
    digitalWrite (JalEA1, LOW);
    digitalWrite (JalR1, LOW);

    if (Timer1An == false)
    {
      previousMillisZu1 = currentMillisJal;
      Timer1An = true;
      Serial.println("previousMillisZu1 gesetzt");         //Nur zum Testen
    }
    IstJal1M = IstJal1;
    IstJal1 = IstJal1M + currentMillisJal - previousMillisZu1;

    if (SollJal1 < IstJal1)
    {
      Jal1Zu = false;
      IstJal1 = SollJal1;
    }

    Serial.println("Zufahren");    //Nur zum Testen
    Serial.print("Soll: ");        //Nur zum Testen
    Serial.println(SollJal1);      //Nur zum Testen
    Serial.print("Ist: ");         //Nur zum Testen
    Serial.println(IstJal1);       //Nur zum Testen
  }

  if (Jal1Zu == false && Jal1Auf == false)
  {
    digitalWrite (JalEA1, HIGH);
    digitalWrite (JalR1, HIGH);
    if (Timer1An)               //Nur zum Testen
    { //Nur zum Testen
      Serial.println("STOP");   //Nur zum Testen
    }                           //Nur zum Testen
    Timer1An = false;

  }
  delay(1);
}

Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde da eine Zustandsmaschine bauen. Einen endlichen Automaten.
Mit eindeutig benannten Zuständen und klaren übersichtlichen 
Transformationen.

Es soll ja wohl mehr als eine Jalousie werden. Also die Variablen nicht 
durchnummerieren, sondern in Strukturen/Arrays verpacken.

Am Rande:
Dieses erzeugt ein kurzes Relais Zucken
void setup()
{
  Serial.begin(9600);
  pinMode(JalEA1, OUTPUT);                   // Relais als Ausgänge deklarieren
  pinMode(JalR1, OUTPUT);                    // Relais als Ausgänge deklarieren
  digitalWrite (JalEA1, HIGH);
  digitalWrite (JalR1, HIGH);

}


Besser:
void setup()
{
  Serial.begin(9600);
  digitalWrite (JalEA1, HIGH);
  digitalWrite (JalR1, HIGH);
  pinMode(JalEA1, OUTPUT);                   // Relais als Ausgänge deklarieren
  pinMode(JalR1, OUTPUT);                    // Relais als Ausgänge deklarieren

}

: Bearbeitet durch User
Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arduino F. schrieb:
> Am Rande:
> Dieses erzeugt ein kurzes Relais Zucken void setup()
> Besser:

kannst du das mal erklären?

für mich sieht es nach einem Designfehler aus.

im Zuckfall, erst out -> low dann set high kann zucken wenn ein pullup 
verbaut ist!
gibt high low high und muss zucken,
in dem Falle wäre ein pulldown die bessere Wahl
gibt low low high aus ohne zucken.

: Bearbeitet durch User
Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> kannst du das mal erklären?

Auch wenn es nicht explizit im Eingangsposting steht, "sehe" ich da 
invers angesteuerte Relaiseingänge. (lasse mich gerne korrigieren)

pinMode(JalEA1, OUTPUT); // zieht den Pin auf Low
digitalWrite (JalEA1, HIGH); // zieht den Pin auf High
Der Pin geht durch eine kurze Low Phase




digitalWrite (JalEA1, HIGH); // aktiviert den Pullup
pinMode(JalEA1, OUTPUT); // zieht den Pin auf High
Kein Low Pulse

: Bearbeitet durch User
Autor: Sascha W. (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jonny,

was soll das genau bezwecken ?

IstJal1M = IstJal1;
IstJal1 = IstJal1M + currentMillisJal - previousMillisZu1

Da deine Mainloop ja wesentlich schneller läuft als die Millis, addierst 
du dir hier doch ständig den Istwert mit dem Istwert, muliplizierst ihn 
als mal 2 ohne das sich die Millis geändert haben. Kein Wunder das der 
Sollwert ruck zuck errecht wird!
Verwende lieber einen Timer mit 1ms, der dir den itswert in Abhängigkeit 
von der Richtung hoch oder runter zählt. In Main vergleichst du dann 
ober der gewünschte Wert erreicht wurde.
Die Verwendung von Millis ist nicht ganz so einfach, denn auch die long 
Variable läuft mal über und dann stimmt die Berechnung nicht mehr.

Sascha

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arduino F. schrieb:
> Auch wenn es nicht explizit im Eingangsposting steht,

eben drum hab ich das nicht gelesen!

Arduino F. schrieb:
> "sehe" ich da
> invers angesteuerte Relaiseingänge. (lasse mich gerne korrigieren)

jetzt sehe ich das auch

Jonny H. schrieb:
> digitalWrite (JalEA1, LOW);                           // Relais Schalten

er schaltet low aktiv, dann ist das

Arduino F. schrieb:
> pinMode(JalEA1, OUTPUT);                   // Relais als Ausgänge
> deklarieren
>   pinMode(JalR1, OUTPUT);                    // Relais als Ausgänge
> deklarieren
>   digitalWrite (JalEA1, HIGH);
>   digitalWrite (JalR1, HIGH);

oder auch dies

Arduino F. schrieb:
> digitalWrite (JalEA1, HIGH);
>   digitalWrite (JalR1, HIGH);
>   pinMode(JalEA1, OUTPUT);                   // Relais als Ausgänge
> deklarieren
>   pinMode(JalR1, OUTPUT);                    // Relais als Ausgänge
> deklarieren

total überflüssig!

es reicht zum Setzen der Relais
pinMode(JalEA1, OUTPUT); // gibt ja low

zum Rücksetzen der Relais
pinMode(JalEA1, INPUT);  // gibt ja high durch einen pullup, vermutlich 
schon eingebaut.

Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> total überflüssig!
Im Grunde ja.
Wobei das Schalten des Relais mit digitalWrite() dem "Prinzip der 
geringsten Verwunderung" entspricht.
Und darum halte ich meinen Weg für besser, auch wenn es vielleicht ein 
paar Extratakte kostet.

: Bearbeitet durch User
Autor: Tschegg the Tschegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> im Zuckfall, erst out -> low dann set high kann zucken wenn ein pullup
> verbaut ist!
> gibt high low high und muss zucken,
> in dem Falle wäre ein pulldown die bessere Wahl
> gibt low low high aus ohne zucken.

Lass zucken Kumpel, das wird schon :-)

Autor: Jonny H. (jonny123) Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha W. schrieb:
> Hallo Jonny,
>
> was soll das genau bezwecken ?
>
> IstJal1M = IstJal1;
> IstJal1 = IstJal1M + currentMillisJal - previousMillisZu1
>
> Da deine Mainloop ja wesentlich schneller läuft als die Millis, addierst
> du dir hier doch ständig den Istwert mit dem Istwert, muliplizierst ihn
> als mal 2 ohne das sich die Millis geändert haben. Kein Wunder das der
> Sollwert ruck zuck errecht wird!
> Verwende lieber einen Timer mit 1ms, der dir den itswert in Abhängigkeit
> von der Richtung hoch oder runter zählt. In Main vergleichst du dann
> ober der gewünschte Wert erreicht wurde.
> Die Verwendung von Millis ist nicht ganz so einfach, denn auch die long
> Variable läuft mal über und dann stimmt die Berechnung nicht mehr.
>
> Sascha

Stimmt, da habe ich zu kompliziert gedacht.
Ich weiss leider nicht wie ich da die Timer anwenden soll.
Meinst du die Bibliothek "Timer.h"?

In die komplette Steuerung soll auch noch eine RealTimeClock für eine 
Zeitschaltuht integriert werden. Wäre die Laufzeitberechnung damit viel 
komplexer als über die Timer funktion?

Arduino F. schrieb:
> Ich würde da eine Zustandsmaschine bauen. Einen endlichen Automaten.
> Mit eindeutig benannten Zuständen und klaren übersichtlichen
> Transformationen.
>
> Es soll ja wohl mehr als eine Jalousie werden. Also die Variablen nicht
> durchnummerieren, sondern in Strukturen/Arrays verpacken.
>
> Am Rande:
> Dieses erzeugt ein kurzes Relais Zucken

Ja stimmt, eine Zustandmaschine wäre übersichtlicher. Werde ich 
umsetzen, sobald ich das Problem mit der Zeitberechnung hinbekommen 
habe.

Das Zucken habe ich hiermit auch behoben, Danke.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.