Alte Graupner C05 Servos an hott Empfänger

Bernd Langner

Moderator
Teammitglied
Hallo oktapapa

Das sieht stark nach Eigenbau aus das IC ist ein SN 28654
Servo IC . Die Beschaltung siehst du in meinen Beiträgen auf der ersten Seite.

Die ganz alten C0 5 hatten die Elektronik in den Bausteinen der Empfänger.
Im Gehäuse der Servos müßten nur die Motoren und das Poti sein.

Hier hat jemand dann diese Platine geplant und augenscheinlich selbst geätzt.
Auch die Lötungen sehen sehr Hobbymäßig aus.

An das IC werden über den Rundstecker der Motor und das Poti angeschlossen.
Die Ansteuerung übernimmt das IC auf der Platine.

Gruß Bernd
 
SN 28654

SN 28654

Das IC „SN 28654“ wurde früher in vielen industriellen Servos verwendet und auch häufig in Eigenbau-Servoverstärkern und -Schaltmodulen; es gibt mehrere (leicht) unterschiedliche Schaltungsvarianten – hier 3 Beispiele. Ein Vorteil war die mögliche Ansteuerung durch positive und auch negative Impulse (Eingang positiv = Pin-3 und negativ = Pin-1 und dann Brücke von Pin-2 nach Pin-3). Für die heutigen Servo-Elektroniken inzwischen überholt und zu groß, aber bei den „Bastlern“ immer (noch) beliebt da rel. problemlos zu löten gegenüber SMD – aber wer bastelt heute schon noch, gibt ja (fast) alles zu China-Spotpreisen ?

Gruß Erich
 

Anhänge

  • 28654-1.jpg
    28654-1.jpg
    159,3 KB · Aufrufe: 504
  • 28654-2.jpg
    28654-2.jpg
    102,4 KB · Aufrufe: 472
  • 28654-3.jpg
    28654-3.jpg
    32,4 KB · Aufrufe: 277
Hallo !

Hallo !

Vielen Dank,
habe mir gestern bei E-Bay dieses Buch von Helmut Bruß gekauft, eben die erwähnte Ausgabe von 1980...Bin gespannt was da so drinsteht.
Meiner Erfahrung nach sind die Kohlen am Poti ja das Hauptproblem bei diesen Servos. In den großen, alten ohne Elektronik haben wir alte kohlen gegen Bleistiftminen, ich glaube es war die Härte " HB" ausgetauscht, die Kohlen waren eingeklemmt. Bei den "neueren" sind sie eingeklebt. Könnte man es vielleicht mit Sekundenkleber versuchen ? Hat es vielleicht jemand versucht ? War(en) der/die Versuch(e) erfolgreich ?

Viele Grüße....
 

Bernd Langner

Moderator
Teammitglied
Hallo oktapapa

Bist du sicher der Stift in der Regel ist eher so das die Kohleschicht durchgeschliffen wird
um die Neutralstellung.

comp_DSCN0464.jpg

Die Firma Preh hat früher offene Trimmer da könnte man die Kohlestifte ausbauen.
Eventuell findet man die Dinger noch auf Amateurfunkflohmärkten.

Das Bild zeigt die Widerstandsbahn von einem Poti aus einem Sender
hier sieht man wie die Kohlebahn eingearbeitet ist da gibt es auch keine Rettung
ausser das Poti tauschen.

Gruß Bernd
 
Hallo

Hallo

Sehr aufschlußreiches Bild, aber in meinem Fall sind tatsächlich die Kohlen praktisch weg....

Wegen der Poties werde ich nachfragen.....

Viele Grüsse
 
Alte Graupner Varioprop Servos ohne Elektronik weiter nutzen

  • Simulation einer Varioprop Schaltstufe durch Arduino -
