Forum: Mikrocontroller und Digitale Elektronik ESP8266 D1 mini, Schlafmodus und ext. Interrupt


von Christian (elektrojunkie)


Lesenswert?

Werte Community,

zuerst mal vorweg, das ist mein erster Beitrag hier, bzw. anders gesagt, 
ich bin der Neue hier. :)

Weiters möchte ich euch bitten mit mir erbarmen zu haben, denn ich weiß 
nicht was ich tue. hahaha Zumindest nich bei allem.

Zu meinem Problem:


Ich habe schon lange nicht mehr programmiert, deshalb hat ein Freund mir 
ein bisschen geholfen. Von ihm habe ich auch den ESP 8266 D1 mini 
bekommen und wir haben für die Programmierung VS Code mit dem Plugin 
PlatformIO verwendet. Ob man damit Debuggen kann weiß ich bis dato noch 
nicht.

Mein Projekt funktioniert soweit so gut, nur möchte ich einen kleinen 
Zusatz dabei haben. Ohne diesen Zusatz ist das Ganze ziemlich lästig. 
Ich komme aber gleich darauf zu sprechen.

Vorab möchte ich jedoch sagen, dass durch euer prüfendes Auge der 
bisherige Code sicherlich besser zu schreiben ist, mir ist aber das 
momentan egal, hauptsache das Programm tut was es soll. Bin nämlich ein 
bisschen im Zeitdurck und möchte einfach das es läuft.

Nun aber zu den Einzelheiten:

Ich habe einen ESP8266 D1 mini, einen Motortreiber "Motor Driver Module 
BTS7960", einen Motor, zwei Schalter (keine Taster, obwohl im Programm 
mit Taster benannt), einen LDR und ein Poti.

Der ESP ist folgendermaßen programmiert:
Über den LDR und das Poti wird ein Schwellwert festgelegt welcher bei 
Über oder Unerschreiten den Motor eine gewisse Zeit laufen lässt. Dieser 
zieht eine Klappe nach oben. Da mir aufgefallen ist, dass beim 
Runterlaufen die Klappe schneller unten ist wurde für die Fahrt nach 
unten eine kürzere Zeit eingestellt. Deshalb gibt es im Programm zwei 
Zeiten.
Der ESP geht dann in den Schlafmodus und wacht alle Minuten einmal auf, 
schaut nach ob die Werte des LDR noch passen oder sich verändert haben 
und geht wieder schlafen. Der Schalfmodus ist einfach um Strom zu 
sparen, da das ganze über ein Akkupack betrieben wird. Zu erwähnen ist, 
dass die Zeit auf Grund von Testzwecken momentan auf 5 Sekunden 
eingestellt ist, später aber auf eine Minute verändert werden soll.Die 
beiden Schalter sind dazu da, dass die Klappe manuell hoch oder runter 
gefahren werden kann.

Nun kommt aber das Problem!

Der Schalter wird jedoch nur dann erkannt wenn der Controler aufwacht 
und der Schalter gedrückt ist.  Daher möchte ich, dass durch Drücken des 
Schalters der Controller mittels Interrupt aufgeweckt wird, je nach 
Schalter entweder die Klappe nach oben oder unten gefahren wird, und 
danach der Controller wieder schlafen geht.
Der Part mit den Interrupts ist im Code noch nicht vorhanden. Ich habe 
zwar schon vieles probiert, aber nichts davon funktioniert wirklich.

Könnt ihr mir hier weiterhelfen wo ich ansetzen soll?

Eines sei hier noch erwähnt, beim Controller wurde zwischen Pin D0 und 
Pin RST eine fixe Brücke, (also mittels Draht miteinander verbunden) 
gelegt. Das habe ich so im in diversen Beiträgen gelesen. Dies wird zum 
Schlafen bzw. Aufwecken des Controllers benötigt. Für die Programmierung 
des Contrllers muss ich die Brücke jedoch öffnen. Ihr wisst das aber 
wahrscheinlich viel besser als ich.

Im Code sind noch Textausgaben die ich zu Testzwecken verwendet habe, 
sollen euch aber nicht weiter stören.

