Untested code but should work with your current wiring/pin assignment
A quick analogy of what an interrupt is and why it is useful
Picture a fire alarm system with a processor, an alarm sounder and a fire detection sensor.
If the program loop took 1 minute to loop back to the start, if the fire detector sensor triggered, it could take almost 1 minute to reach the code line where the alarm sounder is triggered.
Using an "ISR - interrupt service routine" attached to the sensor pin means as soon the the pin changes state the processor will halt loop execution, jump out of the loop and run the defined ISR subroutine ( sound the alarm ) and then when finished executing the ISR subroutine will pass back to the loop allowing it to continue to run.
When you are trying to measure the time period of pulses - using a solution that can instantly record the time the pulse changes (goes HIGH, goes LOW or CHANGES state) is a must
#include <EnableInterrupt.h>
#define SERIAL_PORT_SPEED 57600
#define RC_NUM_CHANNELS 6
// define the array cell positions that we will store our values in, e.g. channel one will be stored in array position zero, channel 2 in array position 1 and so on...
#define RC_CH1 0
#define RC_CH2 1
#define RC_CH3 2
#define RC_CH4 3
#define RC_CH5 4
#define RC_CH6 5
// define physical pins used to connect Arduino to the radio receiver - can be any digital or analog pins - best to avoid pin 13
#define RC_CH1_INPUT 2
#define RC_CH2_INPUT 3
#define RC_CH3_INPUT 4
#define RC_CH4_INPUT 5
#define RC_CH5_INPUT 6
#define RC_CH6_INPUT 7
// define 3 arrays to store time values
uint16_t rc_values[RC_NUM_CHANNELS]; // the final channel readings will be stored here
uint32_t rc_start[RC_NUM_CHANNELS]; // the start time of the pulse - i.e. the time the pin changes to HIGH will be stored here
volatile uint16_t rc_shared[RC_NUM_CHANNELS]; // the channel times (current time minus start time = pulse width)are stored here during the interrupt routine but they must be copied from this array to our rc_values array to be used in the loop due to their volatile nature - e.g. the values were changed outside of the loop by the (ISR) interrupt service routine
// subroutine called in loop to copy volatile array values from memory to rc_values array so we can use them in our loop
void rc_read_values() {
noInterrupts(); // turn off interrupts
memcpy(rc_values, (const void *)rc_shared, sizeof(rc_shared)); // copy volatile array values from rc_shared array to rc_values array
interrupts(); // turn interrupts on
}
// subroutine to calculate all channel time values - we pass 2 patameters into the subroutine - the channel number e.g. RC_CH1 and the pin number e.g. RC_CH1_INPUT and it stores the value in our shared (volatile) array
void calc_input(uint8_t channel, uint8_t input_pin) {
if (digitalRead(input_pin) == HIGH) {
rc_start[channel] = micros(); // if pin went high its the start of a pulse so store the time the pin changed
} else {
uint16_t rc_compare = (uint16_t)(micros() - rc_start[channel]); // pin has gone low so calulate "pulse period" - current time - start time to get channel time value
rc_shared[channel] = rc_compare; // store channel time value in our shared volatile array
}
}
// series of routines - passing in the parameters - values of storage array number and input pin number using the generic calc_input(storage array number, input pin number)
void calc_ch1() {
calc_input(RC_CH1, RC_CH1_INPUT);
}
void calc_ch2() {
calc_input(RC_CH2, RC_CH2_INPUT);
}
void calc_ch3() {
calc_input(RC_CH3, RC_CH3_INPUT);
}
void calc_ch4() {
calc_input(RC_CH4, RC_CH4_INPUT);
}
void calc_ch5() {
calc_input(RC_CH5, RC_CH5_INPUT);
}
void calc_ch6() {
calc_input(RC_CH6, RC_CH6_INPUT);
}
void setup() {
Serial.begin(SERIAL_PORT_SPEED);
// define pin modes
// output pins
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
// input pins
pinMode(RC_CH1_INPUT, INPUT);
pinMode(RC_CH2_INPUT, INPUT);
pinMode(RC_CH3_INPUT, INPUT);
pinMode(RC_CH4_INPUT, INPUT);
pinMode(RC_CH5_INPUT, INPUT);
pinMode(RC_CH6_INPUT, INPUT);
// assign interrupts (Interrupt Service Routine) to pins and the name of the subroutine code to run when the pin changes
// enableInterrupt(pin number, subroutine name, state - options HIGH/LOW/CHANGE)
enableInterrupt(RC_CH1_INPUT, calc_ch1, CHANGE);
enableInterrupt(RC_CH2_INPUT, calc_ch2, CHANGE);
enableInterrupt(RC_CH3_INPUT, calc_ch3, CHANGE);
enableInterrupt(RC_CH4_INPUT, calc_ch4, CHANGE);
enableInterrupt(RC_CH5_INPUT, calc_ch5, CHANGE);
enableInterrupt(RC_CH6_INPUT, calc_ch6, CHANGE);
}
void loop() {
rc_read_values(); // refresh values by copying values from memory to array each loop
Serial.print("CH1:"); Serial.print(rc_values[RC_CH1]); Serial.print("\t");
Serial.print("CH2:"); Serial.print(rc_values[RC_CH2]); Serial.print("\t");
Serial.print("CH3:"); Serial.print(rc_values[RC_CH3]); Serial.print("\t");
Serial.print("CH4:"); Serial.print(rc_values[RC_CH4]); Serial.print("\t");
Serial.print("CH5:"); Serial.print(rc_values[RC_CH5]); Serial.print("\t");
Serial.print("CH6:"); Serial.println(rc_values[RC_CH6]);
// swtich our pins high of low
// pin 13 (channel 1)
if (rc_values[RC_CH1] > 1400 )
{
digitalWrite(13, HIGH);
}
else
{
digitalWrite(13, LOW);
}
// pin 12 (channel 2)
if (rc_values[RC_CH2] > 1400 )
{
digitalWrite(12, HIGH);
}
else
{
digitalWrite(12, LOW);
}
// pin 11 (channel 3)
if (rc_values[RC_CH3] > 1400 )
{
digitalWrite(11, HIGH);
}
else
{
digitalWrite(11, LOW);
}
// pin 10 (channel 4)
if (rc_values[RC_CH4] > 1400 )
{
digitalWrite(10, HIGH);
}
else
{
digitalWrite(10, LOW);
}
// pin 9 (channel 5)
if (rc_values[RC_CH5] > 1400 )
{
digitalWrite(9, HIGH);
}
else
{
digitalWrite(9, LOW);
}
// pin 8 (channel 6)
if (rc_values[RC_CH6] > 1400 )
{
digitalWrite(8, HIGH);
}
else
{
digitalWrite(8, LOW);
}
}
Info about volatile valuesA variable should be declared volatile whenever its value can be changed by something beyond the control of the code section in which it appears, such as a concurrently executing thread. In the Arduino, the only place that this is likely to occur is in sections of code associated with
interrupts, called an interrupt service routine.
https://www.arduino.cc/reference/en/language/variables/variable-scope-qualifiers/volatile/