Angeregt durch die softwaremäßige Realisierung von Impulsteilen durch einen Arduino wie zum Beispiel für alte Varioprop oder sogar die Tipp Tipp Anlagen Varioton. Nachdem ich eine alte Variophon 8S mit Arduino-Impulsteil und einem FrSky 2,4 GHz HF-Teil versorgt habe wollte ich die Absicht einen Weg zu finden, wie man die alten Bellamatic in eine schöne Retro-Lösung mit einbeziehen könnte. Also vorweg genommen, es funktioniert sowohl die Lösung für Varioton/Variophon-Anlagen als in abgeänderter Form natürlich für Varioprop-Anlagen Hier möchte ich die Lösung für Varioprop vorstellen. Also stellte ich ein paar Überlegungen an, wie man zunächst an die Empfängersignale kommt. Ich dachte am besten wäre wohl ein PPM-Signal. Dies würde sich durch mehrere Schaltstufen durchleiten lassen und jede Schaltstufe nimmt sich gemäß ihrer Nummer Kanal 1, 2 usw. einfach das richtige Signal raus. Zum Glück habe ich im Internet ein Programmstück für den Arduino gefunden, welches genau das ermöglicht. Eine PWM Lösung wäre auch nicht uninteressant aber wohl aufwendiger, wenn man mit mehreren Schaltstufen arbeiten möchte und letzten Endes müsste man zum durchleiten doch wieder ein Summensignal daraus erzeugen. Deswegen habe ich mich gleich für einen PPM-Empfänger entschieden. Der FrSky D4R-II kann bei richtigem jumpern am ersten Anschluß ein PPM-Signal für 8 Kanäle liefern. Ich habe auch Postings im Internet gefunden, die von einem Graupner C12, C17 und C19 PPM Signale abgreifen.

Siehe:

https://wiki.mikrokopter.de/c17

https://wiki.mikrokopter.de/c12

https://wiki.mikrokopter.de/c19



Hier der Link zu dem Programmstück:

https://www.hackster.io/abhilashpatel121/reading-rc-receiver-ppm-signal-using-arduino-c42929

Das Progrämmchen arbeitet folgendermaßen: Liegt am Pin 2 des Arduino eine fallende Flanke an, wird per Interrupt ein Unterprogramm aufgerufen. Es liefert im Array ch[1], ch[2], ch[3], ch[4], ch[5], ch[6] 6 Signale für 6 Kanäle. Reicht also zum Beispiel für eine Varioprop 12. Die Werte muss man jetzt nur noch weiterverarbeiten.

Die alten Graupner Varioprop Servos ohne Elektronik werden mit einer Spannung von 2,4V betrieben. Eine Richtungsänderung wird durch Umpolung erreicht. Der von mir verwendete Arduino proMini arbeitet mit 16MHz und einer Arbeitsspannung von 5V. Das sind zuviel für die alten Servos. Also verwendete ich eine H-Brücke L298N DUAL FULL-BRIDGE DRIVER MULTIWATT15 ST für die Stromversorgung und die Umpolung.

Bild1.png
L298N DUAL FULL-BRIDGE DRIVER MULTIWATT15 ST

Damit lässt sich das Servo mit einer externen 2,4V Quelle versorgen und die Laufrichtung ändern. Ein solcher Baustein kann so zwei Motoren steuern. Das Bauteil hier ist fast etwas zu groß um in ein leeres Schaltstufengehäuse eingebaut zu werden. Es gibt auch kleinere Lösungen mit anderen Bauteilen, diese können aber nur ein Servo schalten.

Bild2.png


Bei der H-Bridge müsste man aus der Bohrung am Kühlkörper eine entsprechend große Nut reinsägen, die Pins links vollkommen nach innen biegen und einzeln gut isolieren. Dann könnte alles reinpassen. Übrigens der Arduino hier ist ein proMini. Die Schaltstufenplatine ist von einer Varioton, aber die Varioprop hat in etwa die gleichen Abmessungen.





