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

Best way to send data from many sensors

Hi,

For an application I have a nRF51 at my disposal and I need to transfer about 3'000Bytes. I found in the documentation that the nRF51 can use the S130 SoftDevice which support BLE 4.2. The data I have to transfer come from 1 to 50 sensors and are divided in 2 categories with 3 respective 6 parameters each as follow:

Sensor No1

  • Data type A
  • --Parameter A1
  • --Parameter A2
  • --Parameter A3
  • Data type B
  • --Parameter B1
  • --Parameter B2
  • --Parameter B3
  • --Parameter B4
  • --Parameter B5
  • --Parameter B6

Sensor No2

  • Data type A
  • --Parameter A1
  • --Parameter A2
  • --Parameter A3
  • Data type B
  • --Parameter B1
  • --Parameter B2
  • --Parameter B3
  • --Parameter B4
  • --Parameter B5
  • --Parameter B6

Sensor NoX

  • Data type A
  • --Parameter A1
  • --Parameter A2
  • --Parameter A3
  • Data type B
  • --Parameter B1
  • --Parameter B2
  • --Parameter B3
  • --Parameter B4
  • --Parameter B5
  • --Parameter B6

I thought that a way to transfer these results would be to use 2 customized services (a service for type A and a service for type B) with 3 respective 6 characteristics (A1-A3 and B1-B6) each. Each characteristic should have up to 50 values. The number of values in each characteristic would indicate the number of sensors.

Has someone a better / a more suitable solution for this use case?

