I can't send an integer over BLE over 1 byte

I'm using the LightBlue app on Android to send data to an Arduino Nano 33 IOT with BLE. When I try to send integers in hex format with the LightBlue app it works unless I send something bigger than one byte. When I send "FF" which is 255 or 1 byte I also see 255 in the serial monitor but if I send "100" which is 256 I get 1 again. Basically, everything over 1 byte makes it produce garbage numbers after that. I can fix the issue by spamming it with a bunch of zeros. Presumably, that clears a buffer and there's a mismatch in the packet size or something.

Here is my code:

#include <ArduinoBLE.h>

BLEService stepperService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service

// BLE LED Switch Characteristic - custom 128-bit UUID, writable by central
BLEIntCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLEWrite);


const int ledPin = LED_BUILTIN; // pin to use for the LED
int delayStepper = 100; 
void setup() {
  Serial.begin(9600);
  while (!Serial);

  // set LED pin to output mode
  pinMode(ledPin, OUTPUT);

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

    while (1);
  }

  // set advertised local name and service UUID:
  BLE.setLocalName("Stepper motor control");
  BLE.setAdvertisedService(stepperService);

  // add the characteristic to the service
  stepperService.addCharacteristic(switchCharacteristic);

  // add service
  BLE.addService(stepperService);

  // set the initial value for the characeristic:
  switchCharacteristic.writeValue(100);

  // start advertising
  BLE.advertise();

  Serial.println("BLE LED Peripheral");
}

void loop() {
  // listen for BLE peripherals to connect:
  BLEDevice central = BLE.central();
  Serial.println("No central found");
  
  // if a central is connected to peripheral:
  if (central) {
    Serial.print("Connected to central: ");
    // print the central's MAC address:
    Serial.println(central.address());

    // while the central is still connected to peripheral:
    while (central.connected()) {
      // if the remote device wrote to the characteristic,
      // use the value to control the LED:

      if (switchCharacteristic.written()) {
        delayStepper = switchCharacteristic.value();
        Serial.print("New value is: ");
        Serial.println(delayStepper);

      }
    }

    // when the central disconnects, print it out:
    Serial.print(F("Disconnected from central: "));
    Serial.println(central.address());
  }
}

Here's the serial monitor log after sending 0x00, 0xFF, 0x0100, 0x0101, 0x0102 from the LightBlue app:

  • 18:56:59.632 -> No central found
  • 18:56:59.632 -> No central found
  • 18:56:59.632 -> No central found
  • 18:56:59.632 -> No central found
  • 18:56:59.632 -> No central found
  • 18:56:59.632 -> Connected to central: 59:20:d4:80:e5:e9
  • 18:57:06.077 -> New value is: 0
  • 18:57:09.510 -> New value is: 255
  • 18:57:15.029 -> New value is: 1
  • 18:57:19.293 -> New value is: 257
  • 18:57:21.902 -> New value is: 513

what' the “Data format” you see in LightBlue app when you try to write the new value?

Hex. I also tried all the other ones but the one in the post is HEX.

I tried your code but changed the print into
Serial.println(delayStepper, HEX);
to see better what would be received

I'm on iOS and I use nRF Connect instead of LightBlue app.

I connected and sent FFFF and then DEADBEEF

Serial Monitor show

...
No central found
No central found
Connected to central: 2d:35:90:ae:11:3f
New value is: FFFF
New value is: EFBEADDE

So it seems to work and of course there is the little endian / big endian discrepancy as DEADBEEF was displayed in an HEX reversed way.

âžś can you try with nRF Connect

Unfortunately, all the BLE apps are as generic as possible and do not support data types. They just handle bytes and sometimes strings.
The bad thing is the Bluetooth specification has defined some descriptors that allow you to describe the data type (e.g., 32 bit integer) and even units (volt, ampere, ... ). But it seems they are not used.

What do you want to use as a central when developed your peripheral devices?

1 Like

Isn't DEADBEEF reversed FEEBDAED and not EFBEADDE? I feel like I'm missing something?

No, the byte order is inverted.

0x12345678 -> 0x78, 0x56, 0x34, 0x12 Four bytes LSB is send first

1 Like

Ah I thought it would use nibbles as a unit for some reason, bytes makes way more sense. It looks like the "Signed little endian" encoding works for integers. If I want to move to sending long ints later I assume I will have to switch to unsigned little endian, correct?

You can use unsigned and signed data types. You just need to remember how signed data types are created (twos complement). The app will show you the bytes but it is harder to create/decode them by hand. I am not even sure if you can set 32-bit data in the apps.

If you use two Arduinos this is all not a problem. You can just use whatever data type is best for your application. Also when you would write your own apps this would be fine.

What will be on the other side, I assume you won’t use a generic BLE app to change the data?

I want to start of easy and just control the speed and the direction of the stepper motor. That means that for the first version I just need a simple GUI with a knob and a slider. I think you can do this with the Blynk BLE app. Later I want to control the speed of a leadscrew in m/s and add slow deacceleration to reduce vibrations. So first a generic app and then maybe more.

The end goal is that I can control a mounting platform for a telescope without touching physical knobs on the machine so that I don't induce vibrations but that will have to wait.

Ok

On Android you can use MIT appInventor with BLE

Eventually I'm going to need to write my own program anyways for my PC + phone with code for smoothing etc. Do you know any BLE libraries? I can write Python, C#, Java, Javascript and C++. I listed the languages that I think are most fit for a job like this first.

pygatt or Bleak might be worth testing then

1 Like

Ok thanks I'll take a look. With nrf Connect I don't seem to have the problem. I think I'll just write my python programs and then convert if necessary on the microcontroller or before sending the data. I'll mark the post as solved and thanks again guys.

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