ArduinoH_BridgeEmpfänger Servo (Rundstecker)
5VPlus
Pin 2Signal
Pin 3Pin 6 (ENABLE A)
Pin 4 in_1Pin 5 (INPUT 1)
Pin 5 in_2Pin 7 (INPUT 2)
5VPin 9 (Logic Supply Voltage Vss)
A0Pin 5 (Abgriff Servopoti)
Pin 2 (OUTPUT 1)Pin 1 (+/- 2,4V)
Pin 3 (OUTPUT 2)Pin 3 (-/+ 2,4V)
GND/MassePin 8 (GND)
Pin 1*1)
GND/MasseGND
GND/MassePin 8 (Servopoti minus)
5VPin 6 (Servopoti plus)


  • Stimmt hier die Originalbeschreibung nicht? Laut Beschreibung wäre hier der Anschluss „Current Sensing A“. Erst als ich mich traute Masse anzulegen funktionierte es.




Servostecker-Belegung Varioprop Micro 05
Bild3.png


Normalerweise würde man bei der H-Bridge an Pin 4 wohl die externe Stromversorgung von 2,4 V anschließen. Ich war aber mutig und habe probiert was die Servomotoren so vertragen. Dabei stellte ich fest, daß nur noch eine Spannung von 3V an den Output-Pins übrigblieb. Ein Blick in einen alten Graupnerkatalog bestätigte, daß die Servomotoren bis zu 3V vertragen.

Meine Versuchsanordnung
IMG_5994.JPG


Programmcode


C-ähnlich:
unsigned long int a,b,c;
int x[15],ch1[15],ch[7],i;
//specifing arrays and variables to store values

const int in_1 = 4 ;
const int in_2 = 5 ;
const int intrpt = 2;       // setze interrupt auf pin 2
const int schaltstufe = 2;  // TAER  1=Throttle, 2=Aileron, 3=Elevator, 4=Rudder
const int pwmPin = 3 ;         //initialisiere pin 3 als pwmPin
const int ServoPin = 0;        // Analog In - Servo potentiometer
const int servoSpeed = 200 ;   // Servomotorgeschwindigkeit, Maximum ist 255

int ServoPos = 1500 ;         // Servoposition Mitte
int KnueppelPos = 1500 ;
float Diff = 0 ;
float Teiler = 1.5 ;    // 1.5 hat sich als brauchbarer Wert herausgestellt.

void setup() {   // Interruptroutine
  pinMode(intrpt, INPUT_PULLUP);
  pinMode(in_1, OUTPUT);
  pinMode(in_2, OUTPUT);
  pinMode(pwmPin,OUTPUT);
  ch[schaltstufe] = 512;  // Knüppel neutral


  attachInterrupt(digitalPinToInterrupt(intrpt), read_me, FALLING);
  // enabling interrupt at pin intrpt
}


void loop() {

    read_rc();
   
    // Diese Abfrage wird deswegen benötigt, da der erste Wert von ch[schaltstufe]
    // = -1000 ist und auch zwischendurch Werte aus dem Rahmen fallen.
    if (ch[schaltstufe] > 0 && ch[schaltstufe] < 1023){
        ServoPos  = map(analogRead(ServoPin), 0, 1023, 1000, 2000);
        KnueppelPos = map(ch[schaltstufe], 0, 1023, 1000, 2000);
    }
   

    Diff = KnueppelPos - ServoPos;
    // Servo in eine Richtung
            if (Diff > 40){  // So 50, 60 sind hier gute Werte Je genauer die
                             // Knüppel arbeiten, desto geringer kann der Wert sein

              // Servomotor in die gewünschte eine Richtung laufen lassen
              digitalWrite(in_1,LOW) ;
              digitalWrite(in_2,HIGH) ;
              analogWrite(pwmPin,servoSpeed) ;    

              // Hier wird der Servoweg auf mehrere Schleifendurchläufe aufgeteilt,
              // damit der Bremsweg des Motors nicht so lang ist. Teiler wurde auch
              // durch Versuche ermittelt.
              delay(Diff/Teiler);                                

              //Servomotor zum Abbremsen umpolen
              digitalWrite(in_1,HIGH) ;
              digitalWrite(in_2,LOW) ;
              analogWrite(pwmPin,servoSpeed) ;
              delay(30);  // Dieser Wert wurde durch Versuche ermittelt. Am besten
                          // wäre eine Funktion, die den Bremsweg berücksichtigt.
                   
              //Servomotor aus
              digitalWrite(in_1,LOW) ;
              digitalWrite(in_2,LOW) ;
              analogWrite(pwmPin,servoSpeed) ;
            }
 
   
    // Servo in andere Richtung
            if (Diff < -40){
              // Servomotor in die gewünschte andere Richtung laufen lassen
              digitalWrite(in_1,HIGH) ;
              digitalWrite(in_2,LOW) ;
              analogWrite(pwmPin,servoSpeed) ;

              // Hier wird der Servoweg auf mehrere Schleifendurchläufe aufgeteilt,
              // damit der Bremsweg des Motors nicht so lang ist. Teiler wurde auch
              // durch Versuche ermittelt.
              delay((abs(Diff/Teiler)));                    
             
              //Servomotor zum Abbremsen umpolen
              digitalWrite(in_1,LOW) ;
              digitalWrite(in_2,HIGH) ;
              analogWrite(pwmPin,servoSpeed) ;              
              delay(30);  // Dieser Wert wurde durch Versuche ermittelt. Am besten
                          // wäre eine Funktion, die den Bremsweg berücksichtigt.
             
              //Servomotor aus
              digitalWrite(in_1,LOW) ;
              digitalWrite(in_2,LOW) ;
              analogWrite(pwmPin,servoSpeed) ;
            }
} // loop



