This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Adding timestamps to ble tms service's raw characteristic.

Hello,

I'm implementing some ble service that send node id, timestamps, accel values, gyro values.

So I'm trying to modify ble tms service at Nordic-Thingy53-FW .

I want to add node id and timestamp at raw characteristic, so gatt client can request for notification of that characteristic.

But now, I have some problem adding node id and timestamps.

I add two attribute

uint32_t  time_ms

uint8_t  id

to ble_tms_raw_t type at ble_tms.h file.

And also change m_motion.c file's drv_motion_evt_handler function to assign value to node id and timestamps.

static void drv_motion_evt_handler(drv_motion_evt_t const * p_evt, void * p_data, uint32_t size)
{
    switch (*p_evt)
    {
        case DRV_MOTION_EVT_RAW:
        {
            APP_ERROR_CHECK_BOOL(size == sizeof(int32_t) * RAW_PARAM_NUM);

            ble_tms_raw_t data;
            int32_t     * p_raw = (int32_t *)p_data;

            /* p_raw is in 16Q16 format. This is compressed for BLE transfer. */

            // Set upper and lower overflow limits.
            static const int16_t overflow_limit_upper[RAW_PARAM_NUM] = {
                                                    (1 << (RAW_Q_FORMAT_ACC_INTEGER_BITS - 1)) - 1,
                                                    (1 << (RAW_Q_FORMAT_ACC_INTEGER_BITS - 1)) - 1,
                                                    (1 << (RAW_Q_FORMAT_ACC_INTEGER_BITS - 1)) - 1,
                                                    (1 << (RAW_Q_FORMAT_GYR_INTEGER_BITS - 1)) - 1,
                                                    (1 << (RAW_Q_FORMAT_GYR_INTEGER_BITS - 1)) - 1,
                                                    (1 << (RAW_Q_FORMAT_GYR_INTEGER_BITS - 1)) - 1,
                                                    (1 << (RAW_Q_FORMAT_CMP_INTEGER_BITS - 1)) - 1,
                                                    (1 << (RAW_Q_FORMAT_CMP_INTEGER_BITS - 1)) - 1,
                                                    (1 << (RAW_Q_FORMAT_CMP_INTEGER_BITS - 1)) - 1};

            static const int16_t overflow_limit_lower[RAW_PARAM_NUM] = {
                                                    -(1 << (RAW_Q_FORMAT_ACC_INTEGER_BITS - 1)),
                                                    -(1 << (RAW_Q_FORMAT_ACC_INTEGER_BITS - 1)),
                                                    -(1 << (RAW_Q_FORMAT_ACC_INTEGER_BITS - 1)),
                                                    -(1 << (RAW_Q_FORMAT_GYR_INTEGER_BITS - 1)),
                                                    -(1 << (RAW_Q_FORMAT_GYR_INTEGER_BITS - 1)),
                                                    -(1 << (RAW_Q_FORMAT_GYR_INTEGER_BITS - 1)),
                                                    -(1 << (RAW_Q_FORMAT_CMP_INTEGER_BITS - 1)),
                                                    -(1 << (RAW_Q_FORMAT_CMP_INTEGER_BITS - 1)),
                                                    -(1 << (RAW_Q_FORMAT_CMP_INTEGER_BITS - 1))};

            int16_t overflow_check;

            for (uint8_t i = 0; i < RAW_PARAM_NUM; i++)
            {
                overflow_check = p_raw[i] >> 16;    // Right shift 16 to remove decimal part.

                if (overflow_check >= overflow_limit_upper[i])
                {
                    NRF_LOG_WARNING("p_raw[%d] over limit. Val: %d limit: %d \r\n", i, overflow_check, overflow_limit_upper[i]);
                    p_raw[i] = overflow_limit_upper[i] << 16;
                }
                else if (overflow_check < overflow_limit_lower[i])
                {
                    NRF_LOG_WARNING("p_raw[%d] below limit. Val: %d limit: %d \r\n", i, overflow_check, overflow_limit_lower[i]);
                    p_raw[i] = overflow_limit_lower[i] << 16;
                }
                else
                {
                    // No overflow has occured.
                }
            }
            data.id = 1;

            data.time_ms = (((uint32_t)app_timer_cnt_get()) * (APP_TIMER_PRESCALER + 1) * 1000) / APP_TIMER_CLOCK_FREQ;

            data.accel.x =      (int16_t)(p_raw[0] >> RAW_Q_FORMAT_ACC_INTEGER_BITS);
            data.accel.y =      (int16_t)(p_raw[1] >> RAW_Q_FORMAT_ACC_INTEGER_BITS);
            data.accel.z =      (int16_t)(p_raw[2] >> RAW_Q_FORMAT_ACC_INTEGER_BITS);

            data.gyro.x =       (int16_t)(p_raw[3] >> RAW_Q_FORMAT_GYR_INTEGER_BITS);
            data.gyro.y =       (int16_t)(p_raw[4] >> RAW_Q_FORMAT_GYR_INTEGER_BITS);
            data.gyro.z =       (int16_t)(p_raw[5] >> RAW_Q_FORMAT_GYR_INTEGER_BITS);

            data.compass.y =   -(int16_t)(p_raw[6] >> RAW_Q_FORMAT_CMP_INTEGER_BITS); // Changed axes and inverted. Corrected for rotation of axes.
            data.compass.x =    (int16_t)(p_raw[7] >> RAW_Q_FORMAT_CMP_INTEGER_BITS); // Changed axes. Corrected for rotation of axes.
            data.compass.z =    (int16_t)(p_raw[8] >> RAW_Q_FORMAT_CMP_INTEGER_BITS);

            (void)ble_tms_raw_set(&m_tms, &data);
        }
        break;
        
        /*.......*/

        default:
            NRF_LOG_WARNING("drv_motion_evt_handler: Unknown data!\r\n");
            break;
    }
}