Thanks in advance for you ideas.

  • (oh no:)

    I would never flood (G)ATT stack with dozens of handles when the only thing you need to do is transport some data. Simply define single service with single characteristic and define structured protocol on top of that which will clearly identify what sensor data you are currently transporting. Yes, you will have some formatting overhead but unless you don't pair these two devices only once and perform typically "hanging" connection without disconnecting/reconnecting after every transfer you don't want to deal with (G)ATT overhead when having large number of objects on the stack to enumerate, enable etc.

    Simply define some reasonable (ASN.1 BER-TLV?:) structure where you say by TAG values what type of data are going through the pipe and it should be easy to format it on one side and decode on the other.

  • Hi,

    Thanks endnode for your answer.

    I'm not sure that I understand what you mean correctly. The solution you propose uses 1 custom profile with 2 services and 1 characteristic each containing structured defined data as follow, is that right?

    Custom Profile

    • Service with data type A
    • --Characteristic A
    • -- --Protocol version 1
    • -- --Sensor No1 Parameter A1
    • -- --Sensor No1 Parameter A2
    • -- --Sensor No1 Parameter A3
    • -- --Sensor No2 Parameter A1
    • -- --Sensor No2 Parameter A2
    • -- --Sensor No2 Parameter A3
    • -- --Sensor NoX Parameter A1
    • -- --Sensor NoX Parameter A2
    • -- --Sensor NoX Parameter A3
    • Service with data type B
    • --Characteristic B
    • -- --Protocol version 1
    • -- --Sensor No1 Parameter B1
    • -- --Sensor No1 Parameter B2
    • -- --Sensor No1 Parameter B3
    • -- --Sensor No1 Parameter B4
    • -- --Sensor No1 Parameter B5
    • -- --Sensor No1 Parameter B6
    • -- --Sensor No2 Parameter B1
    • -- --Sensor No2 Parameter B2
    • -- --Sensor No2 Parameter B3
    • -- --Sensor No2 Parameter B4
    • -- --Sensor No2 Parameter B5
    • -- --Sensor No2 Parameter B6
    • -- --Sensor NoX Parameter B1
    • -- --Sensor NoX Parameter B2
    • -- --Sensor NoX Parameter B3
    • -- --Sensor NoX Parameter B4
    • -- --Sensor NoX Parameter B5
    • -- --Sensor NoX Parameter B6

    The Protocoll version would allow to change the content or the formating without changing anything else. Your proposition is indeed very interesting! Thank you!

    -------- UPDATE 24.05.2017

    Hi,

    Thanks endnode for your explanations.

    The solution you propose uses then only 1 custom profile with 1 services and 1 characteristic containing structured defined data as follow, is that right?

    Custom Profile

    • Service type A
    • --Characteristic A
    • -- --Protocol Header containing: protocol version XY (1B), data type (1B), size (1B), sensor number/status (1B)
    • -- --|Sensor No1 Parameter A1|
    • -- --|Sensor No1 Parameter A2|
    • -- --|Sensor No1 Parameter A3|
    • -- --|Sensor No1 Parameter B1|
    • -- --|Sensor No1 Parameter B2|
    • -- --|Sensor No1 Parameter B3|
    • -- --|Sensor No1 Parameter B4|
    • -- --|Sensor No1 Parameter B5|
    • -- --|Sensor No1 Parameter B6|
    • -- --|Sensor No2 Parameter A1|
    • -- --|Sensor No2 Parameter A2|
    • -- --|Sensor No2 Parameter A3|
    • -- --|Sensor No2 Parameter B1|
    • -- --|Sensor No2 Parameter B2|-- DATA
    • -- --|Sensor No2 Parameter B3|
    • -- --|Sensor No2 Parameter B4|
    • -- --|Sensor No2 Parameter B5|
    • -- --|Sensor No2 Parameter B6|
    • -- --|Sensor NoX Parameter A1|
    • -- --|Sensor NoX Parameter A2|
    • -- --|Sensor NoX Parameter A3|
    • -- --|Sensor NoX Parameter B1|
    • -- --|Sensor NoX Parameter B2|
    • -- --|Sensor NoX Parameter B3|
    • -- --|Sensor NoX Parameter B4|
    • -- --|Sensor NoX Parameter B5|
    • -- --|Sensor NoX Parameter B6|

    Yes I have indeed one GATT Server, so Notifications seems to be the appropriate way to solve this. Furthermore some of the sensor data are already available in the Server but some other data need to be requested and would be delayed, so using Notification shouldn't be a problem. Using the Notifications automatically activate the CCCD (Client Characteristic Configuration Descriptor -> Core Specification, Volume 3, Part G, section 3.3.3.3) in the Server (Slave) nRF51+S130 Stack which need to be activated by the Client (Master) in order to enable the notifications, right? Update : Using the Notifications automatically create the CCCD without activating it allowing the Client to write (0x0001) in the Server to enable the Notification.

    A) You mentioned that if the Client need to send data in the Server it should use Write without confirmation method. Do you mean to enable the Notification Characteristic or to write in the Server? Update : Client to Server transport through Write methods (two types) and from Server to Client through Notify/Indicate (async) methods (Read methods is kind of old-fashion "pull" model).

    B) You said that with the same Characteristic I can make the communication bi-directional. If the Client Write data in the Server in Characteristic A, will the Client received the data it just sent over Notify or these are two different memory regions? I though that if I want to offer the possibility that the Client can send data in the Server I will have to create a new Characteristic B which is writable with Normal Write, Write without response or Signed Write. It not true then. Update : In terms of "performance" of connection time and throughput the experience is suggesting to design single "tube" (or pair of Tx/Rx buffers) on top of some Characteristic Value and then define more condensed protocol with Write/Notify methods.

    C) In the Nordic Stack how are Notifications sent? I simply have to set a table, its length and call the function notify? What if the table length is bigger than one BLE packet? Update : The Notify method provides ATT_MTU-3 values with ATT_MTU equals 23 by default and can be negotiated once per connection to minimum from Server and Client max values.

    D) The solution you propose is to encapsulate "data"/"data stream" into BLE using only one Characteristic basically? Using Notify for Server -> Client communication and Write or Write without response for Client -> Server communication.

    E) For now I plan to have a header containing: protocol version XY (1B), data type (1B), size (1B), sensor number/status (1B) making 4Bytes overhead. Why do you mention 0-125B (1B is 0-255)? BLE 4.2 should be able to transfers up to 247B L2CAP Payload, so about 244B data.

    Yes I need a very scalable solution and your proposition seems indeed very flexible and interesting! Thank you very much for your help!

    -------- UPDATE 07.06.2017

    Hi,

    Thanks endnode for your explanations and rct42 for your comment.

    Finally I will start with the NUS (Nordic UART Service) example which uses one custom profile with two services (one for Write and one Notify) and I will implement my own data protocol inside as follow:

    Custom Profile

    • Service 1 (Notify)
    • --Characteristic 1
    • -- --Protocol version
    • -- --Header
    • -- --DATA Header - Sensor 1
    • -- --DATA Sensor 1
    • -- --DATA Header - Sensor 2
    • -- --DATA Sensor 2
    • -- --DATA Header - Sensor X
    • -- --DATA Sensor X
    • Service 2 (Write)
    • --Characteristic 1
    • -- --Protocol version
    • -- --Header
    • -- --DATA Header - Sensor 1
    • -- --DATA Sensor 1
    • -- --DATA Header - Sensor 2
    • -- --DATA Sensor 2
    • -- --DATA Header - Sensor X
    • -- --DATA Sensor X

    Thank you very much for your help!

  • No. Profile is set of GATT and GAP rules. So I propose to define your profile with one Service, that contains one Characteristic. If you only need to transmit the data from that GATT Server then you allow Notification method on that Characteristic (which will create automatically CCCD handle attached to it on the stack), if you need to transport data from GATT Client side then you will use Write without confirmation method. If you need bi-directional communication you combine it, still single Service with single Characteristic is enough. And now on top of Value handle of that Characteristic you play with your protocol: that side which has the sensors and transmits data simply reads the sensor data, encapsulate them with some TAG and Length envelopes and transmit. On the receiver side you can see (by pre-defined TAGs) which data value belongs to which sensor.

  • Your proposal is like for 60 sensors to design 60 different URLs on the server instead of single page which displays everything. The principles of GATT Server/Client are pretty similar to any other Server/Client architecture you know from other technologies.

  • Then for "protocol" version: you simply allocate some TAGs in your first protocol version, is formatting of the content of particular TLV object is to be changed in any next version you can simply define new TAG and its formatting. If you arrive to device which supports newer version (= will send TLVs with new TAGs) and older version (= won't understand these TAGs) then receiver simply ignores any TLV which has unknown TAG.

Related