Hier kommt der Code der die PPM Signale beschafft rein. Er findet sich mit Hilfe des obigen Links. Man kann den Code fast 1:1 so verwenden, man muß nur die Variablendeklarationen nach oben ziehen, die Hauptschleife eliminieren und oben in die Hauptschleife integrieren.

void read_me()  {
….
}
void read_rc(){
…
}

Probleme und Fazit:
Ein Problem war immer wieder das Nachlaufen des Motors beim Abschalten, was zur Folge hatte, daß das Servo nicht richtig neutralisierte. Erst als ich begann, die Pinbelegung des Servopotis heraus zu messen um so den genauen Rückweg anzusteuern und im Programm zu berücksichtigen besserte sich das Problem etwas. Statt der 30ms Abbremsung wäre eine Funktion wünschenswert, die dynamischer reagiert.
Da ich mich zu erinnern glaubte, daß es damals schon Servos gab, die nicht so genau neutralisierten schloß ich, dass die Ingenieure früher hardwaremäßig ein ähnliches Problem hatten, wie ich softwaremäßig.
Die Servobewegung wirkt vielleicht etwas wenig flüssig. Das liegt daran, dass die Bewegungen über mehrere Schleifendurchläufe erzielt werden. Vermutlich ist der Arduino für diese Aufgabe etwas zu schwach getaktet. Eine Funktion die genau den Bremsweg berechnen könnte wäre wünschenswert.
Als erstes habe ich mich nach der viel investierten Zeit gefreut, dass es im Prinzip funktioniert. Nicht ganz perfekt, aber immerhin ließe sich ein leichter Segler sicher damit steuern. Vielleicht kann ich den einen oder anderen anregen sich weitere Gedanken zu machen. Ich versuche nun –ein paar leere Schaltstufengehäuse oder wirklich kaputte Schaltstufen aufzutreiben (Funtionierende wären zu schade) und mit einer günstigen Schaumwaffel die auch noch zu beschaffen wäre erste Flugerfahrung zu sammeln.
 
Zuletzt bearbeitet:

S_a_S

User
eine Schaltungsbeschreibung für die Varioprop-Servo-Bausteine mit Rundstecker findest Du auf S. 78 (Einkanal mit Transistoren) oder S. 79 (Zweikanal mit SAK100) im Buch von Gunter Miel

Der Ansatz mit Arduino ist aber auch interessant. Totbereich konnte in den IC-Schaltungen über RC-Glieder angepasst werden (machst Du über Diff). Was Dir noch fehlt, ist die von der Regeldifferenz abhängige Berechnung der servoSpeed - dann muss der Motor nicht immer aus maximaler Geschwindigkeit auslaufen, sondern wird vorher schon langsamer.

