Converting uint8_t using Arduino 33 BLE and nRF

Hey guys,

i successfully connected my Arduino 33 BLE with my Android device. Therefore I am simply using the example Arduino 33 BLE -> Central -> PeriphalExplorer. I want to set a value on my phone and work with it on the Arduino. When i use characteristic.value() I can get the set value but in an uint8_t format. Now i am trying to convert it into an integer but it doesnt work. There are only a few people asking the same question and the answer is always "simply assign it". If i do so I get "536967856" for the value 3. How does it work? Let me know if you need more information.

Thx guys :wink:

#include <ArduinoBLE.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

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

    while (1);
  }

  Serial.println("BLE Central - Peripheral Explorer");

  // start scanning for peripherals
  BLE.scan();
}

void loop() {
  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();

    // see if peripheral is a LED
    if (peripheral.localName() == "FelixBLE") {
      // stop scanning
      BLE.stopScan();

      explorerPeripheral(peripheral);
      // peripheral disconnected, we are done
      while (1) {
        // do nothing
      }
    }
  }
}

void explorerPeripheral(BLEDevice peripheral) {
  // connect to the peripheral
  Serial.println("Connecting ...");

  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

  // discover peripheral attributes
  Serial.println("Discovering attributes ...");
  if (peripheral.discoverAttributes()) {
    Serial.println("Attributes discovered");
  } else {
    Serial.println("Attribute discovery failed!");
    peripheral.disconnect();
    return;
  }

  // read and print device name of peripheral
  Serial.println();
  Serial.print("Device name: ");
  Serial.println(peripheral.deviceName());
  Serial.print("Appearance: 0x");
  Serial.println(peripheral.appearance(), HEX);
  Serial.println();

  // loop the services of the peripheral and explore each
  for (int i = 0; i < peripheral.serviceCount(); i++) {
    BLEService service = peripheral.service(i);

    exploreService(service);
  }

  Serial.println();

  // we are done exploring, disconnect
  Serial.println("Disconnecting ...");
  peripheral.disconnect();
  Serial.println("Disconnected");
}

void exploreService(BLEService service) {
  // print the UUID of the service
  Serial.print("Service ");
  Serial.println(service.uuid());

  // loop the characteristics of the service and explore each
  for (int i = 0; i < service.characteristicCount(); i++) {
    BLECharacteristic characteristic = service.characteristic(i);

    exploreCharacteristic(characteristic);
  }
}

void exploreCharacteristic(BLECharacteristic characteristic) {
  // print the UUID and properties of the characteristic
  Serial.print("\tCharacteristic ");
  Serial.print(characteristic.uuid());
  Serial.print(", properties 0x");
  Serial.print(characteristic.properties(), HEX);

  // check if the characteristic is readable
  if (characteristic.canRead()) {
    // read the characteristic value
    characteristic.read();

    if (characteristic.valueLength() > 0) {
      // print out the value of the characteristic
      Serial.print(", value 0x");
      printData(characteristic.value(), characteristic.valueLength());
    }
  }
  Serial.println();

  // loop the descriptors of the characteristic and explore each
  for (int i = 0; i < characteristic.descriptorCount(); i++) {
    BLEDescriptor descriptor = characteristic.descriptor(i);

    exploreDescriptor(descriptor);
  }
}

void exploreDescriptor(BLEDescriptor descriptor) {
  // print the UUID of the descriptor
  Serial.print("\t\tDescriptor ");
  Serial.print(descriptor.uuid());

  // read the descriptor value
  descriptor.read();

  // print out the value of the descriptor
  Serial.print(", value 0x");
  printData(descriptor.value(), descriptor.valueLength());

  Serial.println();
}

void printData(const unsigned char data[], int length) {
  for (int i = 0; i < length; i++) {
    unsigned char b = data[i];

    if (b < 16) {
      Serial.print("0");
    }

    Serial.print(b, HEX);
  }
}

