Klopfsensor an Interrupt Port

Ich wollte gerade mal schnell ein kleines Nano Projekt durchziehen, aber ich komme nicht weiter, weil es nur funktioniert, wenn ich unnatürlich fest auf den Sensor klopfe.
Es ist dieser flache Piezzo mit einer kleinen Verstärkerplatine.
Ich habe einen Timer laufen, der sofort anhalten soll, wenn ein moderates Geräusch (Klopfen auf den Tisch) registriert wird.
Ich hab den Digtalen Port 3 als Eingang für den Klopfsensor genommen, da ich da einen Interrupt aufsetzen kann.
Muß der Sensor an einen analogen Port?

Hier mal der code:

#include <Adafruit_NeoPixel.h>  //Neopixel library
#include <TM1637.h>             //Display
// Pin-Konfiguration
const int buttonPin = 2;  // Pin, an dem der Taster angeschlossen ist
#define PIN 6             // Pin, an dem der Neopixel-Streifen angeschlossen ist
#define NUMPIXELS 5       // Anzahl der LEDs im Streifen
// Definiere die Pins für das TM1637-Modul
const int CLK = 4;  // Takt-Pin des TM1637-Moduls
const int DIO = 5;  // Daten-Pin des TM1637-Moduls

// Variablen für den Timer
unsigned long startTime = 0;    // Startzeit des Timers
unsigned long elapsedTime = 0;  // Gemessene Zeit in Millisekunden
bool timerRunning = false;      // Status des Timers
bool lastButtonState = HIGH;    // Status des Tasters beim letzten Überprüfen

// Erstelle ein NeoPixel-Objekt
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
// Erstelle ein TM1637-Objekt
TM1637 display(CLK, DIO);

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);                              // Taster-Pin als Eingang mit internem Pullup-Widerstand
  Serial.begin(9600);                                            // Serielle Kommunikation starten
  pixels.begin();                                                // Initialisiere die Neopixel-Bibliothek
  pixels.show();                                                 // Alle Pixel ausschalten
  display.set(5);                                                // Helligkeit des Displays einstellen (0-7)
  attachInterrupt(digitalPinToInterrupt(3), stopTimer, RISING);  // Interrupt an Pin 3 auf steigende Flanke setzen
}

void loop() {
  bool buttonState = digitalRead(buttonPin);  // Tasterzustand lesen

  // Überprüfen, ob der Taster gedrückt wurde (fallende Flanke)
  if (buttonState == LOW && lastButtonState == HIGH) {
    if (!timerRunning) {
      // Timer starten nach LED-Sequenz
      startampel();
      startTimer();  // Timer startet nach der LED-Sequenz
    } else {
      // Timer stoppen, wenn er bereits läuft
      stopTimer();
    }
    delay(50);  // Entprellen, um versehentliche Mehrfachauslösungen zu verhindern
  }

  // Aktuellen Status des Tasters für die nächste Abfrage speichern
  lastButtonState = buttonState;

  // Falls Timer läuft, die aktuelle Laufzeit anzeigen
  if (timerRunning) {
    displayTime(millis() - startTime);  // Funktion zur Anzeige der laufenden Zeit aufrufen
  }

  delay(10);  // Kurze Pause für glattere Ausgabe
}

// Funktion zum Setzen der Farbe eines einzelnen Pixels
void setPixelColor(int pixel, uint8_t red, uint8_t green, uint8_t blue) {
  if (pixel >= 0 && pixel < NUMPIXELS) {
    pixels.setPixelColor(pixel, pixels.Color(red, green, blue));
  }
}

// Funktion zum Setzen der Farben mehrerer LEDs
void startampel() {
  displayTime(0);               //reset display
  setPixelColor(0, 255, 0, 0);  // first pixel out of the loop to get an immediate start
  pixels.show();
  for (int i = 1; i <= NUMPIXELS; i++) {  // Setzt eine nach der anderen LED auf Rot
    setPixelColor(i, 255, 0, 0);
    delay(1000);
    pixels.show();
  }
  for (int i = 0; i <= NUMPIXELS; i++) {
    setPixelColor(i, 0, 255, 0);  // Setzt alle LEDs auf Grün
  }
  pixels.show();
}

