ARduinoBLE write INT?

I’m using ArduinoBLE and am able to write a value from my phone to the arduino. I’m expecting an int but I get a byte(s). When I send 1 from my phone I get 49 in the serial monitor. If I send a two digit value I get like 5 digits.

I’m using BLEIntCharacteristic to create the var and expected an int value.

This is a newbie question - but - how do I get an int from the value sent from the phone? For one digit I can subtract 40ish. How do I deal with multiple digits?

Thank you for any help.

49 is the ASCII value of the character representing a 1 so no surprise there

You can deal with multiple digits in one of several ways but the easiest is to use the parseInt() function

See Serial.parseInt() - Arduino Reference

Thanks UKHeliBob.

I'm using readValue() to get the value - so value is passed as a byte. Can I use Serial.parseInt()? I'm not reading Serial input - I already have the value. How do I convert value to int?

byte value = 0;
lux_thresholdCharacteristic.readValue(value);
Serial.print(F("XXX value: "));
Serial.println(value);
Serial.print(F("lux_thresholdCharacteristic.value(): "));
Serial.println(lux_thresholdCharacteristic.value());

Please post your complete sketch

Here it is (warts and all):

/* TSL2591 Digital Light Sensor */
/* Dynamic Range: 600M:1 */
/* Maximum Lux: 88K */

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2591.h>
#include <ArduinoBLE.h>


Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); // pass in a number for the sensor identifier (for your use later)

const int UPDATE_FREQUENCY = 2000; // Update frequency in ms

int previousLux = 0;
long previousMillis = 0;  // last time readings were checked, in ms

BLEService environmentService("181A");  // Standard Environmental Sensing service

BLEIntCharacteristic lux_thresholdCharacteristic("2A6E", BLERead | BLEWrite);// | BLENotify

int led9 = 9;           // the PWM pin the LED is attached to
float sensor_lux=0;
const int RELAY_PIN = 3;  // the Arduino pin, which connects to the IN pin of relay
int lux_threshold=50;


void displaySensorDetails(void)
{
  sensor_t sensor;
  tsl.getSensor(&sensor);
  Serial.println(F("------------------------------------"));
  Serial.print  (F("Sensor:       ")); Serial.println(sensor.name);
  Serial.print  (F("Driver Ver:   ")); Serial.println(sensor.version);
  Serial.print  (F("Unique ID:    ")); Serial.println(sensor.sensor_id);
  Serial.print  (F("Max Value:    ")); Serial.print(sensor.max_value); Serial.println(F(" sensor_lux"));
  Serial.print  (F("Min Value:    ")); Serial.print(sensor.min_value); Serial.println(F(" sensor_lux"));
  Serial.print  (F("Resolution:   ")); Serial.print(sensor.resolution, 4); Serial.println(F(" sensor_lux"));  
  Serial.println(F("------------------------------------"));
  Serial.println(F(""));
  delay(500);
}






void configureSensor(void)
{
  // You can change the gain on the fly, to adapt to brighter/dimmer light situations
  //tsl.setGain(TSL2591_GAIN_LOW);    // 1x gain (bright light)
  tsl.setGain(TSL2591_GAIN_MED);      // 25x gain
  //tsl.setGain(TSL2591_GAIN_HIGH);   // 428x gain
  
  // Changing the integration time gives you a longer time over which to sense light
  // longer timelines are slower, but are good in very low light situtations!
  //tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS);  // shortest integration time (bright light)
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
  tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);  // longest integration time (dim light)

  /* Display the gain and integration time for reference sake */  
  Serial.println(F("------------------------------------"));
  Serial.print  (F("Gain:         "));
  tsl2591Gain_t gain = tsl.getGain();
  switch(gain)
  {
    case TSL2591_GAIN_LOW:
      Serial.println(F("1x (Low)"));
      break;
    case TSL2591_GAIN_MED:
      Serial.println(F("25x (Medium)"));
      break;
    case TSL2591_GAIN_HIGH:
      Serial.println(F("428x (High)"));
      break;
    case TSL2591_GAIN_MAX:
      Serial.println(F("9876x (Max)"));
      break;
  }
  Serial.print  (F("Timing:       "));
  Serial.print((tsl.getTiming() + 1) * 100, DEC); 
  Serial.println(F(" ms"));
  Serial.println(F("------------------------------------"));
  Serial.println(F(""));
}






