Projekt Überwachung/Schalter/Termin Planung/ Abfall Kalender / Servo / Relais / LCD Menü über Encoder /offenes Projekt/ zum Nachbau

Hallo,

ich möchte gern für meine Werkstatt eine kleine Box bauen die mir den Alltag etwas erleichtern könnte. Nicht immer fällt mir alles ein oder ich vergesse zu schauen.

Da ich gerade viel Spaß am basteln habe, und hier im Forum bei mein Tests viel Hilfe bekommen hatte, wage ich mich an ein neues Projekt.

Eine Kleine Box mit vielen drin.

  • Ein Melder wenn sich jemand dem Eingang nähert ( „ bekomme das nicht immer mit !“) mit Sound Ausgabe „ Achtung es nähert sich eine Person dem Objekt „ auf Meter z.b.
  • CO2 Warner . !!Wenn möglich!!
  • Überwachung einer Maschine „ reicht ein Lichtsensor – wenn es dunkel wird Achtung „
  • Terminplaner
  • Kalender mit wichtigen Sachen die ich mir nicht merken kann
  • Abfall Kalender soll dort gleich mit angezeigt werden ( Sd Karte .. bei mir wäre es eine Calendar (.ics) Datei die wir jedes Jahr bekommen )
  • 1 oder 2 Relais oder ein Servo und ein Relai sollten auch mit ran ( kommt auf platz an „pins“)
  • Echtzeit Uhr ist klar sowie Sound Mp3 Modul
  • und was nicht zu vergessen ist „ wir wohnen hier auf dem Dorf und gerne kommt der eine oder andere mal vorbei auf ein Gespräch und ein Bier :wink: „ also bevor hier der eine oder andere sich die frage stellt, darf ich noch fahren … kommt ein Tester mit rein oder ran über ein Kabel .

Ich habe jetzt angefangen das ganze aufzubauen in wokwi.

Am Anfang kommt die Zeit und Überwachung und Temperatur. In der Mitte der anzeige (3 zeile )

sollen später die Tages Infos laufen /Termine Abfall ….

Im Untermenü kann man dann die andern Sachen auswählen .

Kommt aber eine Warnung ! Maschine Aus Oder es Kommt Jemand oder … soll das später sofort eine Meldung Kommen Akustisch sowie im Display .

Mal sehen ob jemand Lust hat mit zu basteln oder mit Ideen und Tipps helfen kann .

Zur zeit Hänge ich total fest beim auswählen oder Menü erstellen . Hab schon so 100 Seiten durch und so richtig geht’s nicht. Mit Taster ja mit Drehregler nöö

Vielleicht hat ja hier jemand eine Idee wie man das machen könnte mit 4-5 Unterpunkten für die auswahl- z.b. Relais an/aus, kommende Termine, Maschinen Warnung abschalten , Alk Tester .

LG bin für jede Idee offen und für alles Dankbar

Hier mal der Link zum Aufbau

schaut ordentlich aus dein Code und benutzt konsequent functions.
Trotzdem würde ich es persönlich anders angehen.
Dem Code schrittweise neue Funktionen hinzufügen.

Auch die Menüstruktur-Struktur schrittweise erstellen.
Im Prinzip hast du
Auslöser für einen Menüpunkt vorwärts bzw. Menüpunkt rückwärts
Und diesem Prinzip folgend kommt dann immer was neues hinzu.
Nach dem Untermenü folgt das Unter-untermenü usw.

Wenn du da erst mal das ganze "Inhaltsverzeichnis" anlegst und dann versuchst das zu füllen schleppst du immer eine Menge Leerbehälter mit herum.
Aber ab einem bestimmten Punkt ist das dann Geschmacksache

vgs

hallo vielen Dank für das Lob . Ich arbeite mich seit paar Wochen erst wieder ein . ( nach einen großen Rückfall "Gesundheitlich ") Die Hilfe im Forum ist super und ich bastel den Code so das ich noch Überblick habe .

Mit dem Menü . Puh da stehe ich gerade selber auf dem Schlauch. Normal reichen 5-6 Menü punkte aus . Aber via Dreh-Encoder findet man nur Infos die nicht gehen.

