#include <Arduino.h>
#include <SdsDustSensor.h>
#define PM_SERIAL_RX D7
#define PM_SERIAL_TX D8
SdsDustSensor sds(PM_SERIAL_RX, PM_SERIAL_TX);
float pm25, pm10;
void setup()
{
Serial.begin(74880);
while (!Serial)
{
} // Wait for Serial to start
delay(750);
sds.begin();
Serial.println();
Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
Serial.println(sds.setQueryReportingMode().toString()); // ensures sensor is in 'query' reporting mode
}
void loop()
{
sds.wakeup();
delay(30000); // working 30 seconds
PmResult pm = sds.queryPm();
if (pm.isOk())
{
Serial.print("PM2.5 = ");
Serial.print(pm.pm25);
Serial.print(", PM10 = ");
Serial.println(pm.pm10);
}
else
{
Serial.print("Could not read values from sensor, reason: ");
Serial.println(pm.statusToString());
}
WorkingStateResult state = sds.sleep();
if (state.isWorking())
{
Serial.println("Problem with sleeping the sensor.");
}
else
{
Serial.println("Sensor is sleeping");
delay(60000); // wait 1 minute
}
}
Nun wollte ich das Beispiel mit millis() umsetzen, mein gedanklicher Ansatz war:
#include <Arduino.h>
#include <SdsDustSensor.h>
#define PM_SERIAL_RX D7
#define PM_SERIAL_TX D8
SdsDustSensor sds(PM_SERIAL_RX, PM_SERIAL_TX);
float pm25, pm10;
unsigned long lastMeasurement = 0;
void setup()
{
Serial.begin(74880);
while (!Serial)
{
} // Wait for Serial to start
delay(750);
sds.begin();
Serial.println();
Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
Serial.println(sds.setQueryReportingMode().toString()); // ensures sensor is in 'query' reporting mode
unsigned long now = millis();
lastMeasurement = now;
}
void loop()
{
unsigned long now = millis();
if ((now - lastMeasurement) > 60 * 1000)
{
sds.wakeup();
lastMeasurement = now;
}
}
also hier, erstmal jede Minute sds.wakeup() aufrufen, aber es gilt ja auch noch dann den Rest des Codes nach weiteren 30 Sekunden auszuführen.
PmResult pm = sds.queryPm();
if (pm.isOk())
{
Serial.print("PM2.5 = ");
Serial.print(pm.pm25);
Serial.print(", PM10 = ");
Serial.println(pm.pm10);
}
else
{
Serial.print("Could not read values from sensor, reason: ");
Serial.println(pm.statusToString());
}
WorkingStateResult state = sds.sleep();
if (state.isWorking())
{
Serial.println("Problem with sleeping the sensor.");
}
else
{
Serial.println("Sensor is sleeping");
delay(60000); // wait 1 minute
}
Ich weiß das stellt jetzt nicht soviel Eigenleistung dar, aber ich habe etliche Versuche mit weiteren Zeitabfragen und Variablen hinter mir, die immer nur mit einem riesen Knoten im Gehirn und natürlich ohne Lösung, geendet haben.
Vielleicht ist hier jemand so nett um mir auf die Sprünge zu helfen, so das ich zu einem Ergebniss komme.
HotSystems:
Ich kenne den Sensor nicht, vermute aber, du musst auch die 30Sek. Aufwachzeit mit berücksichtigen und einbinden.
Genau das ist ja Inhalt meiner Fragestellung, vielleicht habe ich mich das nicht verständlich genug Ausgedrückt!
Der Sensor läuft nach dem sds.wakeup() selbständig an. Jetzt soll nach 30 Sekunden der 3.Codeblock, den ich im Eröffungspost gezeigt habe, noch ausgeführt werden. Das bekomme ich leider nicht hin.
fckw:
Der Sensor läuft nach dem sds.wakeup() selbständig an. Jetzt soll nach 30 Sekunden der 3.Codeblock, den ich im Eröffungspost gezeigt habe, noch ausgeführt werden. Das bekomme ich leider nicht hin.
Dann setze den 3. Codeblock in eine Funktion und rufe die nach dem wakeup auf.
Vermute allerdings dass deine Rechnung nicht passt. Da sollte besser stehen: (60UL * 1000)
HotSystems:
Dann setze den 3. Codeblock in eine Funktion und rufe die nach dem wakeup auf.
Vermute allerdings dass deine Rechnung nicht passt. Da sollte besser stehen: (60UL * 1000)
Danke für deine Hilfe, ich habe den Rest in eine Funktion gepackt nur um dann festzustellen, das die ja nur einmal aufgerufen wird und meine "zweite If-Abfrage mit i " somit sinnlos ist, der Knoten will nicht platzen. Danke auch für den Hinweis mit dem UL, ich habe dafür jetzt einfach eine globale Variable definiert.
Hier noch mein aktueller Code:
#include <Arduino.h>
#include <SdsDustSensor.h>
#define PM_SERIAL_RX D7
#define PM_SERIAL_TX D8
SdsDustSensor sds(PM_SERIAL_RX, PM_SERIAL_TX);
float pm25, pm10;
unsigned long timer = 60;
unsigned long lastMeasurement = 0;
void setup()
{
Serial.begin(74880);
while (!Serial)
{
} // Wait for Serial to start
delay(750);
sds.begin();
Serial.println();
Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
Serial.println(sds.setQueryReportingMode().toString()); // ensures sensor is in 'query' reporting mode
unsigned long now = millis();
lastMeasurement = now;
}
void measure(unsigned long t)
{
if ((t - lastMeasurement) > timer * 500)
{
PmResult pm = sds.queryPm();
if (pm.isOk())
{
Serial.print("PM2.5 = ");
Serial.print(pm.pm25);
Serial.print(", PM10 = ");
Serial.println(pm.pm10);
}
else
{
Serial.print("Could not read values from sensor, reason: ");
Serial.println(pm.statusToString());
}
WorkingStateResult state = sds.sleep();
if (state.isWorking())
{
Serial.println("Problem with sleeping the sensor.");
}
else
{
Serial.println("Sensor is sleeping");
}
}
}
void loop()
{
unsigned long now = millis();
if ((now - lastMeasurement) > timer * 1000)
{
sds.wakeup();
lastMeasurement = now;
measure(now);
}
}
Das was Du brauchst ist eine klasssiche Schrittkette.
Ich hab mal was gebastelt - Achtung es ist ungetestet.
// Forensketch - nur geschrieben, nicht kompiliert / ungetestet
#include <Arduino.h>
#include <SdsDustSensor.h>
#define PM_SERIAL_RX D7
#define PM_SERIAL_TX D8
SdsDustSensor sds(PM_SERIAL_RX, PM_SERIAL_TX);
float pm25, pm10;
unsigned long timer = 60;
unsigned long lastMeasurement = 0;
void setup()
{
Serial.begin(74880);
while (!Serial)
{
} // Wait for Serial to start
delay(750);
sds.begin();
Serial.println();
Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
Serial.println(sds.setQueryReportingMode().toString()); // ensures sensor is in 'query' reporting mode
unsigned long now = millis();
lastMeasurement = now;
}
void measure()
{
PmResult pm = sds.queryPm();
if (pm.isOk())
{
Serial.print("PM2.5 = ");
Serial.print(pm.pm25);
Serial.print(", PM10 = ");
Serial.println(pm.pm10);
}
else
{
Serial.print("Could not read values from sensor, reason: ");
Serial.println(pm.statusToString());
}
WorkingStateResult state = sds.sleep();
if (state.isWorking())
{
Serial.println("Problem with sleeping the sensor.");
}
else
{
Serial.println("Sensor is sleeping");
}
}
void loop()
{
if (millis() - lastMeasurement) > timer * 1000)
{
schrittkette();
}
}
void schrittkette()
{
enum {wecken, aufwachen, messen, setzen};
static int schritt = wecken;
static unsigned long lastmillis = millis();
const unsigned long wakeuptime = 30000;
switch (schritt)
{
case wecken: // sorgt dafür, das der Sensor gestartet wird
sds.wakeup();
lastmillis = millis(); // Aufwachstart merken
schritt = aufwachen; // nächster Schritt:
break;
case aufwachen: // wartet "Aufwachzeit" ab - setzt dann nächsten Schritt
if (millis() - lastmillis > wakeuptime) // Zeit bis aufgewacht abgelaufen?
// ggfls. kann das auch auf "... antwortet der Sensor"
// geändert werden
schritt = messen;
break;
case messen: // Sollte klar sein
measure(); // ACHTUNG! Hier kann auch ein Rückgabewert ausgewertet werden, ob die Messung erfolgt ist!
schritt = setzen;
break;
case setzen:
lastMeasurement = millis(); // Und erst hier wird die Zeit gemerkt....
schritt = wecken; // da lastMeasurement gesetzt ist, wird wecken erst nach dem Ablauf des Timing ausgeführt
break;
default:
schritt = wecken;
break;
}
}
Einfach mal einspielen und testen...
Wenn fehler sind, bitte Bescheid geben.
my_xy_projekt:
Das was Du brauchst ist eine klasssiche Schrittkette.
Ich hab mal was gebastelt - Achtung es ist ungetestet.
Einfach mal einspielen und testen...
Wenn fehler sind, bitte Bescheid geben.
Super Vielen Dank, der Code funktioniert erstmal, es hat nur eine Klammer in der Loop gefehlt, auch musste ich die Funktionen entsprechend ihres Aufrufs sortieren, weil VS Code mit PlatformIO plugin sonst Fehler auswirft.
Hier der Code:
#include <Arduino.h>
#include <SdsDustSensor.h>
#define PM_SERIAL_RX D7
#define PM_SERIAL_TX D8
SdsDustSensor sds(PM_SERIAL_RX, PM_SERIAL_TX);
float pm25, pm10;
unsigned long timer = 60;
unsigned long lastMeasurement = 0;
void setup()
{
Serial.begin(74880);
while (!Serial)
{
} // Wait for Serial to start
delay(750);
sds.begin();
Serial.println();
Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
Serial.println(sds.setQueryReportingMode().toString()); // ensures sensor is in 'query' reporting mode
}
void measure()
{
PmResult pm = sds.queryPm();
if (pm.isOk())
{
Serial.print("PM2.5 = ");
Serial.print(pm.pm25);
Serial.print(", PM10 = ");
Serial.println(pm.pm10);
}
else
{
Serial.print("Could not read values from sensor, reason: ");
Serial.println(pm.statusToString());
}
WorkingStateResult state = sds.sleep();
if (state.isWorking())
{
Serial.println("Problem with sleeping the sensor.");
}
else
{
Serial.println("Sensor is sleeping");
}
}
void schrittkette()
{
enum
{
wecken,
aufwachen,
messen,
setzen
};
static int schritt = wecken;
static unsigned long lastmillis = millis();
const unsigned long wakeuptime = 30000;
switch (schritt)
{
case wecken: // sorgt dafür, das der Sensor gestartet wird
sds.wakeup();
lastmillis = millis(); // Aufwachstart merken
schritt = aufwachen; // nächster Schritt:
break;
case aufwachen: // wartet "Aufwachzeit" ab - setzt dann nächsten Schritt
if (millis() - lastmillis > wakeuptime) // Zeit bis aufgewacht abgelaufen?
// ggfls. kann das auch auf "... antwortet der Sensor"
// geändert werden
schritt = messen;
break;
case messen: // Sollte klar sein
measure(); // ACHTUNG! Hier kann auch ein Rückgabewert ausgewertet werden, ob die Messung erfolgt ist!
schritt = setzen;
break;
case setzen:
lastMeasurement = millis(); // Und erst hier wird die Zeit gemerkt....
schritt = wecken; // da lastMeasurement gesetzt ist, wird wecken erst nach dem Ablauf des Timing ausgeführt
break;
default:
schritt = wecken;
break;
}
}
void loop()
{
if ((millis() - lastMeasurement) > timer * 1000)
{
schrittkette();
}
}
Danke nochmal, so habe ich eine gute Basis um weiter zu machen!
fckw:
Super Vielen Dank, der Code funktioniert erstmal, es hat nur eine Klammer in der Loop gefehlt, auch musste ich die Funktionen entsprechend ihres Aufrufs sortieren, weil VS Code mit PlatformIO plugin sonst Fehler auswirft.
Danke nochmal, so habe ich eine gute Basis um weiter zu machen!
Wie geil ist das denn...
Ich hab das gerade noch nachgebaut..
Mit seriellen Ausgaben, da bin ich auch auf die fehlende Klammer gestossen...
#include <Arduino.h>
#include <SdsDustSensor.h>
#define PM_SERIAL_RX D7
#define PM_SERIAL_TX D8
SdsDustSensor sds(PM_SERIAL_RX, PM_SERIAL_TX);
float pm25, pm10;
unsigned long timer = 60;
unsigned long lastMeasurement = 0;
void setup()
{
Serial.begin(115200);
while (!Serial)
{
} // Wait for Serial to start
delay(750);
sds.begin();
Serial.println();
Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
Serial.println(sds.setQueryReportingMode().toString()); // ensures sensor is in 'query' reporting mode
unsigned long now = millis();
lastMeasurement = now;
}
void measure()
{
PmResult pm = sds.queryPm();
if (pm.isOk())
{
Serial.print("PM2.5 = ");
Serial.print(pm.pm25);
Serial.print(", PM10 = ");
Serial.println(pm.pm10);
}
else
{
Serial.print("Could not read values from sensor, reason: ");
Serial.println(pm.statusToString());
}
WorkingStateResult state = sds.sleep();
if (state.isWorking())
{
Serial.println("Problem with sleeping the sensor.");
}
else
{
Serial.println("Sensor is sleeping");
}
}
void loop()
{
if ((millis() - lastMeasurement) > timer * 1000)
{
schrittkette();
}
}
void schrittkette()
{
enum {wecken, aufwachen, messen, setzen};
static int schritt = wecken;
static unsigned long lastmillis = millis();
const unsigned long wakeuptime = 30000;
switch (schritt)
{
case wecken: // sorgt dafür, das der Sensor gestartet wird
Serial.println(F("Wecken"));
sds.wakeup();
lastmillis = millis(); // Aufwachstart merken
schritt = aufwachen; // nächster Schritt:
break;
case aufwachen: // wartet "Aufwachzeit" ab - setzt dann nächsten Schritt
Serial.println(F("aufwachen"));
if (millis() - lastmillis > wakeuptime) // Zeit bis aufgewacht abgelaufen?
// ggfls. kann das auch auf "... antwortet der Sensor"
// geändert werden
schritt = messen;
break;
case messen: // Sollte klar sein
Serial.println(F("messen"));
measure(); // ACHTUNG! Hier kann auch ein Rückgabewert ausgewertet werden, ob die Messung erfolgt ist!
schritt = setzen;
break;
case setzen:
Serial.println(F("setzen"));
lastMeasurement = millis(); // Und erst hier wird die Zeit gemerkt....
schritt = wecken; // da lastMeasurement gesetzt ist, wird wecken erst nach dem Ablauf des Timing ausgeführt
break;
default:
Serial.println(F("DEFAULT!"));
schritt = wecken;
break;
}
}
Meine Ausgaben (runtergekürzt):
21:21:09.239 ->
21:21:10.266 -> Firmware version [year.month.day]: -1.-1.-1
21:21:11.295 -> Mode: undefined
21:22:11.282 -> Wecken
21:22:13.336 -> aufwachen
21:22:43.335 -> aufwachen
21:22:43.335 -> aufwachen
21:22:43.335 -> aufwachen
21:22:43.335 -> aufwachen
21:22:43.335 -> aufwachen
21:22:43.335 -> messen
21:22:44.363 -> Could not read values from sensor, reason: Not available
21:22:45.389 -> Sensor is sleeping
21:22:45.389 -> setzen
Und ja, er startet neu.
Was Du jetzt machen musst, ist das setzen noch verändern.
DA(!) muss das schlafengehen rein.
Was Du jetzt machen musst, ist das setzen noch verändern.
DA(!) muss das schlafengehen rein.
Ich glaube ich brauche den Schritt setzten garnicht, weil ich alles (deepsleep) in der measure() Funktion ausführe.
Was meinst du mit, "Und ja, er startet neu."?
Besten Dank!
fckw:
Ich glaube ich brauche den Schritt setzten garnicht, weil ich alles (deepsleep) in der measure() Funktion ausführe.
Was meinst du mit, "Und ja, er startet neu."?
Besten Dank!
Ich würde das mit dem schlafen gehen eben nicht im Messzyklus machen, sondern selbst bestimmen, das
a) der Messzyklus erfolgreich war
b) ein Timeout eingetreten ist (Sensor defekt/nicht geantwortet what ever)
Und erst dann die Schrittkette dahin führen, das der sensor wieder schlafen geht.
Ich hab die libnur geladen, aber keinen Sensor. Da (siehe meinen SerMon) der Sleep wieder aus der Messung aktiviert wird, ist das kritisch - Du kannst nicht innerhalb der Schrittkette darauf reagieren.
[edit]
Doch Du brauchst das setzen: lastMeasurement = millis(); // Und erst hier wird die Zeit gemerkt....
Mit dieser Zeile wird festgelegt, wann der letzte Schritt erfolgte.
Mit der Var lastMeasurement kommst Du im Loop wieder an und erst wenn dort der Wert überschritten ist, geht es wieder von vorne los - Das war der "Neustart"
[/edit]
Meinen Nachsatz vergiss. Er war nur, weil der "Sensor geht schlafen" eingetreten war und ich nicht erneut auf das aufwachen warten wollte - aber das wird auch angezeigt
22:46:25.255 ->
22:46:26.315 -> Firmware version [year.month.day]: -1.-1.-1
22:46:27.309 -> Mode: undefined
22:47:27.329 -> Wecken
22:47:29.360 -> aufwachen
22:47:59.383 -> aufwachen
22:47:59.383 -> messen
22:48:00.410 -> Could not read values from sensor, reason: Not available
22:48:01.403 -> Sensor is sleeping
22:48:01.403 -> Nicht gemessen! - Wecke Sensor erneut auf!
22:48:01.436 -> unbekannter Zustand - gehe zu wecken
22:48:01.436 -> Wecken
22:48:03.458 -> aufwachen
mit diesem Code:
#include <Arduino.h>
#include <SdsDustSensor.h>
#define PM_SERIAL_RX D7
#define PM_SERIAL_TX D8
SdsDustSensor sds(PM_SERIAL_RX, PM_SERIAL_TX);
float pm25, pm10;
unsigned long timer = 60;
unsigned long lastMeasurement = 0;
void setup()
{
Serial.begin(115200);
while (!Serial)
{
} // Wait for Serial to start
delay(750);
sds.begin();
Serial.println();
Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
Serial.println(sds.setQueryReportingMode().toString()); // ensures sensor is in 'query' reporting mode
unsigned long now = millis();
lastMeasurement = now;
}
int measure()
{
signed int stat = -1;
PmResult pm = sds.queryPm();
if (pm.isOk())
{
Serial.print("PM2.5 = ");
Serial.print(pm.pm25);
Serial.print(", PM10 = ");
Serial.println(pm.pm10);
stat = 0;
}
else
{
Serial.print("Could not read values from sensor, reason: ");
Serial.println(pm.statusToString());
stat = 1;
}
WorkingStateResult state = sds.sleep();
if (state.isWorking())
{
Serial.println("Problem with sleeping the sensor.");
}
else
{
Serial.println("Sensor is sleeping");
}
return stat;
}
void loop()
{
if ((millis() - lastMeasurement) > timer * 1000)
{
schrittkette();
}
}
void schrittkette()
{
enum {wecken, aufwachen, messen, setzen};
static int schritt = wecken;
static unsigned long lastmillis = millis();
const unsigned long wakeuptime = 30000;
static int messzyklen = 0;
const int maxmesszyklen = 5;
switch (schritt)
{
case wecken: // sorgt dafür, das der Sensor gestartet wird
Serial.println(F("Wecken"));
sds.wakeup();
lastmillis = millis(); // Aufwachstart merken
schritt = aufwachen; // nächster Schritt:
break;
case aufwachen: // wartet "Aufwachzeit" ab - setzt dann nächsten Schritt
Serial.println(F("aufwachen"));
if (millis() - lastmillis > wakeuptime) // Zeit bis aufgewacht abgelaufen?
// ggfls. kann das auch auf "... antwortet der Sensor"
// geändert werden
schritt = messen;
break;
case messen: // Sollte klar sein
{
Serial.println(F("messen"));
signed int rueckgabe = measure(); // Die Funktion gibt jetzt einen Wert zurück!
if (rueckgabe == -1 || rueckgabe == 1)
{
messzyklen++;
Serial.println(F("Nicht gemessen! - Wecke Sensor erneut auf!"));
schritt = wecken;
}
if ((messzyklen > maxmesszyklen) || (rueckgabe == 0))
{
Serial.println(F("Maximale Messzyklen erreicht - Schluß! / oder Werte gesammelt"));
messzyklen = 0;
schritt = setzen;
}
else
{
Serial.println(F("unbekannter Zustand - gehe zu wecken"));
schritt = wecken;
}
break;
}
case setzen:
Serial.println(F("setzen"));
lastMeasurement = millis(); // Und erst hier wird die Zeit gemerkt....
schritt = wecken; // da lastMeasurement gesetzt ist, wird wecken erst nach dem Ablauf des Timing ausgeführt
break;
default:
Serial.println(F("DEFAULT!"));
schritt = wecken;
break;
}
}
Da siehst Du, was geht und das Du ggfls. auf irgendwas und wie reagieren kannst.
na dann....
[Nachtrag:]
Ich hab das mal ohne serielle Ausgabe vom "aufwachen" gemacht:
23:00:30.757 ->
23:00:31.784 -> Firmware version [year.month.day]: -1.-1.-1
23:00:32.812 -> Mode: undefined
23:01:32.807 -> Wecken
23:02:04.840 -> messen
23:02:05.869 -> Could not read values from sensor, reason: Not available
23:02:06.898 -> Sensor is sleeping
23:02:06.898 -> Nicht gemessen! - Wecke Sensor erneut auf!
23:02:06.898 -> unbekannter Zustand - gehe zu wecken
23:02:06.932 -> Wecken
23:02:38.938 -> messen
23:02:39.966 -> Could not read values from sensor, reason: Not available
23:02:40.993 -> Sensor is sleeping
23:02:40.993 -> Nicht gemessen! - Wecke Sensor erneut auf!
23:02:40.993 -> unbekannter Zustand - gehe zu wecken
23:02:40.993 -> Wecken
23:03:13.050 -> messen
23:03:14.077 -> Could not read values from sensor, reason: Not available
23:03:15.071 -> Sensor is sleeping
23:03:15.071 -> Nicht gemessen! - Wecke Sensor erneut auf!
23:03:15.105 -> unbekannter Zustand - gehe zu wecken
23:03:15.105 -> Wecken
23:03:47.143 -> messen
23:03:48.171 -> Could not read values from sensor, reason: Not available
23:03:49.166 -> Sensor is sleeping
23:03:49.166 -> Nicht gemessen! - Wecke Sensor erneut auf!
23:03:49.199 -> unbekannter Zustand - gehe zu wecken
23:03:49.199 -> Wecken
23:04:21.207 -> messen
23:04:22.266 -> Could not read values from sensor, reason: Not available
23:04:23.259 -> Sensor is sleeping
23:04:23.259 -> Nicht gemessen! - Wecke Sensor erneut auf!
23:04:23.292 -> unbekannter Zustand - gehe zu wecken
23:04:23.292 -> Wecken
23:04:55.327 -> messen
23:04:56.355 -> Could not read values from sensor, reason: Not available
23:04:57.349 -> Sensor is sleeping
23:04:57.349 -> Nicht gemessen! - Wecke Sensor erneut auf!
23:04:57.382 -> Maximale Messzyklen erreicht - Schluß! / oder Werte gesammelt
23:04:57.382 -> setzen
my_xy_projekt:
Da siehst Du, was geht und das Du ggfls. auf irgendwas und wie reagieren kannst.
na dann....
[Nachtrag:]
Ich hab das mal ohne serielle Ausgabe vom "aufwachen" gemacht:
Spitze, danke für den Input. Habe deinen Code gleich mal ausprobiert und "studiert". Ich habe nur ein paar Anpassungen an den seriellen Ausgaben gemacht und bis jetzt nur den "gut Zustand getestet" (Sensor ok).
Hier mein Code:
#include <Arduino.h>
#include <SdsDustSensor.h>
#define PM_SERIAL_RX D7
#define PM_SERIAL_TX D8
SdsDustSensor sds(PM_SERIAL_RX, PM_SERIAL_TX);
float pm25, pm10;
unsigned long timer = 60;
unsigned long lastMeasurement = 0;
void setup()
{
Serial.begin(74880);
while (!Serial)
{
} // Wait for Serial to start
delay(750);
sds.begin();
Serial.println();
Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
Serial.println(sds.setQueryReportingMode().toString()); // ensures sensor is in 'query' reporting mode
}
int measure()
{
signed int stat = -1;
PmResult pm = sds.queryPm();
if (pm.isOk())
{
Serial.print("PM2.5 = ");
Serial.print(pm.pm25);
Serial.print(", PM10 = ");
Serial.println(pm.pm10);
stat = 0;
}
else
{
Serial.print("Could not read values from sensor, reason: ");
Serial.println(pm.statusToString());
stat = 1;
}
WorkingStateResult state = sds.sleep();
if (state.isWorking())
{
Serial.println("Problem with sleeping the sensor.");
}
else
{
Serial.println("Sensor is sleeping");
}
return stat;
}
void schrittkette()
{
enum
{
wecken,
aufwachen,
messen,
setzen
};
static int schritt = wecken;
static unsigned long lastmillis = millis();
const unsigned long wakeuptime = 30000;
static int messzyklen = 0;
const int maxmesszyklen = 5;
switch (schritt)
{
case wecken: // sorgt dafür, das der Sensor gestartet wird
Serial.println(F("Wecken"));
sds.wakeup();
lastmillis = millis(); // Aufwachstart merken
schritt = aufwachen; // nächster Schritt:
break;
case aufwachen: // wartet "Aufwachzeit" ab - setzt dann nächsten Schritt
{
if (millis() - lastmillis > wakeuptime) // Zeit bis aufgewacht abgelaufen?
{
Serial.println(F("Messzeit erreicht"));
schritt = messen;
}
break;
}
case messen: // Sollte klar sein
{
Serial.println(F("Sensor auslesen"));
signed int rueckgabe = measure(); // Die Funktion gibt jetzt einen Wert zurück!
if (rueckgabe == -1 || rueckgabe == 1)
{
messzyklen++;
Serial.println(F("Nicht gemessen! - Wecke Sensor erneut auf!"));
schritt = wecken;
}
if ((messzyklen > maxmesszyklen) || (rueckgabe == 0))
{
Serial.print(F("Anzahl der Messzyklen: "));
Serial.println(messzyklen);
Serial.println(F("Warte auf neues wecken"));
messzyklen = 0;
schritt = setzen;
}
else
{
Serial.println(F("unbekannter Zustand - gehe zu wecken"));
schritt = wecken;
}
break;
}
case setzen:
Serial.println(F("setzen"));
lastMeasurement = millis(); // Und erst hier wird die Zeit gemerkt....
schritt = wecken; // da lastMeasurement gesetzt ist, wird wecken erst nach dem Ablauf des Timing ausgeführt
break;
default:
Serial.println(F("DEFAULT!"));
schritt = wecken;
break;
}
}
void loop()
{
if ((millis() - lastMeasurement) > timer * 1000)
{
schrittkette();
}
}
Und hier noch dazu die serielle Ausgabe:
Firmware version [year.month.day]: 18.11.16
Mode: query
Wecken
Messzeit erreicht
Sensor auslesen
PM2.5 = 328.80, PM10 = 546.30
Sensor is sleeping
Anzahl der Messzyklen: 0
Warte auf neues wecken
setzen
Wecken
Messzeit erreicht
Sensor auslesen
PM2.5 = 291.90, PM10 = 514.30
Sensor is sleeping
Anzahl der Messzyklen: 0
Warte auf neues wecken
setzen
Wecken
Messzeit erreicht
Sensor auslesen
PM2.5 = 285.00, PM10 = 509.40
Sensor is sleeping
Anzahl der Messzyklen: 0
Warte auf neues wecken
setzen
Wecken
Messzeit erreicht
Sensor auslesen
PM2.5 = 250.90, PM10 = 459.90
Sensor is sleeping
Anzahl der Messzyklen: 0
Warte auf neues wecken
setzen
Wecken
Messzeit erreicht
Sensor auslesen
PM2.5 = 234.30, PM10 = 439.50
Sensor is sleeping
Anzahl der Messzyklen: 0
Warte auf neues wecken
setzen
Wecken
Messzeit erreicht
Sensor auslesen
PM2.5 = 244.20, PM10 = 456.60
Sensor is sleeping
Anzahl der Messzyklen: 0
Warte auf neues wecken
setzen
Wecken
Messzeit erreicht
Sensor auslesen
PM2.5 = 216.00, PM10 = 412.10
Sensor is sleeping
Anzahl der Messzyklen: 0
Warte auf neues wecken
setzen
fckw:
Ich habe nur ein paar Anpassungen an den seriellen Ausgaben gemacht und bis jetzt nur den "gut Zustand getestet" (Sensor ok).
Na siehste - gar nicht schlimm
Du kannst auch die Weckzeit versuchen zu verkürzen, indem Du prüfst, ob der Sensor schon verfügbar ist.
Dann wäre die Zeit ein Timeout-Kriterium, was zum Abbruch führt.
Zudem würde ich sds.sleep(); ins letzte case schieben - aber das ist wohl Geschmackssache...
my_xy_projekt:
Na siehste - gar nicht schlimm
Du kannst auch die Weckzeit versuchen zu verkürzen, indem Du prüfst, ob der Sensor schon verfügbar ist.
Dann wäre die Zeit ein Timeout-Kriterium, was zum Abbruch führt.
Zudem würde ich sds.sleep(); ins letzte case schieben - aber das ist wohl Geschmackssache...
Alles gut!
Der Sensor liefert unmitterlbar nach dem WakeUp schon Werte (pm.isOk), die 30sec will ich nur für einen Spülvorgang.
Funktionsprinzip: Der Sensor saugt Luft in eine Messkammer und ermittelt mit einem Laser die enthaltenen Partikel in zwei größen.
Den Code im letzten case werde ich wohl noch entsprechend anpassen.
Grüße
The SDS011 with the Principle of the laser dispersion, the particle concentration between 0.3 and 10 in the air available. It is stable and reliable with digital output and built-in fan.
Accurate and reliable: laser detection, stable, good consistency;
Quick response: response time is less than 10 seconds when scene changes.
Easy integration: UART output (or IO output can be customized), built-in fan.
High Resolution: 0.3ug/m3 resolution.
Report incorrect product information.
Auf Deutsch erscheint:
The SDS011 with the Principle of the Laserstreuung, can the Partikelkonzentration between 0,3 and 10 in the air available. Es ist mit Digitalausgang und eingebautem Lüfter stabil und zuverlässig.
Genaue und zuverlässige: Laser-Erkennung, stabil, gute Konsistenz;
Schnelle Antwort: Antwortzeit ist weniger als 10 Sekunden, wenn sich die Szene ändert.
Einfache Integration: UART-Ausgang (oder IO-Ausgang kann angepasst werden), Lüfter eingebaut;
Hohe Auflösung: Auflösung von 0,3ug / m3.
Falsche Produktinformationen melden
Das hat ein Chinese von Hand übersetzt (und paar Worte vergessen), denke ich. Wo kommt das Wort "can" her?
Hat immerhin 0.3 nach 0,3 übersetzt !
my_xy_projekt:
Da siehst Du, was geht und das Du ggfls. auf irgendwas und wie reagieren kannst.
na dann....
Jetzt habe die "Schrittkette" um ein case (Count) erweitert. Es soll jede Minute ein Variable hochgezählt werden um nach x Durchläufen ins nächste case springen.
case count:
{
counter++;
Serial.println(counter);
lastMeasurement = millis();
if (counter == 2)
{
schritt = wecken;
}
break;
}
Soweit funktioniert es, aber was ich nicht verstehe, warum wird diese if-Bedingung erst durchlaufen, nachdem "counter" auf 3 gezählt hat, was mache ich falsch?
Hier noch mein ganzer Code:
#include <Arduino.h>
#include <SdsDustSensor.h>
#include "DHTesp.h"
#define PM_SERIAL_RX D7
#define PM_SERIAL_TX D8
SdsDustSensor sds(PM_SERIAL_RX, PM_SERIAL_TX);
DHTesp dht;
float humidity;
float temperature;
float pm25, pm10;
const unsigned long timer = 60;
unsigned long lastMeasurement = 0;
void setup()
{
Serial.begin(74880);
while (!Serial)
{
} // Wait for Serial to start
delay(750);
sds.begin();
Serial.println();
Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
Serial.println(sds.setQueryReportingMode().toString()); // ensures sensor is in 'query' reporting mode
sds.sleep();
dht.setup(0, DHTesp::DHT22);
humidity = dht.getHumidity();
temperature = dht.getTemperature();
Serial.print(F("Temperature: "));
Serial.print(temperature, 2);
Serial.print(F("°C \t"));
Serial.print(F("Humidity: "));
Serial.print(humidity, 1);
Serial.println(F("%"));
}
int measure()
{
signed int stat = -1;
PmResult pm = sds.queryPm();
if (pm.isOk())
{
Serial.print(F("PM2.5 = "));
Serial.print(pm.pm25);
Serial.print(F(", PM10 = "));
Serial.println(pm.pm10);
stat = 0;
//humidity = dht.getHumidity();
//temperature = dht.getTemperature();
Serial.print(F("Temperature: "));
Serial.print(temperature, 2);
Serial.print(F("°C \t"));
Serial.print(F("Humidity: "));
Serial.print(humidity, 1);
Serial.println(F("%"));
}
else
{
Serial.print(F("Could not read values from sensor, reason: "));
Serial.println(pm.statusToString());
stat = 1;
}
WorkingStateResult state = sds.sleep();
if (state.isWorking())
{
Serial.println(F("Problem with sleeping the sensor."));
}
else
{
Serial.println(F("Sensor is sleeping"));
}
return stat;
}
void schrittkette()
{
enum
{
count,
wecken,
aufwachen,
messen,
setzen
};
static int schritt = count;
static unsigned long lastmillis = millis();
const unsigned long wakeuptime = 10000;
static int messzyklen = 0;
const int maxmesszyklen = 5;
static int counter = 0;
switch (schritt)
{
case count:
{
counter++;
Serial.println(counter);
lastMeasurement = millis();
if (counter == 2)
{
schritt = wecken;
}
break;
}
case wecken: // sorgt dafür, das der Sensor gestartet wird
Serial.println(F("Wecken"));
sds.wakeup();
lastmillis = millis(); // Aufwachstart merken
schritt = aufwachen; // nächster Schritt:
break;
case aufwachen: // wartet "Aufwachzeit" ab - setzt dann nächsten Schritt
{
if (millis() - lastmillis > wakeuptime) // Zeit bis aufgewacht abgelaufen?
{
Serial.println(F("Messzeit erreicht"));
schritt = messen;
}
break;
}
case messen: // Sollte klar sein
{
Serial.println(F("Sensor auslesen"));
signed int rueckgabe = measure(); // Die Funktion gibt jetzt einen Wert zurück!
if (rueckgabe == -1 || rueckgabe == 1)
{
messzyklen++;
Serial.println(F("Nicht gemessen! - Wecke Sensor erneut auf!"));
schritt = wecken;
}
if ((messzyklen > maxmesszyklen) || (rueckgabe == 0))
{
Serial.print(F("Anzahl der Messzyklen: "));
Serial.println(messzyklen);
Serial.println(F("Warte auf neues wecken"));
messzyklen = 0;
schritt = setzen;
}
else
{
Serial.println(F("unbekannter Zustand - gehe zu wecken"));
schritt = wecken;
}
break;
}
case setzen:
Serial.println(F("setzen"));
counter = 0;
schritt = count;
break;
default:
Serial.println(F("DEFAULT!"));
schritt = count;
break;
}
}
void loop()
{
if ((millis() - lastMeasurement) > timer * 500)
{
schrittkette();
}
}
Ich habe "counter" auch schon global deklariert und im "loop" hochgezählt, leider gleiches Ergebniss.
fckw:
Jetzt habe die "Schrittkette" um ein case (Count) erweitert. Es soll jede Minute ein Variable hochgezählt werden um nach x Durchläufen ins nächste case springen.
Ich habe "counter" auch schon global deklariert und im "loop" hochgezählt, leider gleiches Ergebniss.
lastMeasurement wäre bei Dir mit der aktuellen Zeit gesetzt
Damit ist die Bedingung
if ((millis() - lastMeasurement) > timer * 500)
für die nächsten 500ms nicht erfüllt.
Das führt zu folgender Konstellation:
nach dem Start vergehen 500 ms bis die Bedingung erfüllt ist.
dann geht es ins case count
dann wieder 500 ms Ruhe
dann wieder case count
dann wieder 500 ms Ruhe
dann wieder case count
Jetzt ist der Zähler ereicht - > nächster Schritt soll wecken sein.
Da Du aber lastMeasurement wieder gesetzt hast:
wieder 500ms Ruhe
erst jetzt geht es ins wecken.
Wenn Du die Schrittkette nicht alle 500ms sondern alle 5Sekunden beginnen willst, ändere den Parameter in der Bedingung. also von 500 (ms) auf 5000 (ms) (5000/1000=5sekunden)
Du kannst das auch mit dem count machen.
Dann das if komplett aus dem loop raus und im case count die Bedingung rein und dort den nächsten Schritt setzen.
my_xy_projekt:
Ich bin noch am überlegen, was Du willst..
Im Prinzip will ich einen zusätzlichen Schritt (Count) der jede Minute durchlaufen wird, damit ich dort z.B einen DHT Sensor auslesen kann, der Rest der Kette soll nach X durchläufen abgearbeitet werden.
lastMeasurement wäre bei Dir mit der aktuellen Zeit gesetzt
Damit ist die Bedingung
if ((millis() - lastMeasurement) > timer * 500)
für die nächsten 500ms nicht erfüllt.
Danke ich denke ich habe das Problem erkannt, aber noch keine Lösung.
PS: Die Zeit wird ja noch mit einem Faktor multipliziert (timer = 60), also sind es zum hier zum testen 30 Sec.
fckw:
Im Prinzip will ich einen zusätzlichen Schritt (Count) der jede Minute durchlaufen wird, damit ich dort z.B einen DHT Sensor auslesen kann, der Rest der Kette soll nach X durchläufen abgearbeitet werden.
Dann muss das anders werden.
Variante 1:
zusätzliche Bedingung für den Sensor schaffen.
void loop()
{
static dhtmillis = 0;
if (millis() - dhtmillis > 2000)
{
readhum();
dhtmillis = millis();
}
if ((millis() - lastMeasurement) > timer * 500)
{
schrittkette();
}
}
void readhum()
{
//Hier alles rund um den Sensor
}
Die Alternative mit der Schrittkette wäre:
case count:
{
if ((counter == 0 || counter == 5))
{
readhum();
}
if (counter > 9)
{
schritt = wecken;
// [edit] und hier den counter wieder zurücksetzen ;)
}
break;
}
finde ich aber persönlich zu unübersichtlich und nicht sauber genug getrennt.