Pages: [1]   Go Down
Author Topic: Aus RC Signal- Varriable Frequenz erzeugen !!!  (Read 903 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo liebe Arduino Freunde. Ich bin Neu in diesem Forum und möchte mal versuchen ein wenig weisheit auszutauschen.Habe seit 2 wochen einen arduino,und bi dahin keinen plan von programmierung.. aber ich wills wissen.....

Ich habe ein PWM Signal eines RC empfängers Eingelesen und werte von 0-etwa 500 erhalten (die Pulsweite). den Zahlenwert habe ich mit einen Tiefpass geglättet  und Mit einer Funktion auf 2048 Werte nichtlinear interpoliert.(range 0-500 entspricht also  range 1024-0-1024) Funktioniert spitze.....!

Jetzt Möchte ich gern aus diesen werten (2x 1024 werte(fürSteuerhebel nach Links und rechts bewegen)) ein varriable frequenz aus Rechteckimpulsen Generieren (für eine SchrittmotorenSteuerung die Takt und Richtungseingänge besitzt). also ich möchte eine maximale Frequenz von eta 15kHz erzeugen, die stufenlos bis null ruterregelbar ist. da ich noch ein zihmlicher anfänger bin hab ich keine Ahnung wie ich das machen könnte.
Ich habe mir überlegt das ich einen Timer (den es sicher giebt) jede Sekunde 15 000 mal unabhängig vom Hauptprogramm zählen. ist mein gemessener RC Wert zb. 1 löst der timer alle 49 999 "zählungen ein "PIN = HIGH" aus. bei den wert 1024 würde der timer dann jeden gezählten taht den Pin auf high setzten.
Ich glaube das ist nur mit interupts zu lösen, aber keinen dunst wie ich da zugreifen kann, ist mir noch zu hoch. und es soll ja auch nicht die performance meines Hauptprogrammes sosehr beinflussen. Mit einen DelayMicroseconds() oder so... Brems ich mir ja alles aus? wie stell ich den Presaler beim timer ein? werd aus der sache nicht schlau vieleicht hat ja ein findiger etwas Code für mich...

das ist das programm von mir was erstmal bis dahin gut funktioniert....Bitte Hilffeeeee++?

[


/////////////////////////////////initialisierungen daten zum PWM einlesen////////////////////////////////

int RCPin = 2;                                                               //Eingang rc signal
int Motor_drehrichtung = 13;                                                // LED Pin(Motor Drehrichtungssignal für SM steuerung
int timeX = 0;                                                             //Gelesener Zahlenwert des RC Signals
int timeX_old = 0;                                                        // im vorherigen Durchlauf gemessener Wert (time X)
int timeX_final = 0;                                                     // Fertiger ausgegebener Wert
int Zero_delay_timeLED = 250;                                           // Mittelstellung des RC Steuerhebels

long lastPulseX = 0;                                                  // die Zeit in Millisecunden des letzten Pulses
long mstime = 0;                                                     // Liest die zeit in Millisecunden
long hptime = 0;                                                    //  Liest die Zeit in Microsecunden

extern volatile unsigned long timer0_overflow_count;
unsigned long hpticks (void)
{
 return (timer0_overflow_count << smiley-cool + TCNT0;
}

/////////////////////////////////initialisierungen für die Nichtlineare Kurvenumsetztung der werte////////////////////////////////

#define SMOOTHSTEP( Xsmoth) (( Xsmoth) * ( Xsmoth) * (3 - 2 * ( Xsmoth)))
#define SMOOTHSTEP_plus( Xsmoth_plus) (( Xsmoth_plus) * ( Xsmoth_plus) * (3 - 2 * ( Xsmoth_plus)))

float TimeX_Min_Val_minus = 1024.0;            //Input Min Value ,hier wird die zu Interpolierende Range festgelegt
float TimeX_MAX_Val_minus = 0.0;              //Input Max Value, hier wird die zu Interpolierende Range festgelegt
float TimeX_Min_Val_plus = 0.0;              //Input Min Value ,hier wird die zu Interpolierende Range festgelegt
float TimeX_MAX_Val_plus = 1024.0;          //Input Max Value ,hier wird die zu Interpolierende Range festgelegt
float N = 250.0;  
float Nplus = 250.0;                      //Maximaler eingangswert
float v;                                 //smoothstep expression variable


float Xsmoth;   //final smoothstepped value
float Xsmoth_plus = (Xsmoth - 250);

/////////////////////////////////////

void setup() {
 Serial.begin(115200);                                      // Kommunikationsgeschwindigkeit Pc
 pinMode(RCPin, INPUT);                                    //R/C Pin als Input setzten
 pinMode(Motor_drehrichtung, OUTPUT);                     //LED simuliet Rückwärtslauf (pin High versteht Schrittmotorsteuerung als RW)
}
void loop() {

 if(millis() - lastPulseX >= 5)                               //Signal alle 5 Millisecunden auslesen
 {
   while(!digitalRead(RCPin) == HIGH)                         //Auf das Nächste RC Signal von RCPin Warten
   {
     continue;
   }
   mstime = millis();
   hptime = hpticks();                                        //wenn das Signal Ankommt, Beginn der Startzeit aufzeichnun
   while(!digitalRead(RCPin) == LOW){
     continue;
   }
   mstime = millis();
   timeX = (hpticks()) - hptime - 220;                       //Hier wird der unterschied zwischen start und endzeit ermittelt, Das Ergebnis ist das Rc Signal.

////////////////////////////////////////Tiefpassfilter zum glätten des gemessenen wertes///////////////////////////////////////////////

   timeX_final = (0.1 * timeX) + (0.9 * timeX_old);       //10 Prozent des Wertes des ersten Durchgangs, werden mit 90 Prozent des Wertes des 2. Durchganges addiert
  
  /////////////////////////////////// Wertebereich begrenzen////////////////////////////////////////////////////////////////////////////
if (timeX_final > 500)                                  
   {timeX_final = 500;}

if (timeX_final < 0)
   {timeX_final = 0;}
///////////////////////////////////////werte in CW und CCW übersetzen///////////////////////////////////////////////////////////////////
if (timeX_final < 250)
  {
    v = timeX_final / N;                                                            // Unterteilungen geteilt durch die nummer an schritten.
    v = SMOOTHSTEP(v);                                                             // Starten der smoothstep expression on v.
    Xsmoth = (TimeX_MAX_Val_minus * v) + (TimeX_Min_Val_minus * (1 - v));         // Lineare Interpolation Ausführen auf basis der zuvor gesetzten werte
   digitalWrite (Motor_drehrichtung,HIGH);
  }



if (timeX_final > 250)
  {
    v = (timeX_final - 250) / Nplus;                                                         // Unterteilungen geteilt durch die nummer an schritten.
    v = SMOOTHSTEP(v);                                                                      // Starten der smoothstep expression on v.
    Xsmoth = ((TimeX_MAX_Val_plus * v) + (TimeX_Min_Val_plus * (1 - v)));                  // Lineare Interpolation Ausführen auf basis der zuvor gesetzten werte
    digitalWrite (Motor_drehrichtung,LOW);
  }

////////////////////////////////////////////Eingegangener wert zu nächsten Loopdurchlauf übergeben//////////////////////////////////////
 timeX_old = timeX_final;
////////////////////////////////////////Visuelle Tstausgabe der Kurve_nur zum Visualisieren gedacht kammt später natürlich raus//////////////////////////////////////////////////////////////////

/*   for ( float i=0; i < (Xsmoth/10) ; i++)         // Dieser schritt wird sooft wiederholt bis die ein bestimmter Bruchteil der zahl des gemessen wetes erreicht is
                                                  
    {
      Serial.print("///");                          //Zeigt am PC  "///" bei jeden For schleifen durchlauf an.          
    }

 Serial.print("  ");  
 */Serial.println(Xsmoth);  //Zeigt das Aktuelle errechnete Ergebniss an




///////////////////////////////////////////Werte für nächsten loopdurchlauf übergeben////////////////////////////////////////////////
   hptime = 0;
   lastPulseX = millis();
 }  

}

][/code]
Logged

AREA COLOGNE
Offline Offline
Edison Member
*
Karma: 15
Posts: 1067
I am 1 of 10 who understands binary
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Kommt jetzt auf die Perfomance deines Programmes an:
Code:
unsigned long pmicros;
int nextCall=HIGH;

void setup(){
  pinMode(13,OUTPUT);
 }

void loop(){
Low_PWM(13,30,75);    //erster Wert AusgangsPin,Base Frequenz,Ontime 0-100%
}

void Low_PWM(int Pin, int Fre, int Value){
long time;
long ontime;
time=1000000/Fre;
  ontime=time/100*Value;
  if (micros() - pmicros > time && nextCall==HIGH) {
    digitalWrite(Pin,HIGH);
    pmicros=micros();
    nextCall=LOW;
  }
  if (micros() - pmicros > ontime&& nextCall==LOW){
    digitalWrite(Pin,LOW);
    nextCall=HIGH;
  }
}
 
Versuch es mal mit dem int Fre auf 15000 ob es funktioniert
Logged

So ist das Leben:
Manchmal bis du das Denkmal, manchmal die Taube!

0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo grüss dich, Danke für den Code.. Ich habs mal in meinen eingefügt und "Xsmoth" (mein Resultierender wert) als Fre eingesetzt. Also prinzipiell funktioniert es allerdings nur bis ca 30Hz. dann ist schluss.entweder mein Hauptprogramm blockiert weiteres oder es ist noch eine begrenzung eingestellt...keine ahnung.... Ich denke als irgend eine Funktion in dem Loop wird as glaube ich nicht funktionieren, zumindest nicht mit 15Khz.
habe jetzt von einem "FrequencyTimer2" gelesen, aber nicht verstanden ob er mir was nützt.
Giebt es denn keine andere möglichkeit?
Was wäre wenn ich einen Externen NE555 (Timer IC) dazu verwende meine Impulse zu generieren, könnte man den nicht einfach über analogWrite() eine spannung von 0-5V aneben und er generiert mir eine Freqenz von 0-15kHz?????? Geht das technisch? hab einen Rechteckgenerator mit dem NE555 gebaut womit ich einen Poti eine frequenz regeln kann. allerdings habe ich einen Dipschalter einbauen müssen womit ich verschieden Kondensatoren wechsel kann, damit ich unterschiedliche frequenzbereiche nutzen kann. allerdings würde das ja hier jetzt nicht gehen, ich brauchte ja die komplette 0-15kHz in einer Range....

aber wenns irgendwie mit timer und interrupt geht wäre auch gut. nur hab ich damit noch nie etwas gemacht....Hat jemand eine iDEE???
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo, also ich habs jetzt hinbekommen, Ich hab zu meinen Programm eine Interrupt service Routine gestartet .wobei ein timer bis 655XX Zählt.
 aus em ich wiederum auf pin 9 ein rechtecksignal generiere. die frequenz hängt von meinem Eingelesenen RC Signal (Xsmoth) ab.
funktioniert  von 0 bis 15kHz kann ich mit meiner Fernsteuerung die frequenz regeln.

Allerdings sind dadurch 2 neue Probleme entstanden. erstes ist das vermutlich durch den timer mein eingelesenes Signal vom Rc Empfänger willkürlich ab und an Unmögliche werte einliest. da muss irgendwas mit dem timing nicht mehr stimmen.
Das zweite ist das ich beim Initialisieren des Arduino oder nach einem Reset eine Kurze schnelle frequenzfolge auf pin 9 (mein ausgang) habe, was sozusagen meinen schrittmotor beim einschalten des arduino ungewollt 200-300 schritte machen lässt. kann man das unterbinden, oder irgendwie sagen it einem Delay das die Interrupt Routine erst nach 2 Sekundn nach initialisieren beginnt, oder das 2 sekunden meine sample (0= 0V 255=5V) auf null stehen. oder bekomme ich das damit auch nicht weg.

das ist mein Code bis Jetzt der eigentlich funktioniert bis auf die 2 problemchen...
Code:

/////////////////////////////////initialisierungen daten timer und Interrupt////////////////////////////////
float Xsmoth_plus = (Xsmoth - 250); //final smoothstepped value
float Xsmoth;
int taktPin = 9;
void writetakt( uint8_t val ) {
  OCR1A = (val);
}
uint16_t phase = 0;
uint16_t speed = 0;
uint8_t sample = 0;

SIGNAL(TIMER1_OVF_vect){
  writetakt(sample);
  phase += speed;

  if(phase >= 32768)
  sample = 255;
  else
  sample = 0;
  if (Xsmoth < 1)
   sample = 0;
}
/////////////////////////////////initialisierungen daten zum PWM einlesen////////////////////////////////
int RCPin = 2;                                                               //Eingang rc signal
int Motor_drehrichtung = 13;                                                // LED Pin(Motor Drehrichtungssignal für SM steuerung
int timeX = 0;                                                             //Gelesener Zahlenwert des RC Signals
int timeX_old = 0;                                                        // im vorherigen Durchlauf gemessener Wert (time X)
int timeX_final = 0;                                                     // Fertiger ausgegebener Wert
int Zero_delay_timeLED = 250;                                           // Mittelstellung des RC Steuerhebels

long lastPulseX = 0;                                                  // die Zeit in Millisecunden des letzten Pulses
long mstime = 0;                                                     // Liest die zeit in Millisecunden
long hptime = 0;                                                    //  Liest die Zeit in Microsecunden

extern volatile unsigned long timer0_overflow_count;
unsigned long hpticks (void)
{
 return (timer0_overflow_count << 8) + TCNT0;
}

/////////////////////////////////initialisierungen für die Nichtlineare Kurvenumsetztung der werte////////////////////////////////

#define SMOOTHSTEP( Xsmoth) (( Xsmoth) * ( Xsmoth) * (3 - 2 * ( Xsmoth)))
#define SMOOTHSTEP_plus( Xsmoth_plus) (( Xsmoth_plus) * ( Xsmoth_plus) * (3 - 2 * ( Xsmoth_plus)))

float TimeX_Min_Val_minus = 1500.0;            //Input Min Value ,hier wird die zu Interpolierende Range festgelegt
float TimeX_MAX_Val_minus = 0.0;              //Input Max Value, hier wird die zu Interpolierende Range festgelegt
float TimeX_Min_Val_plus = 0.0;              //Input Min Value ,hier wird die zu Interpolierende Range festgelegt
float TimeX_MAX_Val_plus = 1500.0;          //Input Max Value ,hier wird die zu Interpolierende Range festgelegt
float N = 250.0;  
float Nplus = 250.0;                      //Maximaler eingangswert
float v;                                 //smoothstep expression variable

/////////////////////////////////////

void setup() {
 Serial.begin(115200);                                      // Kommunikationsgeschwindigkeit Pc

 pinMode (taktPin, OUTPUT);
 pinMode(RCPin, INPUT);                                    //R/C Pin als Input setzten
 pinMode(Motor_drehrichtung, OUTPUT);                  //LED simuliet Rückwärtslauf (pin High versteht Schrittmotorsteuerung als RW)

 TCCR1A = _BV(WGM10) | _BV(COM1A1);
 TCCR1B = _BV(CS10) | _BV(WGM12);

 TIMSK1 |= _BV(TOIE1);

}
void loop() {

 if(millis() - lastPulseX >= 5)                               //Signal alle 5 Millisecunden auslesen
 {
   while(!digitalRead(RCPin) == HIGH)                         //Auf das Nächste RC Signal von RCPin Warten
   {
     continue;
   }
   mstime = millis();
   hptime = hpticks();                                        //wenn das Signal Ankommt, Beginn der Startzeit aufzeichnun
   while(!digitalRead(RCPin) == LOW){
     continue;
   }
   mstime = millis();
   timeX = (hpticks()) - hptime - 220;                       //Hier wird der unterschied zwischen start und endzeit ermittelt, Das Ergebnis ist das Rc Signal.

////////////////////////////////////////Tiefpassfilter zum glätten des gemessenen wertes///////////////////////////////////////////////

   timeX_final = (0.1 * timeX) + (0.9 * timeX_old);       //10 Prozent des Wertes des ersten Durchgangs, werden mit 90 Prozent des Wertes des 2. Durchganges addiert
  
  /////////////////////////////////// Wertebereich begrenzen////////////////////////////////////////////////////////////////////////////
if (timeX_final > 500)                                  
   {timeX_final = 500;}

if (timeX_final < 0)
   {timeX_final = 0;}
///////////////////////////////////////werte in CW und CCW übersetzen///////////////////////////////////////////////////////////////////
if (timeX_final < 250)
  {
    v = timeX_final / N;                                                            // Unterteilungen geteilt durch die nummer an schritten.
    v = SMOOTHSTEP(v);                                                             // Starten der smoothstep expression on v.
    Xsmoth = (TimeX_MAX_Val_minus * v) + (TimeX_Min_Val_minus * (1 - v));         // Lineare Interpolation Ausführen auf basis der zuvor gesetzten werte
   digitalWrite (Motor_drehrichtung,HIGH);
  }



if (timeX_final > 250)
  {
    v = (timeX_final - 250) / Nplus;                                                         // Unterteilungen geteilt durch die nummer an schritten.
    v = SMOOTHSTEP(v);                                                                      // Starten der smoothstep expression on v.
    Xsmoth = ((TimeX_MAX_Val_plus * v) + (TimeX_Min_Val_plus * (1 - v)));                  // Lineare Interpolation Ausführen auf basis der zuvor gesetzten werte
    digitalWrite (Motor_drehrichtung,LOW);
  }

////////////////////////////////////////////Eingegangener wert zu nächsten Loopdurchlauf übergeben//////////////////////////////////////
 timeX_old = timeX_final;                    // messwert für Tiefpass an nächsten Durchlauf übergeben
 
 speed = Xsmoth;                            //Ausgabe Frequenz geschwindigkeit

 Serial.println(Xsmoth);              //Zeigt das Aktuelle errechnete Ergebniss an

///////////////////////////////////////////Werte für nächsten loopdurchlauf übergeben////////////////////////////////////////////////
   hptime = 0;
   lastPulseX = millis();
 }  

}

Logged

Pages: [1]   Go Up
Jump to: