Kreuzmischer

Author: Dipl.-Ing. Wilfried Klaas

Board: Arduino Duemilanove

Was ist ein Kreuzmischer?

Ein Kreuzmischer mischt 2 Servosignale, also die Ruderausschläge, zweier Kanäle auf 2 Ausgangskanäle so zusammen, dass der eine Kanal beide Ausgangskanäle proportional steuert, während der 2 Kanal die beiden Ausgangskanäle gegengesetzt steuert. Beispiele für den Einsatz: Kettenfahrzeug mit 2 getrennten Kettenantrieben, Flugzeug mit einem V-Leitwerk, Boot mit 2 Schrauben zur Ruderunterstützung… Damit lässt sich über einen Kreuzküppel der Fernsteuerung das Gefährt einfach handhaben.

Und wie funktioniert das?

Beim Kreuzmischen kann man einfach für den 1. Ausgangskanal die beiden Eingangskanäle addieren, während man für den 2. Kanal den Steuerkanal abzieht. Also z.B. so:

A1 = ESC + STE; A2 = ESC - STE;

Nun sieht man hier ganz leicht, das wir das so einfach nicht machen können. Sagen wir mal, unsere Eingangs- und Ausgangssignale sind im Bereich -128 bis 128. Fahren wir nun voll Kraft voraus, dann hat Kanal A1 einen Wert von 128 und und Kanal A2 ebenfalls einen Wert von 128. Wenn wir jetzt etwas Seitenruder geben, sagen wir mal mit -60 dazu. Dann wird aus A1 = 128 + -60 = 68. OK und A2 = 128 - -60 = 128 + 60 = 188;
Upps, den Wert können wir jetzt nicht mehr darstellen. Denn wir können ja nur bs 128 steuern.
Um das zu umgehen, gibt es, je nach Einsatzzweck verschiedene Möglichkeiten: * Wir lassen alles so wie beschrieben und ignorieren Werte > 128. Dann wäre im o. Fall A1 = 68 und A2= 128. * Oder wir halbieren immer jeden Servoweg. Dann wäre A1 = 64 + -30 = 34 und A2= 64 - -30= 94. Dazwischen sind natürlich noch viele andere Möglichkeiten drin.

Programm

Zuerst lesen wir die beiden Empfängerkanäle ein, dann wird gerechnet und zwar je nach Einstellung entweder nach Methode 1 oder 2. Was wir hier (wie bei meinen RC Projekten fast immer) machen, wir bestimmen beim Starten zunächst die Nullpunkte des Empfängers. Dann werden alle Werte durch einen Puffer geschleift. Der enthält 10 Werte und wenn man einen Wert abfragt, wird automatisch der Mittelwert über diese Werte gebildet. (Größter und kleinster fliegen dabei raus.) Dadurch ist man vor kruzen Empfangsstörungen sicher, aber das System reagiert nicht ganzt so schnell. Das kann evt. für Flugzeuge und Hubschrauber nicht gut sein. Da sollte man sich eine andere Strategie einfallen lassen, oder aber einfach den Puffer verkleinern. z.B. auf 4.
UPDATE: 18.10.2012: Ich habe auch diesen Kreuzmischer auf meine RCReceiver Bibliothek umgebaut. Und ich habe den Servoreverse pro Kanal eingebaut. Dazu werden 2 weitere Pins abgefragt.
UPDATE: 18.11.2013: Ich habe beide Programme auf den aktuellen Stand der RCReceiver Bibliothek umgebaut.

Kreuzmischer.ino
#include <debug.h>
#include <makros.h>
#include <RCReceive.h>
#include <Servo.h>
 
/*
 Kreuzmischer. Kanal 1 ist Geschwindigkeit, Kanal 2 ist Steuerung.
 Der Empfänger wird vom Pin 2 und 3 gelesen, 
 */
 
// Hardwareanbindung für Arduino Hardware
// Empfängerkanäle
const byte PIN_RC_THR = 2; // das ist INT 0 aber Pin 2!!!!
const byte PIN_RC_STE = 3; // das ist INT 1 aber Pin 3!!!!
 
// Modus Soft oder Hard
const byte PIN_MODE = 4;
const byte PIN_REVERS_1 = 7;
const byte PIN_REVERS_2 = 8;
 