characteristic.value() returns a 'uint8_t *' which is a pointer to an array, not the value. Use the readValue() function to get the actual value.

Thx for the fast response. How exactly do I use the readValue() function? In the documentation it say i should use byte as the value. When i use it like given and print out the value it says "1" for the value "3".

When i use it like given and print out the value it says "1" for the value "3".

I want to set a value on my phone and work with it on the Arduino

How have you set up the phone as a peripheral device? What service, characteristics and characteristic values? How do you know that you are sending a value of 3?

Can you show the full print out from the library example sketch?

When i use it like given and print out the value it says "1" for the value "3".

How do you know that you are sending a value of "3"?

Is it printing out 0x01?

Hey, in the picture you can see the settings. This is what I get from the serial monitor:

BLE Central - Peripheral Explorer

Found 80:2b:f9:10:ff:d8 ''

Found 70:db:72:8e:93:88 'FelixBLE'

Connecting ...

Connected

Discovering attributes ...

Attributes discovered

Device name: FelixBLE

Appearance: 0x0

Service 1801

** Characteristic 2a05, properties 0x20**

Service 1800

** Characteristic 2a00, properties 0x2, value 0x46656C6978424C45**

** Descriptor 2803, value 0x021800012A**

** Descriptor 2a01, value 0x0000**

** Characteristic 2a01, properties 0x2, value 0x0000**

** Descriptor 2803, value 0x021A00A62A**

** Descriptor 2aa6, value 0x00**

** Characteristic 2aa6, properties 0x2, value 0x00**

Service 0d26

** Characteristic 1d26, properties 0x2, value 0x33**

Disconnecting ...

Disconnected

Service 0d26 is my test service and at the end you can find the value 3. How can I use it as an Integer?

Service 0d26 is my test service and at the end you can find the value 3. How can I use it as an Integer?

Yes, 0x33 is the Hex value of an ASCII character 3.

0X33 = decimal 51 = character '3'

For a simple method, you can use strtol() to convert the "0x33" to a decimal ascii value (51) , then subtract decimal ascii for '0' (48) from that number to give an integer value 0-9.

void setup() {
 Serial.begin(115200);
 char* value = "0x33";
 int myInt = strtol(value,NULL,16) - '0'; 
 Serial.println(myInt);
 Serial.print(myInt*3);
}
void loop() {}

If you have values which are not going to be a single digit between 0 and 9, but a longer string of hex chars there are different methods to convert. Google convert hex string to bytes.

What is the char* format for longer values?

For example if the value were 123 or 567, or 12345 what would the library show with

printData(characteristic.value(), characteristic.valueLength());

Thanks a lot at this point cattledog. It works!

When I use a higher value it prints emh...nothing. Not even the string "value".

1d26 was value 1
2d26 was value 123
3d26 was value 12345

Service 0d26
	Characteristic 1d26, properties 0x2, value 0x31
		Descriptor 2803, value 0x022C00262D
		Descriptor 2d26, value 0x
	Characteristic 2d26, properties 0x2
		Descriptor 2803, value 0x022E00263D
		Descriptor 3d26, value 0x
	Characteristic 3d26, properties 0x2

Another question: How can I save the value? I try to use the "readValue(value)" function. In the documentation it says it stores the value in the value given to "readValue". When I try to use it as following:

char* value = 0;
      characteristic.readValue(value);
      int myInt = strtol(value,NULL,16) - '0';
      Serial.println(myInt);
      Serial.print(myInt*3);

it says:

Arduino: 1.8.14 Hourly Build 2021/03/09 09:33 (Windows 10), Board: "Arduino Nano 33 BLE"

C:\Users\felix\Desktop\test\FinalBLETest\FinalBLETest.ino: In function 'void exploreCharacteristic(BLECharacteristic)':

FinalBLETest:124:37: error: no matching function for call to 'readValue(char*&)'

       characteristic.readValue(value);

                                     ^