Im Grunde Möchte ich nur das diese Startanzeige kommt , aber sowie man drückt kommt man in das Menü .

Bis Jetzt nicht :slight_smile:

LG Toni

fändest du denn Drehencoder gut?
Es gibt eine Encoder-library NewEncoder die funktioniert einwandfrei und bietet
einige schöne Funktionen an:
Hat einen integrierten der Zähler der automatisch rauf/runter gezählt wird.

Den Zahlenbereich kann man eingrenzen.
Wenn man an min bzw. max ankommt bleibt der Zahlenwert auf min bzw. max.
Man kann den Zähler und die min/max-Werte bei laufendem Programm neu setzen.
Damit müsste man das eigentlich sehr komfortabel programmieren können.
vgs

im Grunde ja . ich möchte das Gehäuse nicht mit Hoch runter tasten und so belegen verunstalten.
So ein Drehregler mit Drucktaster ist doch perfekt . Ein Loch bohren und gut ist . Und sieht sicher schöner aus.

Zumal man nicht erst überlegen muss ob ich jetzt hoch oder runter drücke :slight_smile:
Ich würde das cool finden .

Wie gesagt ich habe mir jetzt minimal 100 Seiten angeschaut im web . Von Videos und Codes und bla bla bla .
Selbst wo andere schreiben geht . Schreiben wieder andere ja im Jahr 2012 heute nicht mehr mit rotary.h
Selbst hier im Forum gibt dazu Beiträge Menü mit rotary.h testen geht nicht :frowning:
Ich wollte ja nach der Startanzeige genau jetzt das Menü aufbauen und später den Rest . Aber gerade finde ich noch nicht die Lösung und meine ist Blödsinn
lg

Edit : ist es eigentlich möglich zusammen bei wokwi.com an ein Projekt zu arbeiten ?

Also dann kommt hier ein Demo-Code der einige Features hat:

Zwei Macros für komfortablen Debug-Output
Sag mir die Quellcodedatei des Programms das im Flashspeicher ist
einfach zu benutzender Timer
NewEncoder-Demo mit zwei Modi die über den Encoder-Button umgeschaltet werden

// start of macros dbg and dbgi
#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);
// usage: dbg("1:my fixed text",myVariable);
// myVariable can be any variable or expression that is defined in scope

#define dbgi(myFixedText, variableName,timeInterval) \
  do { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  } while (false);
// usage: dbgi("2:my fixed text",myVariable,1000);
// myVariable can be any variable or expression that is defined in scope
// third parameter is the time in milliseconds that must pass by until the next time a
// Serial.print is executed
// end of macros dbg and dbgi

#include "Arduino.h"

void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__));
  Serial.print( F("  compiled ") );
  Serial.print(F(__DATE__));
  Serial.print( F(" ") );
  Serial.println(F(__TIME__));
}


boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - periodStartTime >= TimePeriod )
  {
    periodStartTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  }
  else return false;            // not expired
}

unsigned long MyTestTimer =  0;                   // variables MUST be of type unsigned long
const byte    OnBoard_LED = 13;

unsigned long buttonReleaseTimer;

void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);

  if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
    digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
  }
}


#include "NewEncoder.h"

const byte EncChA_Pin = 2;
const byte EncChB_Pin = 3;
const int minVal = -20;
const int maxVal =  20;
const int startVal = 2;

// Pins 2 and 3 should work for many processors, including Uno. See README for meaning of constructor arguments.
// Use FULL_PULSE for encoders that produce one complete quadrature pulse per detnet, such as: https://www.adafruit.com/product/377
// Use HALF_PULSE for endoders that produce one complete quadrature pulse for every two detents, such as: https://www.mouser.com/ProductDetail/alps/ec11e15244g1/?qs=YMSFtX0bdJDiV4LBO61anw==&countrycode=US&currencycode=USD

NewEncoder myEncoderObject(EncChA_Pin, EncChB_Pin, minVal, maxVal, startVal, FULL_PULSE);
// myEncState is a variable of type EncoderState
// EncoderState is a structured variable that has two "simple" variables
// .currentValue which is type int16_t
// (16 bit signed integer valuerange -36767 to 36767)
// currentValue counts up / down with each pulse created through rotating the encoder
// and
// .currentClick which is of type "EncoderClick"
// the variable type "EncoderClick" can have just 3 values
// NoClick, DownClick, UpClick where "click" means a "pulse" created through rotating the encoder
NewEncoder::EncoderState myEncState;

