Dual Tachometer / RPM Display

Hallo zusammen

Ich versuche gerade ein Doppel Tachometer / RPM Display zu bauen, jedoch kriege ich die 2te RPM Messung nicht hin.

Hardware:
-Arduino Uno
-1602A Display mit IC2
-2x Lichtschranke MH-B

Pinbelegung
Display GND-GND; VCC-5V; SDA-A4;SCL-A5
Lichtschranke 1 GND-GND; VCC-5V; Out-D2
Lichtschranke 2 GND-GND;VCC-5V; Out-D3

Grundsätzlich läuft die erste RPM anzeige (Out von Lichtschranke 1 auf D2) jedoch kriege ich die 2te nicht drauf da ich die pins nicht zuordnen kann.

kann mir jemand helfen ?

Hier der Code

#include <LiquidCrystal_I2C.h>       //i2c library file 
LiquidCrystal_I2C lcd(0x27, 16, 2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

float value = 0;
float rev = 0;
int oldtime = 0;
int rpm1 = 2;
int rpm2 = 3;
int time;

void isr()          //interrupt service routine
{
  rev++;
}

void setup()
{
  lcd.init();                       // initialize the lcd
  lcd.init();
  lcd.backlight();
  attachInterrupt(0, isr, RISING); //attaching the interrupt

  lcd.setCursor(0, 0);
  lcd.print("Dual");
  lcd.setCursor(0, 1);
  lcd.print("RPM Display");
  delay(3000);
}

void loop()
{
  delay(600);
  detachInterrupt(0);           //detaches the interrupt
  time = millis() - oldtime;    //finds the time
  rpm1 = (rev / time) * 60000;   //calculates rpm
  oldtime = millis();           //saves the current time
  rev = 0;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Mot 1: ");
  lcd.setCursor(7, 0);
  lcd.print(rpm1);
  lcd.setCursor(13, 0);
  lcd.print("RPM");
  lcd.print("   ");
  lcd.setCursor(0, 1);
  lcd.print("Mot 2:");
  lcd.setCursor(7, 1);
  lcd.print(rpm2);
  lcd.setCursor(13, 1);
  lcd.print("RPM");
  lcd.print("   ");
  attachInterrupt(0, isr, RISING);

}

(deleted)

hardware3718:
kann mir jemand helfen ?

Gut vorbereitet.

Dann hier mal ein Schnipsel - Ich bin sicher, das Du den umsetzen kannst.

void isr()          //interrupt service routine
{
  rev++;
}

void isr1()
{
  rev1++
}
void setup()
{
  lcd.init();                       // initialize the lcd
  lcd.init();
  lcd.backlight();
  attachInterrupt (0, isr, RISING); //attaching the interrupt
  attachInterrupt (1, isr1, RISING); // attach next interrupt
  lcd.setCursor (0, 0);
  lcd.print ("Dual");
  lcd.setCursor (0, 1);
  lcd.print ("RPM Display");
  delay (3000);
}

void loop()
{
  delay (600); 
  detachInterrupt (0);          //detaches the interrupt
  detachInterrupt (1);          
  time = millis() - oldtime;    //finds the time
  rpm1 = (rev / time) * 60000;   //calculates rpm
  attachInterrupt (0, isr, RISING);
  attachInterrupt (1, isr1, RISING);
  oldtime = millis();           //saves the current time
}

Ah, ich denke wo der gedankliche Hänger bei Dir ist.
Schau mal hier:

Im Gegensatz zu PCINT ist die Bezeichnung der ISR für attachinterrupt NICHT festgelegt.

Jeder interruptpin bekommt eine eigene - von dir frei mit Namen versehende - Serviceroutine.

Schöne Idee. Las uns teilhaben, wie es weiter geht.

Hallo zusammen

sorry bin hier neu im forum und arduino welt. Hatte immer wieder geschaut wegen antwort unter "my posts" aber da sehe ich ja nur meinen 8)

