PWM Frequenz verdoppelt ausgeben

Hallo,

ich lese über Pin 3 einnen Impuls ein, der von einem NE555 generier wird.

Ich würde jetzt gerne an Pin 9 pro eingelesenen Impuls an Pin 3 zwei Impulse ausgeben (verdoppeln)!

Ich habe mich an der PWM Library von runnerup versucht!

http://forum.arduino.cc/index.php/topic,117425.0.html

#include 
#include  

int tachOut = 9; 
int32_t frequency; //frequency (in Hz)
const byte tachInterrupt = 1; // tach signal on interrupt 1 (digital pin 3)
byte engineCylinders = 2; // for tach calculation 

int RPMpulses = 0;

void setup()
{

  //initialize all timers except for 0, to save time keeping functions
  InitTimersSafe(); 

  pinMode(tachInterrupt, INPUT_PULLUP); // enable internal pullup for tach pin
  attachInterrupt(tachInterrupt, countRPM, FALLING);

}

void countRPM()
{
  RPMpulses++;
}

void loop()
{
  RPMpulses = 0;
 if (RPMpulses == 1);
 {
  frequency = RPMpulses*engineCylinders;
  SetPinFrequency(tachOut, frequency);
  pwmWrite(tachOut, 125);
  }
}

Hallo,

ist etwas unklar formuliert.

Generiert der NE555 nur manchmal Impulse oder ständig? Sind das wirklich Impulse oder Rechtecksignale? Ich glaube das wird per µC unnötig kompliziert. Denn du müßtest ja erstmal wissen mit welcher Frequenz kommen die Impulse/Signale und wieviele sind das. Goggle mal nach "Frequenzverdoppler" Schaltungen. Ich denke das ist einfacher.

Hallo Doc_Arduino,

Der NE555 generiert ständig Rechtecksignale.

Aber es kann doch nicht so schwer sein bei eins rein -> zwei auszugeben.

Meine max Frequenz wird nicht höher als 400Hz.

petemanzel: Aber es kann doch nicht so schwer sein bei eins rein -> zwei auszugeben.

Hallo, das versteh ich grad nicht. Wenn es nicht so schwer ist, wieso bekommst du es nicht hin ?

Aber in der tat, es ist mit dem 74HC4046 wirklich einfach. Da brauchst du keinen Arduino. Das ist ein PLL-IC und damit kannst du es sicher leicht hinbekommen.

Hallo,

also den einen Satz hätte ich mir jetzt auch verkniffen. :)

Mit meinen Kenntnissen sage ich mal das es mit µC nicht möglich ist, bei unbekannten Signal mal einfach so die Frequenz zu verdoppeln. Das Prinzip der kleinen Elektronikschaltungen mit Kondensator beruht ja darauf auf halben Wege der steigenden und fallenden Flanke schon eine Umschaltung zu erzeugen am Logikgatter. Beim µC nicht möglich. Man kann nur die fallende oder steigende Flanke erkennen oder den Low oder High Pegel am Pin. Den halben Pegel erkennen gibts nicht. Wenn man auf die Flanken triggert und einen Pin umschalten läßt, hat man am Ausgang eine 1:1 Frequenz.

Man kann nur tricksen wenn die eingehende Frequenz konstant und bekannt ist. Dann kann man einen Timer vorbereiten und bei Bedarf ein- und ausschalten. Am Pinausgang taktet dann die voreingestellte Frequenz.

Oder man vermisst die eingehende Frequenz mit mehr Aufwand, errechnet die benötigten Timereinstellungen, stellt den Timer neu ein läßt dann einen Pin takten. Ist immer miminal verzögert.

Im Moment fällt mir da nichts besseres ein.

Ob das den Aufwand wert ist statt einer kleinen IC Schaltung mußt du wissen.

Entschuldigung wenn das nicht so einfach wie gedacht ist. Zumindestens bei mir. ;)

Entschuldigt bitte alle!

Ich wollte damit natürlich niemandem unterstellen, nicht hilfsbereit zu sein, mein Problem zu lösen.

Das war mehr ein Schrei in denn Himmel.

