Bei Interrupt lesen
Was dieses Beispiel zeigt
Der Sensor teilt Ihrem Controller selbst mit, wann gelesen werden soll. Der BMV080 meldet sich über seinen active-low-Ausgang IRQ. Dieses Beispiel erkennt die fallende Flanke mit einem Interrupt und liest dann PM2.5, solange IRQ auf Low bleibt. Der Sensor läuft im
kontinuierlichen Modus: Sein Interrupt kann im Duty-Cycling-Modus nicht als Trigger verwendet werden.
Verbinden Sie zusätzlich zum Qwiic-Kabel oder zur I2C-Verdrahtung aus dem Quick Start noch eine weitere Leitung:
| Controller | Soldered BMV080 Particulate Matter Sensor |
|---|---|
GPIO 13 (IRQ_PIN im Sketch) | IRQ |
Das Beispiel verwendet Pin 13. Wenn Ihr Board an diesem Pin keinen Interrupt unterstützt, gibt der Sketch
Not a valid interrupt pin! aus: Verbinden Sie IRQ mit einem Pin, der einen Interrupt unterstützt, und passen Sie IRQ_PIN entsprechend an.
Der Beispielcode
Dies ist InterruptTrigger.ino aus der festgelegten Bibliothek, ohne den Kopfkommentar. Der Sketch selbst ist unverändert, so wie er ausgeliefert wird. Er verwendet die Standardadresse des Boards, 0x57.
Dieses Beispiel verwendet außerdem attachInterrupt(), detachInterrupt(),
digitalPinToInterrupt(), pinMode() und digitalRead()
(Arduino-Referenz),
die zum Arduino-Core gehören und nicht Teil der Soldered-BMV080-Bibliothek sind.
#include "BMV080-SOLDERED.h"
BMV080 bmv080; // Create an instance of the BMV080 class
#define BMV080_ADDR 0x57 // BMV080 default I2C address
#define IRQ_PIN 13 // Declare interrupt pin
bool triggered = false; // Interrupt flag
void setup()
{
Serial.begin(115200);
while (!Serial) delay(10); // Wait for Serial to become available
Wire.begin();
// Attempt to initialize the sensor via I2C
if (bmv080.begin(BMV080_ADDR, Wire) == false)
{
Serial.println("BMV080 not detected");
while (1)
;
}
Serial.println("BMV080 found!");
// Initialize the sensor
if (bmv080.init())
{
Serial.println("BMV sensor initialized");
}
else
{
Serial.println("BMV initialization failed");
while (1)
;
}
// Set the sensor mode to continuous mode
// The hardware interrupt of the BMV080 sensor unit cannot be used as trigger
// in duty cycling mode.
if(bmv080.setMode(BMV080_MODE_CONTINUOUS) == true)
{
Serial.println("BMV080 set to continuous mode");
}
else
{
Serial.println("Error setting BMV080 mode");
}
enable_external_interrupt(true); // Enable external interrupt handling for the IRQ pin
}
void loop()
{
// Check if interrupt flag was set
if (triggered == true)
{
Serial.println("Interrupt triggered");
triggered = false; // Reset the interrupt flag
// Keep reading sensor data
do
{
Serial.print("Reading BMV080: ");
if (bmv080.readSensor())
{
float pm25 = bmv080.PM25();
Serial.print(pm25);
if (bmv080.isObstructed() == true)
{
Serial.print("\tObstructed");
}
Serial.println();
}
} while (digitalRead(IRQ_PIN) == LOW);
}
delay(150);
Serial.print(".");
}
void enable_external_interrupt(bool enable)
{
int checkPin = digitalPinToInterrupt(IRQ_PIN);
if (checkPin == -1)
{
Serial.println("Not a valid interrupt pin!");
}
else
{
Serial.println("Valid interrupt pin.");
}
pinMode(IRQ_PIN, INPUT_PULLUP); // Configure IRQ pin as input with internal pull-up resistor
if (enable)
{ // Enabel external interrupt
attachInterrupt(digitalPinToInterrupt(IRQ_PIN), ISR_handler, FALLING );
}
else
{ // Disable external interrupt
detachInterrupt(digitalPinToInterrupt(IRQ_PIN) );
}
}
void ISR_handler(void)
{
// Set interrupt flag
triggered = true;
}
Erwartetes Ergebnis, hier von einem ESP32-Entwicklungsboard (ESP32-WROOM-32), bei dem
IRQ mit GPIO 13 verbunden ist und IRQ_PIN unverändert bleibt:
BMV080 found!
BMV sensor initialized
BMV080 set to continuous mode
Valid interrupt pin.
......Interrupt triggered
Reading BMV080: 7.18
......Interrupt triggered
Reading BMV080: 7.26
......Interrupt triggered
Reading BMV080: 7.09
Solange der Sketch wartet, erscheint alle 150 ms ein Punkt. Jedes Mal, wenn der Sensor ein Signal gibt, gibt der Sketch Interrupt triggered aus, dann Reading BMV080: mit
dem PM2.5-Wert in µg/m³, gefolgt von Obstructed, wenn die Sicht des Sensors blockiert ist. Ihre Werte hängen von der Luft um den Sensor ab.
Verwendete Funktionen
BMV080()returns NoneErstellt das Sensorobjekt. Es nimmt keine Argumente entgegen: Die Adresse und der Wire-Port werden an begin() übergeben.
ReturnsKonstruktor; kein Rückgabewert.
begin(const uint8_t address = BMV080_DEFAULT_ADDRESS, TwoWire &wirePort = Wire)returns boolLegt die I2C-Adresse und den Wire-Port fest, die die Bibliothek verwendet, und prüft, ob der Sensor unter dieser Adresse antwortet. Der I2C-Bus wird dabei nicht gestartet, rufen Sie daher zuerst Wire.begin() auf, wie im Beispiel.
Returnstrue, wenn der Sensor unter der Adresse geantwortet hat, sonst false.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
address | uint8_t | Die I2C-Adresse des Sensors. Standardmäßig BMV080_DEFAULT_ADDRESS, also 0x57, die Standardadresse des Boards. |
wirePort | TwoWire & | Der zu verwendende I2C-Port. Standardmäßig Wire. |
init()returns boolBereitet den Sensor über den Bosch-Driver vor: liest die Driver-Version, öffnet den Sensor, führt einen Soft-Reset durch und liest die ID des Sensors. Rufen Sie sie nach begin() und vor allem anderen auf.
Returnstrue, wenn jeder Schritt erfolgreich war, false, wenn einer fehlgeschlagen ist.
setMode(uint8_t mode)returns boolStartet die Messung im gewählten Modus. Verwenden Sie den kontinuierlichen Modus zusammen mit dem Interrupt.
Returnstrue, wenn der Bosch-Driver die Messung gestartet hat, sonst false.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
mode | uint8_t | BMV080_MODE_CONTINUOUS für kontinuierliche Messung, wie hier, oder BMV080_MODE_DUTY_CYCLE für Duty Cycling. |
readSensor(bmv080_output_t *bmv080_output = nullptr)returns boolLässt den Bosch-Driver einmal Daten vom Sensor abrufen und verarbeiten. Wenn ein neuer Messwert eintrifft, speichert ihn die Bibliothek für PM25() und isObstructed().
Returnstrue, wenn während dieses Aufrufs ein neuer Messwert eingetroffen ist, sonst false.
Parameter
| Name | Typ | Beschreibung |
|---|---|---|
bmv080_output | bmv080_output_t * | Optional. Eine Bosch-Ausgabestruktur, in die der neue Messwert kopiert wird. Das Beispiel lässt sie weg. |
PM25()returns floatGibt den PM2.5-Wert der letzten Messung zurück: Partikel mit einem Durchmesser von 2,5 µm oder kleiner.
ReturnsPM2.5-Massenkonzentration in µg/m³.
isObstructed()returns boolGibt das Obstruction-Flag der letzten Messung zurück. Der Sensor setzt es, wenn sich ein feststehendes Objekt in seinem optischen Pfad befindet.
Returnstrue, wenn die letzte Messung blockiert war, sonst false.
Zusammenfassung
Die Interrupt-Routine setzt nur ein Flag, und loop() übernimmt das Lesen. IRQ ist
active low, daher löst das Beispiel bei der fallenden Flanke aus und setzt den Pin als
Eingang mit Pull-up.