WiFi interfering with my own Interrupt function.

User avatar
ian9000
Posts: 1
Joined: Thu Jun 15, 2023 3:42 pm

WiFi interfering with my own Interrupt function.

Postby ian9000 » Thu Jun 15, 2023 3:47 pm

What am I doing wrong?

I want to use a ESP32 to receive signals from 433Mhz, take that message and place on a MQTT topic.

My code below works until I add WiFi.

The circuit is simple. I have a ESP32 WROOM and connected to GPIO35 is a QAM_RX 433Mhz receiver

My code basically sets up an function to trigger on an Interrupt of when the state changes on GPIO35.
In that function I record the time (millis) and then when the state changes and calls the Interrupt I record the time and take the difference. I then record the duration of my and its state in an array of struct called PULSE.
Of course the function first looks for a preample before recording and likewise a postample to stop.

Simple enough.

Compile the code and press a button a 433 device I have and bingo my code display the recorded message in the PULSE buffer.

My problem comes when I add the WiFi library. The extra code is enabled by the #define. At the moment I simply initate the library and connect to my MyWifi, nothing else.
At this point my code stops working. Sometimes my code detects the preample but never a full message.

I tried running my code on Core0 so the WiFi could have core1, but that didn't work.

What am I missing?

I read in the forums of people having trouble with WiFi interfering with Timers, but my interrupt is being triggered by state change on GPIO35.

I know from previous tests (without WiFi enabled) my received single was giving me 132 elements in my PULSE buffer. So I tried adding a counter to see how many times my function was being triggered when the WiFi was enabled. If answer was variable and never once did I get 132.

Any ideas?

Code: Select all

#define BASEPROTOCOL433_RX_PREAMPLE_THRESOLD_MIN	8000
#define BASEPROTOCOL433_RX_PREAMPLE_THRESOLD_MAX 25000
#define RAWBITBUFFERSIZE   150

// Declare states that we can be in
#define	BASEPROTOCOL433_RX_LISTENMODE				0x00		//  Listening for a message to start on the RX
#define	BASEPROTOCOL433_RX_RECEIVEMODE				0x01		//  Currently receiving a message over RX
#define BASEPROTOCOL433_RX_MESSAGERECEIVED			0x02		//  Received a complete message
#define BASEPROTOCOL433_SETUP                       0xF0

// Struct which is used to store received pulses in a buffer
typedef struct {
  bool state;                       // state 0 or 1 (Boolean)
  unsigned int duration;            // duration of the state in ms
} PULSE;

//#define USE_WIFI
#ifdef USE_WIFI
  const char* wifi_ssid     = "MyWiFi";
  const char* wifi_password = "0101010101";
  const char* wifi_hostname = "ESP32";

  #include <WiFi.h>
#endif

#include <Arduino.h>
TaskHandle_t Task1;
volatile PULSE rawBitBuffer[RAWBITBUFFERSIZE];
volatile unsigned int rawBitBufferPosition  = 0;
volatile byte baseProtocolState = BASEPROTOCOL433_SETUP;
volatile unsigned long lastRedTime = 0;

void IRAM_ATTR qam_rx4_isr() {

  static unsigned int prevTime = 0; // lastTime
  unsigned int newTime = micros();  // now

  // Calculate the duration of the current signal state
  unsigned int duration = newTime - prevTime;

  bool state = digitalRead(35);

  // If we find the preample (4.5ms < x < 12.5ms) trigger baseProtocolState to receiving mode
  if ((duration > BASEPROTOCOL433_RX_PREAMPLE_THRESOLD_MIN) && (duration < BASEPROTOCOL433_RX_PREAMPLE_THRESOLD_MAX) ) {
    if (baseProtocolState == BASEPROTOCOL433_RX_RECEIVEMODE) {
        baseProtocolState = BASEPROTOCOL433_RX_MESSAGERECEIVED;
        detachInterrupt(35);
    } else {
        baseProtocolState = BASEPROTOCOL433_RX_RECEIVEMODE;
    }
  }

	if (baseProtocolState == BASEPROTOCOL433_RX_RECEIVEMODE) {
		// Store the duration of the received pulse
		rawBitBuffer[rawBitBufferPosition].state = !state;
		rawBitBuffer[rawBitBufferPosition].duration = duration;
		rawBitBufferPosition++;
	}

	// Check for a buffer overflow
	if (rawBitBufferPosition == (RAWBITBUFFERSIZE - 1)) {
		baseProtocolState =BASEPROTOCOL433_RX_LISTENMODE;
		rawBitBufferPosition = 0;
	}

  prevTime = newTime;

}

