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.

  • I really recommend you to use a DK if you do development. Things are a lot easier when you have a debugger so that you can see what's going on, either through debugging or via logging (the USB is not a supported log backend at this point in time). 

    The symptoms you describe looks like an APP_ERROR_CHECK(err_code) receiving an err_code != 0, but that can be literally anything. Either some issues with the USB, timers, softdevice, flash, you name it.

  • Yes you are right. I will definitely use DK next time, but I have to complete this project with the dongle. I have already ordered these and the hardware is ready that uses the dongle. So cant change this time.

    Well I have checked by making green led on & off when it goes in ble_evt_handler, and blue led when it goes into timer_handler. The code snippet for both are following.

    But All I see is green LED is continuously ON, which means it is always in ble_evt_handler, and it is not going into timer_handler, that is why it is not sending any data.

    Now, I know the problem. I do not know why is it happening?

    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;
      }
    }
    

    static void repeated_timer_handler(void *p_context) {
        nrf_gpio_pin_set(LED1);       //BLUE LED
        for (int i = 0; i < sizeof(devices); i++) {
          app_uart_put(devices[i]);
          devices[0] = 0;
          }
          deviceLength = 0;
          nrf_gpio_pin_clear(LED1);
    }

Reply
  • Yes you are right. I will definitely use DK next time, but I have to complete this project with the dongle. I have already ordered these and the hardware is ready that uses the dongle. So cant change this time.

    Well I have checked by making green led on & off when it goes in ble_evt_handler, and blue led when it goes into timer_handler. The code snippet for both are following.

    But All I see is green LED is continuously ON, which means it is always in ble_evt_handler, and it is not going into timer_handler, that is why it is not sending any data.

    Now, I know the problem. I do not know why is it happening?

    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;
      }
    }
    

    static void repeated_timer_handler(void *p_context) {
        nrf_gpio_pin_set(LED1);       //BLUE LED
        for (int i = 0; i < sizeof(devices); i++) {
          app_uart_put(devices[i]);
          devices[0] = 0;
          }
          deviceLength = 0;
          nrf_gpio_pin_clear(LED1);
    }

Children
  • Hello,

    I am not saying you can't use the dongle in the product, but you should write your application on a DK, and when everything is working, you can program it on the dongle. Not too late to do this.

    If the LED is on, it means that the pin is low/cleared. It is active low. This means that you are not in the BLE_GAP_EVT_ADV_REPORT. You may get the adv reports, but it is difficult to see that the LED turns off for a couple of ms every now and then.

  • Yes I figured it after sending the reply. The leds are active low in the dongle. But still the problem is the same. It is not storing the advertised data with the above code that I had mentioned in my last reply. It can send me the data if I use "i" instead of "deviceLength++" like the following snippet but I cannot be able to store the data.

    Now I am looking for another way to store the data, maybe in the main loop or need to start and stop scanning explicitly. 

    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];
    }

  • 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?

Related