Ich hoffe hier die entsprechenden Antworten zu erhalten und bedanke mich 
vorab recht herzlich für eure Beiträge Codeergänzungen bzw. Hinweise.

LG Christian


P.S.: Hier noch der bis dato funktionierende Code:



1
#include <Arduino.h>
2
#include "user_interface.h"
3
4
5
float helligkeit = 0;
6
bool Taster1 = false;
7
bool Taster2 = false;
8
9
int helligkeitsschwelle = 950;
10
int dunkelschwelle = 970; //750
11
int currentTime = 0;
12
int LaufzeitHoch = 20;  //Laufzeit *0.01s = tatsächliche Laufzeit  //255 Runter
13
int LaufzeitRunter = 295;                                           //295 Hoch
14
int Schlafzeit = 5; //in Sekunden
15
int i = 0;
16
static int state = 0;    // 0 ist zu, 1 ist offen
17
byte statebyte;
18
byte rtcStore[1];
19
20
void setup() {
21
  // put your setup code here, to run once:
22
  Serial.begin(9600);
23
  system_rtc_mem_read(64, rtcStore, 1);
24
  state = (int)rtcStore[0];
25
26
  pinMode(D1, INPUT_PULLUP);  // AUF
27
  pinMode(D2, INPUT_PULLUP);  // ZU
28
  pinMode(D5, OUTPUT);        //Eingang 1
29
  pinMode(D6, OUTPUT);        //Eingang 2
30
  pinMode(D7, OUTPUT);        //Eingang 3
31
  pinMode(D8, OUTPUT);        //Eingang 4
32
33
  // digitalWrite(D5,LOW);
34
  // digitalWrite(D6,LOW);
35
  // digitalWrite(D7,LOW);
36
  // digitalWrite(D8,LOW);
37
  
38
39
}
40
41
void startDeepSleep(){
42
  Serial.println("Going to deep sleep...");
43
  ESP.deepSleep(Schlafzeit * 1000000);
44
  yield();
45
}
46
47
void MotorAus() {
48
  digitalWrite(D5, LOW);
49
  digitalWrite(D6, LOW);
50
  currentTime = 0;
51
}
52
53
void KlappeRunter() {
54
  if(state != 1) {
55
    Serial.print("Motor auf \n");
56
    while(currentTime < LaufzeitRunter) {
57
      digitalWrite(D5, HIGH);
58
      digitalWrite(D6, LOW);
59
      currentTime += 1;
60
      delay(10);
61
      }
62
    state = 1;
63
    rtcStore[0] = (byte)1;    //Abspeichern der Tür offen Position
64
    system_rtc_mem_write(64, rtcStore, 1);  //Schreiben in den permanenten Speicherbereich
65
    MotorAus();
66
  }
67
  
68
}
69
70
void KlappeRauf() {
71
  if(state != 0) {
72
   Serial.print("Motor zu \n");
73
    while(currentTime < LaufzeitHoch) {
74
      digitalWrite(D5, LOW);
75
      digitalWrite(D6, HIGH);
76
      currentTime += 1;
77
      delay(10);
78
      }
79
    state = 0;
80
    rtcStore[0] = (byte)0;
81
    system_rtc_mem_write(64, rtcStore, 1);
82
    MotorAus();
83
  }
84
  
85
}
86
87
void loop() {
88
89
  for(i = 0; i<5; i++) {
90
    helligkeit += analogRead(A0);
91
  }
92
  helligkeit = helligkeit/5;
93
 
94
  Taster1 = digitalRead(D1);    //Gedrückt == 0
95
  Taster2 = digitalRead(D2);
96
97
98
99
  // put your main code here, to run repeatedly:
100
  Serial.print("\n");
101
  Serial.print("\n");
102
  Serial.print(helligkeit);  //*0.003125
103
  Serial.print("\n");
104
  Serial.print("Status: ");
105
  Serial.print(state);
106
  Serial.print("\n");
107
  Serial.print(Taster1);
108
  Serial.print(" , ");
109
  Serial.print(Taster2);
110
  Serial.print("\n");
111
112
113
  if( (Taster1 && Taster2) && (round(helligkeit) < helligkeitsschwelle)) { 
114
    KlappeRunter();
115
  }
116
  else if((Taster1 && Taster2) && (round(helligkeit) > dunkelschwelle)) { 
117
    KlappeRauf();
118
  }
119
  else if(!Taster1 && Taster2) {
120
    KlappeRauf();
121
  }
122
  else if(Taster1 && !Taster2) {
123
    KlappeRunter();
124
  }
125
126
  // if(!Taster1 || (round(helligkeit) < helligkeitsschwelle)) {  //|| (helligkeit < helligkeitsschwelle)
127
  //   MotorLinks();
128
  // }
129
  // else if(!Taster2 || (round(helligkeit) > dunkelschwelle)) {  //|| (helligkeit > dunkelschwelle)
130
  //   MotorRechts();
131
  // }
132
  
133
 
134
  MotorAus();
135
  
136
  //delay(5000);
137
  startDeepSleep();
138
}

