Mit 3 Encodern 1 Relais Steuern

@postmaster-ino vielen vielen dank, ja leider Künstlergehilfe muss lernen öfters nein zu sagen :smiley: Danke jetzt hab ich einen Lösungsansatz

Wenn die 3 Encoder einen Sinn machen sollen, wird jeder ja wohl eine andere Triggerzeit auslösen.

Wieder eine gemeine Frage: Was soll passieren, wenn der Duscher mehrere Encoder betätigt? Der User macht das!
Sollen sich die Zeiten addieren, ersertzen oder sonst was?

Wie kann der Duscher eigentlich das Wasser außerhalb der Zeiten ausschalten oder gilt was läuft, das läuft (wie bei den früheren Tankstellen in Russland. Du hast für 20 Rubel Benzin gewählt, dann läuft der durch, egal was Dein Tank dazu sagt)

Gruß Tommy

Paheber:
@franz54 ja und wie muss der code aussehen das der Arduino zählt ?

Das sind ganz normale Impulse, als ob du eine Taste auf HIGH / LOW abfragst. Einmal HIGH / LOW ist ein Impuls. Und für jeden Wechsel in einem Merker+1 adieren. Wenn der nächste Impuls nach sagen wir 100ms nicht kommt. Dann den Merker wieder auf Null. Weil da wohl nur jemand gespielt hat. Wenn es größer 7 Impulse werden, dann Wasser marsch. Beispiele für solche Arduino Tastenabfragen findest du z.B. in Youtube.

Franz

@tommy durch drucken des Encoder Tasters stoppt man das Wasser wieder

@franz54 vielen Dank :slight_smile:

Hi

Der Jurs-Sketch macht, was Du von Deinen Encodern haben willst - zählen.
Dabei werden die 20 Rasten wohl bis 80 hochzählen - wirst Du aber wohl sehen.

MfG

