【问题标题】:ESP32 SPI/i2c/xTask interference/instabilityESP32 SPI/i2c/xTask 干扰/不稳定
【发布时间】:2020-12-21 02:51:12
【问题描述】:

我目前正在制作一个高带宽发射器,在 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;
        }
    }
}

任务已添加到以下sn-p中:

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 / TaskYield
  • 在 3.3v 线路上使用大电容 + 用于 ADC 的陶瓷
  • 为每个设备使用 AMS1117 3.3 regs
  • 为 ESP 使用 2 个 AMS1117 3.3 regs
  • 使用锂离子 + 升压转换器作为电源

当前理论:SPI和i2c总线之间存在资源冲突,这会锁定一个阻塞ADS线程的互斥锁?当你解决这个问题时,i2c 总线会输出随机值

我觉得我已经尝试了所有方法,所以我只是希望这是一个资源冲突,并且是一个简单的解决方法的已知问题!非常感谢任何帮助!

【问题讨论】:

  • 最简单的方法是不要将他们可怕的库用于 SPI 或 I2C。根据数据表自己做。去过那里,做到了——他们的图书馆是垃圾。你用得越少,你的生活就会越好。

标签: c++ arduino i2c spi esp32


【解决方案1】:

我过去也遇到过同样的问题。

这很可能是由于传输过程中电源线的下降以及微芯片逻辑的相关故障。因此,这是一个电子问题,而不是编程问题。

原因是发射器要求的电流峰值会迅速导致电源线上的电压下降。

在 GND 和 Vcc 之间焊接一个 10 µF 电容器很容易解决(注意电容器极性)。

【讨论】:

    【解决方案2】:

    ESP32 I2C 库中的任务线程和 I2C 似乎存在一些奇怪的问题。有人提到它here,但没有给出解决方案。我在通过 I2C 从不同线程读取 BME 280 温度传感器时遇到问题,即使我有一个互斥锁来避免同时读取传感器。我发现如果我在每个线程中连续读取传感器两次,第二次读取总是可靠的,只有线程中的第一次读取往往会给出错误的读数。所以我现在就这样做,即使它只是一个 hack。不确定这是否对您有帮助。

    【讨论】:

      猜你喜欢
      • 2014-11-11
      • 2011-03-19
      • 2017-05-04
      • 1970-01-01
      • 2020-07-23
      • 2016-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多