Grüße Stefan
 

S_a_S

User
Code:
  Diff = KnueppelPos - ServoPos;
  // einfacher P-Regler
  servoSpeed = abs(Diff) * faktor; // auch mit dem faktor kann man spielen
  if (servoSpeed >255)
      servoSpeed =255;   // hier gegebenenfalls noch auf Maximalwert begrenzen oder auch eine map() verwenden.

    // Servo in eine Richtung
            if (Diff > 40){  // ggf. noch mit Totbereich spielen
              // Servomotor in die gewünschte eine Richtung laufen lassen
              digitalWrite(in_1,LOW) ;
              digitalWrite(in_2,HIGH) ;
              analogWrite(pwmPin, servoSpeed) ; 
          } else if (Diff < 40) { // ggf. noch mit Totbereich spielen
              // Servomotor in die gewünschte andere Richtung laufen lassen
              digitalWrite(in_1,HIGH) ;
              digitalWrite(in_2,LOW) ;
              analogWrite(pwmPin, servoSpeed) ; 
          } else {
              //Servomotor aus - falls dies nicht über servoSpeed = 0 eh schon so ist.
              digitalWrite(in_1,LOW) ;
              digitalWrite(in_2,LOW) ;
              analogWrite(pwmPin,0) ;
          }

Hier hab ich mal einen primitiven Ansatz eines P-Reglers skizziert. Ob jetzt zum Bremsen noch in die Gegenrichtung gesteuert werden muss, hängt auch vom Totbereich ab. Ob ein delay noch erforderlich ist, hängt von der Frequenz des PWM-Signals (üblicherweise 2ms) und der Abarbeitung der Schleife ab, nicht dass es da seltsames retriggern bein nächsten Schreiben des PWM-Registers mit analogWrite() gibt.


Grüße Stefan
 
Hallo Stefan,

läuft insgesamt nicht schlecht. Also die Servobewegung ist flüssiger. Die Diff-Toleranz liegt jetzt bei 10 (habe Taranis mit Hallsensoren), faktor liegt bei 0.4. Werde weiter experimentieren.
 
Was ich noch vergessen habe, das Servo singt recht. Es scheint mir, als ob es in Minimalbereichen die Position noch korrigieren möchte. Leider lassen sich keine Videos hochladen.
 

S_a_S

User
das Quietschen erinnert mich an alte, kleine Mabuchi-Motoren mit ausgeschlagenen oder trockenen Lagern. Tritt ja auch nicht bei jeder Bewegung auf, nur wenn recht hohe Geschwindigkeit ansteht. Liegt also vermutlich nicht an der Ansteuerung - und kann eventuell mit einem kleinen Tropfen Öl behandelt werden (kommt aber wieder). Oder das Getriebe braucht etwas Fett an den richtigen Stellen...

Aber sieht gut aus (hab auch noch ein paar der großen 2,4V Linearservos im Schrank...).

Grüße Stefan
 

S_a_S

User
hallo Herbert,

500Hz (hab auch was von 490Hz gelesen und mir schien Dein Ton tatsächlich etwas niedriger als der im verlinkten Video) ist das PWM-Geräusch , das wird von der Motorwicklung wiedergegeben. Die PWM-Frequenz kann man auch ändern.

Die alten analogen ICs haben die Pulsweite mit den 20ms-Pulsen aus der Fernsteuerung synchronisiert, die daraus resultierenden 50Hz kommen aus der kleinen "Bassreflexbox" C05 nicht rüber oder werden als Schnarren interpretiert.

Grüße Stefan
 
UPDATE

Das Neutralisierungsproblem ist gelöst. Durch den Einsatz einer anderen, kleineren H-Bridge (DRV8838) neutralisiert das MICRO 05 Servo jetzt sauber.

So wird der DRV8838 verschaltet:
Micro05-DRV8838.png


Hier das Programm dazu:
C-ähnlich:
// für H-Bridge Chip DRV8838
// (Funktioniert)