ICH BIN IMMER DANKBAR FÜR JEDEN BEITRAG!

Kann man denn nicht aus der steigenden und der fallenden Flanke ein neues Signal generieren?

Hallo,

alles gut, keine Sorge, wir wissen wie du das meinstest. :)

Naja, wie oben schon geschrieben. Du erkennst eine Zustandsänderung und schaltest einen Pin um. Dann haste nichts gekonnt. Außen ändert sich genaue ein Zustand und im Programm ändert sich genau ein Zustand. Alles weitere ist mehr Aufwand. Wie oben geschrieben. Haste das gelesen? Nachvollziehbar?

Okay, vielleicht doch eine eingeschränkte Idee ... Es gibt nur eine Bedingung, wenn die Frequenz bekannt und konstant ist, dann kann man auf Grund der erkannten Flanke einen Pin schalten und verzögert wieder umschalten innerhalb der Zeit bis sich das äußere Signal wieder ändert. Dann könnte man die Frequenz verdoppeln. Nur muß dazu die anliegende Frequenz bekannt und konstant sein wie gesagt.

petemanzel: Kann man denn nicht aus der steigenden und der fallenden Flanke ein neues Signal generieren?

OK, OK...

Aber warum willst du das so umständlich machen ? Sieh dir mal den 4046 an und lies dich da ein wenig ein. Der ist für solche Sachen gebaut.

Naja, wenns unbedingt der Arduino sein muss geht das mit steigender und fallender Flanke schon.

Passt sich aber nicht unendlich an und hat einige unschöne Nachteile.

Du musst deine Maximalfrequenz planen, du sagtest 400Hz, heist also 2,5ms. Von steigender bis fallender Flanke also nur 1,25ms. Folglich muss dein Ausgang vor dieser Zeit wieder umgeschaltet werden

Steigender Flanke -> Ausgang High für 1ms -> Ausgang Low Fallende Flanke...selbes Spiel.

Nun hat der 555 aber nicht immer ein 50:50 Verhältniss von Impuls zu Pause. Das kann sich verschieben und dann bekommst du eben keine 2 Impulse mehr, weil der Ausgang noch High ist wenn schon die Fallende Flanke kommt. Du bist also gezwungen die Impulszeit weiter zu verkürzen, auf 500µs oder weniger. Was dann aber bei 50Hz Taktfrequenz extrem schlechtes Impuls/Pauseverhältniss ergibt(0,5ms/10ms).

Ja, man kann das machen, aber jeder der etwas Ahnung von Elektronik hat wird es vermeiden. Allenfalls als Proof of Concept (also probieren obs überhaupt geht) taugt das und zum lernen. Reale Anwendungen dann lieber mit dem oben genannten Baustein basteln.

Hallo,

genau das hatte ich erwähnt, vielleicht zu kurz gefasst. Man müßte aller 1/4 der Eingangsperiodendauer einen Pin umschalten.

Aber mal eine andere Frage an den TO. Was machst du mit dem NE555 Taktgenerator sonst noch? Außer damit dem Arduino zu befeuern.

Hallo,

parallel dazu hatte ich schon versucht die reine Machbarkeitsstudio zu tippen. Ohne nähere Angaben wofür der NE555 sonst noch da ist, ist das zugegebenermaßen etwas sinnlos, sollte aber funktionieren. Theoretisch könnte die sich noch automatisch auf die Low und High Dauer einmessen und nachregeln, wenn die Änderungen langsam genug sind.

Ist ungetestet kompiliert jedoch fehlerfrei. Im Grunde genommen ist es eine Ablaufsteuerung.

/* Bedingung Frequenz ist konstant und bekannt
 * angenommen 400Hz liegen an,
 * dann beträgt die Periodendauer 2,5ms = 2500µs
 * davon 1/4 Periode 625µs
 */

unsigned long viertelPeriode = 625;   // 1/4 Periode [µs]
unsigned long last_micros;

const byte PIN_IN = 3;
const byte PIN_OUT = 4;

enum {ONE, TWO, THREE, FOUR}
Phase = ONE;

