Neues RC Projekt - 16 Kanal Schalter für Lichtsteuerung

Hallo zusammen,

nach einer etwas längeren Pause melde ich mich mal wieder zu dem Thema.

Der Sketch funktioniert ja bisher eigentlich soweit ganz gut. Einzig das Problem das er durch die langsam fallenden PWM Werte einen falschen Kanal schaltet ist noch da. Ich habe mal die Fernsteuerung meines Nachbarn ausgelesen und auch dort ist dieses Verhalten feststellbar. Also beim betätigen des Tasters ist der richtige Wert annähernd sofort da und bei loslassen dauert es etwas bis er wieder neutral ist.
Ich dachte mir jetzt ich löse das mit einem "busy" Merker. Den wollte ich im case auf 1 setzen und wenn der Kanal geschaltet hat wieder auf 0. Das ganze in der readRCinput mit einer if Schleife abgefragt das er nur einen neuen Wert einliest, wenn busy =0 ist. Ich bekomme es aber nicht hin, den gleichen Merker in der Class und gleichzeitig auch ausserhalb in dem case oder der ReadRCInput zu verwenden. Gibt es denn dazu Möglichkeiten?
Danke nochmal für eure Hilfe und Anregungen.
Gruß Thomas

mit Sketch und einer Serie von Serial Ausgaben wäre das vermutlich leichter zu sehen was du siehst...

Moin,

man sieht diesen Effekt ja in Post #80. Hier ist der Sketch in dem ich das probiert habe:

// 16 Kanal Schalter für Lichtsteuerung V1.2
// Fernsteuerung: Flysky i6X
// CPU: Arduino Nano
// https://forum.arduino.cc/t/neues-rc-projekt-16-kanal-schalter-fur-lichtsteuerung/1143800/23


enum State {IDLE, PULSE, MEMA, MEMB};  // Leerlauf, Impulse,

class Kanal {
  protected:
    const byte channel;
    const byte pin;
    const byte mem;
    
   
    State state;
    uint32_t previousMillis = 0; // Zeitmanagement

  public:
    Kanal(const byte channel, const byte pin, const byte mem) : channel(channel), pin(pin), mem(mem) {}
   


    void fire() {
      switch (state) {
        case IDLE:
         if (mem == 0) {
            previousMillis = millis();
            digitalWrite(pin, HIGH);   
            state = PULSE;
         }
          else {
            previousMillis = millis();
            digitalWrite(pin, HIGH);      
            state = MEMA;
            busy = 0;
          }
          break;
        case MEMB:
        previousMillis = millis();
          digitalWrite(pin, LOW);
          //delay(400);
          state = IDLE; 
          busy = 0;      
          break;
      }

    }

    void begin() {
      pinMode(pin, OUTPUT);
    }

    void update(uint32_t currentMillis = millis()) {
      switch (state) {
        case PULSE :
          if (currentMillis - previousMillis > 1000) {   // nach n millisekunden abschalten
            digitalWrite(pin, LOW);
            state = IDLE;
            busy = 0;
          }
          break;
        case MEMA :
          if (currentMillis - previousMillis > 1000) {  // nach n millisekunden in den nächsten Status
            state = MEMB;

          }
          break;
      }
    }
};

const byte PWMPin1 {2};
const byte PWMPin2 {3};
uint16_t PWMEingang1;
uint16_t PWMEingang2;
uint16_t Start;
uint16_t Wartezeit;
uint32_t currentMillis;




Kanal kanal [] = {
  //                channel, Pin,  mem,   befehl auf serieller
  /*  Daten Kanal01 = */{1,   4,   1 },  // a
  /*  Daten Kanal02 = */{2,   5,   0 },  // b
  /*  Daten Kanal03 = */{3,   6,   1 },  // c
  /*  Daten Kanal04 = */{4,   7,   1 },  // d
  /*  Daten Kanal05 = */{5,   8,   0 },  // e
  /*  Daten Kanal06 = */{6,   9,   0 },  // f
  /*  Daten Kanal07 = */{7,  10,   0 },  // g
  /*  Daten Kanal08 = */{8,  11,   0 },  // h
  /*  Daten Kanal09 = */{9,  12,   0 },  // i
  /*  Daten Kanal10 = */{10, 13,   0 },  // j
  /*  Daten Kanal11 = */{11, A0,   0 },  // k
  /*  Daten Kanal12 = */{12, A1,   0 },  // l
  /*  Daten Kanal13 = */{13, A2,   0 },  // m
  /*  Daten Kanal14 = */{14, A3,   0 },  // n
  /*  Daten Kanal15 = */{15, A4,   0 },  // o
  /*  Daten Kanal16 = */{16, A5,   0 }   // p
};