In file included from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEService.h:23:0,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEDevice.h:25,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/local/BLELocalDevice.h:23,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/ArduinoBLE.h:23,

                 from C:\Users\felix\Desktop\test\FinalBLETest\FinalBLETest.ino:1:

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:64:7: note: candidate: int BLECharacteristic::readValue(uint8_t&) <near match>

   int readValue(uint8_t& value);

       ^~~~~~~~~

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:64:7: note:   conversion of argument 1 would be ill-formed:

FinalBLETest:124:37: error: invalid conversion from 'char*' to 'uint8_t {aka unsigned char}' [-fpermissive]

       characteristic.readValue(value);

                                     ^

FinalBLETest:124:37: error: cannot bind rvalue '(uint8_t)value' to 'uint8_t& {aka unsigned char&}'

In file included from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEService.h:23:0,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEDevice.h:25,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/local/BLELocalDevice.h:23,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/ArduinoBLE.h:23,

                 from C:\Users\felix\Desktop\test\FinalBLETest\FinalBLETest.ino:1:

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:65:7: note: candidate: int BLECharacteristic::readValue(int8_t&) <near match>

   int readValue(int8_t& value);

       ^~~~~~~~~

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:65:7: note:   conversion of argument 1 would be ill-formed:

FinalBLETest:124:37: error: invalid conversion from 'char*' to 'int8_t {aka signed char}' [-fpermissive]

       characteristic.readValue(value);

                                     ^

FinalBLETest:124:37: error: cannot bind rvalue '(int8_t)value' to 'int8_t& {aka signed char&}'

In file included from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEService.h:23:0,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEDevice.h:25,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/local/BLELocalDevice.h:23,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/ArduinoBLE.h:23,

                 from C:\Users\felix\Desktop\test\FinalBLETest\FinalBLETest.ino:1:

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:66:7: note: candidate: int BLECharacteristic::readValue(uint16_t&) <near match>

   int readValue(uint16_t& value);

       ^~~~~~~~~

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:66:7: note:   conversion of argument 1 would be ill-formed:

FinalBLETest:124:37: error: invalid conversion from 'char*' to 'uint16_t {aka short unsigned int}' [-fpermissive]

       characteristic.readValue(value);

                                     ^

FinalBLETest:124:37: error: cannot bind rvalue '(uint16_t)value' to 'uint16_t& {aka short unsigned int&}'

In file included from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEService.h:23:0,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEDevice.h:25,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/local/BLELocalDevice.h:23,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/ArduinoBLE.h:23,

                 from C:\Users\felix\Desktop\test\FinalBLETest\FinalBLETest.ino:1:

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:67:7: note: candidate: int BLECharacteristic::readValue(int16_t&) <near match>

   int readValue(int16_t& value);

       ^~~~~~~~~

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:67:7: note:   conversion of argument 1 would be ill-formed:

FinalBLETest:124:37: error: invalid conversion from 'char*' to 'int16_t {aka short int}' [-fpermissive]

       characteristic.readValue(value);

                                     ^

FinalBLETest:124:37: error: cannot bind rvalue '(int16_t)value' to 'int16_t& {aka short int&}'

In file included from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEService.h:23:0,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEDevice.h:25,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/local/BLELocalDevice.h:23,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/ArduinoBLE.h:23,

                 from C:\Users\felix\Desktop\test\FinalBLETest\FinalBLETest.ino:1:

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:68:7: note: candidate: int BLECharacteristic::readValue(uint32_t&) <near match>

   int readValue(uint32_t& value);

       ^~~~~~~~~

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:68:7: note:   conversion of argument 1 would be ill-formed:

FinalBLETest:124:37: error: invalid conversion from 'char*' to 'uint32_t {aka long unsigned int}' [-fpermissive]

       characteristic.readValue(value);

                                     ^

FinalBLETest:124:37: error: cannot bind rvalue '(uint32_t)value' to 'uint32_t& {aka long unsigned int&}'

