Vibration Dedection

Mein Fensterübewachungssensor soll mittels eines Piezoelement die Vibration des Glases aufnehmen und beurteilen können handlet es sich um Klopfen oder Glasbruch. Eine Vibration soll eine gewisse Zeit als digitale Information anliegen und via BSS an ein Central gesendet werden. EinGlasbruch soll daurhaft als digitales Signal den Central zur Verfügung stehen. Um dies zu programmieren muss zuerst der PiezoSensor verstanden werden.
Piezo Element



Gedanken zum Piezoelement
Was und für was man ein Piezoelement verwenden kann, muss man nicht mehr erklären, es gibt genügend Informationen im Internet. Alerdings hat jede Verwendungszweck andere Bedingungen und Bedürfnisse und genau auf diese gehe ich hier ein.
Anwendung:
- Der Sensor soll Glasbruch und Vibration erkennen können. Er muss also eine gewisse Fläche aufweisen, so dass es eine gute Verbindung zwischen Glas und Sensor entsteht.
- Er sollte eine Grösse aufweisen, so dass er nicht störend wirkt.
- Der Sensor ist polarisiert, dh. Rot bzw. Plus muss auf den analogen Eingang.
Schema:
- Der Sensor benötigt nicht viel. Er erzeugt bei Vibration eine proportionale Spannung und diese kann man mit einem analogen Eingang messen.
- Ein paralleler Widerstand, am besten über den analogen Eingang stabilisiert das Eingangssignal und man hat einen definierten Innenwiderstand. In meinem Falle sind die analogen Eingänge wenn der Sensor nicht angebracht sind damit schön auf 0V.
- Die analogen Eingänge der MCU haben meistens eine interne Schhutzschaltung, daher sehe ich kein Bedürfniss für eine Zenerdiode.
- Wirft zum Beispiel jemand einen Stein in die Scheibe und trifft den Sensor direkt, dann scheint mir ein serieller Widerstand von 10k Ohm als Spannungsteiler sinnvoll, damit keine zu grosse Überspannung entsteht.
- Der Sensor solle klein und unauffällig sein, also wenig Komponenten verwenden.
- Mir müssen keine genauen Meswerte ermitteln, sondern nur zwischen Fenster auf/zu, klopfen und Glasbruch unterscheiden können.
- Die Schutzschaltung oder Zenerdiode köpft das Eingangssignal, daher ist ein Spannungsteiler je nach Glas, Grösse und Montage empirisch zu ermitteln. Der Messbereich sollte im Auswertungsbereich liegen, so dass wir unterscheiden zwischen Vibration und Glasbruch entscheiden können.
- Da ich kein überflüssiges Glas zum zerstören habe, musste ein Bilderrahmen für Vibrationstest herhalten.
- Mit dem analogen Input kann man nur sporadische Messpunkte messen und nicht die Vibrationskurve wie mit einem Signalprozesor. Dies weil die MCU ja noch anderes macht. Details dazu wirst du im Abschnitt Berechnung erfahren.
Berechnung der Vibration
Wenn wir die Berechnung bzw. die Ermittlung der Vibration durchführen wollen, dann müssen wir zuerst verstehen wie die Messdaten, oder anders gesagt die analog Werte ermitttelt werden. Im Codefenster sehen wir wie der Mainloop die Daten einliest. Ohne jetzt auf die Details einzugehen sehen wir, dass der Loop noch digitale Eingänge einliest, dass er mit dem Bluetooth kommuniziert und dass er advertising Data aufbereitet. Wir müssen erwarten, dass der Loop unterschiedliche ausführungszeiten aufweist. Damit haben wir nicht eine konstante Sampling Rate!
Unser Modul kann 2 Fenster mit 2 Flügel bedienen, darum hat es vier Piezo analog Eingänge!
void loop() {
if (!isInitialized) {
isInitialized = true;
Serial.println(" The Window monitor has been started");
}
timer.tick();
BLEDevice central = BLE.central();
//if a central is connected to peripheral:
if (central) {
// while (central.connected()) {
//timer.tick();
long currentMillis = millis();
if (currentMillis - previousMillis >= 100) {
previousMillis = currentMillis;
if (updateBatteryLevel() && StateManager.isConnected) {
batteryLevelChar.writeValue(oldBatteryLevel); // and update the battery level characteristic
}
if (CheckWindowShas('L', Window1ShasLeftPin, 2)) hasChanges = true;
if (CheckWindowShas('R',Window1ShasRightPin, 4)) hasChanges = true;
if (CheckWindowShas('L', Window2ShasLeftPin, 6)) hasChanges = true;
if (CheckWindowShas('R',Window2ShasRightPin, 8)) hasChanges = true;
}
if (hasChanges) {
if (StateManager.isConnected && binarySensor.GetReporting( PARVALTYPMOCL)) binarySensor.CreateSensorStatusEvent(PARVALTYPMOCL, bssResponseChar);
binarySensor.GetCompressedlSensorValues(serviceData);
Serial.print("Compressed Sensor Value: "); for (int i=0; i<16;i++) { Serial.print(serviceData[i],HEX); Serial.print("-"); } Serial.println();
BLE.advertise();
hasChanges = false;
}
if (checkAndAddPiezo1Level()){ }
if (checkAndAddPiezo2Level()){ }
if (checkAndAddPiezo3Level()){ }
if (checkAndAddPiezo4Level()){ }
// if buffer starts with filling value by value an new serie should start
if (vibaNr1.NewSerie()) { timer.in(2000, analysePiezo, &vibaNr1.nr); }
if (vibaNr2.NewSerie()) { timer.in(2000, analysePiezo, &vibaNr2.nr); }
if (vibaNr3.NewSerie()) { timer.in(2000, analysePiezo, &vibaNr3.nr); }
if (vibaNr4.NewSerie()) { timer.in(2000, analysePiezo, &vibaNr4.nr); }
// Serial.println(" Die Analyse beginnt in 2 sec");
// }
}
}
Oszilloskope
Auf dem Bild sieht man das Signal das dass Oszilloskope aufzeichnet, wenn ein Gegenstand auf das Glas fällt wo der Piezo-Sensor aufgeklebt ist. Dabei erkennen wir, dass das Signal bereits bei 5V abgeschnitten ist. Damit haben wir schon einen wesentlichen Informationsverlust, denn bei Glasbruch müssten wir ja einen grösseren Wert erkennen können. Für unseren Sensor müssen wir also einen geeigneten Spannungsteiler bestimmen.