int16_t currentValue;
int16_t prevEncoderValue;

int16_t tempMin = 10;
int16_t tempMax = 30;
int16_t actualTemperature;
int16_t storedTemperature;

int16_t rpmMin = 40;
int16_t rpmMax = 50;
int16_t actualRpm;
int16_t storedRpm;


const byte EncBtnPin = 4;

const byte TEMPERATURE_MODE = 0;
const byte RPM_MODE = 1;

byte myMode = TEMPERATURE_MODE;
byte myLastMode = myMode;


void setup() {
  pinMode(EncBtnPin, INPUT_PULLUP);

  Serial.begin(115200);
  PrintFileNameDateTime(); 

  Serial.println("Starting");

  if (!myEncoderObject.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  } else {
    // store values of currentValue and EncoderClick into variable myEncState
    myEncoderObject.getState(myEncState);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = myEncState.currentValue;
    Serial.println(prevEncoderValue);
  }
}

void pushBtnTogglesMode(byte p_IO_Pin, byte &p_mode) {

  static int buttonState;             // the current reading from the input pin
  static int lastButtonState = LOW;   // the previous reading from the input pin

  // the following variables are unsigned longs because the time, measured in
  // milliseconds, will quickly become a bigger number than can be stored in an int.
  static unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
  unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

  // read the state of the switch into a local variable:
  int reading = digitalRead(p_IO_Pin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        if (p_mode == 1) {
          p_mode = 0;
        }
        else {
          p_mode = 1;
        }
      }
    }
  }
  // save the reading. Next time through the loop, it'll be the lastButtonState:
  lastButtonState = reading;  
}

void CheckForModeChange() {
  if (myMode != myLastMode) {
    myLastMode = myMode;
    Serial.print("mode changed new mode ");
    
    if (myMode == TEMPERATURE_MODE) {
      Serial.println("Temperature");      
    }
    if (myMode == RPM_MODE) {
      Serial.println("rpm");      
    }

    if (myMode == RPM_MODE) {
      storedTemperature = actualTemperature; // store actual temperature for later RE-storing
      myEncoderObject.newSettings(rpmMin, rpmMax, storedRpm , myEncState); // setup encoder for rpm-mode
      actualRpm = myEncState.currentValue;
      dbg("RPM-Mode active", actualRpm);
      Serial.println();
    }

    if (myMode == TEMPERATURE_MODE) {
      storedRpm = actualRpm;                  // store actual RPM for later RE-storing
      actualTemperature = storedTemperature;  // restore temperature as we are changing to temperature-mode
      myEncoderObject.newSettings(tempMin, tempMax, actualTemperature, myEncState); // setup encoder for temperature-mode
      actualTemperature = myEncState.currentValue;
      dbg("TemperatureMode active", actualTemperature);
      Serial.println();
    }
  }
}

void PrintEncoderValue() {
  // very important ! this stores actual values into variable myEncState
  if (myEncoderObject.getState(myEncState)) { //<<<== very important
    Serial.print("Encoder: ");
    if (myMode == TEMPERATURE_MODE) {
      Serial.print("Temperature=");      
    }
    if (myMode == RPM_MODE) {
      Serial.print("rpm=");      
    }
    currentValue = myEncState.currentValue;

    // if currentValue has REALLY changed print new currentValue
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;

      // if currentValue stayed the same because the number is at upper/lower limit
      // check if encoder was rotated by using the UpClick / DownClick-values
    } else
      switch (myEncState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("at upper limit.");
          break;

        case NewEncoder::DownClick:
          Serial.println("at lower limit.");
          break;

        default:
          break;
      }
  }
}  


void loop() {
  BlinkHeartBeatLED(OnBoard_LED,250);
  
  pushBtnTogglesMode(EncBtnPin, myMode); // check if button was pressed if Yes change value of variable myMode

  CheckForModeChange();

  PrintEncoderValue();
  
  // update value according to active mode
  if (myMode == TEMPERATURE_MODE) {
    actualTemperature = myEncState.currentValue;
  }
  else {
    actualRpm = myEncState.currentValue;
  }
}