// Ausgänge
const byte SERVO_1 = 9; // PWM Kanal 
const byte SERVO_2 = 10; // PWM Kanal
const byte LED = 13; // LED auf dem Board
 
RCReceive escReceiver;
RCReceive servoReceiver;
 
Servo a1, a2;
 
void setup() {
  // Kanäle auf Ausgang, und dann deaktivieren
  pinMode(SERVO_1, OUTPUT);
  pinMode(SERVO_2, OUTPUT);
 
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
 
  // Eingang für RC
  pinMode(PIN_RC_THR, INPUT_PULLUP); 
  pinMode(PIN_RC_STE, INPUT_PULLUP);     
 
  escReceiver.attach(PIN_RC_THR);
  servoReceiver.attach(PIN_RC_STE);
 
  // Eingang Modus
  pinMode(PIN_MODE, INPUT_PULLUP); 
  pinMode(PIN_REVERS_1, INPUT_PULLUP); 
  pinMode(PIN_REVERS_2, INPUT_PULLUP); 
 
  // Servos definieren
  a1.attach(SERVO_1);
  a2.attach(SERVO_2);
 
  a1.write(90);
  a2.write(90);    
 
#ifndef __AVR_ATtinyX4__ 
#ifdef debug
  Serial.begin(57600); 
  Serial.flush();
  Serial.println("RC V-mixer");
  delay(100);
#endif
#endif
}
 
void loop() {
  // Aktuellen RC-Wert Gas lesen
  escReceiver.poll();
 
  // und gleich auch für's Steuerservo
  servoReceiver.poll();
 
  dbgOut("E:");
  dbgOut(escReceiver.getLastRCValue());
  dbgOut(",S:");
  dbgOutLn(servoReceiver.getLastRCValue());
 
  if (escReceiver.hasError() || servoReceiver.hasError()) {
    a1.write(90);
    a2.write(90);    
  }
  else if (escReceiver.hasNP() && servoReceiver.hasNP()) {
    doWork();
  }
#ifdef debug
//  delay(100);
#endif
}
 
/*
Modus Soft berechnung, Werte werden jeweils halbiert und dann addiert.
 */
void doWork() {
  // Werte holen
  int escValue = escReceiver.getValue();
  int servoValue = servoReceiver.getValue();
  dbgOut("E:");
  dbgOut(escValue);
  dbgOut(",S:");
  dbgOutLn(servoValue);
 
  // Nullpunkte festlegen
  escValue = escValue - escReceiver.getNP();
  servoValue = servoValue - servoReceiver.getNP();
 
  // Hier wird zwischen hard und soft unterschieden.
  if (digitalRead(PIN_MODE) == 0) {
    // jetzt Wertebereich verkleinern
    escValue = escValue / 2;
    servoValue = servoValue / 2;
  }  
 
  // die eigentliche Berechnung
  int servo1 = escValue + servoValue;
  int servo2 = escValue - servoValue;
 
  // Und damit das nicht aus dem Ruder läuft, etwas begrenzen
  servo1 = constrain(servo1, -128, 128);
  servo2 = constrain(servo2, -128, 128);
 
  if (digitalRead(PIN_REVERS_1) == 0) {
    // Servokanal 1 umkehren
    servo1 = servo1 * -1;
  }
 
  if (digitalRead(PIN_REVERS_2) == 0) {
    // Servokanal 1 umkehren
    servo2 = servo2 * -1;
  }
 
  // Nullpunkte wieder hinzu
  servo1 = servo1 + 128;
  servo2 = servo2 + 128;
 
  // Auf den Servo umsetzen
  servo1 = map(servo1,0, 255,0,180);
  servo2 = map(servo2,0, 255,0,180);
 
  // und einstellen
  a1.write(servo1);
  a2.write(servo2);
}

Programm mit Interrupt

Vielleicht ist euch aufgefallen, daß gerade beim Kreuzmischer die Servos arg zittern. Das liegt weder am Arduino noch an der Programmierung, naja, vielleicht doch, aber nicht so offentsichtlich. Denn wie wir bereits bei der RC Bibliothek gesehen haben, stören sich die Servo Bibliothek und der pulseIn() gegenseitig. Linderung, wenn auch keine Abhilfe, schafft da, das ganze Auswerten des Empfängers ebenfalls mit Intterupts zu machen. Hier das entsprechende Programm.

