RC Steuerung auslesen

Hallo,

ich habe ein Problem, eventuell kann mir ja einer helfen.
Über eine Servo Lib lese ich die Kanalinformation meiner 2,4Ghz Modellbaufunke aus. An dem 6. Kanal habe ich das vorhandene Potenziometer durch
ein Wiederstandsarray ersetzt. An diesem hängen mehrere Taster. Ich kann also jetzt durch drücken eines Beliebigen Tasters eine Servostellung übertragen. Sprich ich möchte mir damit einen kleinen Multiswitch bauen. Diese Servostellung lese ich in den Arduino ein und die Lib wandelt mir die Pulsdauer in einen Wert zwichen 0 und 254 um. Soweit so gut :slight_smile:
Ich möchte jetzt das wenn ich Taster 1 betätige das dieser wert mir einen Ausgangspin des Arduinos schaltet. Ist der Pin aus so wird er eingeschaltet und umgekehrt. Mein Problem besteht jetzt darin das es ein paar ms dauert bis der gemessene Wert stabil ist. Sprich wenn ich den Taster betätige lese ich zwichenwerte mit ein die mir dann ungewollt andere Ausgänge mit schalten. Ich bekomme es einfach nicht hin es so zu Programmieren das ich diesen Wert entprelle. Also z.b. erst wenn der Wert länger als 250ms anliegt das dann geschaltet wird. Mit der delay Funktion möchte ich aus bekannten Gründen nicht Arbeiten und mit dem Blinkwithoutdelay Beispiel komm ich nicht so richtig zu dem Ergebniss was ich gern hätte.

Also noch einmal eine kurze zusammenfassung:

Wert aus dem Empfänger auslesen und Umwandeln Funktioniert.
Ich versteh nur nicht wie ich warten kann bis der Wert so stabiel ist das ich in zum schalten verwenden kann.

