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

Storing adv data

Hi. My application is scanning ble beacons for 1 sec every minute, and I want to store this data in an array to be sent every 10 min. I am getting the data in BLE_GAP_EVT_ADV_REPORT in p_ble_evt->header.evt_id, then I am printing to verify what I have received, and then I am storing the data using  the following

for (int i=0;i<p_gap_evt->params.adv_report.data.len;i++)
{
    devices[k++]=p_gap_evt->params.adv_report.data.p_data[i];
}

Then in repeated timer handler, I am sending the devices array that should contain all the beacons 30 byte data. At this time I have 5 beacons, so I declared array of size 200. In timer handler, I am doing this.

static void repeated_timer_handler(void * p_context)
{
    for (int i=0;i<sizeof(devices);i++)
    {
        app_uart_put(devices[i]);
    }
}

My main function looks like

int main(void)
{
    // Initialize.
    log_init();
    uart_init();
    power_management_init();
    ble_stack_init();
    scan_init();
    
    app_timer_init();
    
    create_timers();

    scan_start();

    app_timer_start(m_repeated_timer_id, APP_TIMER_TICKS(15000), NULL);

    // Enter main loop.
    for (;;)
    {
        idle_state_handle();
    }
}

But I am not getting anything on console, and if change my first snippet like this

for (int i=0;i<p_gap_evt->params.adv_report.data.len;i++)
{
    devices[i]=p_gap_evt->params.adv_report.data.p_data[i];
}

devices [k++] to devices[i], then in timer handler I get data in devices array but the last data that is stored, not all the data. I want to store the data for 10 scanning instances (1 sec scan every 1 min), then the timer handler will be executed every 10 min to send the data, and the process repeats.

Kindly suggest suitable way to achieve this.

I appreciate your suggestions.

Regards,