Messreihenanalyse
Wenn wir das Piezosignal mit einer Messreihe vergleichen die periodisch (Loop) den analog Eingang liest, dann fallen uns folgend Punkte auf:
- Ab 5V ist der Wert begrenzt und nicht mehr als 1023.
- Bei hoher Frequenz geht Information verloren.
- Um eine gute Reihe zu bekommen, müssen wir einen schnellen gleichmässigen Loop haben.
Warum nicht ISR?
- Die ISR würde bei einem Signal sofort starten und n-mal aufgerufen.
- wir habe damit sofort ein Memory-oder Stackproblem. Ein Crash wäre die Folge.
- bei mehrmaligem ISR call, muss ein Mutex für Datenspeicherung sichergestellt werden.
- wir müssten closure Themen betrachten.
- Debugging von ISR ist alles andere als easy.
Also ein cleverer Loop ist einfacher und zudem die MCU macht ja nichts anderes als Eingänge lesen!

Die Analyse
Nehmen wir an, wir haben die Pegeleinstellung im Griff, und der Loop ist genug schnell um damit eine brauchbare Messreihe zu erhalten. Dann müssen wir uns mit der Analyse der Daten beschäftigen. Dabei gibt es folgendes zu sagen:
- wie lange dauert ein Vibration, oder anders gesagt, wann ist die Messreihe beendet?
- Wie viele Messdaten haben wir?
- Wie beurteilen wir ob es eine Vibration oder Glasbruch ist?
- Müssen wir jeden Messwert speichern?
Die VibAnalyse Class
Für die Analyse der Vibration, bzw. Lesen und auswerten des analog Wertes haben wir einen Ringbuffer und Methoden dazu die diesen auffüllen oder auslesen und die Werte auswerten.
- Der Ringbuffer speichert eine Messserie. Er ist Eigenbau, ist relativ einfach und seine Funktionalität adaptiert meine Bedürfnisse.
- Wird das erste Element gespeichert, dann wird Start vib gesetzt, damit beginnt eine Messreihe.
- Ich gehe davon aus, dass eine Vibration nach 2 Sekunden vorbei ist, darum wird bei einem Start einer Messreiehe ein Timer gestartet der nach 2 Sekunden die Auswertroutine ausführt.
- Es gibt 4 simple Berechnungen (Summe, Volumen, Spitzenwert, und Durchschnittswert). Es ist angedacht nur eine zu vewenden, ja nach Bedarf.
- die Berechnungsmethoden sind entweder Peak oder Get.
- Will man mehrere unterschiedliche Berechnungen der gleichen Messreihe, muss man mit Peak arbeiten und nur die letzte mit Get. Get entfernt alle Messwerte aus dem Buffer, peak nicht.
- Ist der Buffer voll, wird nichts mehr hineingefüllt (nicht die letzten n Werte, sondern die ersten n Werte sind enthalten).
- Messwerte werden gespeichert, wenn sie ein min haben und das Delta zum vorherigen gross genug ist. Es wird der Wert und die Zeit gespeichert,. 1. Wert hat ms der MCU und alle folgenden delta ms.
struct Value {
int ms;
int val;
};
class VibAnalyse {
private:
RingBuffer _ribu;
public:
byte nr;
int lastValue = 0;
VibAnalyse() = default;
VibAnalyse(int size, byte n);
~VibAnalyse();
void RandomFillRingBuffer(int max); // for Testvalues
bool NewSerie();
void AddValue(int x, bool pct = false);
int PeekSumVibration( Value* v);
int PeekVolumeVibration( Value* v);
int PeekPeakVibration( Value* v);
int PeekAverageVibration( Value* v);
int GetSumVibration( Value* v);
int GetVolumeVibration( Value* v);
int GetPeakVibration( Value* v);
int GetAverageVibration( Value* v);
};
Da die Programme mit Kommentar gut dokumentiert sind, werden sie hier nicht noch einmal abgedruckt. Unter Goodies kann man sich die Sourcen herunter laden.
Goodies
Goodies
Challenges
Es ist gar nicht so einfach, die analog Werte richtig einzulesen und daraus das richtige Resultat zu ermitteln:
- Wertebereich festlegen , so dass die richtigen Werte anliegen.
- Werte einlesen mit Geschwindigkeit und Menge
- Werte aufbereiten zu einem Entscheidungsresultat.
Intro
nothing yet
Hier ended die Seite