Android Question BLE WriteData

fjb

Member
Licensed User
Longtime User
WriteData (Service As String, Characteristic As String, Data() As Byte)
Is there a way to write a large string or series of values with this method?
for example
102,111,254,254,126,050
when I try to write those values to the arduino i only get the first block of value. (102)
Android has a BLEStringCharacteristic. Is there away to send a large string to the arduino from an android?
 

emexes

Expert
Licensed User
WriteData (Service As String, Characteristic As String, Data() As Byte)
Is there a way to write a large string or series of values with this method?

If your Arduino is set up to look like a BLE device with a(t least one) writeable characteristic to accept the multibyte data, then: yes.

I have a vague recollection about size being 20 bytes maximum per write.

Your code should look something like:
B4X:
Dim DataToSend() As Byte = Array As Byte(102, 111, 254, 254, 126, 50)    'best not to have leading 0s on integer decimal literals
WriteDate(ToService, ToCharacteristic, DataToSend)
 
Last edited:
Upvote 0

fjb

Member
Licensed User
Longtime User
Thanks for the response. I have done as you suggest however I still am only able to get the first block of numbers. Since everything is compiling and running with b4a I assume it is indeed sending that entire array I guess my question should go to the Arduino forum. I don't see any way in the Arduino to get anything beyond that first byte. There are not many examples for the ble communication that I can find. I am using the MKR1010 board, the ArduinoBLE library example ButtonLED, and the BLE example(s) found in this forum. I am not sure if the Arduino method BLEStringCharacteristic is the answer not much help for it's usage. Also the leading zero was a typo.
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
When you write multiple bytes to the characteristic with nRF Connect, how many of those bytes does the Arduino (seem to) receive?
 
Upvote 0

fjb

Member
Licensed User
Longtime User
Only the first byte in the array. This is my first step into BLE. I like to do first and learn later. Looks like this time I will have to learn first. Thanks for the help.
 
Upvote 0

fjb

Member
Licensed User
Longtime User
I have made some headway. I am able to get the Arduino to read and write as many hex values as I need. I don't know what the limit is but 50 bytes seems to work.
You write from the arduino with DEC values and it is received as HEX in nRF Connect. So for me it is a matter of converting HEX to DEC and visa versa.

Below is the Arduino code. I found it posted somewhere and added my modifications.
Now off to figure out how to put it all together in an app on the phone using B4A.

Sending a bunch of random values using nRF Connect produces this in the Serial Monitor.
The outgoing values are recieved in the nRF Connect app.

arduino serial monitor:
/*
BLE_events
Bluetooth device active, waiting for connections...
Connected event, central: 7c:ef:d9:ab:0b:fe
Characteristic updated. UUID: D65D0396-0004-4381-9985-653653CE831F   value:
incoming:
HEX: AA-AB-AC-AF-AE-AF-BA-BB-BC-BD-BE-BF-CA-CC-CB-CD-CE-CF-DA-DB-DC-DD-DE-DF-FA-FB-FC-FD-FE-FF-0-0-A5-8E-0-0-0-0-0-0-
DEC: 170-171-172-175-174-175-186-187-188-189-190-191-202-204-203-205-206-207-218-219-220-221-222-223-250-251-252-253-254-255-0-0-165-142-0-0-0-0-0-0-
outgoing:
HEX: A-14-1E-28-32-3C-46-50-5A-64-6E-78-82-8C-96-A0-AA-B4-BE-D2-DC-E6-FA-FF-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-
DEC: 10-20-30-40-50-60-70-80-90-100-110-120-130-140-150-160-170-180-190-210-220-230-250-255-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

arduibni code:
/*
/*
  Callback test

  This example creates a BLE peripheral with three services. It demonstrates the
  following device callback events: BLEConnected, BLEDisconnected; and
  the following characteristic events: BLESubscribed, BLEUnsubscribed, BLEUpdated

  The circuit:
  - Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
    Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.

  You can use a generic BLE central app, like LightBlue (iOS and Android) or


  nRF Connect (Android), to interact with the services and characteristics
  created in this sketch.

  created 7 Mar 2022
  by Tom Igoe
*/

#include <ArduinoBLE.h>

// this define is a macro. It says "take whatever is in parentheses
// and add it in the middle of this string. This way you don't have
// to write out the whole string in each characteristic:
#define MY_UUID(val) ("D65D0396-" val "-4381-9985-653653CE831F")

