Serielle Schnittstelle und LCD

Hallo

ich möchte über den Arduino Uno eine Drehzahl anzeigen und diese ebenfalls per serier Schnittstelle an den PC senden. Die Drehzahl wird über einen Hall-Sensor erfasst und per Interrupt dann die Drehzahl ausgegeben.
Ohne die Ausgabe über die serielle Schnittstelle funktioniert das Programm ohne Probleme, jedoch binde ich die Ausgabe ein, erkennt der Controller kein Interrupt mehr.

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

float rpm;
long TimeOld;
long TimeNew;
float diffTime=0;

void setup()
{
  TimeOld = 0;
  lcd.begin(16,2);
  lcd.setCursor(0,0);
  lcd.print("Drehzahl:");
  Serial.begin(9600);
  attachInterrupt(0, reaktion, FALLING);
}

void loop()
{
  attachInterrupt(0, reaktion, FALLING); 
}
void reaktion()
{
  TimeNew=millis();
  diffTime=TimeNew-TimeOld;
  rpm = (1/((diffTime/1000)))*60;
  TimeOld = TimeNew;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Drehzahl:");
  lcd.setCursor(0,1);
  lcd.print(rpm);
  lcd.print(" 1/min");
  Serial.println(rpm);
  Serial.println(' 1/min');
}]

Kann mir dabei vllt jemand helfen.

Danke im Voraus!

Drehzalanzeige.ino (711 Bytes)

Kannst du mir erklären, warum du attachInterrupt() auch in der Hauptschleife aufrufst? Wenn du das in der setup-Routine machst, sollte das meines Erachtens ausreichen.

Das ist sonderbar.
Ich habe hier gerade ein Projekt auf dem Steckbrett, bei dem fast eine identische Belegung gewäählt ist.
Ich verwende ebenfalls int0 und die serielle Schnittstelle (PD0 u. PD1), sowie ein LCD an den Pins 5- 10 und das funktioniert problemlos.
Was ich allerdings vermeiden würde, ist die Ausgabe in die ISR zu intergrieren.
Du übertägst mit "gemütlichen" 9600 Baud und wärend dessen sind verm. die Interrupts gesperrt.
Verlege mal alles was geht in die Loop und schreibe in der ISR nur die millis() in die Variable, dann sollte es klappen.

LG Lena

sth77:
Kannst du mir erklären, warum du attachInterrupt() auch in der Hauptschleife aufrufst? Wenn du das in der setup-Routine machst, sollte das meines Erachtens ausreichen.

Au weia, das war mir noch garnicht aufgefallen - NoNoNo, so nicht :frowning:

LG Lena

Die Interruptroutine muß so kurz wie möglich sein um beendet zu sein wenn ein nächster Interrupt kommt; also keine Ausgabe aufs Display oder auf die serielle Schnittstelle in der Interruptroutine. Nur Abspeichern der aktuellen Zeitdifferenz. Dies auch weil in der Interruptroutine millis() nicht weitergezählt wird. Dei Ausgabe aufs Display und die Seriele Schnittstelle machst Du 1 bis 2 mal die Sekunde in der loop() - Funktion.

"rpm = (1/((diffTime/1000)))*60;" kann man umformen damit die Rechnung einfacher ist:
"rpm= 60000/diffTime;) macht das gleiche und ist nur 1 Rechenoperation.

Grüße Uwe

Ich setze zusätzlich auch gerne ein Flag, das mir ein neues Interupt in der Loop signalisiert und erst dann zurückgesetzt wird, wenn alle Operationen durchgeführt worden sind.
Nimmst Du statt einens boolean Flags einen int Counter, der in der ISR incrementiert wird, kannst Du sogar einen Interupt-Overrun erkennen.

LG Lena

uwefed:
"rpm = (1/((diffTime/1000)))*60;" kann man umformen damit die Rechnung einfacher ist:
"rpm= 60000/diffTime;) macht das gleiche und ist nur 1 Rechenoperation.

Stellt das der Compiler bzw Präprozessor nicht sowieso so um?

LG Lena