void setup() {
  Serial.begin(9600);    // Initialize serial communication
  while (!Serial);


  pinMode(LED_BUILTIN, OUTPUT); // Initialize the built-in LED pin
  pinMode(led9, OUTPUT);
  pinMode(RELAY_PIN, OUTPUT);

  
  Serial.println(F("Starting Adafruit TSL2591 Test!"));
  
  if (tsl.begin()) {
    Serial.println(F("Found a TSL2591 sensor"));
  } else {
    Serial.println(F("No sensor found ... check your wiring?"));
    while (1);
  }
    
  /* Display some basic information on this sensor */
  displaySensorDetails();
  
  /* Configure the sensor */
  configureSensor();

  //

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

  BLE.setLocalName("Lux Module");  // Set name for connection
  BLE.setAdvertisedService(environmentService); // Advertise environment service
  environmentService.addCharacteristic(lux_thresholdCharacteristic); // Add lux characteristic
  BLE.addService(environmentService); // Add environment service
  lux_thresholdCharacteristic.setValue(lux_threshold); // Set initial lux value

  BLE.advertise();  // Start advertising
  Serial.print("Peripheral device MAC: ");
  Serial.println(BLE.address());
  Serial.println("Waiting for connections...");
}






void advancedRead(void){
  // More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16 bits full spectrum
  // That way you can do whatever math and comparisons you want!
  uint32_t lum = tsl.getFullLuminosity();
  uint16_t ir, full;
  ir = lum >> 16;
  full = lum & 0xFFFF;
  sensor_lux = tsl.calculateLux(full, ir);
  Serial.print(F("[ ")); Serial.print(millis()); Serial.print(F(" ms ] "));
  Serial.print(F("IR: ")); Serial.print(ir);  Serial.print(F("  "));
  Serial.print(F("Full: ")); Serial.print(full); Serial.print(F("  "));
  Serial.print(F("Visible: ")); Serial.print(full - ir); Serial.print(F("  "));
  Serial.print(F("Lux: ")); Serial.println(sensor_lux, 6);
  Serial.print(F("Lux: ")); Serial.println(sensor_lux);
  Serial.print(F("lux_thresholdCharacteristic.value(): ")); Serial.println(lux_thresholdCharacteristic.value());
  Serial.println(F("---------------------------------"));

  

  if(sensor_lux > lux_thresholdCharacteristic.value()){ //daylight - lights off
    //digitalWrite(LED_BUILTIN, LOW);    // turn the board LED off by making the voltage LOW
    analogWrite(led9, 0);
    digitalWrite(RELAY_PIN, LOW);
  }else{ //dark - TURN ON LIGHTS
    //digitalWrite(LED_BUILTIN, HIGH);   // turn the board LED on (HIGH is the voltage level)
    analogWrite(led9, 255);
    digitalWrite(RELAY_PIN, HIGH);
  }

}







void loop() {
  BLEDevice central = BLE.central();  // Wait for a BLE central to connect

  // If central is connected to peripheral
  if (central) {
    Serial.print("Connected to central MAC: ");
    Serial.println(central.address());    // Central's BT address:
    // Turn on the LED to indicate the connection:
    digitalWrite(LED_BUILTIN, HIGH);

    while (central.connected()) {
      long currentMillis = millis();
      // After UPDATE_FREQUENCY ms have passed, check lux & humidity
      if (currentMillis - previousMillis >= UPDATE_FREQUENCY) {
        previousMillis = currentMillis;
        advancedRead();

        if (lux_thresholdCharacteristic.valueUpdated()) {
          byte value = 0;
          lux_thresholdCharacteristic.readValue(value);
          Serial.print(F("XXX value: ")); Serial.println(value);
          Serial.print(F("lux_thresholdCharacteristic.value(): ")); Serial.println(lux_thresholdCharacteristic.value());
          Serial.println(F("------------------------------------------------------------------"));
          
          //lux_threshold = lux_thresholdCharacteristic.value();
          //lux_thresholdCharacteristic.setValue(lux_threshold);
        }

      }
    }

    // When the central disconnects, turn off the LED
    digitalWrite(LED_BUILTIN, LOW);
    Serial.print("Disconnected from central MAC: ");
    Serial.println(central.address());
  }
}