In file included from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEService.h:23:0,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLEDevice.h:25,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/local/BLELocalDevice.h:23,

                 from C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/ArduinoBLE.h:23,

                 from C:\Users\felix\Desktop\test\FinalBLETest\FinalBLETest.ino:1:

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:69:7: note: candidate: int BLECharacteristic::readValue(int32_t&) <near match>

   int readValue(int32_t& value);

       ^~~~~~~~~

C:\Users\felix\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:69:7: note:   conversion of argument 1 would be ill-formed:

FinalBLETest:124:37: error: invalid conversion from 'char*' to 'int32_t {aka long int}' [-fpermissive]

       characteristic.readValue(value);

                                     ^

FinalBLETest:124:37: error: cannot bind rvalue '(int32_t)value' to 'int32_t& {aka long int&}'

exit status 1

no matching function for call to 'readValue(char*&)'

Do I need another library? But that wouldnt make sense. Why is the function missing?

Documentation: ArduinoBLE - Arduino Reference

When I use a higher value it prints emh...nothing. Not even the string "value".

1d26 was value 1
2d26 was value 123
3d26 was value 12345

I don't know what you are using on your phone to emulate the peripheral, but what happens if you just use the characteristic 1d26 with the higher values.

Another question: How can I save the value?

I don't have any direct experience with that library, so what I know comes from a general understanding of BLE and reading the source code.

This is the function definition for characteristic.value()

const uint8_t* value() const;

We know that it is returning a byte pointer to an array that's passed to printData.

void printData(const unsigned char data[], int length) {
  for (int i = 0; i < length; i++) {
    unsigned char b = data[i];

    if (b < 16) {
      Serial.print("0");
    }

    Serial.print(b, HEX);
    
  }
}

My thinking is that you can save the returned characteristic.value() array in a new array with memcpy.

void setup() {
  Serial.begin(115200);
  const unsigned char data[] = {'3'};
  //const unsigned char data[] = {'3','2','1'};
  //const unsigned char data[] = {'5','4','3','2','1'}; 
  Serial.print("original value = ");
  printData(data,sizeof(data));
  Serial.println();
  char mySavedValue[10];//make large enough for 5 hex values
  memset(mySavedValue,'0',10);//fill with zeros
  memcpy(mySavedValue, data, sizeof(data));
  Serial.print("copied value = ");
  printData(mySavedValue,sizeof(data));
  Serial.println();
}
void loop() {}

void printData(const unsigned char data[], int length) {
  for (int i = 0; i < length; i++) {
    unsigned char b = data[i];

    if (b < 16) {
      Serial.print("0");
    }
    Serial.print(b, HEX);
  }
}

To emulate the periphal I am useing the nRF app. There I set up my GATT server with a "Test" service and these "Test" characteristics. Then I activate a advertiser and choose the data I want to share.

When I give the 1d26 char the value "12345" it says: value 0x3132333435

I have tried you code and there is a problem with:

printData(mysavedValue,sizeof(data))

You enter a char but the function needs a const unsigned char.

void printData(const unsigned char data[], int length) {
  for (int i = 0; i < length; i++) {
    unsigned char b = data[i];

    if (b < 16) {
      Serial.print("0");
    }
    Serial.print(b, HEX);
  }
}

When I try to use it as an const unsigned char it needs to be initialised. When I initialise it this doesnt work due to conversion from void to const void. How can I solve this problem?

memcpy(mySavedValue, data, sizeof(data));

When I give the 1d26 char the value "12345" it says: value 0x3132333435

That looks correct. I'm unclear on why you could not set up and read additional values with these larger numbers in nRF Connect.

Regarding your issues with memcpy are you getting warnings or errors?
Can you post the exact code you are trying, and the error message.

EDIT: I installed the board and library into my IDE, and can now test the example code with modifications and indeed can confirm your error. See the next post.

Declare as global

char mySavedValue[10];