void setup() {
  pinMode (PIN_IN, INPUT_PULLUP);
  pinMode (PIN_OUT, OUTPUT);
}

void loop() {

   Frequenzverdoppler();
   
}  // end of loop


/* *** Funktionen *** */

void Frequenzverdoppler()
{

  if ( (digitalRead(PIN_IN) == LOW) && (Phase == ONE) ) {     // extern LOW erkannt
    last_micros = micros();             // Zeit merken
    digitalWrite(PIN_OUT,HIGH);         // Ausgang umschalten
    Phase = TWO;
  }   

  if ( (micros() - last_micros >= viertelPeriode) && (Phase == TWO) ) {  // wenn 1/4 Periode vorbei
    digitalWrite(PIN_OUT,LOW);                     // Ausgang umschalten
    Phase = THREE;
  }

  if ( (digitalRead(PIN_IN) == HIGH) && (Phase == THREE) ) {            // extern HIGH erkannt
    last_micros = micros();                       // Zeit merken
    digitalWrite(PIN_OUT,HIGH);                   // Ausgang umschalten
    Phase = FOUR;
  }   

  if ( (micros() - last_micros >= viertelPeriode) && (Phase == FOUR) ) { // wenn 1/4 Periode vorbei
    digitalWrite(PIN_OUT,LOW);                    // Ausgang umschalten
    Phase = ONE;
  }
}

Hallo,

habe das noch testen können, funktioniert tatsächlich. :) Dadurch das auf beide Signalpegel abgefragt wird, läuft das syncron zu den Pegeländerungen. Ca. 15µs sind die Signale verschoben zueinander. Bedingt durch einlesen, verarbeiten, ausgeben.

Mit 2Hz Eingangstakt zum nachverfolgen mit LED werden es dann 4Hz. Die 1/4 Periodendauer muß man von Hand setzen.

Nur was macht der NE555 sonst noch? Das wäre gut zu wissen.

/*
 * Doc_Arduino - german Arduino Forum
 * IDE 1.6.12
 * Arduino Mega2560
 * 07.10.2016
 *
 * Frequenzverdoppler
 *
 * Bedingung Frequenz ist konstant und bekannt
 * angenommen 2Hz liegen an,
 * dann beträgt die Periodendauer 500ms = 500.000µs
 * davon 1/4 Periode 125.000µs
 */

unsigned long viertelPeriode = 125000;   // 1/4 Periode [µs]
unsigned long last_micros;

const byte PIN_IN = 4;
const byte PIN_OUT = 13;

enum {ONE, TWO, THREE, FOUR}
Phase = ONE;

void setup() {
  pinMode (PIN_IN, INPUT_PULLUP);
  pinMode (PIN_OUT, OUTPUT);
}

void loop() {

   Frequenzverdoppler();
  
}  // end of loop


/* *** Funktionen *** */

void Frequenzverdoppler()
{

  if ( (digitalRead(PIN_IN) == LOW) && (Phase == ONE) ) {     // extern LOW erkannt
    last_micros = micros();             // Zeit merken
    digitalWrite(PIN_OUT,HIGH);         // Ausgang umschalten
    Phase = TWO;
  }  

  if ( (micros() - last_micros >= viertelPeriode) && (Phase == TWO) ) {  // wenn 1/4 Periode vorbei
    digitalWrite(PIN_OUT,LOW);                     // Ausgang umschalten
    Phase = THREE;
  }

  if ( (digitalRead(PIN_IN) == HIGH) && (Phase == THREE) ) {            // extern HIGH erkannt
    last_micros = micros();                       // Zeit merken
    digitalWrite(PIN_OUT,HIGH);                   // Ausgang umschalten
    Phase = FOUR;
  }  

  if ( (micros() - last_micros >= viertelPeriode) && (Phase == FOUR) ) { // wenn 1/4 Periode vorbei
    digitalWrite(PIN_OUT,LOW);                    // Ausgang umschalten
    Phase = ONE;
  }
}

Etwas klarzustellen. Ein PWM Signal hat eine feste Frequenz und einen variables H-L-Verhältnis. Also hat es gar nichts mit dem Frequenzverdoppeln zu tun.

