Photon external interrupts trigger unnecessarily

Hi there, I’ve been using Particle Photon WiFi boards for a while now for various things. But up until recently (my last two projects) I haven’t really required external interrupt inputs.

Current project detail: I have three quadrature encoders wired to the Photon, all encoders are NPN output with external pull-up resisters soldered to the PCB the Photon is plugged into. These resistors are sized such that a reasonable amount current flows to reduce the influence of electrical noise (i.e. 10mA at 3.3VDC) and the cables are shielded and ground at the PCB. Encoders are power by separate 12vdc supply.

This brings me to my question/problem. If I have WiFi.On() and start to receive many interrupt requests from a single encoder (roughly 600 or 700 pulse per second), somehow the other interrupt routine(s) start counting, but those encoders are not turning (zero pulses), and no DC motors are running so it’s not electrical noise. If I turn WiFi.off() the problem goes away, all encoders count correctly.

This has happened on both my projects requiring external interrupts, the interrupts will either count extra or other interrupts seem to get triggered even though they are not changing.

I have checked for electrical noise and the quadrature square waves look clean. I also tested with a separate PIC Microprocessor 18F452 which supports three external interrupts. This is connect using the same encoders, on the same PCB and the counts are accurate.

See .INO file and log files.

SYSTEM_MODE(AUTOMATIC);
SYSTEM_THREAD(ENABLED);

#define i2c_SDA_data    D0
#define i2c_SCL_clock   D1
#define LH_EncoderA     D2
#define LH_EncB_Input   D3
#define LH_EncoderB     digitalRead(LH_EncB_Input)
#define RH_EncoderA     D4
#define RH_EncB_Input   D5
#define RH_EncoderB     digitalRead(RH_EncB_Input)
#define Steer_pos_encA  A2              // steering encoder interrupt
#define Steer_pos_encB	D6

// define data output structure
typedef struct data_out{
  uint8_t 	Heartbeat;   // iBuffer[0] 0x00
  uint8_t 	CommsPacket; // iBuffer[1] 0x01
  int16_t	Position;      // iBuffer[2] 0x02 0x03
  uint16_t  Ranger;      // iBuffer[4] 0x04 0x05
  uint16_t  Voltage;     // iBuffer[6] 0x06 0x07
  int32_t   FLH_Dist;    // iBuffer[8] 0x08 0x09 0x0a 0x0b
  int32_t   FRH_Dist;    // iBuffer[12] 0x0c 0x0d 0x0e 0x0f
  uint8_t   iConnectStep;// iBuffer[16] 0x10
  uint8_t   Status;      // iBuffer[17] 0x11
};

typedef union data_union_out{
  data_out DATA;
  uint8_t REG[18];
};

data_union_out comms_out;

//**********************************************
//Handles external interrupt for Righthand side encoder
// adds or subtracts 1 to/from an encoder value
//
//**********************************************
void RH_Encoder(void)
{
	if(RH_EncoderB)
	{
		++comms_out.DATA.FRH_Dist;
	}
	else
	{
		--comms_out.DATA.FRH_Dist;
	}
}


//**********************************************
//Handles external interrupt for Lefthand side encoder
// adds or subtracts 1 to/from an encoder value
//
//**********************************************
void LH_Encoder(void)
{
	if(LH_EncoderB)
	{
		++comms_out.DATA.FLH_Dist;
	}
	else
	{
		--comms_out.DATA.FLH_Dist;
	}
}


//**********************************************
//Handles external interrupt for steering encoder
// adds or subtracts 1 to/from an encoder value
//
//**********************************************
void Steer_Encoder(void)
{
	if(digitalRead(Steer_pos_encB))
	{
		--comms_out.DATA.Position;
	}
	else
	{
		++comms_out.DATA.Position;
	}
}


//**********************************************
// Function to read i2c encoder valves
//  
//  
//**********************************************
void readi2c_encoders(void)
{
  uint8_t i2c_buf[32];

  // First set the pointer to zero
  Wire.beginTransmission(0x28); // transmit to slave device
  Wire.endTransmission();    // stop transmitting
  uint8_t result = Wire.requestFrom(0x28, 10);
  if(result > 0)    // request bytes from slave device
  {
    uint8_t i2c_ptr=0;
    while(Wire.available()){   // slave may send less than requested
      i2c_buf[i2c_ptr] = Wire.read();    // receive a byte as character
      ++i2c_ptr;
    }

    comms_out.DATA.FLH_Dist = ((int32_t)i2c_buf[3]<<24) + ((int32_t)i2c_buf[2]<<16) + ((int32_t)i2c_buf[1]<<8) + i2c_buf[0];
    comms_out.DATA.FRH_Dist = ((int32_t)i2c_buf[7]<<24) + ((int32_t)i2c_buf[6]<<16) + ((int32_t)i2c_buf[5]<<8) + i2c_buf[4];
    comms_out.DATA.Position = ((int16_t)i2c_buf[9]<<8) + i2c_buf[8];
  }
}


