Page 1 of 1

Speeding up data acquisition with PLAY

Posted: Tue Jan 27, 2015 9:34 am
by gabriele
Hi all

I would like to develop a simple application to log sensors data (mag gyro and acc) from the iNemo to
my pc. I am using the serial-over-usb driver to communicate with Matlab through the serial port.
For data acquisition I am using the PLAY library.

These are my sensor configurations:

Code: Select all

// Gyro configuration
static const L3GD20_Config l3gd20_cfg_1 = {
  L3GD20_FS_500DPS,
  L3GD20_PM_SLEEP_NORMAL,
  L3GD20_ODR_380Hz_Fc_25,
  L3GD20_AE_XYZ,
  L3GD20_End_LITTLE,
  L3GD20_BDU_CONTINOUS
};

// ACC configuration
static const LSM303DLHC_ACC_Config lsm303dlhc_acc_cfg_1 = {
  LSM303DLHC_ACC_FS_4G,
  LSM303DLHC_ACC_PM_NORMAL,
  LSM303DLHC_ACC_ODR_1344Hz,
  LSM303DLHC_ACC_AE_XYZ,
  LSM303DLHC_ACC_BDU_BLOCKED,
  LSM303DLHC_ACC_HR_Enabled
};

// COMP configuration
static const LSM303DLHC_COMP_Config lsm303dlhc_comp_cfg_1 = {
  LSM303DLHC_COMP_FS_1_9_GA,
  LSM303DLHC_COMP_ODR_220_Hz,
  LSM303DLHC_COMP_WM_CONTINUOS
};


I have two threads: one to acquire data and another to write on the serial port.

Code: Select all

 
static msg_t Thread1(void *arg) {

// *** some code ****//

while (TRUE) {

   chSysLock();

    // Gyro acquisition
    gyroStartAcquiringDevice(&GYROD1, &gyro_cfg_1);
    gyroGetData(&GYROD1, &gyro_d_1);
    gyroStopReleasingDevice(&GYROD1);

    // Acc acquisition
    accelStartAcquiringDevice(&ACCELD1, &accel_cfg_1);
    accelGetData(&ACCELD1, &accel_d_1);
    accelStopReleasingDevice(&ACCELD1);

    compStartAcquiringDevice(&COMPD1, &comp_cfg_1);
    compGetData(&COMPD1, &comp_d_1);
    compStopReleasingDevice(&COMPD1);

 chSysUnlock();
}

static msg_t Thread2(void *arg) {

       //*** some code ***//
      while(TRUE)   {
                chprintf(//*** sensor data from gyro_d_1, accel_d_a, comp_d_1***//);
               chThdSleepMilliseconds(TC);
       }
}

Both threads have the same priority.

My problem is as following:
if TC > 50 msec everything is ok. If TC < 50 msec i get some repetitions in the data I read. For example, in two
consecutive timestamps i get the same gyro sample but different acc and mag values.
I thought that it could happen when Thread1 is preempted by Thread2 during the execution of the data acquisition code,
which represents the critical section. That is why I locked the code of data acquisition in Thread1 but it did not solved
the problem.

I have two questions:
1) How to speed up the data acquisition (maybe with some sensor configuration)?
2) Why did not the synchronization of Thread2 with Thread1 on the shared resources work?

Thank you for your help!

Re: Speeding up data acquisition with PLAY

Posted: Tue Jan 27, 2015 12:31 pm
by RoccoMarco
Hi,
startSensorAcquiringDevice() and stopSensorReleasingDevice() are useful if you want to use the same resource by different threads. In this case startSensor() and stopSensor() would be enought.

Anyway when you start a MEMS (shifting it from sleepmode to activemode) a wakeup time is required. On L3GD20 and LSM303DLHC datasheets I haven't found this info explicitely but on LSM6DS e LIS3MDL datasheet yes!
Image

This wait time could not be avoided so my suggestion is don't turn off device. In order to do this my suggestion is to make a single start before while(TRUE).

Code: Select all

static msg_t Thread1(void *arg) {

// *** some code ****//
gyroDevice(&GYROD1, &gyro_cfg_1);
accelDevice(&ACCELD1, &accel_cfg_1);
compDevice(&COMPD1, &comp_cfg_1);

while (TRUE) {

    gyroGetData(&GYROD1, &gyro_d_1);
    accelGetData(&ACCELD1, &accel_d_1);
    compGetData(&COMPD1, &comp_d_1);
}
compStop(&COMPD1);
accelStop(&ACCELD1);
gyroStop(&GYROD1);


Enable compatibility mode since on iNEMO mems are wired on I2CD2 and SPID2 that share the same DMA, compatibility mode enable and disable communication in every function (otherwise communication channel is started in sensorStart() and stopped in sensorStop()).

Code: Select all

accelChangeMode(&ACCELD1, ACCEL_COMPATIBILITY_MODE);
gyroChangeMode(&GYROD1, GYRO_COMPATIBILITY_MODE);
compChangeMode(&COMPD1, ACCEL_COMPATIBILITY_MODE);

Increase ODR too.

Ciao,
RM

Re: Speeding up data acquisition with PLAY

Posted: Tue Jan 27, 2015 2:58 pm
by gabriele
Hi

I have just modified my code as you suggested. Now it is really better!

With TC = 10 msec I have some repeated data only for the magnetometer (which has a maximum
ODR lower than the other MEMS).
To get some repetitions in accelerometer and gyroscope data I have to push the sampling frequency
towards really high values.

Only to help someone else:
Maybe you meant

Code: Select all

gyroStart(&GYROD1, &gyro_cfg_1);
accelStart(&ACCELD1, &accel_cfg_1);
compStart(&COMPD1, &comp_cfg_1);

instead of

Code: Select all

gyroDevice(&GYROD1, &gyro_cfg_1);
accelDevice(&ACCELD1, &accel_cfg_1);
compDevice(&COMPD1, &comp_cfg_1);

Right?
There are no *Device() functions in gyro.h, accel.h and comp.h.

Thanks again for your immediate help

Ciao

Re: Speeding up data acquisition with PLAY

Posted: Tue Jan 27, 2015 3:29 pm
by RoccoMarco
Disadvantages of copy and paste, my fault :mrgreen:

I would like to use FIFO to acquire more data and make a single reading but Seems That FIFO is not mandatory for each MEMS. So to keep PLAY as much abstract as possible I had to avoid using FIFO.

I will continue developing soon. Actually I'm working on other ChibiOS videos and on a website to share them http://playembedded.org/.

Thanks for using PLAY. Feel free to contact me if you find some bugs.