Ich arbeite mich langsam von turtorial zu turtorial in funktionen und library's ein und versuche auch anhand beispiele diese zu verstehen. gewisses kann ich, gewisses noch nicht :wink: ist aber sehr interessant. ich komme sonst aus der cnc und sps welt und baue viele verrückte sachen.

vielleicht muss ich das ganze auch umcoden.

Das auslesen und darstellen dieser 2 RPM's ist nur ein Teil eines projektes wo noch was dazu kommt. aber ich denke ich mach das schritt für schritt.

ich versuche heute abend das von euch beantwortete um zu setzen/zu studieren.

Hier aber trotzdem noch die gesamt idee.

1 Arduino (nano, uno oder was auch immer für einer nötig ist)
Input signale
-Liest 2 RPM's aus in 5 zentels sekunden. Drehzahlbereich bis 0-20k
-Liest 2 temperaturen aus in 5 zentels sekunden. Messbereich... mit nem PT100 0-100°
-stellt die Daten auf einem display dar (momentan das 1601 mit I2C) habe aber auch noch OLed's, da das 1601 bei 5 zentel refresh schon ziemlich flackert. Die OLeds würden auch angeschlossen mit I2C, habe ich jedoch noch nicht geschafft.
Output Signale
-Gibt zusätzlich optisches Feedback der beiden RPM's in form von LED's wieder. (bsp. RPM >5K Grün, >10K Orange, >15K Rot)
-Schaltet bei Temperatur 1&2 ab einer gewissen Temperatur einen Ausgang (Lüfter)

Das ganze ist für ein doppelmotoriges Anzeigedisplay bei welchem die Drehzahlen und Temperaturen überwacht und verarbeitet werden müssen.

Ist momentan für mich noch etwas zu komplex aber ich denke step By step kriege ich das mit eurer hilfe hin :slight_smile:

Danke vorab ! Nico

My Page

(deleted)

Hallo Peter

Danke für den wichtigen Tipp ! Ich hatte mir zu Anfang auch überlegt wie ich dies beim Arduino am besten angehe. Dein Konzept macht absolut Sinn. Z.t. ist man halt ziemlich überwältigt wenn man von Simplen SPS auf Ardunio's trifft :smiley:

Der Temperatursensor sieht gut aus. Habe eine Arduinoversion gefunden (SE042) welchen ich auch gerade gut auf dem breadboard zum testen benutzen kann.

Dann werde ich heute abend zuerst mal die eingaben verarbeitung und ausgaben definieren und schematisch darstellen.

Gruess Nico

(deleted)

Hallo Peter

Ja hab mir diese auch bestellt. Die sind perfekt ! Die idee ist dann bei der Motorhalterung wo am meisten Wärme erzeugt wird den Sensor mittels einer Bohrung zu montieren.
Das Bier Messe ich gerne mit direkter Messmethode und nicht über ein Sensor :grinning:

Hallo,

Du schreibst Drehzahl 0-2k , meinst Du 0-2000U/min ? das sind dann bei 1imp/Umdr etwa 0-330Hz. die willst Du in 500ms messen. Damit bekommst Du bei 10 Hz einen Messwert von 5 oder 6 . Das ist eine ziemlich schlechte Auflösung.

Wenn man die Messzeit bei kleinen Frequenzen relativ klein halten will , macht man eine Periodendauer- Messung. Zeit zwischen zwei Flanken messen und daraus die Frequenz berechen.

Zudem solltest Du die in der ISR verwendeten Variablen als volatile deklarieren und bei der Übergabe der Messwerte dann ATOMIC_BLOCK(ATOMIC_RESTORESTATE) verwenden falls Dir der Intrrupt dazwischen funken kann.

Heinz

Hallo Heinz

Danke für deine Antwort. Das ist mir zum jetzigen Zeitpunkt gerade noch etwas viel fachchinesisch.

Ich möchte eine "realtime" drehzahlmessung mit anzeige auf Display. die 500ms ist die refreszeit vom ganzen Loop. Also refresh auf dem Display. ist der loop schneller, flackert das display unleserlich, ist er langsahmer, hat das system eine zu langsahme reaktionszeit. vielleicht habe ich das falsch ausgedrückt. Die messung funktioniert soweit mit dem eingefügten skript, jedoch eben nur mit einem sensor. weiteres kann ich erst später sagen wenn ich wieder zuhause in der bastelstube sitze :slight_smile:

Die drehzahlen an der Welle welche ich messen will sind 0-20000U/min. ob das mit dem genannten sensor überhaupt geht konnte ich leider nicht herausfinden.

Hallo,
ich befürchte Du hast den Sketch nicht ganz verstanden. Frequenz messen in realtime geht nicht.

schau mal hier

WIKI

Heinz

Hallo Heinz

So wie ich das verstanden habe messe ich nicht direkt die Frequenz einer elektrischen spannung (wie im Wiki beschrieben) sondern eher ein Impuls welcher vom sensor ausgegeben wird. 0V = negativ Puls, 5V = Positiver Puls.
Also anzahl impulse in einer gewissen "messzeit" umgerechnet auf minuten ergibt drehzahl.
erhöhe ich die messzeit muss die umrechnung auch angepasst werden.
Es kann schon gut sein das ich mir das falsch vorstelle, liegt aber daran das mein hintergrundwissen nicht so gross ist. Hat der Ardunio eine integrierte "clock" welche zur berechnung von Pulsen etc. verwendet werden kann ?

Ich stelle mir das vor.

Loop Start

1:Arduino empfängt impulse von einem gewissen eingang und zählt diese für 500ms. Die Messzeit entnimmt er von der im arduino integrierten clock als referenz wie lange das ist.

2:er zählt z.b. 100 Pulse. rechnet diese auf die Minute aus und erhält dann die pulse pro minute was dann den RPM entsprechen würde. in diesem fall 100 x 120 = 12000 rpm.

3:Dies wird auf dem Display dargestellt

Loop Ende

so meine abstrakten gedanken

hardware3718:
so meine abstrakten gedanken

Naja, ist schon fast so.
Nicht Du sondern die vom Rest losgelöste Serviceroutine zählt fortlaufend die Impulse auf dem PIN INT0/1.

Im loop schaust Du in regelmässigen Abständen - z.B. alle 500ms - wieviele Impulse seit der letzten Lesung eingetroffen sind und errechnest daraus Deine UPM / Kmh
Dann den Zähler löschen. Los gehts von vorn.

Interrupt zähleroutine
pulsZaehler++
Ende

Loop Start
wenn millis()-letzteAuswertezeit>500 dann
verarbeite pulsZaehler
lösche Zaehlerstand

2:er zählt z.b. 100 Pulse. rechnet diese auf die Minute aus und erhält dann die pulse pro minute was dann den RPM entsprechen würde. in diesem fall 100 x 120 = 12000 rpm.

3:Dies wird auf dem Display dargestellt

Loop Ende

Du kannst auch die Impulslänge messen. Und aus der Länge des Impulses errechnen wie viele Impulse in die Zeit passen.

(deleted)

Hallo Peter

Genau wie dein Grossvater gesagt hatte bin ich nun zum ersten ziel meines Projektes gekommen :smiley:
Danke an Peter und auch my_xy_project für die hilfe über die hürde wie ich den 2ten Interrupt einbinden kann.
(zuerst musste ich mal herausfinden was das genau ist ;))

Habe dann den Code angepasst und aus den paar fehlern beim compilieren so mir das ganze zusammen gereimt das es nun funktioniert. klappt mit distanzmessungs modul und auch mit der lichtschranke.

Hier meine Lösung:

#include <LiquidCrystal_I2C.h>          //i2c library file
LiquidCrystal_I2C lcd(0x27, 16, 2);     // set the LCD address to 0x27 for a 16 chars and 2 line display

float value = 0;
float rev = 0;
float rev1 = 0;
int oldtime = 0;
int rpm1 = 0;
int rpm2 = 0;
int time;