int busy = 0;
 
void setup() {

  pinMode (PWMPin1, INPUT);
  pinMode (PWMPin2, INPUT);
  Serial.begin(115200);

  for (auto &i : kanal) {
    i.begin();
  }
  Serial.println("und go");

}

void loop() {   // ein Durchlauf benötigt etwa 40ms = Zykluszeit
  Start = millis(); 
  readRCinput(); 
  checkRCSwitch1();
  Serial.print(F("PWM CH1: "));
  Serial.print(PWMEingang1);
  Serial.print(F("  PWM CH2: "));
  Serial.println(PWMEingang2);
  Start = millis();
  Serial.print(F("Millis"));
  Serial.println(Start);
  Serial.print(F("busy = "));
  Serial.println(busy);



  uint32_t currentMillis = millis();
  for (auto &i : kanal) {
    i.update(currentMillis);
  }
}



void readRCinput(){
 if (busy == 0){
  int PWM1IN = pulseIn(PWMPin1, HIGH ); //Read PWM Pulse
  if (PWM1IN > 900 && PWM1IN < 2100)
  {
    PWMEingang1 = PWM1IN;
  }
  int PWM2IN = pulseIn(PWMPin2, HIGH ); //Read PWM Pulse
  if (PWM2IN > 900 && PWM2IN < 2100)
  {
    PWMEingang2 = PWM2IN;
}
}
}
void checkRCSwitch1()
{
  switch (PWMEingang1)
  {
    case 950 ... 1050:
      busy = 1;
      kanal[0].fire();
      break;
    case 1950 ... 2050:
      busy = 1;
      kanal[1].fire();
      break;
    case 1100 ... 1200:
      kanal[2].fire();
      break;
    case 1800 ... 1900:
      kanal[3].fire();
      break;
    case 1240 ... 1340:
      kanal[4].fire();
      break;
    case 1350 ... 1450:
      kanal[5].fire();
      break;
    case 1530 ... 1630:
      kanal[6].fire();
      break;
    case 1660 ... 1760:
      kanal[7].fire();
      break;
    default:
      break;
  }
}

Er meckert halt an, das der Merker "busy" in der class nicht deklariert ist. Deshalb die Frage ob es eine Möglichkeit gibt einen Merker quasi "global" zu nutzen. In und ausserhalb der Class.

Gruß Thomas

er hat ja recht. Dort wo die Klasse steht, hast noch kein globales busy.
Hättest du das

int busy = 0;

vor der Klasse definiert, wüsste die Klasse auch dass es ein busy gibt.

Auch wenns dann vieleicht kompiliert, schön ist was anderes.

Das Problem ist die EINGABE und nicht die AUSGABE.
Daher gehört die EINGABE richtig gestellt.

checkRCSwitch1 muss so erweitert werden, dass erst dann zur Ausgabe gefeuert wird, wird der (gemappte) Wert lang genug anliegt.

Hi Noiasca,

Da hast du absolut recht. Aber anscheinend ist das bei allen Fernsteuerungen so, von daher glaube ich nicht das sich das berichtigen lässt. Bleibt also nur hier am sketch zu feilen. Da das ganze eher Zeit unkritisch ist, dürfte das am Ende irgendwie gehen. Funktion geht mir da über Schönheit.

Bei deinem Lösungsansatz müsste ich aber irgendwie die Toleranz mit berücksichtigen die sich ergibt. Als Beispiel, erster PWM Wert ist 2000, dann müsste die zweite Messung (im Abstand von 100ms??) im Rahmen von 2000 +/1 z.b. 15 sein. Dann erst geht er in den Case und schaltet den Kanal.

nein.
nimm den gemappten wert aus checkRCSwitch1, aber eben nicht sofort feuern sondern z.b. nach 500ms

... (jetzt muss ich mal hochscrollen) ...

genau das hab dir schon vor 20 Tagen vorgeschlagen.
Bitte den Sketch aus #71 analysieren.
Vieles dürfte stimmen.

ich werde es mal probieren und gebe dann Rückmeldung :+1:
Danke erst Mal.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.