void setup() {
  Serial.begin(115200);
  Serial1.begin(9600);
  Wire.end();
  // i2c setup
  Wire.setSpeed(CLOCK_SPEED_100KHZ);
  Wire.begin(); // being being an i2c master

  //WiFi.off();
  WiFi.on();

  pinMode(LH_EncoderA, INPUT_PULLUP);
  pinMode(LH_EncB_Input, INPUT_PULLUP);
  pinMode(RH_EncoderA, INPUT_PULLUP);
  pinMode(RH_EncB_Input, INPUT_PULLUP);
  pinMode(Steer_pos_encA, INPUT_PULLUP);
  pinMode(Steer_pos_encB, INPUT_PULLUP);

  // Setup encoder external interrupts
  Serial.printlnf("LH ISR %u", attachInterrupt(LH_EncoderA, LH_Encoder, RISING));
  // Setup encoder external interrupts
  Serial.printlnf("RH ISR %u", attachInterrupt(RH_EncoderA, RH_Encoder, RISING));
  // Setup encoder external interrupts
  Serial.printlnf("Steer ISR %u", attachInterrupt(Steer_pos_encA, Steer_Encoder, RISING));
}

void loop()
{
  //readi2c_encoders();  // Using a PIC 18F452 to read all three encoders (comment in for testing)
  Serial.printlnf("LH:%ld RH:%ld Pos_Enc:%d", comms_out.DATA.FLH_Dist, comms_out.DATA.FRH_Dist, comms_out.DATA.Position);
  delay(1000);
}

Encoder log file from putty:
LH:0 RH:9083 Pos_Enc:-31
LH:0 RH:9083 Pos_Enc:-31
LH:0 RH:9083 Pos_Enc:-31
LH:0 RH:9083 Pos_Enc:-31
LH:0 RH:9083 Pos_Enc:-31
LH:0 RH:9053 Pos_Enc:-31
LH:0 RH:8947 Pos_Enc:-31
LH:0 RH:8771 Pos_Enc:-31
LH:0 RH:8598 Pos_Enc:-31
LH:0 RH:8404 Pos_Enc:-31
LH:0 RH:8277 Pos_Enc:-31
LH:0 RH:8065 Pos_Enc:-31
LH:0 RH:7881 Pos_Enc:-31
LH:0 RH:7790 Pos_Enc:-31
LH:0 RH:7187 Pos_Enc:-31
LH:0 RH:6452 Pos_Enc:-36
LH:0 RH:5663 Pos_Enc:-41
LH:0 RH:4905 Pos_Enc:-41
LH:0 RH:4168 Pos_Enc:-48
LH:0 RH:3910 Pos_Enc:-48
LH:0 RH:3904 Pos_Enc:-48
LH:0 RH:3898 Pos_Enc:-48
LH:0 RH:3874 Pos_Enc:-48
LH:0 RH:3596 Pos_Enc:-48
LH:0 RH:3382 Pos_Enc:-48
LH:0 RH:3070 Pos_Enc:-48
LH:0 RH:2468 Pos_Enc:-48
LH:0 RH:1787 Pos_Enc:-57
LH:0 RH:1018 Pos_Enc:-59
LH:0 RH:839 Pos_Enc:-59
LH:0 RH:422 Pos_Enc:-62
LH:0 RH:62 Pos_Enc:-62
LH:0 RH:-128 Pos_Enc:-62
LH:0 RH:-305 Pos_Enc:-62
LH:0 RH:-290 Pos_Enc:-62
LH:0 RH:13 Pos_Enc:-62
LH:0 RH:10 Pos_Enc:-62
LH:0 RH:3 Pos_Enc:-62
LH:0 RH:-3 Pos_Enc:-62
LH:0 RH:-8 Pos_Enc:-62
LH:0 RH:-11 Pos_Enc:-62
LH:0 RH:-14 Pos_Enc:-62
LH:0 RH:-16 Pos_Enc:-62
LH:0 RH:-16 Pos_Enc:-62
LH:0 RH:-16 Pos_Enc:-62
LH:0 RH:-16 Pos_Enc:-62
LH:0 RH:-17 Pos_Enc:-62

As can be seen from the log file, Pos_Enc counts pulses even though I’m only turning one of the encoders, but if I turn WiFi.off() this is not the case.

Any help would be much appreciated, thanks heaps.