Hall0,
je nach gesendetem MQTT Topic Wert löse ich eine for-Schleife aus, die einfach nur bis 10 hochzählt. Publishe ich zb. eine 1, wird sie gestartet, bei 0 beendet, aber natürlich erst, wenn die 10 erreicht ist.
Ist es irgendwie via MQTT möglich, diese for-Schleife vorzeitig zu unterbrechen, also bevor 10 erreicht wird?
Gruß Kymchy
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
/* Globals */
bool looprunning;
// Update these with values suitable for your network.
const char* ssid = "wFRITZ!Box";//put your wifi ssid here.
const char* password = "xxxxxxxxxxxxxxxx";//put your wifi password here.
const char* mqtt_server = "192.168.178.105";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup_wifi() {
delay(100);
// We start by connecting to a WiFi network
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length)
{
Serial.print("Command is : [");
Serial.println(topic);
int p =(char)payload[0]-'0';
if(p == 0){
looprunning = false;
} else{
looprunning = true;
}
Serial.print("gesendeter MQTT Topic Wert: ");
Serial.println(p);
Serial.print("looprunning Wert: ");
Serial.println(looprunning);
Serial.println();
} //end callback
void reconnect() {
// Loop until we're reconnected
while (!client.connected())
{
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
//if you MQTT broker has clientID,username and password
//please change following line to if (client.connect(clientId,userName,passWord))
if (client.connect(clientId.c_str()))
{
Serial.println("connected");
//once connected to MQTT broker, subscribe command if any
client.subscribe("Arduino/Test/Loop/OnOff");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 6 seconds before retrying
delay(6000);
}
}
} //end reconnect()
void loopme(){
if(looprunning == true){
for (int i = 0; i < 11; i++)
{
Serial.print("Counter: ");
Serial.println(i);
delay(100);
}
delay(1000);
};
}
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
loopme();
delay(2000);
}
Hallo,
Du sprichst für mich in Rätseln. Die einzige for Schleife die ich sehe ist die.
void loopme(){
if(looprunning == true){
for (int i = 0; i < 11; i++)
{
Serial.print("Counter: ");
Serial.println(i);
delay(100);
}
delay(1000);
};
und die willst Du vorzeitig verlassen ? Abhängig von was ?
Du könntest anstelle der festen 11 eine variable nutzen.
Aber der Sinn der Funktion st mir nicht klar
Heinz
Ja, diese for-Schleife ist gemeint. Die Sinnhaftigkeit sei erstmal dahingestellt, ist nur zu Testzwecken.
Die Schleife wird ausgelöst, wenn, wie ich schon schrieb, der Payload eines MQTT Topic einen bestimmten Wert bekommt. Das geschieht in der Callback Funktion. Ein neuer Payload kann aber nur ausgewertet werden, wenn die For-Schleife mindestens einmal komplett durchgelaufen ist.
Meine Frage ist nun, ob es möglich ist, den Payload des Topic auch innerhalb dieser Scheife auszuwerten, um dann ein Break zu veranlassen.
Ich verstehe es auch immer noch nicht. Aber ein genereller Tip für so was: Vergiss while und for Schleifen und auch delay. Wenn du auf Ereignisse reagieren willst benutzt man Statemaschienen und zum Timing in diesen dann millis. Am besten fängst du noch mal ganz neu an.
die Schleife soll Mal als Animation für einen LED Ring mit 60 LEDs dienen(Laufring). Warum sollte ich das nicht mit einer for-Schleife machen. Das habe ich in einem anderen Sketch schon so realisiert. Ich hatte diesen nur zu Testzwecken eingerichtet, um zu gucken, ob ich in einer Schleife ein MQTT Topic abfragen kann. Um mehr ging es mir nicht.
möchtest du dass
a) dein Sketch während der Animation weiterhin reagiert
oder
b) dein Sketch während der Animation für andere Aktivitäten blockiert ist?
Nur für den Fall dass du dich für b) entscheidest:
Führe aus, warum du "unterbrechen" willst.
ich denke Mal a wäre die richtige Antwort. Da der LED Ring 60 LEDs hat, dauert es eine Zeit, bis die Animation durchgelaufen ist. Die Animation zeigt mir an, ob eine Warmwasserzirkulationspumpe läuft. Diese steuere ich über Alexa. Stelle ich die Zirkulationspumpe ab, soll auch die Animation sofort stoppen. Das läuft jetzt auch schon so, bis auf die Tatsache, dass die Animation eben noch bis zu Ende läuft, wenn die Pumpe schon aus ist. Ist vielleicht etwas kleinkariert, vielleicht wollte ich es zu perfekt machen...
Ich hoffe, dass ich das jetzt einigermaßen verständlich erklärt habe, besser kann ichs, glaube ich, nicht.
/*
Etwas laufen lassen nur wenn man es benötigt:
https://forum.arduino.cc/t/mqtt-schleife-vorzeitig-unterbrechen/1170641/8
2023-09-22 by noiasca
code in sketch
*/
bool looprunning = true;
void setup() {
Serial.begin(115200);
}
void loop() {
//loopme();
runNonBlocking();
}
void runNonBlocking() {
if (looprunning == true) {
static uint32_t previousMillis = 0; // store timestamp
static uint8_t i = 0; // the iteration counter (old: i from for)
const uint8_t iMax = 10; // max iterations
const uint16_t intervalShort = 100; // old "delay(100)"
const uint16_t intervalLong = 1000; // old "delay(1000)"
uint16_t interval = intervalShort; // current interval
if (i == 0)
interval = intervalLong;
if (millis() - previousMillis > interval) {
previousMillis = millis();
Serial.print("Counter: ");
Serial.println(i);
if (i == iMax) i = 0; else i++;
}
}
}
void loopme() {
if (looprunning == true) {
for (int i = 0; i < 11; i++)
{
Serial.print("Counter: ");
Serial.println(i);
delay(100);
}
delay(1000);
};
}
Tipp: schau dir das Beispiel "Blink Without Delay" aus der IDE an.
Arbeite es so lange durch bis du es ohne nachsehen aus dem Kopf hinschreiben kannst.
Damit kannst du jede Nebenläufigkeit erledigen.
Schritt 2:
zum "abschalten" von Pixeln bräuchte man dann vermutlich noch einen else zweig falls looprunning (was wohl besser isAnimationRunning heißen soll) false wäre.