Dat is ne jute Frage. Käme auf einen Versuch an
Du kannst ja mal ein Demo-Projekt anlegen und den Link posten
Du sagst ne änderung an
statt
Serial.print("Hello Word!");

Serial.print("blablaquatschi");

ich mache die Änderung und speichere neu und dann lädst du es neu
und prüfst ob die Änderung drin ist
vgs

1 Like

der link ist ja angelegt :slight_smile: nur kann man da niemanden einladen .
das menü

Struktur:

Menü

  1. Anstehende Termin anzeigen „ kommende 4 tage „

  2. Überwachung Maschinen Sensor
    ----- an
    -----aus

  3. Relai 1(aussen)
    ------an
    ------aus

  4. Relai 2(...)
    ------an
    ------aus

  5. Abfall Kalender anzeigen wieder für 4 tage z.b.

  6. Uhr stellen „ kein plan ob das geht „

  7. ALK tester

  8. frei ---
    z.b.
    reicht total aus finde ich .
    jetzt muss ich mir erst mal dein code ansehen .
    Du kannst bei wokwi dir nur eine copy speichern oder das als zip runterladen . so sehe ich das . LG

Ach du scheisse hätte nicht gedacht was ich für den Drehregler alles brauche.

Ich hab das kurz gefasst und in der simu. Geht der auch schon ./ wenn ich start ausschalte /

wir reden aber von dem gleich DEBO ROT SWITCH: Entwicklerboards - Kodierter Drehschalter bei reichelt elektronik

Ja der Demo-Code ist für den KY-040 Encoder. Ich habe es eben vor dem posten noch einmal getestet.

Das mit dem WOKWI-code gemeinsam entwickeln frage ich mal bei WOKWI-Discord. Da müsste ganz schnell eine Antwort kommen.

vgs

1 Like

AH es gibt eine möglichkeit !
irre um die ecke
man kopiert das beispiel von mir zu sein Wokwi.

man läd sich das als Zip datei runter ... bearbeitet es und schreibt den andern welche datein neu sind .
dann müsste ich die Datein löschen und die neuen einfügen .
nur so gehts .
oder
man schreibt einfach datei menue.h ... barbeitet :slight_smile:

code

tauschen fertig
@ec2021 arbeitet doch damit . vieleicht weiß er wie man das macht ( zusammen an ein Projekt unter Wokwi) schreiben kann man ja hier

@my_xy_projekt
lacht bestimmt schon. Und fragt sich wie viel Beiträge es diesmal werden. :wink: Er macht das irgendwie blind :slight_smile: finde ich aber mega .

lg

Nicht unbedingt.
Da ich nicht dran teilhaben kann - und eigentlich schon nach dem ersten Zähler nicht mehr wollte, ist das so schon ok.
Ja, ich mach viel mit dem SerMon - bei Sensoren ist schlecht, aber sonst...
Was Du auf dem Display siehst, sehe ich auf dem Monitor :wink:
Hat nen ganz entscheidenen Vorteil: Ich brauch mich nicht um kaputte Kabel kümmern...
Brauchst ja blos heute Mittag rein schauen. Ich hab mir einfach den Sensor emuliert - Wert reinschreiben und gut ist :wink:

1 Like

da haste recht zu 1000% oder um kontakt probleme mit testboard .
"Da ich nicht dran teilhaben kann" ? du siehst das wo überhaupt nicht bei wokwi?
nur für Dich zum drüber schauen
Projekt_X.zip (14,5 KB)

das habe ich gesehen . deswegen sage ich ja du machst das Blind . Hab dir mal noch ein Bild mit gemacht .
Nun siehst du sicher warum ich den test mit dem servo gemacht habe :wink:
Wenn Dir meine Vorarbeit nicht gefällt ... scheiss mich ruhig an . damit kann ich leben . Und wenn du nee Idee hast für das Menü .... raus damit .
LG

