Go Down

Topic: Reading four RC Channels Using Interrupts Using Arduino DUE (COMPLETE GUIDE)  (Read 359 times) previous topic - next topic

MHY

Hi folks. After an extensive search for a code that uses interrupts to read 4 channels of RC receivers, I find some useful codes, but they all had their own weaknesses. Some of them were too slow, since they use the pulseIn() function, and some others didn't work for DUE. So I decided to gather all the advantages in one code. The following code is based on this library (which by the way is less accurate and doesn't work for the DUE). Initially I wanted to make a library, but I don't have time to do that, so I would be grateful if one of you guys carry this load. Here is the code:
Code: [Select]
byte x = 0, m = 1;
const byte MAX_PWM_NUMBER = 5;
byte PWM_COUNTER = 0;
byte MY_PWM;
byte PREVIOUS_CASE;
unsigned long PWM_VALUE[MAX_PWM_NUMBER];
bool PWM_LAST_STATE[MAX_PWM_NUMBER];
bool PWM_TRIGGER_STATE[MAX_PWM_NUMBER];
unsigned long PWM_TIMER[MAX_PWM_NUMBER];
byte PWM_PIN[MAX_PWM_NUMBER];

void setup() {
  Serial.begin(115200);

}

void loop() {
  if ( m == 1)
  {
    if ( x == 0)
    {
  PWm(13);
  Begin(true);
    }
    if ( x == 1)
     {
  PWm(12);
  Begin(true);
    }
      if ( x == 2)
     {
  PWm(11);
  Begin(true);
    }
      if ( x == 3)
     {
  PWm(10);
  Begin(true);
    }
      if ( x == 4)
     {
  PWm(9);
  Begin(true);
    }
    x++;
    if ( x == 5)
    {
      x = 0;
    }
  }

  Serial.print(PWM_VALUE[0]);
  Serial.print("  ");
  Serial.print(PWM_VALUE[1]);
  Serial.print("  ");
  Serial.print(PWM_VALUE[2]);
  Serial.print("  ");
  Serial.print(PWM_VALUE[3]);
  Serial.println("  ");
}

void ISR_GET(byte pwm) {
  unsigned long NOW = micros();
  bool PWM_RECENT_STATE = digitalRead(PWM_PIN[pwm]);
  if (PWM_RECENT_STATE != PWM_LAST_STATE[pwm])
  {
    if (PWM_RECENT_STATE == PWM_TRIGGER_STATE[pwm])
    {
      PWM_TIMER[pwm] = NOW;
    }
      else
      {
        PWM_VALUE[pwm] = (unsigned long)(NOW - PWM_TIMER[pwm]);
        m = 1;
      }
      PWM_LAST_STATE[pwm] = PWM_RECENT_STATE;
    }
}

void ISR0() {
  ISR_GET(0);
}
void ISR1() {
  ISR_GET(1);
}
void ISR2() {
  ISR_GET(2);
}
void ISR3() {
  ISR_GET(3);
}
void ISR4() {
  ISR_GET(4);
}

int Begin(bool TRIGGER_TYPE) {
  PWM_LAST_STATE[MY_PWM] = digitalRead(PWM_PIN[MY_PWM]);
  PWM_TRIGGER_STATE[MY_PWM] = TRIGGER_TYPE;
      m = 0;
      switch (MY_PWM) {
        case 0:
            PREVIOUS_CASE = 4;
            attachInterrupt(digitalPinToInterrupt(PWM_PIN[MY_PWM]), ISR0, CHANGE);
            break;
        case 1:
          PREVIOUS_CASE = 0;
            attachInterrupt(digitalPinToInterrupt(PWM_PIN[MY_PWM]), ISR1, CHANGE);
            
            break;
        case 2:
            PREVIOUS_CASE = 1;
            attachInterrupt(digitalPinToInterrupt(PWM_PIN[MY_PWM]), ISR2, CHANGE);
            break;
        case 3:
            PREVIOUS_CASE = 2;
            attachInterrupt(digitalPinToInterrupt(PWM_PIN[MY_PWM]), ISR3, CHANGE);
            break;
        case 4:
            PREVIOUS_CASE = 3;
            attachInterrupt(digitalPinToInterrupt(PWM_PIN[MY_PWM]), ISR4, CHANGE);
            break;
  return 0;
      }
}

void End() {
  detachInterrupt(digitalPinToInterrupt(PWM_PIN[PREVIOUS_CASE]));
}

void PWm (byte _pin){
  MY_PWM = PWM_COUNTER;
  PWM_COUNTER++;
  if (PWM_COUNTER == 5)
  {
    PWM_COUNTER = 0;
  }
  PWM_PIN[MY_PWM] = _pin;
  pinMode(PWM_PIN[MY_PWM],INPUT_PULLUP);
}