// Funktion zum Ausschalten aller LEDs
void clearAllPixels() {
  for (int i = 0; i < NUMPIXELS; i++) {
    setPixelColor(i, 0, 0, 0);  // Setze jede LED auf schwarz (aus)
  }
  pixels.show();  // Zeige alle Änderungen an
}


// Funktion zum Starten des Timers
void startTimer() {
  startTime = millis();  // Startzeit speichern
  timerRunning = true;
  Serial.println("Timer gestartet");
}

// Funktion zum Stoppen des Timers
void stopTimer() {
  if (timerRunning) {
    elapsedTime = millis() - startTime;  // Gesamtzeit berechnen
    displayTime(elapsedTime);
    timerRunning = false;
    clearAllPixels();
    Serial.print("Timer gestoppt. Laufzeit: ");
    Serial.print(elapsedTime / 1000.0, 2);  // Umrechnung in Sekunden mit zwei Dezimalstellen
    Serial.println(" Sekunden");
  }
}

// Display
void displayTime(unsigned long Result) {
  // Serial.println(Result);   /

  // Begrenze den Wert auf 4 Stellen, um das Display nicht zu überladen
  if (Result > 60000) Result = 60000;
  if (Result < 0) Result = 0;

  int sekunden = Result / 1000;                 // Ganze Sekunden
  int zehntelsekunden = (Result % 1000) / 100;  // Zehntelsekunden
  int hundertstelsekunden = (Result % 100) / 10;


  display.display(0, sekunden / 10);  // Zeigt die Zehnerstelle der Sekunden
  display.display(1, sekunden % 10);  // Zeigt die Einerstelle der Sekunden
  display.point(1);
  display.display(2, zehntelsekunden);  // Zeigt die Zehntelsekunden
  display.display(3, hundertstelsekunden);
}

Mal Pin 2, dann Pin 3 :wink:

Nee, da ist noch ein Taster dran.
Dieser startet das Ganze. Der Taster ist auf 2.
(der kann das übrigens auch stoppen, aber nicht über interrupt.
Der Sensor ist auf 3.
Ich hatte das mit zwei Jumperkabeln getestet (Pin 3 manuell auf 3V).
Funktionierte bestens.
Im Video sieht man wie sehr man den Sensor traktieren muß.

Du hast den Link vergessen :slight_smile:

Danke.

Ja.

Dann fehlt da was, besser so, wäre es ein digitales Signal:

const int klopfPin = 3;   // Pin, an dem der Taster angeschlossen ist
...
attachInterrupt(digitalPinToInterrupt(klopfPin), stopTimer, RISING); // Interrupt an Pin 3 auf steigende Flanke setzen

Ein kleiner Transistor könnte das analoge Signal verstärken und direkt für den digitalen Eingang mit Interrupt nutzbar machen.

1 Like

Ok. das ist schöner, wenn man da die Variable einträgt. Ich hatte Pin 3 hardcoded.
Zum Transistor: Die Platine sollte doch genau das verbaut haben.

Das ist genau das was ich nicht verstehe.

Danke, hatte ich auch gelesen, ich dachte , die kleine Platine sorgt dafür, daß der Pin 3 kurz hochgezogen wird.
Ich habs jetzt mal so geändert und dann gehts mit nem einstellbaren Threshold.

const int knockPin = A0;    // Anschluss des Klopfsensors an A0
int sensorValue = 0;
const int threshold = 50;
  if (timerRunning) {
    displayTime(millis() - startTime); // Funktion zur Anzeige der laufenden Zeit aufrufen
    sensorValue = analogRead(knockPin);
    if (sensorValue > threshold) {          // wenn der Wert den Schwellenwert überschreitet
    Serial.println(sensorValue);
    stopTimer();
 }
  }

  delay(10); // Kurze Pause für glattere Ausgabe
}

Das Foto zeigt keinen Transistor.

Beim diesem Vibrationssensor-Modul gibt es einen digitalen Ausgang und ein Poti zum Einstellen der Empfindlichkeit. Vermutlich hast Du sowas gesucht :wink:

Hatte ich auch gesehen, aber es funktioniert ja - fast.