char bleName[] = "BLE_events";
// BLE service
BLEService myService(MY_UUID("0000"));

// create  characteristics: that differ from the service UUID by 1 digit:
//BLEByteCharacteristic firstChar(MY_UUID("0001"), BLERead | BLEWrite | BLENotify);
//BLEByteCharacteristic secondChar(MY_UUID("0002"), BLERead | BLEWrite | BLENotify);
BLEByteCharacteristic thirdChar(MY_UUID("0003"), BLERead | BLEWrite | BLENotify);
BLECharacteristic fourthChar(MY_UUID("0004"), BLERead | BLEWrite, 40 | BLENotify);

void setup() {

  // init serial, wait 3 secs for serial monitor to open:
  Serial.begin(9600);
  // if the serial port's not open, wait 3 seconds:
  if (!Serial) delay(3000);
  // use builtin LED for connection indicator:
  pinMode(LED_BUILTIN, OUTPUT);

  // begin BLE initialization
  if (!BLE.begin()) {
    Serial.println("starting BLE failed");
    while (true);
  }

  // set the local name peripheral advertises:
  BLE.setLocalName(bleName);
  // print it:
  Serial.println(bleName);
  // set the UUID for the service this peripheral advertises:
  BLE.setAdvertisedService(myService);
  // add the characteristic:
  // myService.addCharacteristic(firstChar);
  // myService.addCharacteristic(secondChar);
  myService.addCharacteristic(thirdChar);
  myService.addCharacteristic(fourthChar);

  // add the service:
  BLE.addService(myService);

  // set characteristic values:
  //firstChar.setValue(0);
  //secondChar.setValue(0);
  thirdChar.setValue(0);
  fourthChar.setValue(0);

  // assign event handlers for connected, disconnected to peripheral
  BLE.setEventHandler(BLEConnected, connectHandler);
  BLE.setEventHandler(BLEDisconnected, disconnectHandler);

  // assign event handlers for characteristics:
  // firstChar.setEventHandler(BLEUpdated, characteristicUpdated);
  //  firstChar.setEventHandler(BLESubscribed, characteristicSubscribed);
  // firstChar.setEventHandler(BLEUnsubscribed, characteristicUnsubscribed);

  // secondChar.setEventHandler(BLEUpdated, characteristicUpdated);
  // secondChar.setEventHandler(BLESubscribed, characteristicSubscribed);
  // secondChar.setEventHandler(BLEUnsubscribed, characteristicUnsubscribed);

  thirdChar.setEventHandler(BLEUpdated, characteristicUpdated);
  thirdChar.setEventHandler(BLESubscribed, characteristicSubscribed);
  thirdChar.setEventHandler(BLEUnsubscribed, characteristicUnsubscribed);

  fourthChar.setEventHandler(BLEUpdated, characteristicUpdated);
  fourthChar.setEventHandler(BLESubscribed, characteristicSubscribed);
  fourthChar.setEventHandler(BLEUnsubscribed, characteristicUnsubscribed);
  // start advertising
  BLE.advertise();
  Serial.println("Bluetooth device active, waiting for connections...");
}

void loop() {
  // poll for BLE events
  BLE.poll();
}

// listen for BLE connect events:
void connectHandler(BLEDevice central) {
  // central connected event handler
  Serial.print("Connected event, central: ");
  Serial.println(central.address());
  digitalWrite(LED_BUILTIN, HIGH);
}

// listen for BLE disconnect events:
void disconnectHandler(BLEDevice central) {
  // central disconnected event handler
  Serial.print("Disconnected event, central: ");
  Serial.println(central.address());
  digitalWrite(LED_BUILTIN, LOW);
}

// listen for characteristic subscribed events:
void characteristicSubscribed(BLEDevice central, BLECharacteristic thisChar) {
  // central wrote new value to characteristic, update LED
  Serial.print("Characteristic subscribed. UUID: ");
  Serial.println(thisChar.uuid());
}

// listen for characteristic unsubscribed events:
void characteristicUnsubscribed(BLEDevice central, BLECharacteristic thisChar) {
  // central wrote new value to characteristic, update LED
  Serial.print("Characteristic unsubscribed. UUID: ");
  Serial.println(thisChar.uuid());
}

