Arduino Uno Frequenz messen + gleichzeit PWM Signal senden

Hallo Zusammen,

ich habe momentan ein Programmierproblem…

Ich möchte mit einem Arduino UNO die Frequenz einer Gabellichtschranke, welche etwa maximal 40 Herz misst, messen und gleichzeitig soll an Pin 9 ein PWM Signal anliegen welches konstant gesendet werden soll.

Der Code um die Frequenz zu messen und das PWM Signal zu senden ist bereits vorhanden und funktioniert allerdings nur einzeln… Sobald ich die beiden Teile zusammenfüge wird zwar noch ein PWM Signal gesendet allerdings ist es sehr abgeschwächt weil der Arduino jetzt noch parallel mit der Frequenzmessung beschäftigt ist…

Hat jemand einen Lösungsvorschlag wie ich beides in den Sketch einfügen kann ohne dass sie diese beiden Aktivitäten im Weg stehen??

// String - Version: Latest 
#include <WString.h>
#include <SoftwareSerial.h>
#include<TimeLib.h>
#include <FreqCount.h>


SoftwareSerial SerialHM(2, 3); // RX, TX
// Connect HM10 Arduino Uno
// TXD Pin 2
// RXD Pin 3


int inpin_FR = 8;
int outpin_PWM = 9;
int high_pwm;

unsigned long T;
double f;
unsigned long k;
double fsum;
long int frq;
int d;
int c;
int counter;


void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
  // If the baudrate of the HM-10 module has been updated,
  // you may need to change 9600 by another value
  // Once you have found the correct baudrate,
  // you can update it using AT+BAUDx command 
  // e.g. AT+BAUD0 for 9600 bauds
pinMode (inpin_FR, INPUT_PULLUP);  
pinMode (outpin_PWM, OUTPUT);
SerialHM.begin(9600);
high_pwm=5;
counter=0;
}

void loop() {

  sende_PWM(high_pwm);

  T = pulseIn(inpin_FR, HIGH) + pulseIn(inpin_FR, LOW);
  if (T==0) {
      Serial.println("Timeout.");
    }
  else {
    f=1/(double)T;        // f=1/T   
    k++;    
    } 
  fsum+=f*1e6;
  if(counter == 8 ){ // ungefähr 1 Sekunde mitteln
  f = fsum/k*0.9925;
  SerialHM.println(f, 0);
  fsum=0.0;
  k=0;
  counter=0;
  }

  //Arduino an Bluetooth
  if (Serial.available()>0) {
      c = Serial.read();
      SerialHM.println(c, DEC);
  }

  //Bluetooth über Arduino an Monitor
  if (SerialHM.available()>0){
    d = SerialHM.read();
    if(d != 0)
    {
      //PWM Signal wird auf den aktuellen Wert gesetzt (1-100)
      high_pwm = d;
      //sende_PWM(d);
      Serial.println(high_pwm);
    }
  }
  counter++;
}


//Funktion zum ständigen Senden des PWM Signals
void sende_PWM(int new_high_pwm)
{
  int low_pwm;
  digitalWrite(outpin_PWM, HIGH);
  delayMicroseconds(new_high_pwm);
  low_pwm = 100-new_high_pwm;
  digitalWrite(outpin_PWM, LOW);
  delayMicroseconds(low_pwm);
}

Hi

40Hz kannst Du doch einfachst pollen (immer wieder abfragen).
40Hz wäre, bei symetrischem Signal, 12,5ms HIGH und 12,5ms LOW.
Der Arduino sollte in dieser Zeit einige tausend Mal den Input-Pin abfragen können und somit auf die Frequenz schließen.
Da eine Auflösung von 12,5 (also 12 oder 13)ms etwas grob sein könnte, kannst Du statt mit millis() (Systemuhr, Milisekunden seit Systemstart, Überlauf nach 49,x Tagen) mit micros() nutzen, Welche Dir eine 250-fache Auflösung ermöglichen (micros() springt in 4er Schritten, deshalb keine 1000-fache Auflösung).

So 'schaust' Du, bis der Pin HIGH ist, merkst Dir die micros(), schaust, bis der Pin LOW ist, merkst Dir die micros().
Jetzt hast Du die Zeit des HIGH-Impuls.
Bei symmetrischem Signal kannst Du jetzt aus der vergangenen Zeit auf die Frequenz schließen.
Wenn HIGH und LOW-Zeiten differieren, kannst Du noch zusätzlich auf das nächste HIGH warten, um eine komplette Periode auszumessen.
Die Rechnung bleibt (bis auf ein x2, da Du jetzt die ganze Periodenlänge und nicht nur einen Impuls hast).