unsigned long int a,b,c;
int x[15],ch1[15],ch[7],i;
//specifing arrays and variables to store values

const int pin_Enable = 5 ;      // H-Bridge zu- bzw. wegschalten
const int pin_Phase = 4 ;       // bestimmt die Motorlaufrichtung
const int intrpt = 3;           // setze interrupt auf pin 2
const int schaltstufe = 1;      // TAER  1 = Throttle, 2 = Aileron, 3 = Elevator, 4= Rudder
const int ServoPin = 0;        // Analog In - Servo potentiometer
const int Toleranz = 20;
int ServoPos = 1500 ;         // Servoposition Mitte
int KnueppelPos = 1500 ;
int KnueppelMitte = 1500 ;
int VerzZeit = 5;       // 5 ist brauchbarer Wert

void setup() {   // Interruptroutine
  Serial.begin(9600);
  pinMode(intrpt, INPUT_PULLUP);
  pinMode(pin_Enable, OUTPUT);
  pinMode(pin_Phase, OUTPUT);
  ch[schaltstufe] = 512;  // Knüppel neutral
 

  attachInterrupt(digitalPinToInterrupt(intrpt), read_me, FALLING);
  // enabling interrupt at pin intrpt
}

void loop() {
    
    read_rc();
    //Serial.print("\n");  Serial.print("ch[schaltstufe] = ");  Serial.print(ch[schaltstufe]);
    // Diese Abfrage wird deswegen benötigt, da der erste Wert von ch[schaltstufe] = -1000 ist und auch zwischendurch Werte aus dem Rahmen fallen.
    //Serial.print("\n");  Serial.print("<ch[schaltstufe] = ");  Serial.print(ch[schaltstufe]);
    if (ch[schaltstufe] >= 0 && ch[schaltstufe] <= 1023){
        ServoPos  = map(analogRead(ServoPin), 0, 1023, 1000, 2000);
        KnueppelPos = map(ch[schaltstufe], 0, 1023, 1000, 2000);
    }
    //Serial.print("\nKnueppelPos = ");  Serial.print(KnueppelPos);
    //Serial.print("\nServoPos = ");  Serial.print(ServoPos);

  if (KnueppelPos > KnueppelMitte + Toleranz){  // Knüppel TIEF
    if (KnueppelPos > ServoPos){ 
        // Servomotor in die gewünschte eine Richtung laufen lassen
        //Serial.print("\nServo in  Richtung TIEF ");
        digitalWrite(pin_Phase,LOW) ;
        digitalWrite(pin_Enable,HIGH) ;
        delay(VerzZeit);
        digitalWrite(pin_Enable,LOW);
        delay(VerzZeit);
    }else{
        if (KnueppelPos < ServoPos - 15) {
          //Serial.print("\nServo in  Richtung HOCH ");
            digitalWrite(pin_Phase,HIGH) ;
            digitalWrite(pin_Enable,HIGH) ;
            delay(VerzZeit);
            digitalWrite(pin_Enable,LOW);
            delay(VerzZeit);
        }else{
            digitalWrite(pin_Enable,LOW);
            delay(VerzZeit);
        }
    }
  } else if (KnueppelPos < KnueppelMitte - Toleranz) {  // Knüppel Hoch
            // Servomotor in die gewünschte andere Richtung laufen lassen
           if (KnueppelPos < ServoPos && ServoPos > 1000){ 
                  digitalWrite(pin_Phase,HIGH) ;
                  digitalWrite(pin_Enable,HIGH) ;
                  delay(VerzZeit);
                  digitalWrite(pin_Enable,LOW);
                  delay(VerzZeit);
            }
            else{
                  if (KnueppelPos > ServoPos + 15) {
                    //Serial.print("\nServo in  Richtung HOCH ");
                      digitalWrite(pin_Phase,LOW) ;
                      digitalWrite(pin_Enable,HIGH) ;
                      delay(VerzZeit);
                      digitalWrite(pin_Enable,LOW);
                      delay(VerzZeit);
                  }else{
                      digitalWrite(pin_Enable,LOW);
                      delay(VerzZeit);
                  }
            }
          } else {   // Knüppel Neutral
                    ServoPos  = map(analogRead(ServoPin), 0, 1023, 1000, 2000);

                    if (ServoPos < KnueppelMitte - Toleranz){
                      digitalWrite(pin_Phase,LOW) ;
                      digitalWrite(pin_Enable,HIGH) ;
                      delay(VerzZeit);
                      digitalWrite(pin_Enable,LOW);
                      delay(VerzZeit);
                    }else{ 
                        if (ServoPos > KnueppelMitte + Toleranz){
                          digitalWrite(pin_Phase,HIGH) ;
                          digitalWrite(pin_Enable,HIGH) ;
                          delay(VerzZeit);
                          digitalWrite(pin_Enable,LOW);
                          delay(VerzZeit);
                        }else{
                    //      Serial.print("\nServo neutral");
                          digitalWrite(pin_Enable,LOW) ;
                          delay(VerzZeit);
                        }
                    }         
            
          }
        digitalWrite(pin_Enable,LOW) ;
 } // loop