void isr()                                //interrupt service routine Pin2
{
  rev++;
}
void isr1()                               //interrupt service routine Pin3
{
  rev1++;
}
void setup()
{
  lcd.init();                            // initialize the lcd
  lcd.backlight();
  attachInterrupt(0, isr, RISING);      //attaching the interrupt on Pin2
  attachInterrupt(1, isr1, RISING);     // attach next interrupt on Pin3

  lcd.setCursor(0, 0);
  lcd.print("Dual");
  lcd.setCursor(0, 1);
  lcd.print("RPM Display");
  delay(3000);
}

void loop()
{
  delay(500);
  detachInterrupt(0);                 //detaches the interrupt on Pin2
  detachInterrupt(1);                 //detaches the interrupt on Pin3
  time = millis() - oldtime;          //finds the time
  rpm1 = (rev / time) * 60000;        //calculates rpm1
  rpm2 = (rev1 / time) * 60000;       //calculates rpm2
  oldtime = millis();                 //saves the current time
  rev = 0;
  rev1 = 0;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Mot 1: ");
  lcd.setCursor(7, 0);
  lcd.print(rpm1);
  attachInterrupt(0, isr, RISING);
  lcd.setCursor(13, 0);
  lcd.print("RPM");
  lcd.print("   ");
  lcd.setCursor(0, 1);
  lcd.print("Mot 2:");
  lcd.setCursor(7, 1);
  lcd.print(rpm2);
  attachInterrupt (1, isr1, RISING);
  lcd.setCursor(13, 1);
  lcd.print("RPM");
  lcd.print("   ");

}

voll cool !! die ausgelesenen rpm's stimmen jedoch glaub ich noch nicht genau. evtl muss ich bei der umrechnung noch was anpassen. aber sonst, voll cool !!

bei der ganzen EVA projektaufstellung bin ich drann, aber leider gestern nicht sehr weit gekommen. mit meinem kleinen 4 jährigen sohn dann doch im bett eingepennt 8) naja... manchmal braucht auch dieser prozessor eine pause hehehehe

1 Like

hardware3718:

float value = 0;

float rev = 0;
float rev1 = 0;
int oldtime = 0;
int rpm1 = 0;
int rpm2 = 0;
int time;




voll cool !! die ausgelesenen rpm's stimmen jedoch glaub ich noch nicht genau. evtl muss ich bei der umrechnung noch was anpassen. aber sonst, voll cool !!

Die Initialisierng des Wertebereiches der Variablen wird durch die Berechnung überschritten.
Und float ist ganz schlecht...

long value = 0;
long rev = 0;
long rev1 = 0;
unsigned long oldtime = 0;
long rpm1 = 0;
long rpm2 = 0;
unsigned long time;

und die ISR musst Du so schnell wie möglich wieder einschalten - da unten ist es eindeutig zu spät.
Das delay() ist Gift. Ersetze es durch:

if (millis()-lastmillis>500)
{
lastmillis=millis();

wobei Du lastmillis noch als unsigned long initialisieren musst.
und und noch eine zusätzliche schliessende Klammer....

so.... ich habe mir nun etwas übersicht verschaft und anhand von beispielen mir etwas zusammen gereimt.
den code muss ich noch etwas aufräumen aber das Grundkonstrukt passt.

Die Eingänge habe ich definiert und alles angeschlossen. anhand eines schema zeichnungs tools habe ich das zusammen gebastelt :smiley:

Die verarbeitung bin ich noch am definieren

Die einzelnen sensoren und ausgaben kann ich jedoch mit einem testprogramm schon testen 8)

verbaut sind nun 2x temp sensoren (1820) 2x distanzsensoren, 6x LED (je 2 grün orange rot), 1x 4CH Relays, 1x 1602 Display angeschlossen über I2C

Ich musste auch von einem UNO auf einen MEGA tauschen da die Pins ausgegangen waren...

hardware3718:
so.... ich habe mir nun etwas übersicht verschaft und anhand von beispielen mir etwas zusammen gereimt.

Ich musste auch von einem UNO auf einen MEGA tauschen da die Pins ausgegangen waren...

Da Du sowieso I2C benutzt, hättest auch nen Einzel PCF 8574 drauf pappen können. (den gibts auch in 16 I/O...)

Na dann räum mal auf und zeig wie das insgesamt aussieht.