DIY Powermeter nRF52840/AD7799

I am developing a bicycle powermeter using the XIAO BLE nRF52840 Sense Breakout board with an AD7799 on a dedicated PCB i also made. I use Segger Embedded Studio v5.42a and nRF5_SDK_17.1.0. For ANT+ communication I use the S212 7.0.1 Softdevice. BPWR Sensor example compiles and runs without any problems.

The ADC is controlled via SPIM and uses the Miso line as a Data Ready Indicator by pulling it low. I want to use that functionality with one Gpiote Input HITOLO Interrupt on the Miso line, and when the Interrupt occurs, I deactivate the gpiote_in_event, to not trigger the interrupt again during SPIM communication. When the 3 bytes have been received, the spim event handler reenables the gpiote in event when beeing called after the transmission and sums puts the three bytes received back together into a 32 bit Integer and increments a counter variable as well.


I use the ant_bpwr_evt_handler to call a function in my ad7799 library which uses the accumulated data read from the adc and the counter value that were already received since the last bpwr page update event. My problem is, what happens if an bpwr page update event occurs, after I wrote the new SPI data to the 32 bit Integer but before the counter is incremented? Then the calculated average of the samples in that time period would be incorrect... Is there some simple way of not taking the values when they are currently being written to? I cannot use a while loop with a boolean I set while changing the values, because the bpwr event handler interrupt has a higher priority than the spi event handler, so that would end up in an endless loop. An if statement would probably work, but I'd miss a whole bpwr page update cycle...

I would appreciate other ideas or solutions as well. Thanks in advance.

  • I totally agree with you, it definitely is more safe with a mutex instead of the boolean. Here is the other accessing part of the code:

    if (!adc_values.locked)
    {
      adc_values.locked = true;
      float adc_sum = adc_values.positive_sum + adc_values.negative_sum;
      float mV_avg = adc_sum / fmaxf((float)adc_values.num_values, 1.f);
      float weight_avg = fmaxf(mV_avg * adc_kg_per_mV, 0);
      float torque_avg = (weight_avg)*1.71675; // 9.81 * 0.175 for Nm
      torqueEff[0] = torqueEff[1] = round((200.f * (adc_sum)) / adc_values.positive_sum);
      pedalSmoothness[0] = pedalSmoothness[1] = round(200.0 * adc_sum / adc_values.max_value);
      *instPWR = (uint16_t)round(torque_avg * TWO_PI * lastRPS * 2); // calc instant pwr
      *accPWR += *instPWR;
      *instCAD = (uint8_t)round(60 * lastRPS); // Calc cadence of last rotation in U/min
      *evt_counter++;
      adc_values.locked = false;
      return true;
    }
    else return false;

Related