But, when GATT client receive the notification of this characteristic, data is not correct.

they have to receive data in <node_id, timestamps, accel_x, accel_y, accel_z, gyro_x, gyro_y, gyro_z> form.

I set node id as 1 but they receive 0 for node id, and timestamps are also not correct.

I think accel and gyro raw data is correct, but node_id and timestamps are not.

I'm using s132 v4.0.2 softdevice, and Nordic Thingy:52 SDK.

Parents
  • Hi, sorry for the delayed response. It seems there could be an error in the line:

    APP_ERROR_CHECK_BOOL(size == sizeof(int32_t) * RAW_PARAM_NUM);

    There could be an issue there with the value of RAW_PARAM_NUM (i.e. you may need to increase this number to 11 since you have added two variables) & also one of your variables has the type uint16_t. This could potentially lead to errors.

    Could you try setting one of the variables as a constant to make sure that this data is being transferred correctly, e.g.:

    data.gyro.y = 1234;

    in drv_motion_evt_handler & see if you receive this value in the GATT client.

  • Um.. I found another way to send timestamps.

    But now I have another problem, I want to receive raw characteristic notification every 20ms, but it's sending notification every 100ms.

    How can I change data sending rate?. I changed motion_freq_hz to 100 in m_motion.h file, DEFAULT_MPU_HZ to 10 in drv_motion.c file, but rate doesn't changed.

  • Very sorry for the delayed response. It seems correct to use motion_freq_hz & changing the value to 100 Hz to get a reading every 10 ms. You should not have to change the DEFAULT_MPU_HZ value. How are you testing this? Could you try connecting to the motion service on nrf connect for mobile & see if you notice a difference when motion_freq_hz is 5 Hz vs 200 Hz? I am not sure you will notice this, but it could be worth a shot.

    You will probably need to disconnect & connect to the Thingy device again to see the update.

    It is a good idea to keep the frequency above 50 Hz, as the integration of the motion data will not be as accurate if the frequency is lower.

Reply
  • Very sorry for the delayed response. It seems correct to use motion_freq_hz & changing the value to 100 Hz to get a reading every 10 ms. You should not have to change the DEFAULT_MPU_HZ value. How are you testing this? Could you try connecting to the motion service on nrf connect for mobile & see if you notice a difference when motion_freq_hz is 5 Hz vs 200 Hz? I am not sure you will notice this, but it could be worth a shot.

    You will probably need to disconnect & connect to the Thingy device again to see the update.

    It is a good idea to keep the frequency above 50 Hz, as the integration of the motion data will not be as accurate if the frequency is lower.

Children
No Data
Related