Hallo Ralf,
kurz Vorweg: mein Sohn hat kürzlich zum Geburtstag einen Calliope Mini geschenkt bekommen. Wir haben dann direkt einen Grove-SDC30-Sensor bestellt und Deine CO2-Ampel ausprobiert. Cooles Projekt! Das mit den Abstürzen ist mir allerdings auch direkt aufgefallen, deshalb hatte ich mich bisher auch noch nicht getraut, eine Kalibrierung vorzunehmen. Außerdem hat die RGB-LED zwischenzeitlich immer mal wieder eine falsche Farbe angezeigt!
Da ich mich noch nicht wirklich gut mit dem Calliope System auskenne, hat es mich erst einmal ein wenig Mühe gekostet herauszufinden, welche Bibliothek Du für den SDC30 verwendest! In Deinen Repositories auf github existieren ja die Projekte pxt-SCD30, scd30-lib sowie scd30. Das die Erweiterung pxt-SCD30 verwendet wird, könntest Du ja vielleicht in dem Readme zu deiner CO2-Ampel erwähnen!
Die genauen Ursachen für die Abstürze kann ich Dir auch noch nicht nennen, ich habe aber ein paar Spekulationen angestellt und bei mir scheint jetzt zumindest alles stabil zu laufen!
Um den Code besser verstehen zu können, habe ich mir folgenden Artikel durchgelesen: https://makecode.microbit.org/device/reactive
In der Bibliothek wird ja eine eigene Endlosschleife gestartet
github: rdmueller/pxt-SCD30/blob/master/main.ts : control.inBackground()
in welcher im Hintergrund ununterbrochen alle zwei Sekunden über den I2C-Bus Messdaten beim Sensor abgeholt werden.
Dazu kommt die Endlosschleife Deiner Ampelanwendung
github: rdmueller/co2-ampel/blob/master/main.ts : basic.forever()
Wenn man jetzt eine Taste drückt, muss der Scheduler also die Rechenzeit an drei „gleichzeitig laufende“ Unterprogramme verteilen. Bei jedem Aufruf von basic.pause() wird nach meinem Verständnis zum nächsten Unterprogramm gewechselt. Wie schnell aber z.B. Funktionen wie basic.showString() wieder Rechenzeit abgeben, konnte ich in der Dokumentation erst einmal nicht finden!
In der Bibliothek wird in der Endlosschleife über die Funktion
readMeasurement() aber z.B. zwischen dem Schreiben und Lesen auf dem
I2C-Bus die Rechenzeit wieder an die anderen Unterprogramme
abgegeben:
pins.i2cWriteNumber(0x61, 0x0300, NumberFormat.UInt16BE, false) basic.pause(10) buf = pins.i2cReadBuffer(0x61, 18, false)
Was passiert, wenn die Pause zu lange dauert? Ist es nicht denkbar, das
der Sensor dann vielleicht keine gültigen Daten mehr zurückliefert?
Im weiteren Verlauf werden die gelesenen Daten ja nicht mehr auf
Plausibilität geprüft sondern einfach weiterverarbeitet! Das könnte ja möglicherweise ein Grund für den Absturz darstellen? Bei
Bedarf ließe sich das ja noch einmal genauer untersuchen, aber
vielleicht kann ja auch ein Calliope-Experte hier im Forum etwas dazu
sagen?
Außerdem ist mir aufgefallen, dass zum Kalibrieren nach drücken der beiden Tasten „AB“ ein Befehl über den I2C-Bus gesendet wird, während offensichtlich im Hintergrund in der Bibliothek weiter Messdaten über I2C abgefragt werden! Hier
herrscht also auch ein großes Konfliktpotential:
Read Measurement Anfrage, in der „Pause“ wird vor dem Lesebefehl in den AB-Tastenhandler gewechselt, wo dann der FRC-Befehl zum Kalibrieren abgesetzt wird…
Und bei der RGB-LED wird ja in jedem Messzyklus die Farbe über den Befehl basic.setLedColor() neu gesetzt, auch wenn sie sich nicht geändert hat! Offensichtlich führt das häufige Neusetzten der Farbe dann zu der falschen Farbanzeige, wobei ich den Fehler hier irgendwo in den Calliope Firmware vermuten würde?!
Um die Ampel zu verbessern, wollte ich deshalb die Endlosschleife in der Bibliothek eliminieren und die Kalibrierfunktion erst dann starten, wenn die letzte readMesurement()-Funktion erfolgreich beendet und gegenüber der Kalibrierfunktion „verriegelt“ wurde. Außerdem wollte ich basic.setLedColor() nur
aufrufen, wenn ein Farbwechsel ansteht!
Um das zu realisieren war es für mich am einfachsten, die pxt-SCD30 Bibliothek
aus dem Projekt zu werfen und die benötigten Funktionen direkt in dem Ampelcode zu integrieren. Immerhin sind das insgesamt noch weniger als 200 Zeilen Code. Trotzdem ist es nach meiner jetzigen Erfahrung leider keine gute Idee, von der JavaScript-Ansicht in die Blockansicht zu wechseln! Beim zurückwechseln wurden bei mir dann manche Kommentare entfernt, andere wurden verdoppelt, hexadezimal angegebene Werte wurden in dezimale Schreibweise umgewandelt, etc. Kurz gesagt: der Code funktioniert zwar weiterhin, wird aber recht unlesbar! Hier nun der geänderte Code:
EDIT: ich habe noch keine Rechte, einen Anhang hinzuzufügen und wenn ich den Code hier einfach einfüge, geht die Formatierung verloren! Soll ich Ihn Dir via Email schicken?
Viele Grüße,
Frank