Bis zum Menu ist noch Platz.
Meine Empfehlung ist schon mal die time-lib von Paul Stoffregen.
Da brauchst Du nichts selber machen, bekommst alles fertig geliefert und sparst Dir ggfls. auch noch viel Schreibarbeit...

Soweit ich es weiß, werden Wokwi-Projekte, wenn man nicht angemeldet ist, bei Betätigung der "Save-Taste" mit einer eindeutigen Projektnummer gespeichert. Diese erscheint nach "Save" im Browser. Kopiert man diesen Link und postet ihn hier, kann jeder darauf zugreifen und wahrscheinlich auch ändern...

Wir könnten diese State Machine mal als Testobjekt nehmen ....

https://wokwi.com/arduino/projects/322215281414898258

jetzt haste mich wieder geärgert :slight_smile: schau ich mir auf jeden fall an . Ich brauch so was zur zeit noch als praktisches beispiel um das besser zu verstehen . Die Examples muss ich mir da anschauen :wink: das hilft mir . Ist ja eh noch mein problem, zumal ich DS3231 da hätte und die gibts dort in der simu nicht . :frowning:

du kannst das ändern . aber es speichert es nur für dich . soweit ich das sehe . `enum {
WARTEN,
ARBEITEN
} Task_Type;

ich mach da jetzt jetzt mal

enum_test  {
   WARTEN,
   ARBEITEN
} Task_Type;

`Edit : nun hab ich das unter mein Projekten stehen mit enum_test aber bei Dir wird sich nichts geändert haben .

Stimmt. Dann gibt es folgende Möglichkeit:

Jeder kopiert sich das Ursprungsprojekt in ein eigenes Projekt und kann dort nach Belieben herumprobieren. Vorschläge werden im Forum veröffentlicht (ggf. zusätzlich mit dem Link).

Einer (der TO?!) verwaltet eine "offizielle" Version mit bekanntem Link. Vom TO akzeptierte Änderungen werden dort eingebracht.

Jeder kann dann damit den eigenen Projekt-Raum selbst updaten oder die eigene Lösung weiter vorantreiben.

Wichtig ist, das die offizielle Version auch hier im Forum geposted wird, um niemanden auszuschließen und zur "sicheren Archivierung"!

1 Like

Nur mal als Frage: Seit Jahren wurde Code hier im Forum "entwickelt".
Das gibt auch Mit-Lerneffekte. Manchmal. Bei mir eher weniger.
Wer das simulieren will, kann das gerne machen, aber Code entwickeln und hier nur noch das Forum missbrauchen um über Ausschnitte zu diskutieren sollte zu denken geben.

Ym2C
Na denne.

So ist das sicher nicht gemeint (ich schrieb ja auch, dass der Code hier zu posten ist)!

Der Vorteil bei der Simulatornutzung ist, dass man vieles auch ohne die reale Hardware testen kann. Das ist schon ein Vorteil... Die Hauptbasis ist und bleibt das Forum!

Nicht falsch verstehen, aber @cooper3210 hat es bereits an anderer Stelle auf den Punkt gebracht: Ich simuliere ALLES was ich nicht habe mit dem Seriellen Monitor oder durch Variablen und blind im wahrsten Sinne des Wortes.
Es gibt das eine oder andere, was ich habe, aber nachdem bis heute nicht geklärt ist, warum der Simulator für einen Loop-Umlauf das 10 fache der Zeit braucht, als ich hier mit echter Hardware, ist die Traute dahingehend gleich NULL.
Code im Forum lesen - fertig. Kann ich den nicht lesen, auch weil ich an eine gänzlich ander Formatierung gewöhnt bin, und ist er kopierfähig, landet er in einer IDE.
Kompilieren geht immer. :wink:

ich habe die TimeLib mal mit übertragen . in mein Projekt . Auf der IDE kann ich das testen und passt . Alles verstanden habe ich noch nicht aber kommt noch .
bei Wokwi würde ich es gerne testen, aber ich bekomme den Serial monitor nicht an .

Edit : wenn ich das richtig verstanden habe reicht es dann .
statt:
lcd.print(aktuell.toString(Zeit));
einfach

lcd.print(hour());
lcd.print(minute());
lcd.print (second());

https://wokwi.com/arduino/projects/323923544235835988