: Verschoben durch Moderator
von Alexander (alecxs)


Lesenswert?

Da hier keiner antwortet versuch ich es mal.

Interrupt-Pins
1
#define INTERRUPT_PIN_1 D1
2
#define INTERRUPT_PIN_2 D2

globale Variablen um den Zustand der Schalter zu speichern und die 
Interrupt-Flags zu aktivieren
1
volatile bool interruptTriggered = false;
2
volatile bool switch1Pressed = false;
3
volatile bool switch2Pressed = false;

Interrupt-Service-Routine (ISR)
1
void switchInterrupt() {
2
  switch1Pressed = digitalRead(INTERRUPT_PIN_1) == LOW;
3
  switch2Pressed = digitalRead(INTERRUPT_PIN_2) == LOW;
4
  interruptTriggered = true;
5
}

Interrupts konfigurieren
1
void setup() {
2
  // ...
3
  pinMode(INTERRUPT_PIN_1, INPUT_PULLUP);
4
  pinMode(INTERRUPT_PIN_2, INPUT_PULLUP);
5
6
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN_1), switchInterrupt, CHANGE);
7
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN_2), switchInterrupt, CHANGE);
8
}

Interrupt-Trigger lesen
1
void loop() {
2
  // ...
3
4
  if (interruptTriggered) {
5
    detachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN_1));
6
    detachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN_2));
7
8
    if (switch1Pressed && switch2Pressed) {
9
      KlappeRunter();
10
    } else if (switch1Pressed) {
11
      KlappeRauf();
12
    } else if (switch2Pressed) {
13
      KlappeRunter();
14
    }
15
16
    switch1Pressed = false;
17
    switch2Pressed = false;
18
    interruptTriggered = false;
19
20
    attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN_1), switchInterrupt, CHANGE);
21
    attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN_2), switchInterrupt, CHANGE);
22
  }
23
24
  // ...
25
}

edit: funktioniert nicht. Interrupts scheinen nicht zu laufen im sleep 
Modus.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Christian schrieb:
> Daher möchte ich, dass durch Drücken des
> Schalters der Controller mittels Interrupt aufgeweckt wird

Das geht nicht. Du kommst beim ESP8266 aus dem Deep-Sleep Modus nur mit 
einem Reset heraus.

von Christian (elektrojunkie)


Lesenswert?

Ok, danke euch beiden.
Dachte man könnte den Controller auch mittels Tastendruck wie oben 
beschrieben auch aufwecken lassen. Aber wenn das nicht geht muss ich das 
wohl oder übel akzeptieren.
Werde nun einen eigenen Taster platzieren der den Contrller mittels RST 
aufweckt.

Vielen Dank nochmal

von A. Z. (donvido)


Lesenswert?

Du müsstest mit deinem Tastendruck den Resetpin UND einen Eingangspin 
bedienen. Am Eingangspin benötigst du dann einen ausreichend 
dimensionierten Tiefpass um direkt nach dem Aufwachen überprüfen zu 
können, ob und welcher Taster gedrückt wurde.

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.