Bevor wir hier weiterraten erzähl uns mal petemanzel was Du überhaupt machen willst.

Grüße Uwe

genau, der 555 kann beides, sowohl Frequenz ändern als auch Taktverhältniss. Und in der Überschrift steht ja was von PWM. Das ist dann mit Abstand messen zwischen zwei Impulsen noch schwerer zu managen.

Ihr geht davon aus, dass der Arduino die Frequenz verdoppeln soll.

Aber der Threadersteller will doch nur "pro eingelesenen Impuls an Pin 3 zwei Impulse ausgeben". bei max. 400Hz

also für mich bedeutet das: Eingangsflanke erkennen. 2 Impulse abfeuern (je 500µs?) fertig.

jetzt mal ganz böse programmiert:

void loop() {
  bool eingang = digitalRead(9);
  if (eingang && !lastEingang){ //positive Flanke
    digitalWrite(3,HIGH);
    delay(500);
    digitalWrite(3,LOW);
    delay(500);
    digitalWrite(3,HIGH);
    delay(500);
    digitalWrite(3,LOW);
  }
  lastEingang = eingang;
}

guntherb: Ihr geht davon aus, dass der Arduino die Frequenz verdoppeln soll.

So steht es jedenfalls in dem Thread-Titel des TO.

die klassische PWM- Funktionalität würd ich dafür nicht nutzen... wie schon von anderen angesprochen ist es sinnvoll die low- Zeit und die High- Zeit zu messen und einen Ausgang mit den halben Werten zu steuern...

Hallo,

hatte nachgefragt. Antwort in Post #2. Wir wissen doch das die Betreffzeile nicht immer mit dem zu tun hat was wirklich gemacht werden soll.

Hallo,

ich habe noch die automatische Frequenzanpassung eingebaut. Es wäre aber durchaus gut wenn der TO die offenen Fragen beantworten könnte. Dann könnte man noch gezielter helfen.

/*
 * Doc_Arduino - german Arduino Forum
 * IDE 1.6.12
 * Arduino Mega2560
 * 07.10.2016
 *
 * Frequenzverdoppler mit automatischer Frequenzanpassung
 *
 * 1/4 Periode wird mit jedem Signalwechsel neu berechnet
 */

unsigned long viertelPeriode = 50;   // pauschaler Startwert  [µs]
unsigned long last_micros1;
unsigned long last_micros2;

const byte PIN_IN = 4;
const byte PIN_OUT = 13;

enum {ONE, TWO, THREE, FOUR}
Phase = ONE;

void setup() {
  
  //Serial.begin(250000);
  
  pinMode (PIN_IN, INPUT_PULLUP);
  pinMode (PIN_OUT, OUTPUT);
}

void loop() {

   Frequenzverdoppler();
   
}  // end of loop


/* *** Funktionen *** */

void Frequenzverdoppler()
{

  if ( (Phase == ONE) && (digitalRead(PIN_IN) == LOW) ) {     // extern LOW erkannt
    last_micros1 = micros();             // Zeit merken
    digitalWrite(PIN_OUT,HIGH);         // Ausgang umschalten
    Phase = TWO;
  }  

  if ( (Phase == TWO) && (micros() - last_micros1 >= viertelPeriode) ) {   // wenn 1/4 Periode vorbei
    digitalWrite(PIN_OUT,LOW);                     // Ausgang umschalten
    Phase = THREE;
  }

  if ( (Phase == THREE) && (digitalRead(PIN_IN) == HIGH) ) {   // extern HIGH erkannt
    last_micros2 = micros();              // Zeit merken        
    viertelPeriode = (last_micros2-last_micros1) / 2;          // Frequenzanpassung   
    digitalWrite(PIN_OUT,HIGH);          // Ausgang umschalten
    Phase = FOUR;
    //Serial.println (viertelPeriode);     // Debug
  }  

  if ( (Phase == FOUR) && (micros() - last_micros2 >= viertelPeriode) ) {  // wenn 1/4 Periode vorbei
    digitalWrite(PIN_OUT,LOW);           // Ausgang umschalten
    Phase = ONE;
  }
}