Problem mit pulseIn()

Hey Leute,
für ein Sensorsystem zur Drehzahlmessung über zwei Gabellichtschranken (s. Anhang) nutze ich einen Arduino UNO zur Auswertung der Lichtpulse (inkrementale Messung über Indexscheibe, s. Anhang) und Umrechnung in RPM. Wenn ich die Sensoren einzeln nutze funktioniert alles fehlerfrei. Beginne ich jedoch beiden Sensoren einen INput zu geben, so kriege ich regelmäßig über einen der beiden Sensorinputs deutlich zu kurze Pulse, so als ob die Messung abbrechen würde, obwohl die Messungen sequentiell stattfinden...

Ich habe es mit delay() probiert und weit auseinanderliegende Inputs (DI13 und DI8) genutzt, um eventuelle Störsignale auszuschließen. Mein Ziel ist, die Drehzahlen sequentiell auszuwerten, was doch auch kein Problem mit einer chronologischen Abarbeitung von pulseIn() darstellen sollte oder nicht?

Hier der Code (Die auskommentierten Sektionen sind Funktionen, die ich später noch erweitern möchte, momentan aber noch nicht greifen):

//LCD
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 3); //Adressierung des I2C-Moduls und Angabe der Zeichen- und Zeilenanzahl

byte counter_in = 4;                //Digital-Input für Tastersignal
unsigned long pulse = 0;            //Puls-Auswerung des Tasters 
byte counter = 0;                   //Zähler
boolean start_bildschirm = true;    //Boolean-Variable für einmalige Anzeige des Start-Bildschirms beim Programmstart 


//Auswertung
/*
***1 --> Auger LH
***2 --> Auger RH
 */

int pulse_in1 = 8;               //Spannungsabgriff U2 vom OPV (Nichtinvertierende Verstärkung mit Photodiode und Laser)
int pulse_in2 = 13;           
unsigned long zahn1;              //Pulslänge dunkel in Mikrosekunden: Auger LH 
unsigned long zahn2;          
unsigned long luecke1;                          //Pulslänge hell in Mikrosekunden
unsigned long luecke2;        
unsigned long totalTime1;               //Summe Pulslängen (über jeweils 60 Messungen)
unsigned long totalTime2; 
unsigned int rpm1;                                   //Berechnete RPM für Mittlere Drehzahl                      
unsigned int rpm2;               


//SPANNUNGSAUSGABE FÜR ADVANTECH-MODUL

int pwm1 = 5;
int pwm2 = 6;
int ocr1;        //Output-Compare-Register Value for Duty-Cycle (8-Bit)
int ocr2;

void setup() {
  // put your setup code here, to run once:

  //LCD
  Serial.begin(9600);
  pinMode(counter_in, INPUT);
  lcd.begin();
  lcd.backlight();


  //Auswertung
  pinMode(pulse_in1, INPUT);                  //Pins für Pulsauswertung und PWM-Output festlegen
  pinMode(pwm1, OUTPUT);

  pinMode(pulse_in2, INPUT);                  
  pinMode(pwm2, OUTPUT);
 
}

