Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - frogie

Pages: [1]
1
Hi, I've been trying to figure this out: my Simblee freezes while trying to read from an I2C device while inside an interrupt (Timer2 interrupt in this case), but only if I have the radio enabled (with SimbleeBLE.begin()).

If I either:
- do not turn on the radio, or
- read from the device from the main loop(), or
- only perform I2C writes inside the timer interrupt
then the chip doesn't freeze.

The device I'm attempting to read from is an accelerometer (MMA8452Q).
Does anyone have a clue why this could be going on?

Below is my test code. If I comment out the setupBLE() line then I see pin0 toggle. If I instead comment out the setupTimer() line and make calls to readAccel() inside loop() it also works!

Code: [Select]
#include <SimbleeBLE.h>
#include <Wire.h>

#define SCLpin 21
#define SDApin 24

#define TIMER2_PRESCALER (8)
#define TIMER2_RESOLUTION ((1<<TIMER2_PRESCALER)/16) // TimerTick = 16M/2^8 = 16 us
// Note: at 16us per tick, the longest delay that can be requested is roughly 1s

#define READ_ACCEL_INTERVAL (10000) // 10ms
#define READ_ACCEL_TICKS (READ_ACCEL_INTERVAL / TIMER2_RESOLUTION)

#define OUT_X_MSB (0x01) // first register of acceleration data

void readAccel()
{
    digitalWrite(1, HIGH);
    // Read the accelerator values
    byte rawData[6];  // x/y/z accel register data stored here
    Wire.beginTransmission(0x1C); // Address of the Accelerometer
    Wire.write(OUT_X_MSB);
    Wire.endTransmission(false); //endTransmission but keep the connection active
    Wire.requestFrom(0x1C, 6); //Ask for bytes, once done, bus is released by default
    while (Wire.available() < 6); //Hang out until we get the # of bytes we expect
 
    for (int x = 0; x < 6; x++)
      rawData[x] = Wire.read();

    // Here I would convert the 6 bytes into 3 words for x, y and z
    digitalWrite(1, LOW);
}

void timer()
{
    if (NRF_TIMER2->EVENTS_COMPARE[0] != 0)
    {
      // Clear interrupt
      NRF_TIMER2->EVENTS_COMPARE[0] = 0;

      // Update the compare value for next multiple
      NRF_TIMER2->CC[0] += READ_ACCEL_TICKS;

      readAccel();
    }
}

void setupTimer()
{
  NRF_TIMER2->TASKS_STOP = 1; // Stop timer
  NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;  // taken from Nordic dev zone
  NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
  NRF_TIMER2->PRESCALER = TIMER2_PRESCALER; // 16MHz / (2^8) = 16 us resolution
  NRF_TIMER2->CC[0] = READ_ACCEL_TICKS;
  NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos;
  NVIC_SetPriority(TIMER2_IRQn, 3);
  dynamic_attachInterrupt(TIMER2_IRQn, timer); // Read accelerometer!
  NRF_TIMER2->TASKS_CLEAR = 1; // Clear timer
  NRF_TIMER2->TASKS_START = 1;  // Start TIMER
}

void setupBLE()
{
  // start the BLE stack
  SimbleeBLE.advertisementData = "Test";
  SimbleeBLE.deviceName = "Test";
  SimbleeBLE.txPowerLevel = 0;
  SimbleeBLE.begin();
}

void setup()
{
  // Setup I2C
  Wire.speed = 400;
  Wire.beginOnPins(SCLpin, SDApin);

  // Setup pins for debugging
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);

  setupBLE();
  setupTimer();
}

void loop()
{
  digitalWrite(0, HIGH);
  delay(1);
 
  digitalWrite(0, LOW);
  delay(1);
}


Pages: [1]
anything