void loop2(void * parameter) {
  // loop2 runs on Core0
  int x;

  while(true) {

    if (baseProtocolState == BASEPROTOCOL433_SETUP) {
      attachInterrupt(digitalPinToInterrupt(35), qam_rx4_isr, CHANGE);
      baseProtocolState = BASEPROTOCOL433_RX_LISTENMODE;
    }

    if (baseProtocolState == BASEPROTOCOL433_RX_MESSAGERECEIVED) {
      for (x = 0; x <= rawBitBufferPosition; x++) {
        Serial.print("x = ");
        Serial.print(x);
        Serial.print(", S = ");
        Serial.print(rawBitBuffer[x].state);
        Serial.print(", D = ");
        Serial.println(rawBitBuffer[x].duration);
      }
      Serial.print("loop2() - core# ");
      Serial.println(xPortGetCoreID());
    

      baseProtocolState = BASEPROTOCOL433_RX_LISTENMODE;
      attachInterrupt(digitalPinToInterrupt(35), qam_rx4_isr, CHANGE);
    }
  }
}

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

  rawBitBufferPosition = 0;
  baseProtocolState = BASEPROTOCOL433_SETUP;
  
  // Run my main code on Core0
  xTaskCreatePinnedToCore(loop2, "qam_rx_task", 20000, NULL, 1, NULL, 0);  

  #ifdef USE_WIFI
    Serial.println("calling setup_wifi()");
    WiFi.disconnect(true);
    delay(1000);

    // Set the WiFi into Station Mode
    WiFi.mode(WIFI_STA);

    // Set the hostname
    WiFi.setHostname(wifi_hostname);

    // Start the WiFi
    WiFi.begin(wifi_ssid, wifi_password);

    // Wait for WiFi to connect
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(WiFi.status());
    }	
  #endif
  
  Serial.println("Setup() done");
}

void loop() {
  // This loop should be on core1 and isn't doing anything apart from display the core its running on.
  // Should be core1
  unsigned long now = millis();

  if (now - lastRedTime > 2000) {
    Serial.print("loop()  - core# ");
    Serial.println(xPortGetCoreID());
    lastRedTime = now;
  }

}

ESP_Sprite
Posts: 9739
Joined: Thu Nov 26, 2015 4:08 am

Re: WiFi interfering with my own Interrupt function.

Postby ESP_Sprite » Fri Jun 16, 2023 2:02 am

WiFi generally adds latency to interrupts. There may or may not be ways around this in your environment, but the better advice would be to look into using the RMT peripheral, as that is specifically built for tasks like this.

MicroController
Posts: 1709
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: WiFi interfering with my own Interrupt function.

Postby MicroController » Fri Jun 16, 2023 9:02 am

Core0 so the WiFi could have core1
IIRC, Core0 is the "PRO" CPU on which the "PROtocol" handling (i.e. WiFi) happens, so you probably want to move your ISR to Core1 ("APP" CPU).

ESP_Sprite
Posts: 9739
Joined: Thu Nov 26, 2015 4:08 am

Re: WiFi interfering with my own Interrupt function.

Postby ESP_Sprite » Sat Jun 17, 2023 4:40 am

MicroController wrote:
Fri Jun 16, 2023 9:02 am
Core0 so the WiFi could have core1
IIRC, Core0 is the "PRO" CPU on which the "PROtocol" handling (i.e. WiFi) happens, so you probably want to move your ISR to Core1 ("APP" CPU).
Tbh, that's selectable from menuconfig (the pro and app nomenclature is a holdover from a beta version of the ESP32, in the current silicon the cores are more-or-less exchangable). By default, it's indeed pinned to core 0, though.

Who is online

Users browsing this forum: No registered users and 91 guests