Ich habe ein weiteres Problem, was ich so nicht erwartet habe.
Das was ich da baue bekommt zeitweise schon sehr starke Schläge ab.
Als ich dann alles verbaut habe, habe ich festgestellt, daß der Nano bei heftigen Schlägen resettet.
Ich kann mir das nur so erklären daß der Sensor eine zu hohe Spannung (weit über 5V) rausgibt, was der Nano nicht mag, oder?

Mal sehen was ich nun mache.

  1. Platine entfernen und nur den Sensor verwenden
    (ich weiß echt nicht genau, was die Platine eigentlich macht.)
  2. Irgendwas mit Zenerdiode und Widerstand basteln.

Was meint ihr?

Ob das die Ursache ist kann ich nicht sagen, aber zumindest stimmt die Aussage. Da ist zwar wenig Energie dahinter, aber direkt an den Pin würde ich nicht gehen.
Schutzwiderstand, FET und dann an den arduino. So würde ich das machen.

Zur Info, ich bin Maschinenbauer. :wink:
Das hier ist aus einem anderen Thread


Macht das Sinn?

Deckt sich auch mit Schaltungen, die in diesem Thread (englisch) in Abwandlungen empfohlen wurden. Allerdings herrscht dort eher die Meinung "Zener- sinnfrei, lieber Schottky-Dioden". Dazu fehlte mir aber das Elektroniker-Wissen, um das zu beurteilen..

Danke derGeppi, Der ist saulang und ab einem gewissen Punkt bin ich lost.
Wie ist die Meinung hier zu der Schaltung oben?

MAKE de hatte mal einen Artikel einer elektronischen Zielscheibe:
https://www.heise.de/select/make/2018/6/1545377782450915
(Artikel nur Abonenten zugänglich)
Dort wird mittels 4 Piezo der Aufschlagpunkt auf einer Zielscheibe berechnet.
Auswertungselektronik ist dabei etwas kompliziert:

Wobei Voffs (hier an R8) eine Spannung zwischen 0 und 5V ist ( 10k Potentiometer) und laut Anleitung so abgeglichen werden daß die Schaltung nicht schwingt.
Der erste OPAMP ist ein Gleichrichter , der zweite eine Verstärkung und der 555 ist als Schmidttrigger geschaltet wobei angenommen wird daß dieser auch weggelassen werden könnte weil der ATmega an seinen Eingängen auch Schmidttriggerfunktion hat. Wie ich das verstanden habe, muß der 555 vom Controller vor der Messung resetiert werden.

Hier findet man den Sketch:

Grüße Uwe

Zumindest baust Du damit etwas Sicherheit ein. Als Zenerdiode würde ich eine mit 4,7 Volt nehmen (wenn Du mit nem 5 V arduino unterwegs bist).
Den Piezo solltest Du verkleben mit dem Untergrund, das erhöht deutlich die Empfindlichkeit.

Danke, ich werde das einmal versuchen und berichten.
Ich hab den verklebt und das wird hier auch leider das Problem sein (siehe Originalpost).
Aber machmal kommt ein Problem haölt erst auf, wenn alles vom Breadboard ins Gehäuse kommt.

@uwefed Sorry, das ist mir als Hobbyelektronioker etwas zu hoch aufgehängt, aber trotzdem danke.

Eine Zenerdiode und einen 1M Ohm Widerstand parallel einzulöten hat nicht viel gebracht.
Wenn ich richtig mit einem festen Gegenstand auf das Brett haue, gibts immer noch nen Reset. Vielleicht ists ja gar nicht der Sensor?
Ich frag mich ob nicht ganau das sowieso schon auf der Platine verbaut ist:

Jetzt bin ich wirklich ratlos und brauche Hilfe.
Mein Nano resettet immer noch, wenn ich fest auf die Rückseite dieses Gehäuses schlage.
Ja, vom Design etwas unglücklich, daß die Platine da fest verschraubt ist, und die Batterien sind auch mit Moosgummi gesichert.

Das eigentlich Seltsame ist, das System resettet auch, wenn ich die Platine entkoppele.
Und noch komischer: Das passiert auch wenn ich den Stecker (unten rechts) des Klopfsensors (Mitte) abziehe, das heißt es kann gar keine Überspannung am Nano ankommen.

Kann dieser Piezzo einen richtig fetten Störimpuls an den ResetPin des Arduino senden?n Rechts