Parents
  • Hello,

     

    devices [k++] to devices[i], then in timer handler I get data in devices array but the last data that is stored, not all the data

     Does k get incremented every time this handler is called? You can try to print it while you get the data, to see why only the last device is stored, and not all of them.

    Is your k variable volatile? Maybe it starts on 0 every time it is called?

  • Hello,

    Thanks for you reply. Yes I am able to store data and later in the timer handler, prints the data on console. But the thing is I have not changed anything. Sometimes the data prints, sometimes do not. I do not know what is causing this issue. I was not getting data at first, but when I uploaded the program again, I got the data. Then after letting it run for 1 hour, it stopped the data. Now it is not showing the data. I am not sure if need to post another question for this. I am using nrf52840 dongle. Maybe this was the reason I was not getting the data and I thought that I have done something wrong in my code.

  • Again, I really suggest that you develop your application on a DK where you have the possibility to debug. 

    What SDK version do you use?

  • Yes you are absolutely right, but I really cant do at this point, because if I order now, it would take some time to get, and I am going on a holiday. So, this project has to be completed on a dongle.

    I am using SDK 15.3 and softdevice s140.  I build my program using segger embedded studio and use nRF connect programmer for uploading. 

    I figured out (maybe I am wrong) that my program does not go into timer_handler, and spend all the time in scanning, and interval. my scan parameters are

    #define SCAN_INTERVAL 16000
    #define SCAN_WINDOW 1600 
    #define SCAN_DURATION 32000

    1 sec scan and 9 sec interval. But this scan duration is something I donot clearly understand. So I think I need to explicitly stop scan and do other stuff in timer_handler. Maybe the radio is on, so it is not going into timer_handler, or something like this. Can you suggest better way to scan for 1 sec every 10 sec, and at 15 sec, send the stored data via timer_handler. Or any approach to achieve this.

    I appreciate your effort to help me.

    Regards,

  • With the following parameters:

    #define SCAN_INTERVAL 16000
    #define SCAN_WINDOW 1600 
    #define SCAN_DURATION 32000

    You will scan for 1 second every 10 seconds, for 320 seconds (after that it times out and goes to sleep).

    I suggest, if you need to do this without a debugger, that you use your LEDs, and do one thing at a time.

    First, set up a timer and toggle a led (do not turn it on/off, and back off/on in the same timeout handler, but toggle it once every timeout, just to see that the timeout handler is repeatedly called. 

    Also, I suggest that you create your own error handler which only set a specific LED (e.g. the red one), so that you can check whether an error (custom_APP_ERROR_CHECK(err_code)) triggers. Alternatively alter the error handler (APP_ERROR_CHECK()) to do this.

    To toggle, you can use nrf_gpio_pin_toggle(uint32_t pin number) instead of nrf_gpio_pin_set() and nrf_gpio_pin_clear().

    When you have a stable timer, you can start checking that everything returns proper values:

        nrf_gpio_pin_set(LED2);    //Green LED
        if (p_gap_evt->params.adv_report.data.p_data[0] == 0x02) {
          if (p_gap_evt->params.adv_report.data.p_data[1] == 0x01) {
            if (p_gap_evt->params.adv_report.data.p_data[2] == 0x06) {
                for (int i = 0; i < p_gap_evt->params.adv_report.data.len; i++) 
                {
                    devices[deviceLength] = p_gap_evt->params.adv_report.data.p_data[i];
                    deviceLength++;
                }
                devices[deviceLength] = p_gap_evt->params.adv_report.rssi;
                deviceLength++;
                if (deviceLength < 4)
                {
                    nrf_gpio_pin_clear(LEDn) //red led (don't remember the number)
                }
                else
                {
                    nrf_gpio_pin_set(LEDn) //turn off the led to indicate that the parameter deviceLength is incremented properly
                }
            }
          }
        }

    e.g. like this to see whether deviceLength is actually increasing.

    I am not sure how you figure out that things are not working properly. Do you have some way of logging?

  • Hi, thanks for reply.

    I am using app_uart_put() to send to FTDI for showing the data on the terminal. Also, I am using LEDs.

    As you have said, I checked the timer by incremented a counter in timer_handler and printed the value of counter. I  have noticed it is not working correctly, the counter goes from 00 to 06, and then goes back to 00 then 01 and 02. After 02, the program does not go into timer_handler again. If I do not do anything in the timer_handler and just increment a counter. then it works properly. This is strange but true.

    Also, by changing the scan_interval, scan_window and scan_duration parameters. I observed the following.

    1: If scan_interval and scan_window are equal, scan does continuously.

    2: if scan_duration is less than scan_interval (for example: scan_interval 16000 and scan_duration 1000), scan does continuously.

    3: If we set values like scan_interval 16000, scan_window 1600, and scan_duration 1200, then it scans for 1 sec every 10 sec, but does not stop at 12 sec and keeps on doing this like forever. So what is the purpose of scan_duration if it does not stop.

    Now I think I need to explicitly start and stop scan, and need to use driver timer instead of app_timer. I followed this link as it is for app_timer, just changed timer_ticks value to 15000. Maybe I also need to change the data parser inside BLE_GAP_EVT_ADV_REPORT. I saw this data parser but I do not understand if it is OK for me.  https://devzone.nordicsemi.com/f/nordic-q-a/38656/adv-data-parser

     https://devzone.nordicsemi.com/nordic/short-range-guides/b/software-development-kit/posts/application-timer-tutorial

    Regards,

  • if you have access to the UART output then I suggest that you use the NRF_LOG module with UART as backend, instead of app_uart_put. The reason for this is that NRF_LOG will give you information when the APP_ERROR_CHECK() detects something strange. Maybe the error handler fires in your application, causing the application to restart, and hence your counter goes back, and you lose all your previously stored data. 

    So, enable logging in sdk_config.h with UART as backend, and define DEBUG in your preprocessor defines, and monitor the uart log output.

Reply
  • if you have access to the UART output then I suggest that you use the NRF_LOG module with UART as backend, instead of app_uart_put. The reason for this is that NRF_LOG will give you information when the APP_ERROR_CHECK() detects something strange. Maybe the error handler fires in your application, causing the application to restart, and hence your counter goes back, and you lose all your previously stored data. 

    So, enable logging in sdk_config.h with UART as backend, and define DEBUG in your preprocessor defines, and monitor the uart log output.

Children
  • OK I will do as you said. I will enable the logging using uart. And I will get back to you in a day.

  • Hi Edvin,

    Well, i have tried many things and have completed most of my work. But still I am not able to store advertisement data. I am sure that the problem is with storing part, because when I store only one device, it works as expected, but when I store multiple devices in one array as I mentioned above, the application crashes.This storing part is the main part of my application, and I am no C expert, so could not figured out how to store the devices data into one array for specific time to be able to send it and reinitialize the array and repeat the process.

    Can you suggest something. 

    Regards,

    PK SHER

  • Does the log say anything on where the application crashes? You can try to add "DEBUG" to your preprocessor defines if it only says "Fatal error". Then it should give you a line number.

    Looking at your snippet from a couple of posts ago:

    static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) {
      ble_gap_evt_t const *p_gap_evt = &p_ble_evt->evt.gap_evt;
      uint8_t uuid[30];
      uint8_array_t adv_data;
    
      switch (p_ble_evt->header.evt_id) {
      case BLE_GAP_EVT_ADV_REPORT: {
        nrf_gpio_pin_set(LED2);    //Green LED
        if (p_gap_evt->params.adv_report.data.p_data[0] == 0x02) {
          if (p_gap_evt->params.adv_report.data.p_data[1] == 0x01) {
            if (p_gap_evt->params.adv_report.data.p_data[2] == 0x06) {
                for (int i = 0; i < p_gap_evt->params.adv_report.data.len; i++) 
                {
                    devices[deviceLength] = p_gap_evt->params.adv_report.data.p_data[i];
                    deviceLength++;
                }
                devices[deviceLength] = p_gap_evt->params.adv_report.rssi;
                deviceLength++;
            }
          }
        }
        nrf_gpio_pin_clear(LED2);
      }
      default:
        break;
      }
    }
    

    What type is your deviceLength variable?

    Try to set it as a "volatile uint32_t" or whatever uintx_t you use. Just make it volatile. You can declare it at the top of that .c file that you use it in.

    Also, what type of variable is the "devices" variable? Is it an array? what type? How do you declare it? If it is an array, how long is it?

  • Thanks Edvin for your amazing support on this issue, 

    I managed to solve this issue by using two dimensional array to save my devices. Although I do not understand why it did not work with the above code. However the issue has been resolved. 

    Regards,

Related