This compiles for me with with the for loop printing of mySavedValue instead of calling the printData() function. Unfortunately, I don't have a nanoBLE to actually run the sketch.

void exploreCharacteristic(BLECharacteristic characteristic) {
  // print the UUID and properties of the characteristic
  Serial.print("\tCharacteristic ");
  Serial.print(characteristic.uuid());
  Serial.print(", properties 0x");
  Serial.print(characteristic.properties(), HEX);

  // check if the characteristic is readable
  if (characteristic.canRead()) {
    // read the characteristic value
    characteristic.read();

    if (characteristic.valueLength() > 0) {
      // print out the value of the characteristic
      Serial.print(", value 0x");
      printData(characteristic.value(), characteristic.valueLength());
      memset(mySavedValue, '0', 10); //fill with zeros
      memcpy(mySavedValue, characteristic.value(), characteristic.valueLength());
      Serial.print("copied value = ");
      //printData(mySavedValue, characteristic.valueLength());
      for (int i = 0; i < characteristic.valueLength(); i++) {
        unsigned char b = mySavedValue[i];
        if (b < 16) {
          Serial.print("0");
        }
        Serial.print(b, HEX);
      }
      Serial.println();
    }
  }
  Serial.println();

  // loop the descriptors of the characteristic and explore each
  for (int i = 0; i < characteristic.descriptorCount(); i++) {
    BLEDescriptor descriptor = characteristic.descriptor(i);

    exploreDescriptor(descriptor);
  }
}

Are you wanting to save the integer value or the string value?
characteristic.value() just returns a pointer to something like "12345"
Your printout routine is the thing that expands it into a series of 2 digit hexadecimal values. If you want the numeric value, just do

long int value = atol(characteristic.value());

Your printout routine is the thing that expands it into a series of 2 digit hexadecimal values

I'm not clear on whether or not it is a pointer to a character string of base 16 hex characters or a character string of base 10 characters. atol will only work if the string is "12345" and not "3132333435".

The way characteristic.valueLength() is used makes me think the underlying BLE transmissions are hex chars.

blh64:
Are you wanting to save the integer value or the string value?
characteristic.value() just returns a pointer to something like "12345"
Your printout routine is the thing that expands it into a series of 2 digit hexadecimal values. If you want the numeric value, just do

long int value = atol(characteristic.value());

Unfortunately this doesnt work. Within the atol() function is an invalid conversion.

cattledog:
Declare as global

char mySavedValue[10];

This compiles for me with with the for loop printing of mySavedValue instead of calling the printData() function. Unfortunately, I don't have a nanoBLE to actually run the sketch.

void exploreCharacteristic(BLECharacteristic characteristic) {

// print the UUID and properties of the characteristic
 Serial.print("\tCharacteristic ");
 Serial.print(characteristic.uuid());
 Serial.print(", properties 0x");
 Serial.print(characteristic.properties(), HEX);

// check if the characteristic is readable
 if (characteristic.canRead()) {
   // read the characteristic value
   characteristic.read();

if (characteristic.valueLength() > 0) {
     // print out the value of the characteristic
     Serial.print(", value 0x");
     printData(characteristic.value(), characteristic.valueLength());
     memset(mySavedValue, '0', 10); //fill with zeros
     memcpy(mySavedValue, characteristic.value(), characteristic.valueLength());
     Serial.print("copied value = ");
     //printData(mySavedValue, characteristic.valueLength());
     for (int i = 0; i < characteristic.valueLength(); i++) {
       unsigned char b = mySavedValue[i];
       if (b < 16) {
         Serial.print("0");
       }
       Serial.print(b, HEX);
     }
     Serial.println();
   }
 }
 Serial.println();

// loop the descriptors of the characteristic and explore each
 for (int i = 0; i < characteristic.descriptorCount(); i++) {
   BLEDescriptor descriptor = characteristic.descriptor(i);

exploreDescriptor(descriptor);
 }
}

When I use this I can print out the HEX value. This seems not bad. How can I convert that to an integer now?