// Beispiel-Programm aus dem Internet zur Zerlegung des Summensignals welches direkt so verwendet werden kann.
void read_me()  {
 //this code reads value from RC reciever from PPM pin (Pin 2 or 3)
 //this code gives channel values from 0-1000 values
 //    -: ABHILASH :-    //
 // Hier geht es zu Originalquellcode um das richtige Signal aus dem PPM-Strom herauszuholen.
https://www.instructables.com/Reading-RC-Receiver-PPM-Signal-Using-Arduino/
    
    
    void read_rc(){
int i,j,k=0;
  for(k=14;k>-1;k--){if(ch1[k]>10000){j=k;}}      //detecting separation space 10000us in that another array                     
  for(i=1;i<=6;i++){ch[i]=(ch1[i+j]-1000);}}      //assign 6 channel values after separation space
 
UPDATE 2

Nachdem das vorige Update auch nur die cPPM Empfänger behandelte dachte ich mir, eigentlich müsste das doch mit den normalen PWM-Signalen der Empfänger doch auch funktionieren. Gesagt getan und rasch im Internet gesurft. Die Lösung habe ich unter


gefunden.

Also wurde die Interruptroutine für cPPM durch eine für PWM ersetzt.

Eine geringstfügige Änderung musste das Programm jedoch erfahren, der Befehl

attachInterrupt(CHANNEL_1_PIN, calcSignal, CHANGE)​

mußte in

attachInterrupt(digitalPinToInterrupt(pin_PWM_IN), calcSignal, CHANGE)​

geändert werden, da sonst die Interrupt-Routine nicht aufgerufen wurde.

Ansonsten ist das Programm, bis auf geringfügige weitere Anpassung (Variablen) mit der Version vom ersten Update gleich.

C:
// für H-Bridge Chip DRV8838
// Graupner Empfänger z.B. C17
//

//micros when the pin goes HIGH
volatile unsigned long timer_start;
volatile int pulse_time;
//difference between timer_start and micros() is the length of time that the pin
//was HIGH - the PWM pulse length.
volatile int pulse_time;
//this is the time that the last interrupt occurred.
//you can use this to determine if your receiver has a signal or not.
volatile int last_interrupt_time;
#define pin_PWM_IN  3

const int pin_Enable = 5 ;      // H-Bridge zu- bzw. wegschalten
const int pin_Phase = 4 ;       // bestimmt die Motorlaufrichtung

const int ServoPin = 0;        // Analog In - Servo potentiometer
const int Toleranz = 30;

int ServoPos = 1500 ;         // Servoposition Mitte
int KnueppelPos = 1500 ;
int KnueppelMitte = 1500 ;
int VerzZeit = 5;       // 5 ist brauchbarer Wert

void setup() {   // Interruptroutine
  Serial.begin(9600);
  pinMode(pin_Enable, OUTPUT);
  pinMode(pin_Phase, OUTPUT);
  pinMode(pin_PWM_IN, INPUT);

  timer_start = 0;
  attachInterrupt(digitalPinToInterrupt(pin_PWM_IN), calcSignal, CHANGE);

}

void loop() {
   
   
  KnueppelPos = pulse_time;  
  ServoPos  = map(analogRead(ServoPin), 0, 1023, 1000, 2000);

  if (KnueppelPos > KnueppelMitte + Toleranz){  // Knüppel TIEF
    if (KnueppelPos > ServoPos){
        // Servomotor in die gewünschte eine Richtung laufen lassen
        digitalWrite(pin_Phase,LOW) ;
        digitalWrite(pin_Enable,HIGH) ;
        delay(VerzZeit);
        digitalWrite(pin_Enable,LOW);
        delay(VerzZeit);
    }else{
        if (KnueppelPos < ServoPos - 15) {
            digitalWrite(pin_Phase,HIGH) ;
            digitalWrite(pin_Enable,HIGH) ;
            delay(VerzZeit);
            digitalWrite(pin_Enable,LOW);
            delay(VerzZeit);
        }else{
            digitalWrite(pin_Enable,LOW);
            delay(VerzZeit);
        }
    }
  } else if (KnueppelPos < KnueppelMitte - Toleranz) {  // Knüppel Hoch
            // Servomotor in die gewünschte andere Richtung laufen lassen
           if (KnueppelPos < ServoPos && ServoPos > 1000){
                  digitalWrite(pin_Phase,HIGH) ;
                  digitalWrite(pin_Enable,HIGH) ;
                  delay(VerzZeit);
                  digitalWrite(pin_Enable,LOW);
                  delay(VerzZeit);
            }
            else{
                  if (KnueppelPos > ServoPos + 15) {
                      digitalWrite(pin_Phase,LOW) ;
                      digitalWrite(pin_Enable,HIGH) ;
                      delay(VerzZeit);
                      digitalWrite(pin_Enable,LOW);
                      delay(VerzZeit);
                  }else{
                      digitalWrite(pin_Enable,LOW);
                      delay(VerzZeit);
                  }
            }
          } else {   // Knüppel Neutral
                    ServoPos  = map(analogRead(ServoPin), 0, 1023, 1000, 2000);

                    if (ServoPos < KnueppelMitte - Toleranz){
                      digitalWrite(pin_Phase,LOW) ;
                      digitalWrite(pin_Enable,HIGH) ;
                      delay(VerzZeit);
                      digitalWrite(pin_Enable,LOW);
                      delay(VerzZeit);
                    }else{
                        if (ServoPos > KnueppelMitte + Toleranz){
                          digitalWrite(pin_Phase,HIGH) ;
                          digitalWrite(pin_Enable,HIGH) ;
                          delay(VerzZeit);
                          digitalWrite(pin_Enable,LOW);
                          delay(VerzZeit);
                        }else{
                          digitalWrite(pin_Enable,LOW) ;
                          delay(VerzZeit);
                        }
                    }        
           
          }
        digitalWrite(pin_Enable,LOW) ;
} // loop


// Originalcode zu finden unter
// https://www.camelsoftware.com/2015/12/25/reading-pwm-signals-from-an-rc-receiver-with-arduino/

//calcSignal is the interrupt handler
void calcSignal()
{  
    //record the interrupt time so that we can tell if the receiver has a signal from the transmitter
    last_interrupt_time = micros();
    //if the pin has gone HIGH, record the microseconds since the Arduino started up
    if(digitalRead(pin_PWM_IN) == HIGH)
    {
        timer_start = micros();
    }
    //otherwise, the pin has gone LOW
    else
    {
        //only worry about this if the timer has actually started
        if(timer_start != 0)
        {
            //record the pulse time
            pulse_time = ((volatile int)micros() - timer_start);
            //restart the timer
            timer_start = 0;
        }
    }
}


Hier ein Link zum Video
 
Ansicht hell / dunkel umschalten
Oben Unten