ich komme gerade mit meinem Programm wieder nicht weiter :). Kurze Erklärung: DC Motor Pumpe verbunden mit 2 Relay Module LCD-Display, digitalen Lichtsensor und Arduino Uno.
Das Programm sollte die Pumpe ausschalten, wenn der Wasserspiegel im Behälter erreicht wird und einschaltet, wenn das Wasser wieder im Behälter wird, aber mit zeitlicher Verzögerung 10 Sekunden (Zeit nötig um den Behälter wieder nachfüllen)
erstmal habe ich aber den Lichtwert kalibriert.
Alles funktioniert nur die Pumpe sich gleich nach, wenn das Wasser da ist wieder einschaltet.
Ich will, dass die Pumpe sich erstmal wieder automatisch einschalten lässt nach 10 Sekunden.
Ich habe es mit Millis versucht, aber irgendwie kommt es alle durcheinander
Ich hoffe, ich habe es verständlich erklärt.
Danke
Der Sketsch Siehe Unten
#include <SPI.h>
#include <Wire.h>
#include <Digital_Light_TSL2561.h>
#include "rgb_lcd.h"
rgb_lcd lcd;
uint32_t previousMillis = 0;
const int colorR = 255;
const int colorG = 0;
const int colorB = 0;
const int relaisIN1 = 4;
int output_value;
int eingabe;
int upButton = 2;
int downButton = 3;
int selectButton = 5;
int Pumpeein = 7;
int Kalibrierung = 8;
int menu = 1;
bool Sperre = true;
void setup() {
Serial.begin(115200);
pinMode(relaisIN1, OUTPUT);
Wire.begin();
TSL2561.init();
lcd.begin(16, 2);
pinMode(Pumpeein, INPUT_PULLUP);
pinMode(upButton, INPUT_PULLUP);
pinMode(downButton, INPUT_PULLUP);
pinMode(selectButton, INPUT_PULLUP);
pinMode(Kalibrierung, INPUT_PULLUP);
lcd.setRGB(colorR, colorG, colorB);
lcd.setCursor(0, 0);
lcd.clear();
lcd.print("Eingeschaltet");
lcd.setCursor(0, 1);
lcd.print("Drucken Sie Down");
}
void loop() {
//Serial.print("The Light value is: ");
Serial.println(TSL2561.readVisibleLux());
if (!digitalRead(Kalibrierung)) {
output_value = TSL2561.readVisibleLux() + 50;
lcd.clear();
lcd.setCursor(6, 0);
lcd.print("Sensor ist");
lcd.setCursor(0, 0);
lcd.print(TSL2561.readVisibleLux());
lcd.setCursor(0, 1);
lcd.print(output_value);
lcd.setCursor(6, 1);
lcd.print("kalibriert");
Sperre = false;
delay(100);
}
if (!digitalRead(downButton)) {
menu++;
updateMenu();
delay(100);
while (!digitalRead(downButton))
;
}
if (!digitalRead(upButton)) {
menu--;
updateMenu();
delay(100);
while (!digitalRead(upButton))
;
}
if (!digitalRead(selectButton)) {
executeAction();
delay(100);
while (!digitalRead(selectButton))
;
}
if (!digitalRead(Pumpeein)) {
digitalWrite(relaisIN1, LOW);
delay(100);
while (!digitalRead(Pumpeein))
;
}
if (!Sperre && output_value< TSL2561.readVisibleLux() ) {
digitalWrite(relaisIN1, LOW);
}
if (!Sperre && output_value > TSL2561.readVisibleLux() ){
digitalWrite(relaisIN1, HIGH);
}
}
void updateMenu() {
switch (menu) {
case 0:
menu = 1;
break;
case 1:
lcd.clear();
lcd.print(">Medium ist in ");
lcd.setCursor(0, 1);
lcd.print(" Medium ist out");
break;
case 2:
lcd.clear();
lcd.print(" Medium ist in");
lcd.setCursor(0, 1);
lcd.print(">Medium ist out");
break;
case 5:
menu = 2;
break;
}
}
void executeAction() {
switch (menu) {
case 1:
action1();
break;
case 2:
action2();
break;
}
}
void action1() {
lcd.clear();
if (!digitalRead(selectButton)) {
lcd.clear();
lcd.print("Drucken Sie");
lcd.setCursor(0, 1);
lcd.print("Kalibrieren");
delay(100);
}
}
void action2() {
if (!digitalRead(selectButton)) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Medium");
lcd.setCursor(0, 1);
lcd.print("nachfuellen");
delay(100);
}
}
Du suchst einen endlichen Automaten.
Da ich es nciht kompilieren kann, hier ein Ansatz - evtl. sind Schreibfehler drin, die sagt Dir aber der Kompiler.
Und schau, wann die Pumpenbedingung AUS schalten erfüllt sein soll, die must Du eintragen.
#include <SPI.h>
#include <Wire.h>
#include <Digital_Light_TSL2561.h>
#include "rgb_lcd.h"
rgb_lcd lcd;
uint32_t previousMillis = 0;
const int colorR = 255;
const int colorG = 0;
const int colorB = 0;
const int relaisIN1 = 4;
int output_value;
int eingabe;
int upButton = 2;
int downButton = 3;
int selectButton = 5;
int Pumpeein = 7;
int Kalibrierung = 8;
int menu = 1;
bool Sperre = true;
constexpr uint32_t pausezeit {5000}; // Zeit in ms
uint32_t lastmills; // Merker für Abschaltzeit und Pausenanfang
enum pumpenstatus {warten, pumpen, pause}; // Zustände, was die Pumpe machen soll
void setup()
{
Serial.begin(115200);
pinMode(relaisIN1, OUTPUT);
Wire.begin();
TSL2561.init();
lcd.begin(16, 2);
pinMode(Pumpeein, INPUT_PULLUP);
pinMode(upButton, INPUT_PULLUP);
pinMode(downButton, INPUT_PULLUP);
pinMode(selectButton, INPUT_PULLUP);
pinMode(Kalibrierung, INPUT_PULLUP);
lcd.setRGB(colorR, colorG, colorB);
lcd.setCursor(0, 0);
lcd.clear();
lcd.print("Eingeschaltet");
lcd.setCursor(0, 1);
lcd.print("Drucken Sie Down");
}
void loop()
{
//Serial.print("The Light value is: ");
Serial.println(TSL2561.readVisibleLux());
if (!digitalRead(Kalibrierung))
{
output_value = TSL2561.readVisibleLux() + 50;
lcd.clear();
lcd.setCursor(6, 0);
lcd.print("Sensor ist");
lcd.setCursor(0, 0);
lcd.print(TSL2561.readVisibleLux());
lcd.setCursor(0, 1);
lcd.print(output_value);
lcd.setCursor(6, 1);
lcd.print("kalibriert");
Sperre = false;
delay(100);
}
if (!digitalRead(downButton))
{
menu++;
updateMenu();
delay(100);
while (!digitalRead(downButton))
;
}
if (!digitalRead(upButton))
{
menu--;
updateMenu();
delay(100);
while (!digitalRead(upButton))
;
}
if (!digitalRead(selectButton))
{
executeAction();
delay(100);
while (!digitalRead(selectButton))
;
}
switch (pumpenStatus)
{
case warten:
if (!digitalRead(Pumpeein)) // Taste gedrückt
{
digitalWrite(relaisIN1, LOW); // Pumpe an machen
pumpenStatus = pumpen; //
}
break;
case pumpen:
if ( ) // HIER BEDINGUNG EINTRAGEN WANN DIE PUMPE AUSGEHEN SOLL
{
digitalWrite(relaisIN1, HIGH);
lastmilli = millis();
}
break;
case pause:
if (millis() - lastmillis > pausezeit)
{ pumpenStatus = warten; }
break;
}
}
void updateMenu()
{
switch (menu)
{
case 0:
menu = 1;
break;
case 1:
lcd.clear();
lcd.print(">Medium ist in ");
lcd.setCursor(0, 1);
lcd.print(" Medium ist out");
break;
case 2:
lcd.clear();
lcd.print(" Medium ist in");
lcd.setCursor(0, 1);
lcd.print(">Medium ist out");
break;
case 5:
menu = 2;
break;
}
}
void executeAction()
{
switch (menu)
{
case 1:
action1();
break;
case 2:
action2();
break;
}
}
void action1()
{
lcd.clear();
if (!digitalRead(selectButton))
{
lcd.clear();
lcd.print("Drucken Sie");
lcd.setCursor(0, 1);
lcd.print("Kalibrieren");
delay(100);
}
}
void action2()
{
if (!digitalRead(selectButton))
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Medium");
lcd.setCursor(0, 1);
lcd.print("nachfuellen");
delay(100);
}
}
Ist das der sketch der ohne millis funktioniert oder erwartest du darin schon das Verhalten mit einschaltverzögerung?
Du müsstest dir beim ausschalten den aktuellen wert von millis in einer statischen oder globalen variable merken. Und in dem einschalt if zusätzlich die Bedingung millis() - startwert > T10S ergänzen.
Ich habe es geändert, paar Sachen waren für dich bestimmt irreführend. Jetzt mit dem Sketsch passiert aber einfach nichts, Pumpe geht nicht an und damit auch nicht aus.
#include <SPI.h>
#include <Wire.h>
#include <Digital_Light_TSL2561.h>
#include "rgb_lcd.h"
rgb_lcd lcd;
uint32_t previousMillis = 0;
const int colorR = 255;
const int colorG = 0;
const int colorB = 0;
const int relaisIN1 = 4;
int output_value;
int eingabe;
int upButton = 2;
int downButton = 3;
int selectButton = 5;
int Pumpeein = 7;
int Kalibrierung = 8;
int menu = 1;
bool Sperre = true;
constexpr uint32_t pausezeit {5000}; // Zeit in ms
uint32_t lastmillis; // Merker für Abschaltzeit und Pausenanfang
enum pumpenStatus {warten, pumpen, pause}; // Zustände, was die Pumpe machen soll
int pumpenStatus;
void setup()
{
Serial.begin(115200);
pinMode(relaisIN1, OUTPUT);
Wire.begin();
TSL2561.init();
lcd.begin(16, 2);
pinMode(Pumpeein, INPUT_PULLUP);
pinMode(upButton, INPUT_PULLUP);
pinMode(downButton, INPUT_PULLUP);
pinMode(selectButton, INPUT_PULLUP);
pinMode(Kalibrierung, INPUT_PULLUP);
lcd.setRGB(colorR, colorG, colorB);
lcd.setCursor(0, 0);
lcd.clear();
lcd.print("Eingeschaltet");
lcd.setCursor(0, 1);
lcd.print("Drucken Sie Down");
}
void loop()
{
//Serial.print("The Light value is: ");
Serial.println(TSL2561.readVisibleLux());
if (!digitalRead(Kalibrierung))
{
output_value = TSL2561.readVisibleLux() + 50;
lcd.clear();
lcd.setCursor(6, 0);
lcd.print("Sensor ist");
lcd.setCursor(0, 0);
lcd.print(TSL2561.readVisibleLux());
lcd.setCursor(0, 1);
lcd.print(output_value);
lcd.setCursor(6, 1);
lcd.print("kalibriert");
Sperre = false;
delay(100);
}
if (!digitalRead(downButton))
{
menu++;
updateMenu();
delay(100);
while (!digitalRead(downButton))
;
}
if (!digitalRead(upButton))
{
menu--;
updateMenu();
delay(100);
while (!digitalRead(upButton))
;
}
if (!digitalRead(selectButton))
{
executeAction();
delay(100);
while (!digitalRead(selectButton))
;
}
if (!digitalRead(Pumpeein)) { // PUmpe ist aus wenn der Knopf gedruckt ist
digitalWrite(relaisIN1, LOW);
delay(100);
while (!digitalRead(Pumpeein))
;
}
switch (pumpenStatus)
{
case warten:
if (!Sperre && output_value< TSL2561.readVisibleLux() )
{
digitalWrite(relaisIN1, LOW); // Pumpe aus machen
pumpenStatus = pumpen;
lastmillis = millis(); //
}
break;
case pumpen:
if (!Sperre && output_value > TSL2561.readVisibleLux() ) // HIER BEDINGUNG EINTRAGEN WANN DIE PUMPEanGEHEN SOLL
{
digitalWrite(relaisIN1, HIGH);
pumpenStatus = pumpen;
}
break;
case pause:
if (millis() - lastmillis > pausezeit)
{ pumpenStatus = warten; }
break;
}
}
void updateMenu()
{
switch (menu)
{
case 0:
menu = 1;
break;
case 1:
lcd.clear();
lcd.print(">Medium ist in ");
lcd.setCursor(0, 1);
lcd.print(" Medium ist out");
break;
case 2:
lcd.clear();
lcd.print(" Medium ist in");
lcd.setCursor(0, 1);
lcd.print(">Medium ist out");
break;
case 5:
menu = 2;
break;
}
}
void executeAction()
{
switch (menu)
{
case 1:
action1();
break;
case 2:
action2();
break;
}
}
void action1()
{
lcd.clear();
if (!digitalRead(selectButton))
{
lcd.clear();
lcd.print("Drucken Sie");
lcd.setCursor(0, 1);
lcd.print("Kalibrieren");
delay(100);
}
}
void action2()
{
if (!digitalRead(selectButton))
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Medium");
lcd.setCursor(0, 1);
lcd.print("nachfuellen");
delay(100);
}
}
Ich habe ein bißchen bei Adafruit nachgelesen.
Der Sensor kann Gesamthelligkeit und Infrarotanteil (und damit wohl auch sichtbaren Lichtanteil einzeln messen.
Ich nehme an, dass mit größer werdendem Abstand die Lichtintensität abnimmt.
Ich bin aber auch neugierig wie der Code dazu aussieht.
Also @maty247 poste doch mal deinen ganzen Sketch.
Er scheint recht gut struktiert zu sein wie man aus dem gekürzten Sketch sehen kann.
Mit den Bedingungen sollte eigentlich alles stimmen, weil bei dem ursprünglichen Code es funktioniert. Das einzige Problem war das Delay, weil in der Zeit funktionieren die Tasten nicht.
Wie wird das erkannt, ob der Behälter voll oder leer ist?
Das funktioniert, sodass der Behälter aus Glas besteht und ganz unten ist als Ausgang dünnes Glasröhrchen. Auf eine Seite der Röhrchen ist der Lichtsensor und auf der anderen Seite ist eine LED. Damit entstehen unterschiedliche Werte bei befülltem und leerem Behälter. Es erkennt sogar den Wasserspiegel. Das Licht ist in dem Fall sehr wichtig.
Wie wird das erkannt, ob der Behälter voll oder leer ist?
Das funktioniert, sodass der Behälter aus Glas besteht und ganz unten ist als Ausgang dünnes Glasröhrchen. Auf eine Seite der Röhrchen ist der Lichtsensor und auf der anderen Seite ist eine LED. Damit entstehen unterschiedliche Werte bei befülltem und leerem Behälter. Es erkennt sogar den Wasserspiegel. Das Licht ist in dem Fall sehr wichtig.
Das war der ganze Sketch. Das Einzige, was da nicht erwähnt, ist das LED die ist die ganze Zeit an. Deswegen muss sie gar nicht erwähnt werden. Weitere Details Siehe weitere Antworten.
Macht er ja nicht.
Dafür braucht er ja die Pause.
Wenn am unteren Fußpunkt der Auslöser aktiviert ist, geht die Pumpe in Stop.
Jetzt muss der Behälter wieder voll werden. Um nicht sofort auszulösen, wennd er Auslöser unten inaktiv ist vergehen 10 Sekunden, die sind ausreichend um den Behälter neu zu füllen.
-> Manuell. z. B. mit einem Messbecher.
(Ich hab das jetzt sogar so gelöst, das ganz sicher der Auslöser erstmal inaktiv sein muss und erst ab dann die zeit zählt und nicht schon ab dem Punkt, wo der Behälter leer ist)