2
votes

I am currently making a high bandwidth transmitter spreading ADS1115 data over both a LoRa and NRF24 module, however, I am running into lots of issues with the task scheduler and unstable behaviour of i2c (being used for the ADC, both transmitters use SPI). I am trying to read and process data on one core and transmit it on the other. Both processes work perfectly in isolation but not together when together the ADS1115 returns -1 or ~32k, and sometimes when working together the NRF module stops transmitting. Here is the minimal working code:

// 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;
        }
    }
}

The tasks have been added in the following snippet:

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

What works:

  • Disabling either task
  • Concatenating the functions onto one core - giving a bandwidth ~20 lower :(
  • the power lines have minimal noise staying between 3.301-3.302v

What doesn't work:

  • using DigitalRead rather than REG_READ, it causes the task to be permanently blocked, using REG_READ causes the task to be blocked less as time goes by, this was checked by running eTaskGetState(ADSHandle) on the other core
  • Changing i2c pins
  • Disabling the LoRa interrupt
  • moving the LoRa interrupt between cores
  • disabling the watchdog on both cores
  • using the blocking methods of the ADS or the NRF, the ADS blocking method breaks the NRF module too, not sure why but I know the blocking method constantly polls the i2c bus
  • using the adafruit ADS1115 library
  • using small vTaskDelays / TaskYeild
  • using big caps on the 3.3v lines + ceramic for the ADC
  • using AMS1117 3.3 regs for each device
  • using 2 AMS1117 3.3 regs for the ESP
  • using a Li-ion + boost converter as a power source

Current theory: There is a resource conflict between the SPI and i2c bus, this locks a mutex that blocks the ADS thread? When you work around this, the i2c bus spits out random values

I feel like I have tried everything so I am just hoping that this is a resource conflict, and is a known issue with an easy workaround! Any help is much appreciated!

2
The easiest way to go about it is not to use their dreadful library for either SPI nor I2C. Do it yourself, based on the datasheet. Been there, done that - their library is trash. The less you use it, the better off you'll be.Kuba hasn't forgotten Monica

2 Answers

0
votes

There seems to be some wierd issue with task threads and I2C in the ESP32 I2C library. There is mention of it here but no solution given. I have problems with reading a BME 280 temperature sensor through I2C from different threads, even though I have a mutex to avoid reading the sensor at the same time. What I found was that if I read the sensor twice in a row within each thread, the second read is always reliable, only the first read within the thread tends to give an erroneous reading. So I just do that for now, even though it is just a hack. Not sure if this helps you.

0
votes

I got the same issue in the past.

That is due most likely to a drop on the power supply line during the transmission and the correlate malfunction of the microchip logic. Therefore that is an electronic issue and not a programming one.

The reason is the current peak requested by the transmitter that rapidly induce a drop in voltage on the power supply line.

There is an easy fix soldering a 10 µF capacitor between GND and Vcc (take care of the capacitor polarity).