I used a FLYSKY FS-i6 transmitter and an FS-iA6 receiver and  here is the output on serial monitor:
Code: [Select]

1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1499  1105  1495  
1494  1499  1105  1495  
1494  1499  1105  1495  
1494  1499  1105  1495  
1494  1499  1105  1495  
1494  1499  1105  1495  
1494  1499  1105  1495  
1494  1499  1105  1495  
1494  1499  1105  1495  
1494  1487  1108  1500  
1500  1487  1108  1500  
1500  1487  1108  1500  
1500  1487  1108  1500  
1500  1487  1108  1500  
1500  1487  1108  1500  
1500  1487  1108  1500  
1500  1487  1108  1500  
1500  1487  1108  1500  
1495  1499  1105  1495  
1495  1499  1105  1495  
1495  1499  1105  1495  
1495  1499  1105  1495  
1495  1499  1105  1495  
1495  1499  1105  1495  
1495  1499  1105  1495  
1495  1499  1105  1495  
1495  1499  1105  1495  
1500  1486  1109  1499  
1500  1486  1109  1499  
1500  1486  1109  1499  
1500  1486  1109  1499  
1500  1486  1109  1499  
1500  1486  1109  1499  
1500  1486  1109  1499  
1500  1486  1109  1499  
1500  1486  1109  1499  
1499  1499  1096  1499  
1499  1499  1096  1499  
1499  1499  1096  1499  
1499  1499  1096  1499  
1499  1499  1096  1499  
1499  1499  1096  1499  
1499  1499  1096  1499  
1499  1499  1096  1499  
1499  1499  1096  1499  
1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1491  1097  1509  
1500  1491  1097  1509  
1498  1499  1095  1498  
1498  1499  1095  1498  
1498  1499  1095  1498  
1498  1499  1095  1498  
1498  1499  1095  1498  
1498  1499  1095  1498  
1498  1499  1095  1498  
1498  1499  1095  1498  
1498  1499  1095  1498  
1500  1492  1097  1509  
1500  1492  1097  1509  
1500  1492  1097  1509  
1500  1492  1097  1509  
1500  1492  1097  1509  
1500  1492  1097  1509  
1500  1492  1097  1509  
1500  1492  1097  1509  
1500  1492  1097  1509  
1500  1499  1097  1499  
1500  1499  1097  1499  
1500  1499  1097  1499  
1500  1499  1097  1499  
1500  1499  1097  1499  
1500  1499  1097  1499  
1500  1499  1097  1499  
1500  1499  1097  1499  
1500  1499  1097  1499  
1499  1486  1108  1500  
1499  1486  1108  1500  
1499  1486  1108  1500  
1499  1486  1108  1500  
1499  1486  1108  1500  
1499  1486  1108  1500  
1499  1486  1108  1500  
1499  1486  1108  1500  
1499  1486  1108  1500  
1495  1499  1104  1496  
1495  1499  1104  1496  
1495  1499  1104  1496  
1495  1499  1104  1496  
1495  1499  1104  1496  
1495  1499  1104  1496  
1495  1499  1104  1496  
1495  1499  1104  1496  
1495  1499  1104  1496  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1494  1499  1104  1495  
1494  1499  1104  1495  
1494  1499  1104  1495  
1494  1499  1104  1495  
1494  1499  1104  1495  
1494  1499  1104  1495  
1494  1499  1104  1495  
1494  1499  1104  1495  
1494  1499  1104  1495  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1500  1487  1109  1500  
1499  1499  1096  1500  
1499  1499  1096  1500  
1499  1499  1096  1500  
1499  1499  1096  1500  
1499  1499  1096  1500  
1499  1499  1096  1500  
1499  1499  1096  1500  
1499  1499  1096  1500  
1499  1499  1096  1508  
1500  1491  1096  1508  
1500  1491  1096  1508  
1500  1491  1096  1508  
1500  1491  1096  1508  
1500  1491  1096  1508  
1500  1491  1096  1508  
1500  1491  1096  1508  
1500  1491  1096  1508  
1500  1491  1096  1500  
1499  1499  1097  1500  
1499  1499  1097  1500  
1499  1499  1097  1500  
1499  1499  1097  1500  
1499  1499  1097  1500  
1499  1499  1097  1500  
1499  1499  1097  1500  
1499  1499  1097  1500  
1499  1499  1096  1509  
1500  1491  1096  1509  
1500  1491  1096  1509  
1500  1491  1096  1509  
1500  1491  1096  1509

The code is straightforward, but if there is any vague point, don't hesitate to ask your question.

IMPORTANT NOTE:
Since there is a bug in micros() function, replace the attached Wiring.c file in the following directory:
C:\Users\-------\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.12\cores\arduino
(Or something like this)

Go Up