void loop() {
 
  
  if (rcReceiver.hasNP() && !rcReceiver.hasError()) {     // nur wenn der Nullpunkt bestimmt worden ist,
    doWork();                                             // und es keinen Fehler gegeben hat soll die eigentliche Arbeit gemacht werden
  } 
  


void doWork() {
  // put your main code here, to run repeatedly
  
byte value = rcReceiver.getValue();  // auslesen des Empfangenen Wertes  ( 0 - 255 )


if ((value >= 150 && value <= 155) && !rcReceiver.hasError() && (millis() - previousMillis > interval)) { previousMillis = millis(); value1 = !value1; digitalWrite(led1, value1);}

Ich hoffe ich habe mich verständlich ausgedrückt und ihr könnt mit dem Code den ich auf das wesentliche reduziert habe etwas anfangen.

MFG Jens

Ich kann dir deine Frage nicht wirklich beantworten, aber die Idee finde ich genial. Hast du mal ein Array mit höheren Werten probiert oder andere Taster?

Was für eine Funke hast du und welche Funktionen steuerst du damit an?

Frank

Naja, von den Werten hab ich mich an dem Potentiometer was verbaut war Orientiert. Das war ein 5Kohm. Hab dann einfach die Werte so gewählt das ich 20 Taster auslesen kann. Das funktioniert auch sehr gut. Nach dem sich der Wert eingestellt hat Schwankt er maximal um +-1 . also kann mann noch ein vielfaches an Tastern auslesen. Leider bekomme ich die "Verzögerung" bis er steht nicht hin.

Die Funke ist eine FS-CT6B Fly Sky von HobbyKing. Also eine 6 Kanal. Schalten möchte ich damit Lampen und Motoren in einem Funktionsmodellboot.

Jens

moonglass:
Mein Problem besteht jetzt darin das es ein paar ms dauert bis der gemessene Wert stabil ist. Sprich wenn ich den Taster betätige lese ich zwichenwerte mit ein die mir dann ungewollt andere Ausgänge mit schalten. Ich bekomme es einfach nicht hin es so zu Programmieren das ich diesen Wert entprelle. Also z.b. erst wenn der Wert länger als 250ms anliegt das dann geschaltet wird.

Dafür würde ich mir eine Funktion machen, die Du aus der loop heraus dauernd aufrufst und die die Werte für

  • aktuellen Wert
  • Minimalwert im Wertebereich
  • Maximalwert im Wertebereich
  • Mindestverweildauer im Wertebereich
    auswertet und dann entweder false (aktueller Wert ist nicht oder nicht lange genug im Wertebereich) oder true (aktueller Wert ist lange genug im Wertebereich) zurückliefert.

Beispielfunktion wie die Funktion “inRangeSince” im Beispielsketch:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println();
}


boolean inRangeSince(int value, int rangeMin, int rangeMax, unsigned long time)
{
  static boolean lastInRange=false;
  static unsigned long lastMillis;
  boolean thisInRange; 
  unsigned long thisMillis;  
  if (value<rangeMin || value>rangeMax)
  {
    lastInRange=false;
    return false;
  }
  else if (lastInRange==false)
  {
    lastInRange=true;
    lastMillis=millis();
    return false;
  }
  else if (millis()-lastMillis>time)
    return true;
  else 
    return false;  
}


void loop() {
  // put your main code here, to run repeatedly: 
  boolean inRange;
  char linebuf[50];
  int i;
  int rangeTime=250;
  for (i=0; i<255; i++)
  {
    inRange=inRangeSince(i, 150, 155, rangeTime);
    sprintf(linebuf,"i=%d, millis=%ld, in Range since longer than %dms: %d ",i,millis(),rangeTime, inRange);
    Serial.println(linebuf);
    delay(100);
  }
  while(1);
}

Wenn Du auf mehrere verschiedene Werte testen möchtest, brauchst Du diese Funktion mehrfach, oder Du mußt die statischen Variablen als Array anlegen und den Arrayindex des Wertes mit übergeben.

Bei mehreren zu testenden Bereichen würde ich mir auch überlegen, ob nicht eine einzige Funktion sinnvoller ist, die die Bereiche hartcodiert hat und die dann entweder 0 zurückliefert (kein Bereich lange genug gesetzt) oder 1, 2, 3 ,4 etc. falls der aktuelle Wert lange genug in einem Wertebereich stagniert.

Puh, ich denke damit muss ich mich jetzt erstmal eine Weile auseinander setzen. Hab zwar schon hin und wieder mal was für den Arduino Programmiert, aber ich muss zugeben das übersteigt momentan meine Fähigkeiten. Hatte mir das Irgendwie einfacher vorgestellt. Aber trotzdem erstmal danke für deine Hilfe!

Jens

Hallo,

ich habe ein ähnliches Problem anders gelöst, mit dem Befehl pulseIn(). Damit lese ich die Kanäle meiner Funke aus.

Gruß

Ein Alternativ-Vorschlag zu jurs (bin nur zu langsam, nicht besser) :

Auf ± 1 würde ich mich nicht verlassen, Widerstände schwanken z.B. mit der Temperatur ,
aber aus einem Analog-Wert 0 … 255 10 verschiedene zu identifizieren, sollte möglich sein.
20 evtl. auch.

Um eine Beruhigungsphase abzuwarten, musst du noch den Wert des vorigen Zyklus speichern, um die Änderungsrate zu erkennen.
Und bei einer Änderung von z.B. < 5 / 10ms ist dein Ergebnis “gültig”.

#define DX 5
#define DT 10

byte oldvalue;
unsigned long oldtime;

void doWork( )   // wird nur aufgerufen wenn ok 
{ 
   byte value = rcReceiver.getValue();  // auslesen des Empfangenen Wertes  ( 0 - 255 )
   if (value - oldvalue < DX && value - oldvalue > -DX && millis() - oldtime >= DT ) setLed(value);
   else
   {
        // zappelt noch
        if (millis() - oldtime >= DT)
        {
            oldtime = millis();
            oldvalue = value;
        }
   }
}

// Beispiel : Abhängig von value eine LED von 5 Led einschalten
#define NUMLEDS 5
const byte ledPin[5] = {3,4,5,6,7};  // depends on hardware
const byte aktLed[] = {0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4};  // map 16 values to 5 leds 

void setLed(byte value)
{
     value = value >> 4  ; // 0 .. 255 --> 0 .. 15, zum Zugriff auf aktLed
     for ( int i = 0; i < NUMLEDS; i++)
     digitalWrite(ledPin[i],LOW);
     digitalWrite(ledPin[aktLed[value]],HIGH);
}

Die 5 Leds aus 16 aus 256 Werten ist nur ein Beispiel …
Genauso weiss ich nicht, ob die Beispilewerte für DX und DT Sinn machen.