Liebe Arduinofreunde, Liebe Mitleser,
Die Phrase "ich bin Anfänger mit Arduino und co" möchte ich überspringen und gleich zur technischen Fragestellung übergehen.
Seit ein paar Tagen beschäftigt mich der Aufbau eines Schwingungsmessgerät anhand Arduino nano und ADXL335. Im speziellen lässt mich die Signalverarbeitung des Sensors derzeit nicht schlafen Naja nicht ganz, aber meine Ideen zum vorantreiben des Projekts versiegen langsam. Zum Verständniss der Herausforderung folgt eine kurze Projektbeschreibung die aktuelle Herausforderung und anschließend die Dokumentation der aktuellen Situation.
Projektziel:
Es soll anahnd des Beschleunigungssensors ein Schwingungsmessgerät programmiert werden, das eine mechanische Schwingung auf ihre Frequenz untersucht. Die Schwingung bewegt sich im Bereich von 5-15Hz.
Lösungsansatz:
Eine Messdauer von ca. 10 Sekunden soll Rüchschluss auf die Anzahl der Auslenkungen pro Minute erlauben. Anhand der Amplitudenmessung (Zählen der positiven Ausschläge) lässt sich durch Division mit der Messdauer und Multiplikation mit 60 Sekunden eine Aussage über die Ausschläge pro Minute erzielen.
"Schwingungszahl" = (Anzahl der positiven Amplituden / Messdauer) * 60 Sekunden.
Jedoch beginnt hier die aktuelle Herausforderung in der Signalverarbeitung.
Alternative Ansätze wie fft (fast fourier transformation) wurden bereits in Erwägung gezogen, jedoch nicht erfolgreich umgesetzt bzw. muss es doch einfachere Lösungen geben? (Da Anforderungen nicht so hoch sind wie im hochfrequenzbereich)
Herausforderung:
Wie lassen sich einzelne Auslenkungen des Sensors zählen? Beziehungsweise wie lassen sich die Werte im Analogen Eingang zu einer Frequenzinformation der Schwingung umrechnen?
aktuelle Situation:
An den Arduino wurde ein oled display und ein button angeschlossen. Der Button steuert über ein Interrrupt den Start der Messung. Nach betätigen des Tasters beginnt ein Timer zu laufen bis die Messdauer erreicht wurde. Wärend der Messung werden die analog Werte des Beschleunigungssensor ausgelesen. Anschließend wird die berechnete Schwingungszahl angezeigt in [Ausschläge pro minute].
Jedoch klappt die Flankenerkennung der Schwingung nicht. Durch das Betrachten des Signal des Sensor im Serial Plotter ist mir auch klar warum, jedoch weiss ich keine bessere Möglichkeit.
Hier mal die Codelei:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//-----------------------------------ADXL 335--------------------------------
const int zpin = A0;
//------------Bedienung----------------
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPinMessung = 12; // the number of the LED pin
//------------------------ variablen fuer entprellen----------------
volatile unsigned long alteZeit=0, entprellZeit=40;
volatile int buttonCounter = 0;
// variablen fuer zeitnehmung
unsigned long startMillis;
unsigned long currentMillis;
float period = 10.0;
int f = 0;
int Acounter = 0;
int newAcounter = 0;
int S = 0;
double t = 0;
double a = millis();
double c ;
int go = 0;
void setup()
{
Serial.begin(230400);
analogReference(EXTERNAL);
pinMode(zpin, INPUT);
pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, HIGH);
attachInterrupt(0, start_ISR, RISING);
pinMode(ledPinMessung, OUTPUT);
digitalWrite(ledPinMessung, LOW);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3D for 128x64
display.clearDisplay();
homeScreen();
int z = analogRead(zpin);
Serial.print(z);
}
void homeScreen ()
{
display.clearDisplay();
//item
display.setCursor(0,0);
display.setTextSize(2);
display.setTextColor(WHITE);
display.print("Ergebnis");
//periode
display.fillRect(97,0,60,15,WHITE);
display.setCursor(97,4);
display.setTextSize(1);
display.setTextColor(BLACK);
display.print(period);
display.drawLine(0, 15 , 127,15 , WHITE);
//Schwingungszahl auf Schläge pro Minute
display.setCursor(0,25);
display.setTextSize(2);
display.setTextColor(WHITE);
display.print("S:");
display.setCursor(20,17);
display.setTextSize(4);
display.setTextColor(WHITE);
display.print(S);
display.setCursor(97,22);
display.setTextSize(1);
display.setTextColor(WHITE);
display.print("Amp.");
display.drawLine(92, 32 , 120 , 32 , WHITE);
display.setCursor(97,35);
display.setTextSize(1);
display.setTextColor(WHITE);
display.print("min");
//Schwingungszahl bezogen auf ADXL335
display.setCursor(0,48);
display.setTextSize(2);
display.setTextColor(WHITE);
display.print("x:");
display.print(newAcounter);
display.display();
}
void meassuring()
{
display.clearDisplay();
//item
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("Messung");
//periode
display.fillRect(97,0,60,15,WHITE);
display.setCursor(97,4);
display.setTextSize(1);
display.setTextColor(BLACK);
display.print(period);
display.drawLine(0, 15 , 127,15 , WHITE);
//Schwingungszahl bezogen auf ADXL335
display.setCursor(0,25);
display.setTextSize(2);
display.setTextColor(WHITE);
display.print("x:");
display.setCursor(20,17);
display.setTextSize(4);
display.setTextColor(WHITE);
display.print(Acounter);
display.setCursor(97,22);
display.setTextSize(1);
display.setTextColor(WHITE);
display.print("Amp.");
display.drawLine(92, 32 , 120 , 32 , WHITE);
display.setCursor(97,35);
display.setTextSize(1);
display.setTextColor(WHITE);
display.print("per.");
//---------------------------------
display.display();
while(t <= period)
{
c = millis();
t = (c - a) / 1000;
display.fillRect(0,55,127,14,WHITE);
display.setTextSize(1);
display.setTextColor(BLACK);
display.setCursor(39,56);
display.print("t:");
display.print(t);
display.print("sec");
display.display();
int sensorReading = analogRead(zpin);
Serial.println(sensorReading);
display.setCursor(17,17);
display.fillRect(17,17,75,33,BLACK);
display.setCursor(20,17);
display.setTextSize(4);
display.setTextColor(WHITE);
display.print(Acounter);
}
newAcounter = Acounter;
S = (newAcounter / period) * 60;
Acounter = 0;
go = go -1;
t = 0.000;
}
void loop()
{
if (go == 0 )
{
homeScreen();
}
if(go == 1 )
{
meassuring();
}
Serial.println(S);
}
void start_ISR()
{
if((millis() - alteZeit) > entprellZeit)
{
// innerhalb der entprellZeit nichts machen
go++;
alteZeit = millis(); // letzte Schaltzeit merken
a = millis();
}
}
Das Angehängte Bild zeigt zwei Messreihen mit 10 Dauer und den analogen Rohwerten des ADXL335.
Vielen Dank für Ratschläge auch allgemeiner Art möchte ich mich jetzt schon bedanken. Sollte ich wichtige Informationen zu den Spezifikationen vergessen haben (was ws der Fall ist) werde ich diese nachtragen.
Gruß
Ardukus