Service 0d26
    Characteristic 1d26, properties 0x2, value 0x3132333435 copied value = 3132333435

Maybe characteristic.value() does not have a terminating null character at the end? In that case, you have copied out all the bytes and a null characterter into mySavedValue, so just convert that

long int value = atol(mySavedValue);

I think the general approach is to convert the array returned by the characteristic.value() to a null terminated character array (c string). There are many standard c string functions which can work with this null terminated character array, and the null terminated array is more flexible to use than the unterminated byte/char array.

Some standard functions can convert the null terminated array to a numerical value. Important for you will be and atoi() conver to integer, atol()convert to long integer, and atof()convert to floating point number.

First, declare as a global variable an array which will be filled with a null terminated character array.

char c_strValue[10];//size for 9 digit number + null terminator. Will always hold int32_t "long" using atol

Here's the function to convert the unterminated array to a null terminated character array

void nullTerminateArray(const unsigned char array[], int len) //make parameters consistent with characteristic.value()
{
  if (len > 9)
  {
    Serial.println ("length error");
    return;
  }
  memcpy(c_strValue, array, len);
  c_strValue[len] = '\0';//null terminate
  Serial.print("Null terminated character array: ");
  Serial.println(c_strValue);
}

Here's some example code which shows the usage method. Note that you can use it to deal with a floating point value like 12.34.

char c_strValue[10];//size for 9 digit number + null terminator will always fit into int32_t "long" using atol

void nullTerminateArray(const unsigned char array[], int len) //make parameters consistent with characteristic.value()
{
  if (len > 9)
  {
    Serial.println ("length error");
    return;
  }
  memcpy(c_strValue, array, len);
  c_strValue[len] = '\0';//null terminate
  Serial.print("Null terminated character array: ");
  Serial.println(c_strValue);
}


void setup() {
  Serial.begin(115200);
  //const unsigned char value[] = {0x33};//3
  const unsigned char value[] = {0x31, 0x32, 0x33, 0x34, 0x35}; // 12345
  //const unsigned char value[] = {0x2D, 0x31, 0x32, 0x33, 0x34, 0x35}; // -12345
  //const unsigned char value[] = {0x31, 0x30, 0x32, 0x33}; //1023
  //const unsigned char value[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36,0x37,0x38,0x39};//123456789 max length
  //const unsigned char value[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36,0x37,0x38,0x39,0x39};//1234567899 length error
  //const unsigned char value[] = {0x31, 0x32, 0x2E, 0x33, 0x34};// 12.34
  nullTerminateArray(value, sizeof(value));

  //use numerical value or save in variable
  Serial.println(atol(c_strValue) * 2); //long integer
  //Serial.print(atof(c_strValue) * 2); //for float with dp

}
void loop() {}

Here's the library example code PeripheralExplorer with the function added and the call in the exploreCharacteristic(). Compiles but not run.

/*
  Peripheral Explorer

  This example scans for BLE peripherals until one with a particular name ("LED")
  is found. Then connects, and discovers + prints all the peripheral's attributes.

  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 it with another board that is compatible with this library and the
  Peripherals -> LED example.

  This example code is in the public domain.
*/

#include <ArduinoBLE.h>

char c_strValue[10];//size for 9 digit number + null terminator will always fit into int32_t "long" using atol

void setup() {
  Serial.begin(9600);
  while (!Serial);

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

    while (1);
  }

  Serial.println("BLE Central - Peripheral Explorer");

  // start scanning for peripherals
  BLE.scan();
}

void loop() {
  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();

    // see if peripheral is a LED
    if (peripheral.localName() == "LED") {
      // stop scanning
      BLE.stopScan();

      explorerPeripheral(peripheral);

      // peripheral disconnected, we are done
      while (1) {
        // do nothing
      }
    }
  }
}