The readValue code in about halfway through void loop()

Although I know next to nothing about BLE, according to this page ArduinoBLE - Arduino Reference the value is read by reference, ie the value of the variable will be changed by the function call rather than a value being returned, so if you use a variable of the appropriate type it should be automatically populated

What happens if you declare value in your sketch as an int ?

Yes, I tried setting value as int and it wouldn’t compile. I forget what the error was - but it wanted a byte to compile.

Please try it again and post the full error message copied using the "Copy error messages! button in the IDE

          int value = 0;
          lux_thresholdCharacteristic.readValue(value);

Arduino: 1.8.15 (Windows 10), Board: "Arduino NANO 33 IoT"

C:\Users\Pete\Documents\Arduino\tsl2591BLE_pete\tsl2591BLE_pete.ino: In function 'void loop()':

tsl2591BLE_pete:201:54: error: no matching function for call to 'readValue(int&)'

       lux_thresholdCharacteristic.readValue(value);

                                                  ^

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

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

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

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

             from C:\Users\Pete\Documents\Arduino\tsl2591BLE_pete\tsl2591BLE_pete.ino:8:

C:\Users\Pete\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:64:7: note: candidate: int BLECharacteristic::readValue(uint8_t&)

int readValue(uint8_t& value);

   ^~~~~~~~~

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

tsl2591BLE_pete:201:54: error: cannot bind non-const lvalue reference of type 'uint8_t& {aka unsigned char&}' to an rvalue of type 'uint8_t {aka unsigned char}'

       lux_thresholdCharacteristic.readValue(value);

                                                  ^

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

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

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

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

             from C:\Users\Pete\Documents\Arduino\tsl2591BLE_pete\tsl2591BLE_pete.ino:8:

C:\Users\Pete\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:65:7: note: candidate: int BLECharacteristic::readValue(int8_t&)

int readValue(int8_t& value);

   ^~~~~~~~~

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

tsl2591BLE_pete:201:54: error: cannot bind non-const lvalue reference of type 'int8_t& {aka signed char&}' to an rvalue of type 'int8_t {aka signed char}'

       lux_thresholdCharacteristic.readValue(value);

                                                  ^

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

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

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

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

             from C:\Users\Pete\Documents\Arduino\tsl2591BLE_pete\tsl2591BLE_pete.ino:8:

C:\Users\Pete\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:66:7: note: candidate: int BLECharacteristic::readValue(uint16_t&)

int readValue(uint16_t& value);

   ^~~~~~~~~

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

tsl2591BLE_pete:201:54: error: cannot bind non-const lvalue reference of type 'uint16_t& {aka short unsigned int&}' to an rvalue of type 'uint16_t {aka short unsigned int}'

       lux_thresholdCharacteristic.readValue(value);

                                                  ^

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

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

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

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

             from C:\Users\Pete\Documents\Arduino\tsl2591BLE_pete\tsl2591BLE_pete.ino:8:

C:\Users\Pete\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:67:7: note: candidate: int BLECharacteristic::readValue(int16_t&)

int readValue(int16_t& value);

   ^~~~~~~~~

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

tsl2591BLE_pete:201:54: error: cannot bind non-const lvalue reference of type 'int16_t& {aka short int&}' to an rvalue of type 'int16_t {aka short int}'

       lux_thresholdCharacteristic.readValue(value);

                                                  ^

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

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

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

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

             from C:\Users\Pete\Documents\Arduino\tsl2591BLE_pete\tsl2591BLE_pete.ino:8:

C:\Users\Pete\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:68:7: note: candidate: int BLECharacteristic::readValue(uint32_t&)