Statt der Encoder oder den AS5600 würd ich einfach einen Megneten nehmen und an 2 Positionen ( Sanduhr 360 und 180 Grad kontrollieren. Dazu reicht ein Reed-Kontakt oder ein Magnetsensor. Beide bekommt man wasserdicht.

Grüße Uwe

Hallo Zusammen,

Habe mich jetzt heute hingesetzt und weiter rumprobiert mein Code sieht so aus:


#include <Encoder.h>
int LEDblau=6;
int messungPin1 = LOW;
int messungPin1Alt = LOW;
Encoder myEnc(3, 4);

void setup() { 
pinMode(6, OUTPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
Serial.begin(9600);
} 
long oldPosition  = -999;
void loop() {
long newPosition = myEnc.read();
 if (newPosition != oldPosition) {
   oldPosition = newPosition;
   Serial.println(newPosition);
 }
if (newPosition == 20 )
{
 digitalWrite(LEDblau, HIGH);
 delay (2000);
 digitalWrite(LEDblau, LOW);
}
 if (newPosition == 40)
{
 digitalWrite(LEDblau, HIGH);
 delay (2000);
 digitalWrite(LEDblau, LOW);
}
 if (newPosition == 60)
{
 digitalWrite(LEDblau, HIGH);
 delay (2000);
 digitalWrite(LEDblau, LOW);
}
 if (newPosition == 80)
{
 digitalWrite(LEDblau, HIGH);
 delay (2000);
 digitalWrite(LEDblau, LOW);
}
else
{
digitalWrite(LEDblau, LOW);
}
}

Die Blaue LED soll den Switch Symbolisieren

Wenn nun mein Encoder auf den Werten 20,40,60,80 vorbei kommt geht die LED für 2sek an.

Wenn Ich drauf bleibe bleibt auch die LED an logischer weise, wie muss ich in den Code jetzt mit dem Befehl mills einarbeiten um delay zu ersetzen und die LED trotz dem das der Encoder den IF wert hat nach 2 sek aus geht?

  1. Gibt es eine Möglichkeit alle 180° werte in jeweils eine IF schleife zu setzen ? Also 1IF = 0,40,80 etc… und 2IF 20,60,100…etc ?

Vielen Dank für eure Bemühungen und die Geduld mit mir :smiley:

Gruß Philipp

Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
So ist er auch auf portablen Geräten lesbar. Das kannst Du auch noch nachträglich ändern.
Dann bleibt auch die (hoffentlich vorhandene) Formatierung erhalten.

Es gibt keine IF-Schleife, nur eine IF-Abfrage.

Gruß Tommy

Tommy56:
Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
So ist er auch auf portablen Geräten lesbar. Das kannst Du auch noch nachträglich ändern.
Dann bleibt auch die (hoffentlich vorhandene) Formatierung erhalten.

Es gibt keine IF-Schleife, nur eine IF-Abfrage.

Gruß Tommy

Danke hab grad erst die richtige Text Bearbeitung gefunden :smiley:

Dann meine Frage so : kann ich mehrer Werte in einer if-abfrage abfragen ?

gruß philipp

Ja, mit && (AND) und || (OR) verknüpft.

Gruß Tommy

Hi

Du fragst ab, ob ein Vielfaches von 20 erreicht wurde - Das geht auch einfacher.
ergebnis = wert % 20;
% = Modulo - in der Grundschule war Das 'Rest einer Division'
if (!wert%20){
//wir sind auf einem Vielfachem von 20
}

Dort merkst Du Dir, daß wir 'da' sind.
So kannst Du auch in die Abfrage mit einbinden, ob wir noch nicht 'da' sind.

byte wert;
boolean da;
...
loop(){
  if (!wert%20 && !da){ //wird nur ausgeführt, wenn wir noch nicht 'da' sind und eine 20er Position haben
   da=1;
   startzeit=millis();
   digitalWrite(pinLED,HIGH);
  }
  if (da && millis()-startzeit>6000){ //wird nur ausgeführt, wenn wir 'da' sind und die Wartezeit um ist
   digitalWrite(pinLED,LOW);
   da=0;
  }
}

@postmaster-ino Super vielen Dank :DDD

hab den code jetzt eingepflegt hab jetzt nur eine Fehlermeldung “Startzeit” nicht definiert

#include <Encoder.h>
int LEDblau=6;
int messungPin1 = LOW;
int messungPin1Alt = LOW;
byte wert;
boolean da;
Encoder myEnc(3, 4);

 void setup() { 
 pinMode(7, INPUT);
 pinMode(6, OUTPUT);
 pinMode(3, INPUT);
 pinMode(4, INPUT);
 Serial.begin(9600);
 } 
long oldPosition  = -999;
 void loop() {
 long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
  if (newPosition == !wert%40 && !da)
  { //wird nur ausgeführt, wenn wir noch nicht 'da' sind und eine 20er Position haben
   da=1;
   startzeit=millis();
   digitalWrite(LEDblau,HIGH);
  }
  if (da && millis()-startzeit>3000){ //wird nur ausgeführt, wenn wir 'da' sind und die Wartezeit um ist
   digitalWrite(LEDblau,LOW);
   da=0;
  }
 
 else
 {
 digitalWrite(LEDblau, LOW);
 }
 }

Startzeit ist doch aber als Millis() definiert oder ?

Gruß Philipp

Hi

startzeit soll den Wert von millis() aufnehmen - die Variable muß natürlich vorher definiert sein.
Entweder lokal in loop():
static uint32_t startzeit;
oder global oberhalb von setup() - dann ohne static (was das static dort bewirkt, müsste ich nachlesen).
Innerhalb einer Klammer bewirt das static, daß die Variable das Ende der Klammer überlebt und beim nächsten Mal der Wert noch vorhanden ist.
Ähnlich einer globalen Variable - nur ist Diese nur in dieser (und tieferen) Klammer-Ebene sichtbar - und überdeckt gleich heißende globale Variablen.

MfG

Edit
Du hast Da etwas durcheinander gebracht.
Deine IF
if (newPosition == !wert%40 && !da)
macht sicher nicht, was Du willst.
wert%20 ergibt Null, wenn die Wert ohne Rest durch 20 teilbar ist.
Diesen Fall wollen wir ja - nur brauchen wir eine 1 - Das macht das vorgestellte !
!wert%20
Das ergibt 1, wenn der wert ohne Rest durch 20 teilbar ist.
Mein wert ist Dein newPosition.

Es wird Dir außerdem auffallen - wenn Du lange genug in eine Richtung drehst, daß irgendwo 'Mist' passiert.
Der Zahlenvorrat der Zähl-Variable ist nicht ohne Rest durch 20 teilbar!

postmaster-ino:
Ähnlich einer globalen Variable - nur ist Diese nur in dieser (und tieferen) Klammer-Ebene sichtbar - und überdeckt gleich heißende globale Variablen.

Die tieferen Klammerebenen sind innerhalb der übergeordneten Klammerebene in der die static Variable angelegt wurde. Du hast das richtige gemeint.

Da manche das verwechseln könnten, als Ergänzung: Eine in der Klammerung aufgerufene Funktion hat zwar auch Klammern, ist aber keine untergeordnete Klammerebene!

Gruß Tommy

postmaster-ino:
Hi

startzeit soll den Wert von millis() aufnehmen - die Variable muß natürlich vorher definiert sein.
Entweder lokal in loop():
static uint32_t startzeit;
oder global oberhalb von setup() - dann ohne static (was das static dort bewirkt, müsste ich nachlesen).
Innerhalb einer Klammer bewirt das static, daß die Variable das Ende der Klammer überlebt und beim nächsten Mal der Wert noch vorhanden ist.
Ähnlich einer globalen Variable - nur ist Diese nur in dieser (und tieferen) Klammer-Ebene sichtbar - und überdeckt gleich heißende globale Variablen.

MfG

Edit
Du hast Da etwas durcheinander gebracht.
Deine IF
if (newPosition == !wert%40 && !da)
macht sicher nicht, was Du willst.
wert%20 ergibt Null, wenn die Wert ohne Rest durch 20 teilbar ist.
Diesen Fall wollen wir ja - nur brauchen wir eine 1 - Das macht das vorgestellte !
!wert%20
Das ergibt 1, wenn der wert ohne Rest durch 20 teilbar ist.
Mein wert ist Dein newPosition.

Es wird Dir außerdem auffallen - wenn Du lange genug in eine Richtung drehst, daß irgendwo ‘Mist’ passiert.
Der Zahlenvorrat der Zähl-Variable ist nicht ohne Rest durch 20 teilbar!

Sorry postmaster-ino ich versteh es nicht :frowning:

Ich habe es jetzt so in meinen Code eingepflegt

#include <Encoder.h>
int LEDblau=6;
int messungPin1 = LOW;
int messungPin1Alt = LOW;
boolean da;
Encoder myEnc(3, 4);

 void setup() { 
 pinMode(7, INPUT);
 pinMode(6, OUTPUT);
 pinMode(3, INPUT);
 pinMode(4, INPUT);
 Serial.begin(9600);
 } 
long oldPosition  = -999;
 void loop() {
 long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
  static uint32_t startzeit;
  if (!newPosition%20 && !da)
  { //wird nur ausgeführt, wenn wir noch nicht 'da' sind und eine 20er Position haben
   da=1;
   startzeit=millis();
   digitalWrite(LEDblau,HIGH);
  }
  if (da && millis()-startzeit>3000){ //wird nur ausgeführt, wenn wir 'da' sind und die Wartezeit um ist
   digitalWrite(LEDblau,LOW);
   da=0;
  }
 
 else
 {
 digitalWrite(LEDblau, LOW);
 }
 }

Sorry Ich verstehe es grad echt nicht wie das aufgebaut ist

Vielen dank im Voraus

Gruß Philipp

postmaster-ino:
if(!wert%20)

Das heißt quasi "wenn Modulo Wert/20 Null ist" und kann auch

if(wert%20 == 0)

geschrieben werden.

Arbeite dich vielleicht mal ein wenig in die Sprache ein, zb in der Arduino Referenz.

Hi

Gewöhne Dir an, die Klammern einheitlich zu setzen.
Selber setze ich öffnende Klammern ans Ende der Zeile, Die die Klammer öffnet … wow, toller Satz …
Du hast Das bunt gemischt, teilweise sind die Klammern eine Zeile drunter - Das lässt den Code, meiner Meinung nach, nur aufquellen - das Zeug liest Sich nicht mehr.
Auch hast Du einzelne Leerzeilen drin, Die unnötig/unschön sind.
Dann noch: STRG+T - Das rückt den Kram auf Klammerebene ein - so sieht man, was zusammen gehört.

Im Grunde passte der Sketch aber -BIS AUF der ELSE-Zweig der unteren IF.
Was hattest Du Dir dabei gedacht?
Was soll diese IF bewirken und was macht dann der ELSE-Zweig?
Das hätte ich gerne von Dir beantwortet.
Da mir die Encoder.h fehlt, kompiliert Das nicht bei mir - gehe jetzt davon aus, daß Du einen kompilierenden Sketch hier rein gebracht hast - dann sollte Der jetzt sogar ‘tun’.

Trotzdem bestehe ich auf die Beantwortung meiner Fragen.

MfG

#include <Encoder.h>
int LEDblau = 6;
int messungPin1 = LOW;
int messungPin1Alt = LOW;
boolean da;
Encoder myEnc(3, 4);

void setup() {
  pinMode(7, INPUT);
  pinMode(6, OUTPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  Serial.begin(9600);
}
long oldPosition  = -999;
void loop() {
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
  static uint32_t startzeit;
  if (!newPosition % 20 && !da){ //wird nur ausgeführt, wenn wir noch nicht 'da' sind und eine 20er Position haben
    da = 1;
    startzeit = millis();
    digitalWrite(LEDblau, HIGH);
  }
  if (da && millis() - startzeit > 3000) { //wird nur ausgeführt, wenn wir 'da' sind und die Wartezeit um ist
    digitalWrite(LEDblau, LOW);
    da = 0;
  } //<-- den ELSE-Zweig, Der hier stand - Den meine ich im Post!
}

postmaster-ino:
Hi

Gewöhne Dir an, die Klammern einheitlich zu setzen.
Selber setze ich öffnende Klammern ans Ende der Zeile, Die die Klammer öffnet … wow, toller Satz …
Du hast Das bunt gemischt, teilweise sind die Klammern eine Zeile drunter - Das lässt den Code, meiner Meinung nach, nur aufquellen - das Zeug liest Sich nicht mehr.
Auch hast Du einzelne Leerzeilen drin, Die unnötig/unschön sind.
Dann noch: STRG+T - Das rückt den Kram auf Klammerebene ein - so sieht man, was zusammen gehört.

Im Grunde passte der Sketch aber -BIS AUF der ELSE-Zweig der unteren IF.
Was hattest Du Dir dabei gedacht?
Was soll diese IF bewirken und was macht dann der ELSE-Zweig?
Das hätte ich gerne von Dir beantwortet.
Da mir die Encoder.h fehlt, kompiliert Das nicht bei mir - gehe jetzt davon aus, daß Du einen kompilierenden Sketch hier rein gebracht hast - dann sollte Der jetzt sogar ‘tun’.

Trotzdem bestehe ich auf die Beantwortung meiner Fragen.

MfG

#include <Encoder.h>

int LEDblau = 6;
int messungPin1 = LOW;
int messungPin1Alt = LOW;
boolean da;
Encoder myEnc(3, 4);

void setup() {
  pinMode(7, INPUT);
  pinMode(6, OUTPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  Serial.begin(9600);
}
long oldPosition  = -999;
void loop() {
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
  static uint32_t startzeit;
  if (!newPosition % 20 && !da){ //wird nur ausgeführt, wenn wir noch nicht ‘da’ sind und eine 20er Position haben
    da = 1;
    startzeit = millis();
    digitalWrite(LEDblau, HIGH);
  }
  if (da && millis() - startzeit > 3000) { //wird nur ausgeführt, wenn wir ‘da’ sind und die Wartezeit um ist
    digitalWrite(LEDblau, LOW);
    da = 0;
  } //<-- den ELSE-Zweig, Der hier stand - Den meine ich im Post!
}

@postmaster-ino Danke für die Hilfe, else war noch drin da ich zuerst mit 3 Tastern gearbeitet hab und dann auf die encoder gewechselt bin

mein encoder.h ist der von Paul Stoffregen
leider funktioniert das Programm so nicht, jetzt löst er nur bei 0 wert des encoders aus

gruß Philipp

Hi

Lib installiert und geprüft (auf Pins 2 & 3, Da habe ich derzeit einen Encoder dran).
Jo, hast Recht!
Die Zeile muß

  if (!(newPosition % 20) && !da){

lauten - das && bindet stärker, als das & (was, wenn man drüber nachdenke, auch logisch ist).
Und auch das ! ist stärker als das % - nun denn, Klammern kosten ja Nichts.

Was mir beim Testen aufgefallen ist:
Wenn die Sanduhr auf Null (oder einem Vielfachen von 20) stehen bleibt, triggert das Programm laufend neu.
Also den Status (da) auf byte geändert und 3 Status gemacht.

//Quelle https://github.com/PaulStoffregen/Encoder
//Paul Stoffregen
#include <Encoder.h>

int LEDblau = 13;          //'auf L'-LED auf Nano/Uno angepasst
const byte pinA = 2;     //Pins meines Drehencoder
const byte pinB = 3;
uint32_t wartezeit = 3000;
const uint16_t teiler=2400;     //mein Encoder hat 600 'Rasten', macht 2400 Impulse
byte da;    //in BYTE geändert - brauchen 3 Status

Encoder myEnc(pinA, pinB);

void setup() {
  pinMode(pinA, INPUT_PULLUP);
  pinMode(pinB, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  static long oldPosition;
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
  static uint32_t startzeit;
  /*
    if (!(newPosition % teiler) && !da) { //wird nur ausgeführt, wenn wir noch nicht 'da' sind und eine 20er Position haben
      da = 1;
      Serial.print('!');
      startzeit = millis();
      digitalWrite(LEDblau, HIGH);
    }
    if (da == 1 && millis() - startzeit > wartezeit) { //wird nur ausgeführt, wenn wir 'da' sind und die Wartezeit um ist
      digitalWrite(LEDblau, LOW);
      Serial.print('_');
      da = 2;
    }
    if (da == 2 && (newPosition % teiler)) da = 0;
  */
  boolean ntrigger=newPosition % teiler; //no_trigger
  switch (da) {
    case 0://Warte auf Trigger-Position
      if (!ntrigger) {
        da = 1;
        Serial.print('!');
        startzeit = millis();
        digitalWrite(LEDblau, HIGH);
      }
      break;
    case 1://Warte auf Ende der Laufzeit
      if (millis() - startzeit > wartezeit) { //wird nur ausgeführt, wenn wir 'da' sind und die Wartezeit um ist
        digitalWrite(LEDblau, LOW);
        Serial.print('_');
        da = 2;
      }
      break;
    case 2://Warte auf Verdrehen von Trigger-Position weg
      if (ntrigger) da = 0;
      break;
  }
}

Was mir hier auffiel:
Wenn man zu schnell dreht, überspringt der Encoder-Wert einige Zahlen - wodurch die Prüfung dann nicht stattfindet.
Allerdings scheint die Lib mindestens so sattelfest zu sein, daß schnelles Verdrehen zwischen den Fingern (bei 2400 Impulsen pro Umdrehung) und sogar per Akkuschrauber (1500r/min) kein Verzählen statt findet - zumindest reagiert der Sketch danach immer noch bei gefühlt gleichem Winkel (Abflachung der Welle zum Kabel - Das muß vorerst als ‘top’ reichen).

MfG

PS: Also der Sketch lässt jetzt bei mir die Nano-interne ‘L’-LED für 3 Sekunden leuchten, wenn wir (langsam genug … sind bei mir halt doch ‘etwas mehr’ Schritte) eine volle Umdrehung verdreht haben - und die LED zuvor aus war.
Pins, Wartezeit und Anzahl Impulse/Umdrehung (teiler) im Sketch einstellbar.
Ups: die globale oldposition nach loop() verschoben und dort, statt static ‘const’ deklariert … 1x kompilieren (egal, wie klein die Änderung war) hilft Da schon …

@postmaster-ino

Top Vielen Vielen herzlichen dank, hab jetzt mit der byte Funktion es auch verstanden wie das funktioniert. Echt mega vielen Dank!!!

Hab jetzt noch das Anliegen (ich hoffe es ist nicht zu viel verlangt) Durch den taster druck des encoders soll der Ausgang (die LED) ausgehen und auf die nächste 20er Potenz wartenhab mich jetzt schon durch Foren gelesen aber finde keine Lösung die funktioniert fällt ihnen da noch etwas ein?.

nochmals vielen Dank!

Gruß Philipp