// listen for characteristic updated events:
void characteristicUpdated(BLEDevice central, BLECharacteristic thisChar) {
  byte incoming[40];
  byte outgoing[50] {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190.200, 210, 220, 230.240, 250, 255};

  Serial.print("Characteristic updated. UUID: ");
  Serial.print(thisChar.uuid());
  Serial.print("   value: ");
  Serial.println();

  thisChar.readValue(incoming, 40);
  Serial.println("incoming: ");
  Serial.print("HEX: ");

  for (int i = 0; i < 40; i++) {
    Serial.print(incoming[i], HEX);
    Serial.print("-");
  }
  Serial.println();
  Serial.print("DEC: ");

  for (int i = 0; i < 40; i++) {
    Serial.print(incoming[i], DEC);
    Serial.print("-");
  }
  Serial.println();
  thisChar.writeValue(outgoing, 50);

  Serial.println("outgoing: ");
  Serial.print("HEX: ");
  for (int i = 0; i < 40; i++) {
    Serial.print(outgoing[i], HEX);
    Serial.print("-");
  }
  Serial.println();
  Serial.print("DEC: ");
  for (int i = 0; i < 40; i++) {
    Serial.print(outgoing[i], DEC);
    Serial.print("-");
  }
  Serial.println();
}
 
Upvote 0

emexes

Expert
Licensed User
I have made some headway. I am able to get the Arduino to read and write as many hex values as I need. I don't know what the limit is but 50 bytes seems to work.
You write from the arduino with DEC values and it is received as HEX in nRF Connect. So for me it is a matter of converting HEX to DEC and visa versa.
C:
byte outgoing[50] {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190.200, 210, 220, 230.240, 250, 255};

Looking good! šŸ†

One super-minor clarification is that what you are writing and receiving are bytes, which can be represented (printed) in DECimal or HEXadecimal (or binary or octal or whatever).

You can enter HEX numbers directly using 0x prefix eg:

byte outgoing[50] {72, 101, 108, 108, 111, 32, 102, 106, 98, 0}

is same as:

byte outgoing[50] {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x66, 0x6a, 0x62, 0x00}

is same as mix'n'match:

byte outgoing[50] {72, 0x65, 108. 0x6c, 111, 0x20, 102, 0x6a, 98, 0x00}

tbh I thought there should be "=" between "]" and "{" but maybe the Arduino compiler is different to the C that I remember, or maybe I'm getting old :oops:
 
Upvote 0

emexes

Expert
Licensed User
One super-minor clarification is that what you are writing and receiving are bytes, which can be represented (printed) in DECimal or HEXadecimal (or binary or octal or whatever).

Which reminds me:

q. why do programmers often get Halloween and Christmas confused?

a. because OCT 31 = DEC 25

šŸ™ƒ
 
  • Haha
Reactions: udg
Upvote 0

fjb

Member
Licensed User
Longtime User
That is very clever. Can't wait to share that one.

I discovered with the help from the Arduino forum that I was not setting the BLECharacteristic parameters correctly.

arduino code correction:
incorrect
BLECharacteristic fourthChar(MY_UUID("0004"), BLERead | BLEWrite, 40 | BLENotify);

correct
BLECharacteristic fourthChar(MY_UUID("0004"), BLERead | BLEWrite | BLENotify, 40);
 
Upvote 0

mmgh28

New Member
Hello, to send the bytes from b4a you used only the WriteData method or you used SetNotify, could you please share your code, I am also trying to send data from b4a to arduino, but I still have no results. I would greatly appreciate your help.
 
Upvote 0

fjb

Member
Licensed User
Longtime User
I got all of my information from the B4A BLEExample.
To write data from b4a you use the WriteData method. In the peripheral device in my case an arduino mkr1010 I create a characteristic with the notify option then in b4a I set notify to true for that chacteristic and when the data changes in the arduino I do a write data to the characteristic and the b4a Manager_DataAvailable buffer is filled and the sub is fired.

I suggest getting connections and communication working with an app like nrfConnect first. The code I posted above works with a mkr1010 and nrfConnect.

I don't know who came up with the names for these methods and functions but I find them very confusing. It reminds me of moving from CPM to Unix.
 

Attachments

  • B4A_BLE.zip
    8.5 KB · Views: 94
Last edited:
Upvote 0
Top