int readValue(uint32_t& value);

   ^~~~~~~~~

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

tsl2591BLE_pete:201:54: error: cannot bind non-const lvalue reference of type 'uint32_t& {aka long unsigned int&}' to an rvalue of type 'uint32_t {aka long unsigned int}'

       lux_thresholdCharacteristic.readValue(value);

                                                  ^

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

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

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

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

             from C:\Users\Pete\Documents\Arduino\tsl2591BLE_pete\tsl2591BLE_pete.ino:8:

C:\Users\Pete\Documents\Arduino\libraries\ArduinoBLE\src/BLECharacteristic.h:69:7: note: candidate: int BLECharacteristic::readValue(int32_t&)

int readValue(int32_t& value);

   ^~~~~~~~~

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

tsl2591BLE_pete:201:54: error: cannot bind non-const lvalue reference of type 'int32_t& {aka long int&}' to an rvalue of type 'int32_t {aka long int}'

       lux_thresholdCharacteristic.readValue(value);

                                                  ^

exit status 1

no matching function for call to 'readValue(int&)'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Thanks - that alone was helpful. I was just seeing the end of the error; specifically, no matching function for call to 'readValue(int&)' I just tried defining value as uint8_t and it worked.

But I still need to convert the output somehow. i.e.: 1 becomes 49. 11 becomes 12849. How do I convert 12849 back to 11?

Try declaring it as uint16_t and see what happens. It is one of the possible candidates suggested in the error message

uint8_t , uint16_t , uint32_t - all three provide the same result. i.e.: enter 11 on phone and I get 12593 in the Serial Monitor. I'm searching how to convert 12593 to 11.

The V() function returns the number of bytes read, not the value. You are printing both

          lux_thresholdCharacteristic.readValue(value);
          Serial.print(F("XXX value: "));
          Serial.println(value);
          Serial.print(F("lux_thresholdCharacteristic.value(): "));
          Serial.println(lux_thresholdCharacteristic.value());

How many bytes are reported as being read ?

Ugh. Now I'm confused. The debug info I'm printing to Serial Monitor is coming from the advancedRead() function. I'm just realizing that lux_thresholdCharacteristic.valueUpdated() is not triggering. Reading up on that now.

Meanwhile, I did find some mention of using a union (something I'm not familiar with) to map a byte array to an int.

If the value being sent is a two byte integer, then I think you should be reading it with .readValue(buffer,length)

https://www.arduino.cc/en/Reference/ArduinoBLEBLECharacteristicreadValue

Reassemble the bytes in the buffer back to an integer.

Thanks cattledog.

How do I use readValue with a characteristic? The below code causes the error:

no matching function for call to 'readValue(int, int)'.

lux_thresholdCharacteristic.readValue(lux_thresholdCharacteristic.value(), lux_thresholdCharacteristic.valueLength());

How do I use lux_thresholdCharacteristic.value() as buffer?

How do I use lux_thresholdCharacteristic.value() as buffer?

I think you want something like this. I don't know about the byte order of an integer sent by the phone so see if the combination to an integer makes sense.

if (lux_thresholdCharacteristic.valueUpdated()) {
          byte newLuxThresholdValue[2] = {0,0};
          lux_thresholdCharacteristic.readValue(newLuxThresholdValue,2);
          Serial.print(F("newLuxThresholdValue: "));
          Serial.print (newValue[0],HEX);
          Serial.print('\t');
          Serial.println(newValue[1],HEX);
          int newLuxThrVal = newLuxThresholdValue[1] <<8 + newLuxThresholdValue[0];
          //int  newLuxThrVal = newLuxThresholdValue[0] <<8 + newLuxThresholdValue[1];
          Serial.print(F("lux_thresholdCharacteristic.value(): ")); 
          Serial.println(newLuxThrVal);
          Serial.println(F("------------------------------------------------------------------"));

Are you clear that the phone is sending the bytes of an integer and not the text representation of the integer?

I'm just realizing that lux_thresholdCharacteristic.valueUpdated() is not triggering. Reading up on that now.

You have to resolve this. I'm not clear how you get the phone app to update the characteristic value.