Multiple Services with Multiple Characteristics on CurieBLE

Hello,

I'm starting to work with BLE on the Genuino 101, but am running into a little bit of an issue. Everything that I will be talking about here is based off of the CurieBLE LED example, where there is the LED service with one characteristic.

I am adding an additional LED, and I want to create an additional characteristic to the existing service for the new LED. However, I can't figure out how to add a characteristic to a service. Adding both services and characteristics uses something like blePeripheral.addAttribute(). I don't see a way to specify adding a characteristic to a service.

I then tried adding a new service for the LED but ran into a similar problem, the second service I defined would overwrite the first.

Is the Genuino/Arduino 101 restricted to a single service with a single characteristic? I'll include my modified code below trying to add both a new service and a new characteristic.

LED_Modified.ino (3.77 KB)

Hi, you can add multiple characteristics and multiple services.
Take a look at the ButtonLED example to see how it works :slight_smile:

Thank you! I think I was having a few issues with the application I'm using caching some properties about the device.

The LED Button example uses 2 characteristics, and one service. How to specify which characteristic belongs to which service, when adding multiple services? addAttribute belongs to the Peripheral and there is no parameter for the service to which to add the characteristic.
How to solve the problem?

I did a test, and it appears that it depends on the order of adding attributes:

blePeripheral.addAttribute(ledService);
blePeripheral.addAttribute(switchCharacteristic);
blePeripheral.addAttribute(switchCharacteristic1);
blePeripheral.addAttribute(ledService1);
blePeripheral.addAttribute(switchCharacteristic2);

Is this correct, or there is alternative/better way?

Hi,

I am trying to add my own service to my Arduino 101 but it's actually not working... And I don't know why
My phone detect old service used with last program.. (Strand test)
Here is my code :

#include <Adafruit_NeoPixel.h>
#include <CurieBLE.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 6

#define BRIGHTNESS 100

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(12, PIN, NEO_GRB + NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.

BLEPeripheral blePeripheral; // create peripheral instance
BLEService uartService("19B10010-E8F2-537E-4F6C-D104768A1214"); // create service
BLECharacteristic TxChar("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify, 20);
BLECharacteristic RxChar("19B10012-E8F2-537E-4F6C-D104768A1214", BLEWrite, 20);

int Fonction[256] = {1,2,3,4,5};

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT); // use the LED on pin 13 as an output

  // set the local name peripheral advertises
  blePeripheral.setLocalName("LEDCB");
  blePeripheral.setDeviceName("NeoPixel");
  // set the UUID for the service this peripheral advertises
  blePeripheral.setAdvertisedServiceUuid(uartService.uuid());

  // add service and characteristic
  blePeripheral.addAttribute(uartService);
  blePeripheral.addAttribute(TxChar);
  blePeripheral.addAttribute(RxChar);

  // assign event handlers for connected, disconnected to peripheral
  blePeripheral.setEventHandler(BLEConnected, blePeripheralConnectHandler);
  blePeripheral.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);

  // assign event handlers for characteristic
  RxChar.setEventHandler(BLEWritten, switchCharacteristicWritten);

  // advertise the service
  blePeripheral.begin();
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
  #if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  // End of trinket special code
  strip.setBrightness(BRIGHTNESS);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  // Some example procedures showing how to display to the pixels:
  //colorWipe(strip.Color(255, 0, 0), 50); // Red
  //colorWipe(strip.Color(0, 255, 0), 50); // Green
  //colorWipe(strip.Color(0, 0, 255), 50); // Blue
//colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW
  // Send a theater pixel chase in...
  //theaterChase(strip.Color(127, 127, 127), 50); // White
  //theaterChase(strip.Color(127, 0, 0), 50); // Red
  //theaterChase(strip.Color(0, 0, 127), 50); // Blue

  //rainbow(10);
  //rainbowCycle(20);
  //theaterChaseRainbow(25);
  for(int i=0; i<256; i++) {
    blePeripheral.poll();
    execute(Fonction[i]);
  }
}

void execute(int toExecute) {
  switch(toExecute) {
    case 1:
      colorWipe(strip.Color(255, 0, 0), 50); // Red
      break;
    case 2:
      colorWipe(strip.Color(0, 255, 0), 50); // Green
      break;
    case 3:
      colorWipe(strip.Color(0, 0, 255), 50); // Blue
      break;
    case 4:
      theaterChase(strip.Color(127, 127, 127), 50); // White
      break;
    case 5:
      rainbowCycle(20);
      break;
    default:
      break;
  }
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

void blePeripheralConnectHandler(BLECentral& central) {
  // central connected event handler
  digitalWrite(13, HIGH);
}

void blePeripheralDisconnectHandler(BLECentral& central) {
  // central disconnected event handler
  digitalWrite(13, LOW);
}

String toString(const unsigned char* entry, unsigned char len) {
  char Temp[len];
  for (int i=0;i<len;i++) {
    Temp[i] = char(entry[i]);
  }
  String Out = Temp;
  Out.remove(len);
  return Out;
}

const char* tocstChar(String entry) {
  unsigned int len = entry.length();
  char Temp[len];
  for (int i=0;i<len;i++) {
    Temp[i] = entry.charAt(i);
  }
  const char* Out = Temp;
  return Out;
}

void switchCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic) {
  // central wrote new value to characteristic, update LED
  Serial.println("Value updated");
  String In = toString(RxChar.value(), RxChar.valueLength());
  Serial.println(In);
  if(int(RxChar.value()) == 105) {
    Serial.println("Ok");
    for(int i=0; i<256; i++) {
      if(Fonction[i] != 0) {
        Serial.println(Fonction[i]);
        TxChar.setValue((const unsigned char *)"test", 10);
        delay(1000);
      }
    }
  }
}

I found the problem !
I had to restart my Bluetooth on my Phone to detect new service on the Arduino...

Fucking cache ^^

Minicarpet:
I found the problem !
I had to restart my Bluetooth on my Phone to detect new service on the Arduino...

Fucking cache ^^

Dude, Thanks for posting this xD

I have spent alllllllllllllllllllllllll day trying to figure out why my phone wont display both of my characteristics in my single service. But i decided to try restarting the bluetooth because of your post, and Boom I am finally able to continue my project xD

1 Like