void explorerPeripheral(BLEDevice peripheral) {
  // connect to the peripheral
  Serial.println("Connecting ...");

  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

  // discover peripheral attributes
  Serial.println("Discovering attributes ...");
  if (peripheral.discoverAttributes()) {
    Serial.println("Attributes discovered");
  } else {
    Serial.println("Attribute discovery failed!");
    peripheral.disconnect();
    return;
  }

  // read and print device name of peripheral
  Serial.println();
  Serial.print("Device name: ");
  Serial.println(peripheral.deviceName());
  Serial.print("Appearance: 0x");
  Serial.println(peripheral.appearance(), HEX);
  Serial.println();

  // loop the services of the peripheral and explore each
  for (int i = 0; i < peripheral.serviceCount(); i++) {
    BLEService service = peripheral.service(i);

    exploreService(service);
  }

  Serial.println();

  // we are done exploring, disconnect
  Serial.println("Disconnecting ...");
  peripheral.disconnect();
  Serial.println("Disconnected");
}

void exploreService(BLEService service) {
  // print the UUID of the service
  Serial.print("Service ");
  Serial.println(service.uuid());

  // loop the characteristics of the service and explore each
  for (int i = 0; i < service.characteristicCount(); i++) {
    BLECharacteristic characteristic = service.characteristic(i);

    exploreCharacteristic(characteristic);
  }
}

void exploreCharacteristic(BLECharacteristic characteristic) {
  // print the UUID and properties of the characteristic
  Serial.print("\tCharacteristic ");
  Serial.print(characteristic.uuid());
  Serial.print(", properties 0x");
  Serial.print(characteristic.properties(), HEX);

  // check if the characteristic is readable
  if (characteristic.canRead()) {
    // read the characteristic value
    characteristic.read();

    if (characteristic.valueLength() > 0) {
      // print out the value of the characteristic
      Serial.print(", value 0x");
      printData(characteristic.value(), characteristic.valueLength());
      nullTerminateBytes(characteristic.value(), characteristic.valueLength());
      //convert the c_string to an arithmetic number with atoi() atof() atol()
      //can save or use mathematically  
    }
  }
  Serial.println();

  // loop the descriptors of the characteristic and explore each
  for (int i = 0; i < characteristic.descriptorCount(); i++) {
    BLEDescriptor descriptor = characteristic.descriptor(i);

    exploreDescriptor(descriptor);
  }
}

void exploreDescriptor(BLEDescriptor descriptor) {
  // print the UUID of the descriptor
  Serial.print("\t\tDescriptor ");
  Serial.print(descriptor.uuid());

  // read the descriptor value
  descriptor.read();

  // print out the value of the descriptor
  Serial.print(", value 0x");
  printData(descriptor.value(), descriptor.valueLength());
}

void printData(const unsigned char data[], int length) {
  for (int i = 0; i < length; i++) {
    unsigned char b = data[i];

    if (b < 16) {
      Serial.print("0");
    }

    Serial.print(b, HEX);
  }
}

void nullTerminateBytes(const unsigned char data[], int len)
{
  if(len > 9)
   {
    Serial.println ("length error");
    return;
   }
  memcpy(c_strValue, data, len); 
  c_strValue[len] = '\0';//null terminate
  Serial.print("Null terminated chacter array: ");
  Serial.println(c_strValue);
}

blh64:
Maybe characteristic.value() does not have a terminating null character at the end? In that case, you have copied out all the bytes and a null characterter into mySavedValue, so just convert that

long int value = atol(mySavedValue);

When i use this, i get the value but alot bigger: 1234500000
But I could just divide it by 10^i. Thank you guys. I think i can continue working on my project.^^

When i use this, i get the value but alot bigger: 1234500000

You have not placed the null terminator after the last number.

cattledog:
You have not placed the null terminator after the last number.

Sorry it was on the second page and I couldnt see your answer. It works! Thanks a lot now I can really work with it without problems. You got a little typo here but that doesnt matter. Just for your information:

Serial.print("Null terminated character array: ");

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.