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


von Jonny H. (jonny123) Flattr this


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
1
int JalEA1 = 30;                            // Jalousie 1 Relais Ein/Aus an Pin 30
2
int JalR1 = 31;                             // Jalousie 1 Relais Richtung an Pin 31
3
unsigned long previousMillisAuf1 = 0;       // Startwert für Jalousie 1 Auffahren
4
unsigned long previousMillisZu1 = 0;        // Startwert für Jalousie 1 Zufahren
5
unsigned long MaxJal1 = 30000;              // Maximale Laufzeit Jalousie 1
6
unsigned long IstJal1M = 0;                 // Merker Ist-Wert
7
boolean Jal1Auf = false;                    // Jalousie 1 auffahren
8
boolean Jal1Zu = false;                     // Jalousie 1 zufahren
9
boolean Timer1An = false;                   // Status, ob Zeit für Jalousie 1 berechnet wird
10
unsigned long SollJal1 (20000);             // Sollwert Jalousie 1 (NUR ZUM TESTEN AUF 20000 GESETZT)
11
unsigned long IstJal1 (0);                  // Istwert Jalousie 1
12
13
void setup()
14
{
15
  Serial.begin(9600);
16
  pinMode(JalEA1, OUTPUT);                   // Relais als Ausgänge deklarieren
17
  pinMode(JalR1, OUTPUT);                    // Relais als Ausgänge deklarieren
18
  digitalWrite (JalEA1, HIGH);
19
  digitalWrite (JalR1, HIGH);
20
21
}
22
23
void loop()
24
{
25
  unsigned long currentMillisJal = millis();             // Millis für Jalousie
26
27
  if (SollJal1 < IstJal1)                                // Auffahren wenn Soll kleiner als Ist ist
28
  {
29
    Jal1Auf = true;
30
    Jal1Zu = false;
31
    //Serial.println("Auffahren gesetzt");               //Nur zum Testen
32
  }
33
34
  else if (IstJal1 < SollJal1)                           // Zufahren wenn Soll größer als Ist ist
35
  {
36
    Jal1Auf = false;
37
    Jal1Zu = true;
38
    //Serial.println("Zufahren gesetzt");                 //Nur zum Testen
39
  }
40
41
  if (Jal1Auf == true && Jal1Zu == false)                 // Auffahren
42
  {
43
    digitalWrite (JalEA1, LOW);                           // Relais Schalten
44
    digitalWrite (JalR1, HIGH);
45
46
    if (Timer1An == false)                                 // Startzeit Speichern
47
    {
48
      previousMillisAuf1 = currentMillisJal;
49
      Timer1An = true;
50
      Serial.println("previousMillisAuf1 gesetzt");         //Nur zum Testen
51
    }
52
    IstJal1M = IstJal1;                                   // Merker IstZeit setzen
53
    IstJal1 = IstJal1M - currentMillisJal - previousMillisAuf1;   // IstZeit berechnen
54
55
56
    if (IstJal1 < SollJal1)                               // Falls Istzeit kleiner als Sollzeit wird, wird die IstZeit gleichgesetzt wie die SollZeit
57
    {
58
      Jal1Auf = false;
59
      IstJal1 = SollJal1;
60
    }
61
    
62
    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
63
    {
64
      IstJal1 = 0;
65
      Jal1Auf = false;
66
    }
67
68
    Serial.println("Auffahren");   //Nur zum Testen
69
    Serial.print("Soll: ");        //Nur zum Testen
70
    Serial.println(SollJal1);      //Nur zum Testen
71
    Serial.print("Ist: ");         //Nur zum Testen
72
    Serial.println(IstJal1);       //Nur zum Testen
73
  }
74
75
76
  if (Jal1Zu == true && Jal1Auf == false)
77
  {
78
    digitalWrite (JalEA1, LOW);
79
    digitalWrite (JalR1, LOW);
80
81
    if (Timer1An == false)
82
    {
83
      previousMillisZu1 = currentMillisJal;
84
      Timer1An = true;
85
      Serial.println("previousMillisZu1 gesetzt");         //Nur zum Testen
86
    }
87
    IstJal1M = IstJal1;
88
    IstJal1 = IstJal1M + currentMillisJal - previousMillisZu1;
89
90
    if (SollJal1 < IstJal1)
91
    {
92
      Jal1Zu = false;
93
      IstJal1 = SollJal1;
94
    }
95
96
    Serial.println("Zufahren");    //Nur zum Testen
97
    Serial.print("Soll: ");        //Nur zum Testen
98
    Serial.println(SollJal1);      //Nur zum Testen
99
    Serial.print("Ist: ");         //Nur zum Testen
100
    Serial.println(IstJal1);       //Nur zum Testen
101
  }
102
103
  if (Jal1Zu == false && Jal1Auf == false)
104
  {
105
    digitalWrite (JalEA1, HIGH);
106
    digitalWrite (JalR1, HIGH);
107
    if (Timer1An)               //Nur zum Testen
108
    { //Nur zum Testen
109
      Serial.println("STOP");   //Nur zum Testen
110
    }                           //Nur zum Testen
111
    Timer1An = false;
112
113
  }
114
  delay(1);
115
}

von Einer K. (Gast)


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
1
void setup()
2
{
3
  Serial.begin(9600);
4
  pinMode(JalEA1, OUTPUT);                   // Relais als Ausgänge deklarieren
5
  pinMode(JalR1, OUTPUT);                    // Relais als Ausgänge deklarieren
6
  digitalWrite (JalEA1, HIGH);
7
  digitalWrite (JalR1, HIGH);
8
9
}


Besser:
1
void setup()
2
{
3
  Serial.begin(9600);
4
  digitalWrite (JalEA1, HIGH);
5
  digitalWrite (JalR1, HIGH);
6
  pinMode(JalEA1, OUTPUT);                   // Relais als Ausgänge deklarieren
7
  pinMode(JalR1, OUTPUT);                    // Relais als Ausgänge deklarieren
8
9
}

von Joachim B. (jar)


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
von Einer K. (Gast)


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

von Sascha W. (sascha-w)


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

von Joachim B. (jar)


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.

von Einer K. (Gast)


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.

von Tschegg the Tschegger (Gast)


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 :-)

von Jonny H. (jonny123) Flattr this


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.