Kreuzmischer_int.ino
#include <debug.h>
#include <makros.h>
#include <RCReceive.h>
#include <Servo.h>
 
/*
 Kreuzmischer. Kanal 1 ist Geschwindigkeit, Kanal 2 ist Steuerung.
 Der Empfänger wird vom Pin 2 und 3 gelesen, 
 */
 
// Hardwareanbindung für Arduino Hardware
// Empfängerkanäle
const byte PIN_RC_THR = 2; // das ist INT 0 aber Pin 2!!!!
const byte PIN_RC_STE = 3; // das ist INT 1 aber Pin 3!!!!
 
// Modus Soft oder Hard
const byte PIN_MODE = 4;
const byte PIN_REVERS_1 = 7;
const byte PIN_REVERS_2 = 8;
 
// Ausgänge
const byte SERVO_1 = 9; // PWM Kanal 
const byte SERVO_2 = 10; // PWM Kanal
const byte LED = 13; // LED auf dem Board
 
RCReceive escReceiver;
RCReceive servoReceiver;
 
Servo a1, a2;
 
void setup() {
  // Kanäle auf Ausgang, und dann deaktivieren
  pinMode(SERVO_1, OUTPUT);
  pinMode(SERVO_2, OUTPUT);
 
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
 
  // Eingang für RC
  pinMode(PIN_RC_THR, INPUT_PULLUP); 
  pinMode(PIN_RC_STE, INPUT_PULLUP);     
 
  escReceiver.attachInt(PIN_RC_THR);
  servoReceiver.attachInt(PIN_RC_STE);
 
  // Eingang Modus
  pinMode(PIN_MODE, INPUT_PULLUP); 
  pinMode(PIN_REVERS_1, INPUT_PULLUP); 
  pinMode(PIN_REVERS_2, INPUT_PULLUP); 
 
  // Servos definieren
  a1.attach(SERVO_1);
  a2.attach(SERVO_2);
 
  a1.write(90);
  a2.write(90);    
 
#ifndef __AVR_ATtinyX4__ 
#ifdef debug
  Serial.begin(57600); 
  Serial.flush();
  Serial.println("RC V-mixer");
  delay(100);
#endif
#endif
}
 
void loop() {
 
  dbgOut("E:");
  dbgOut(escReciver.getLastRCValue());
  dbgOut(",S:");
  dbgOutLn(servoReciver.getLastRCValue());
 
  if (escReceiver.hasError() || servoReceiver.hasError()) {
    a1.write(90);
    a2.write(90);    
  }
  else if (escReceiver.hasNP() && servoReceiver.hasNP()) {
    doWork();
  }
  else {
    int value = escReceiver.getValue();
    dbgOut("E:");
    dbgOut(value);
    value = servoReceiver.getValue();
    dbgOut("S:");
    dbgOut(value);
    dbgOutLn(", no NP");
  }
 
#ifdef debug
  delay(100);
#endif
}
 
/*
Modus Soft berechnung, Werte werden jeweils halbiert und dann addiert.
 */
void doWork() {
  // Werte holen
  int escValue = escReceiver.getValue();
  int servoValue = servoReceiver.getValue();
  dbgOut("E:");
  dbgOut(escValue);
  dbgOut(",S:");
  dbgOutLn(servoValue);
 
  // Nullpunkte festlegen
  escValue = escValue - escReceiver.getNP();
  servoValue = servoValue - servoReceiver.getNP();
 
  // Hier wird zwischen hard und soft unterschieden.
  if (digitalRead(PIN_MODE) == 0) {
    // jetzt Wertebereich verkleinern
    escValue = escValue / 2;
    servoValue = servoValue / 2;
  }  
 
  // die eigentliche Berechnung
  int servo1 = escValue + servoValue;
  int servo2 = escValue - servoValue;
 
  // Und damit das nicht aus dem Ruder läuft, etwas begrenzen
  servo1 = constrain(servo1, -128, 128);
  servo2 = constrain(servo2, -128, 128);
 
  if (digitalRead(PIN_REVERS_1) == 0) {
    // Servokanal 1 umkehren
    servo1 = servo1 * -1;
  }
 
  if (digitalRead(PIN_REVERS_2) == 0) {
    // Servokanal 1 umkehren
    servo2 = servo2 * -1;
  }
 
  // Nullpunkte wieder hinzu
  servo1 = servo1 + 128;
  servo2 = servo2 + 128;
 
  // Auf den Servo umsetzen
  servo1 = map(servo1,0, 255,0,180);
  servo2 = map(servo2,0, 255,0,180);
 
  // und einstellen
  a1.write(servo1);
  a2.write(servo2);
}