micros() läuft nach einer guten Stunde über, wie Du mit dem Überlauf umgehst, sollte sich bei millis() finden lassen.

MfG

Hallo,

vielen Dank für deine schnelle Antwort!!

Entweder ich verstehe deine Antwort nicht korrekt oder ich habe mich schlecht ausgedrückt.

Das PWM-Signal muss konstant mit der gleichen Frequenz gesendet werden (etwa 10Hz).
Parallel dazu muss der Arduino an Pin 8 die Frequenz der Gabellichtschranke messen und ausgeben.
Die Frequenz der Gabellichtschranke variiert, das heißt sie kann von 1 bis etwa maximal 40 Herz gehen.
Mein Pin 8 zu Frequnzmessung reagiert nur auf eine wirklich sehr kurzen Impuls.. (also kein symmetrisches Signal)

Das Messen der Frequenz funktioniert mit dem Code aber das PWM-Signal wird nicht mehr richtig ausgegeben..

Danke

MfG

Hi

In wie fern muß die Lichtschranke gemessen UND ausgegeben werden?

Das PWM-Signal macht der µC von alleine, Das läuft in Hardware.

Somit hast Du 'alle Zeit der Welt', um die Lichtschranke auszulesen.
Wenn ich Deinen Code recht verstehe, wird der PWM-Wert eh nur über BT angepasst, ist also von der Messung abgelöst.
Oha - Du sendest das PWM-Signal selber in Software - DAS ist natürlich - äh - unglücklich.
Sorry, ging davon aus, daß Du das PWM-Signal von der PWM-Hardware vom µC generieren lässt - oder klöppelst Du Dir Morgens auch erst ein Vehikel zusammen, bevor Du Dein Auto anschaust?

Klar, wenn Du die ganze Zeit dafür brauchst, um Dein PWM-Signal abzuwarten (Das ginge auch nicht-blockierend per millis()/micros() ) und hast somit Aussetzer, wenn Du per PulsIn auf den externen Impuls der Lichtschranke wartest.

Versuche, Dein Programm so umzustrukturieren, daß in JEDEM Durchgang überprüft wird, ob der PWM 'umgeschaltet' werden muß - wenn nicht, dann eben nicht!

Schaue Dir dazu das Beispiel in der IDE 'blink_without_delay' an - Das greift auf millis() zurück und blockiert so den µC nicht - macht halt auch Nichts, außer im Kreis rennen, wenn Nichts gemacht werden soll.

Es hat sich als äußerst hilfreich erwiesen, den Programmablauf 'auf Papier' zu bringen, also, WAS, WANN gemacht werden muß.

Der Nachtwächter Klick zeigt Dir, wie mit millis() an die Sache heran gegangen wird.

MfG

PulseIn blockiert bis die Messung abgeschlossen ist.

Hier wäre wohl eine Interrupt-Lösung vorzuziehen.

Gruß Tommy

Hallo,

Für die Frequenzmessung gibts eine Lib. Schau dir das einmal in Ruhe an.
https://www.pjrc.com/teensy/td_libs_FreqMeasure.html
Messpin ist Pin 8.

Bei deiner Takterzeugung vertehe ich fast nichts.
Möchtest du einen konstanten Takt ausgeben mit 10Hz?
Soll der PWM Takt 10 Hz sein und du veränderst dessen Pulsweite?
Nur egal was, deine 100µs Periodendauer aus dem Sketch ergeben keine 10Hz. Das sind 10kHz.
Irgendwas passt da noch nicht. Wenn die Aufgabe klar ist programmieren wir einen Timer.
Hier wäre dann gut wenn Pin 3 oder 11 frei wären.

Hallo Zusammen,

erstmal viele Dank für die sehr hilfreichen Tipps!!

Ich konnte es mithilfe der Millis() lösen und kann somit ein konstantes PWM-Signal erzeugen.
Die Frequenzmessung habe ich mit der Bibliothek "FrequMeasure" gelöst und bekomme auch korrekte Werte.
Jetzt funktionieren diese beiden Prozesse parallel und stehen sich gegenseitig nicht mehr im Weg!!

Ich danke euch vielmals!!

Grüße

Felix

Hi

Wenn Du so frei wärst, Deinen Sketch mit Deinen Lösungen, hier für die Nachwelt preis zu geben?

Egal ob, schön, daß Du Das lösen konntest!

MfG