void loop() {
  // put your main code here, to run repeatedly:

  if(start_bildschirm == true)        //Überprüfung der boolean-Variable "start_bildschirm"
  {
  lcd.setCursor(0, 1);
  lcd.print("PROSIT-KALIBRIERUNG"); 
  delay(3000);                        //3-sekündige Verzögerung
  lcd.clear();                        //Start-Bildschirm löschen
  start_bildschirm = false;           //if Abfrage für Start-Bildschirm über boolean-Variable sperren  
  }
  /*
  pulse = pulseIn(counter_in, HIGH);
  if(pulse != 0)                      //Implementierung eines Zählers für Tastauswahl der Kalibrierungs-Messung
  {
  counter++;
  lcd.clear();
  Serial.println(counter);
  Serial.println(pulse);
  delay(500);
  }
  
  
  if(counter == 5)                    //Reset des Counters bei 5, da fünf verschiedene Messungen zur Auswahl stehen (1. Auger LH/RH; 2. Tamper; 3. Vibration; 4. FAN Speed; 5. Fumes)
  {
  
    counter = 0;
    Serial.println(counter);
  }
   
  if(counter == 0)                    //If-Else Abfrage für Auswahl der Messung über den Counter         
  {
   */
    //Auswertung
    
  
                                  
    luecke1 = pulseIn(pulse_in1, HIGH, 2000000);
    
    totalTime1  = 2* luecke1;                      //Summe der 120 Einzelmesswerte bilden
    rpm1 = (unsigned int)((1/(totalTime1/pow(10,6)))+0.5);                               //RPM aus Summe berechnen


    luecke2 = pulseIn(pulse_in2, HIGH, 2000000);

    totalTime2 = 2* luecke2;                       //Drehzahlauswertung Auger RH               
    rpm2 = (unsigned int)((1/(totalTime2/pow(10,6)))+0.5); 

  if((((rpm1 < 150 && rpm1  >= 0 &&luecke1 > 1000)  && (rpm1/rpm2 < 1.5) ||  ((int)rpm1 == 0)) && (rpm2 < 150 && rpm2  >= 0 && luecke2 > 1000)  && (rpm2/rpm1 < 1.5) ||  (int)rpm2 == 0)) //Bei RPM = 150 beträgt Puls (min) = 3,333 ms
  {
  
    //Auger LH
    
    lcd.setCursor(10, 1);
    lcd.print("       ");
    
    
    //SPANNUNGSAUSGABE FÜR ADVANTECH-MODUL
    ocr1 = map(rpm1, 0, 117, 0, 103);                                   //OCR-Wert für Duty-Cycle PWM auf Drehzahlbereich der Schnecke mappen; ANGEPASST AUF 1,34V bei 42 RPM
    analogWrite(pwm1, ocr1);                                           //PWM-Output --> Siebschaltung --> Spannungsverdopplung --> Advantech-Modul --> Drehzahlanzeige Prosit
    

    //LCD
    lcd.setCursor(0, 1);
    lcd.print("Auger-LH: ");
    lcd.setCursor(13, 1);
    lcd.print((int)(rpm1+0.5));
    lcd.setCursor(17, 1);
    lcd.print("RPM");


    //Auger RH
    lcd.setCursor(10, 2);
    lcd.print("       ");
    
    
    //SPANNUNGSAUSGABE FÜR ADVANTECH-MODUL
    ocr2 = map(rpm2, 0, 117, 0, 103);                                  
    analogWrite(pwm2, ocr2);  
    

    //LCD
    lcd.setCursor(0, 2);
    lcd.print("Auger-RH: ");
    lcd.setCursor(13, 2);
    lcd.print((int)(rpm2+0.5));
    lcd.setCursor(17, 2);
    lcd.print("RPM");


    //SERIELLER MONITOR
    Serial.println((String)"Auger LH:" + rpm1 + " RPM; luecke1 = " + luecke1 + "\t Auger RH:" + rpm2 + " RPM; luecke2 = " + luecke2);
    Serial.println();
    
    }

    else
     {
      Serial.println();
      Serial.println("ERROR");
      Serial.println((String)"Auger LH:" + rpm1 + " RPM; zahn1 = " + zahn1 + "; luecke1 = " + luecke1 + "\t Auger RH:" + rpm2 + " RPM; zahn2 = " + zahn2 + "; luecke2 = " + luecke2);
      Serial.println();
      Serial.println(); 
     }

}
      
 /*
    else 
    {
      analogWrite(pwm1, 0);              //PWM-Output Reset (0V)
      analogWrite(pwm2, 0); 
      Serial.println("0 RPM");  

      //LCD
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print((String)"Auger-LH: 0 RPM" );
  
      lcd.setCursor(0, 2);
      lcd.print((String)"Auger-RH: 0 RPM");
      
    }  

  }
  
  else if(counter == 1)
  {
    lcd.setCursor(0, 1);
    lcd.print("Tamper: 500 RPM");
  }
  else if(counter == 2)
  {
    lcd.setCursor(0, 1);
    lcd.print("Vibration: 430 RPM");
  }
  else if(counter == 3)
  {
    lcd.setCursor(0, 1);
    lcd.print("FAN Speed: 600 RPM");
  }
  else if(counter == 4)
  {
    lcd.setCursor(0, 1);
    lcd.print("Fumes: 350 RPM");
  }

Grüße :slight_smile:

Ihr Beitrag wurde an seinen aktuellen Speicherort verschoben, da er besser geeignet ist.

Dein Code ist anscheinend unvollständig und auch nicht lesbar.

editiere bitte Deinen Post und füge dort den Code vollständig ein.
Variante 1: in der IDE unter bearbeiten - für Forum kopieren - und dann einfügen
Variante 2: Code mit STRG-A alles markieren und STRG-C kopieren und dann in Deinem Post oben auf den Button </> drücken und STRG-V drücken.
Fertig.

Danke dir,
der Rest des Codes arbeitet nur noch mit dem Drehzahlwert, hat aber mit der Pulsauswertung direkt nichts mehr zu tun.

Ich verstehe, das man selber den für in seinen Augen unnötigen Code weg lässt. Aber wenn explizit danach gefragt wird, sollte man ihn schon liefern.

Untestbarer Code ist untestbar.
Die Emotionale Folge:
Die überwältigende Empfindung, dass der Fragesteller überhaupt nicht möchte, dass man seinen Code testet.

Klarer:
Es ist gut und richtig, den Code soweit zu reduzieren, dass er nur noch das Problem zeigt.
Es ist falsch den Code bis zu untestbarkeit zu verstümmeln.

Das ist ein berechtigter Einwand, der Code ist hochgeladen! :slight_smile:

Da gibt es Erklärungsbedarf.
Dein Display hat nur 3 Zeilen? :wink:
Deine Variable start_Bildschirm ist überflüssig. Den Teil, den Du damit verarbeiten willst, gehört ans Ende von setup().

Deine Pin betreibst Du als INPUT.
Hast Du da genügend Beschaltung dran, das die auch sauber ein Signal bekommen?

Gibt es das Display als 20, 3 Display?? Ich kenne nur 20, 4 oder 16, 2

Ich nutze nur die ersten drei und die Ansteuerung funktioniert so auch :slight_smile:

Guter Einwand... Was genau meinst du mit genügend Beschaltung? Mein LOW-Pegel (also Unterbrechung des Lasers) gibt einen Input von ca. 0.83V. Wird die Photodiode durch Lichteinstrahlung niederohmig, so geht mein OPV (LM324 N) in die Übersteuerung und gibt (Betriebsspannung 5V) ca. 4,5V als Input. Entsprechend der Pin-Levels (U>3.0V --> HIGH; U<1.5V --> LOW) habe ich da doch mehr als geügend Luft oder nicht?

Nicht unbedingt. Die Ladung muss auch schnell genug aufgebraucht wreden.
Nimm mal einen R zwischen PIN und GND. Ich würde um 10K anfangen und mal sehen was passiert.

Haste nen Schaltplan?

Aber separat funktionieren die Sensoren doch problemlos. Das Problem kann dementsrechend doch nicht an den separaten Schaltungen liegen?

Ich werde das aber probieren :+1:

Hallo,
ich weiß nicht ob das schon angesprochen wurde, aber pulseIn wartet auf den Wechel des Pegels. Wenn Du zwei Frequenzen messen willst wird das also nicht klappen.

Heinz

Wieso sollte das nicht klappen. Ich messe erst über DI13 eine Pulsdauer und speichere sie in einer Variable. Danach wird der nächste pulseIn() Aufruf abgearbeit, auf den nächsten Pegelwechsel gewartet und ab da die Pulslänge für die zweite Variable gemessen. Sequentiell und nicht parallel versteht sich.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.