Diskussion

Klaus Hommann, 2015/04/02 13:10
Hallo

Ich habe mir das Franzis Paket gekauft und wollte den Kreuzmischer für mein Panzermodell realisieren. Dazu habe ich das obige Programm in die Arduino IDE kopiert und mir die RCReicer lib heruntergeladen und diese in das Library Dir c:\Users\KLA\Documents\Arduino\ in dieses verzeichnis kopiert. Leider bekomme ich immer diese Fehlermeldung:
Arduino: 1.6.2 (Windows 7), Platine: "Arduino Uno"

kreuzmischer.ino:5:24: fatal error: makros.h: No such file or directory

compilation terminated.

c:\Users\KLA\Documents\Arduino\kreuzmischer\ in diese Dir steht die *.ino Datei und hier

c:\Users\KLA\Documents\Arduino\libraries\RCReceiver\ befindet sich die RCReceiver lib




Wohin muss die Lib kopiert werden oder was muss ich tun, damit die IDE sie findet,

Danke schonmal im Vorraus und frohe Ostern natürlich

Gruss
Klaus
Jörg Golombek, 2014/10/20 20:32
Hallo,
Wie oben bei ardufan habe ich das Problem bei allen Programmen die das Library RCReceive.h benötigen. Ich habe mir das neueste Library eingebunden, im Programm die Schreibweise kontrolliert aber ich become beim Überprüfen immer die Fehlermeldung: "error: 'RCRecive' does not name a type". Ich bin mit meinem Latein am Ende, bitte helft mir.
Danke Jörg
ardufan, 2013/11/17 13:16
Hallo,
bei funktioniert dein Kreuzmischer irgendwie nicht. Da noch ziemlicher Anfänger bin, weiß ich aber nicht, woran genau es liegt. Es kommt eine ganze Reihe Fehlermeldungen, die meiner Meinung hauptsächlich auf die, auch in der RC Reciver library, fehlende Datei RCRecive.h, zurückzuführen sind (es wird dafür aber die Datei EEPROMStruct.h gelistet). Wenn ich bei anderen deiner Projekte den Aufruf im Programm in RCReceive.h umbenenne, wird das Programm kompiliert und geuploadet, funktioniert dann aber trotzdem nicht. Der Servo / ESC wird nicht angesteuert (lediglich die LED auf PIN13 blinkt). Ich verwende übrigens das Arduino ProMini mit 16 Mhz, 328 Prozessor und 5V. Die Fehlermeldungen lauten:

Kreuzmischer:26: error: 'RCRecive' does not name a type
Kreuzmischer:27: error: 'RCRecive' does not name a type
Kreuzmischer.ino: In function 'void setup()':
Kreuzmischer:43: error: 'escReciver' was not declared in this scope
Kreuzmischer:44: error: 'servoReciver' was not declared in this scope
Kreuzmischer.ino: In function 'void loop()':
Kreuzmischer:67: error: 'escReciver' was not declared in this scope
Kreuzmischer:70: error: 'servoReciver' was not declared in this scope
Kreuzmischer.ino: In function 'void doWork()':
Kreuzmischer:89: error: 'escReciver' was not declared in this scope
Kreuzmischer:91: error: 'servoReciver' was not declared in this scope

Vielleicht fehlt auch einfach die entsprechende Datei in der Library-Version, die ich installiert habe.

Ich hoffe du kannst mir helfen,
mfG
Melden Sie sich an, um einen Kommentar zu erstellen.
arduino/modellbau/projekte/kreuzmischer.txt · Zuletzt geändert: 2018/11/04 10:51 von 127.0.0.1
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0