簡體   English   中英

ESP32 SPI/i2c/xTask 干擾/不穩定

[英]ESP32 SPI/i2c/xTask interference/instability

我目前正在制作一個高帶寬發射器,在 LoRa 和 NRF24 模塊上傳播 ADS1115 數據,但是,我遇到了很多任務調度程序問題和 i2c 的不穩定行為(用於 ADC,兩個發射器都使用 SPI)。 我正在嘗試在一個核心上讀取和處理數據並在另一個核心上傳輸數據。 當 ADS1115 一起返回 -1 或 ~32k 時,這兩個進程單獨工作時效果很好,但一起工作時卻不能一起工作,有時當一起工作時,NRF 模塊會停止傳輸。 這是最小的工作代碼:

// flag to indicate that a packet was received
volatile bool transmittedFlag = true;

void IRAM_ATTR setFlag(void) {
    // packet transmission is finished, set the flag
    transmittedFlag = true;
}

void AttemptTrans() {
    lora.setDio0Action(setFlag);
    while (true) {
        if (transmittedFlag || digitalRead(DIO0)) {
            
            int state = lora.startTransmit((uint8_t*)(&LoRaData), sizeof(Data));

            if (state != ERR_NONE) {
                Serial.print(F("failed, code: "));
                Serial.println(state);
            }
            else {
                data.counter++;
                transmittedFlag = false;

            }
            
        }
        if (nrf.txFIFOEmpty()) { //Custom function: read_register(FIFO_STATUS) & _BV(TX_EMPTY);
            nrf.writeFast(&data, sizeof(Data), 0);
            data.counter++;
        }
    }
}

int ads_counter = 0;
void ADSFunc(){
    while (true) {
        uint32_t input = REG_READ(GPIO_IN_REG);
        if (input && 0x400000) { //Digital read on pin 22
            ads.setMultiplexer(ads_counter + 4);
            ADS_RAW[ads_counter] = ads.getConversion(false);
            ads_counter = (ads_counter + 1) % 4;
        }
    }
}

任務已添加到以下代碼段中:

disableCore1WDT();
xTaskCreatePinnedToCore((TaskFunction_t)ADSFunc, "ads", stackSize2, NULL, 1, &ADSHandle, 0);
xTaskCreatePinnedToCore((TaskFunction_t)AttemptTrans, "LoRaTX", stackSize, NULL, 1, &LoRaHandle, 1);

什么有效:

  • 禁用任一任務
  • 將功能連接到一個核心上 - 帶寬降低 ~20:(
  • 電源線的噪音最小,保持在 3.301-3.302v 之間

什么不起作用:

  • 使用 DigitalRead 而不是 REG_READ,它會導致任務被永久阻塞,使用 REG_READ 會導致隨着時間的推移任務被阻塞的次數減少,這是通過在另一個核心上運行eTaskGetState(ADSHandle)來檢查的
  • 更改 i2c 引腳
  • 禁用 LoRa 中斷
  • 在內核之間移動 LoRa 中斷
  • 禁用兩個內核上的看門狗
  • 使用 ADS 或 NRF 的阻塞方法,ADS 阻塞方法也會破壞 NRF 模塊,不知道為什么,但我知道阻塞方法不斷輪詢 i2c 總線
  • 使用 adafruit ADS1115 庫
  • 使用小的 vTaskDelays / TaskYeild
  • 在 3.3v 線路上使用大電容 + ADC 陶瓷
  • 為每個設備使用 AMS1117 3.3 regs
  • 為 ESP 使用 2 個 AMS1117 3.3 regs
  • 使用鋰離子+升壓轉換器作為電源

當前理論:SPI 和 i2c 總線之間存在資源沖突,這會鎖定一個阻塞 ADS 線程的互斥體? 當您解決此問題時,i2c 總線會吐出隨機值

我覺得我已經嘗試了一切,所以我只是希望這是一個資源沖突,並且是一個簡單的解決方法的已知問題! 任何幫助深表感謝!

ESP32 I2C 庫中的任務線程和 I2C 似乎存在一些奇怪的問題。 這里提到它但沒有給出解決方案。 我在通過 I2C 從不同線程讀取 BME 280 溫度傳感器時遇到問題,即使我有一個互斥鎖來避免同時讀取傳感器。 我發現,如果我在每個線程中連續兩次讀取傳感器,第二次讀取總是可靠的,只有線程中的第一次讀取往往會給出錯誤的讀數。 所以我現在就這樣做,即使它只是一個 hack。 不確定這是否對您有幫助。

我過去遇到過同樣的問題。

這很可能是由於傳輸期間電源線上的電壓下降以及微芯片邏輯的相關故障造成的。 因此,這是一個電子問題而不是編程問題。

原因是發射器請求的電流峰值會迅速導致電源線上的電壓下降。

在 GND 和 Vcc 之間焊接一個 10 µF 電容器很容易解決(注意電容器的極性)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM