Hi all!
I've been working on a project involving both an Arduino Uno WiFi (peripheral and server) and Adafruit Feather (central and client). I'm using the Feather essentially as a Serial to BLE bridge which either inputs BLE data from a peripheral into MAX/MSP and Ableton and also allows me to send serial data out and back to specified connected peripherals. The code is provided below.
I've been able to successfully send data generated on the Arduino to the Feather using the Notify function for a while now with no issue. I'm trying to also send data out of Ableton/Max and to connected peripherals that will control a Neopixel strip by providing information about tempo, subdivision, amount of octaves, etc. for different VSTs.
For the time being I'm just trying to test the bare minimum and make sure I can send data from the Feather to the Arduino before messing around with serial data. I'm currently doing this by generating random numbers and writing to the characteristic on the peripheral. However, I'm running into the issue that the peripheral is not receiving any of the info. On the central side it's saying that the characteristic is written to, but the callback for the peripheral never fires and it says that the characteristic is not writable. I am obviously misunderstanding some functions, but I cannot wrap my head around this. The characteristic is allowed to be write only as I never need the Feather to read anything off that specific characteristic. Any help would be greatly appreciated!
Arduino Code - - -
const int VSTsize = 1;
BLEService buttonService("62757474-6F6E-7320-746F-6F206D696469"); //Service UUID
BLECharacteristic ArpeggiatorChr("56535449-6E66-6F72-6D61-74696F6E0000", BLEWrite, VSTsize, true); //UUID, Properties, array size, true = size does not change
void setup() {
Serial.begin(9600);
if (!BLE.begin()) {
Serial.println("starting BLE failed");
while (1)
;
}
BLE.setLocalName("Buttons");
BLE.setAdvertisedService(buttonService);
buttonService.addCharacteristic(ArpeggiatorChr);
BLE.addService(buttonService);
BLE.setEventHandler(BLEConnected, bleConnected); //connected callback
BLE.setEventHandler(BLEDisconnected, bleDisconnected); //disconnected callback
ArpeggiatorChr.setEventHandler(BLEWritten, ArpeggiatorChrWritten); //Characteristic written to callback
ArpeggiatorChr.writeValue(0); //inital value
BLE.advertise();
}
void loop() {
BLEDevice central = BLE.central();
if (central) {
digitalWrite(LED_BUILTIN, HIGH); //device is connected
while (central.connected()) {
if (ArpeggiatorChr.canWrite()) { //can the characteristic be written to?
Serial.println("Characteristic writable!"); //Yes!
} else {
Serial.println("Characteristic NOT writable!"); //No!
}
}
} else {
unsigned long currentMillis = millis();
static unsigned long previousMillis = 0;
int changeTime = 500;
static int ledState = LOW;
if (currentMillis - previousMillis >= changeTime) { //device disconnected, LED blinks
previousMillis = currentMillis;
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(LED_BUILTIN, ledState);
}
}
}
void bleConnected(BLEDevice central) {
Serial.print("Connected event, central: ");
Serial.println(central.address());
}
void bleDisconnected(BLEDevice central) {
Serial.print("Disconnected event, central: ");
Serial.println(central.address());
}
void ArpeggiatorChrWritten(BLEDevice central, BLECharacteristic characteristic) {
Serial.println("Characteristic written to!"); //lets user know device was written to
}
Adafruit Feather Code - - -
#include <bluefruit.h>
int MAX_CONNECTION_COUNT = 2; // total # of possible connections
int CURRENT_CONNECTION_COUNT = 0;
const uint8_t BUTTONS_UUID_SERVICE[] = { //Service UUID
0x69, 0x64, 0x69, 0x6D, 0x20, 0x6F, 0x6F, 0x74,
0x20, 0x73, 0x6E, 0x6F, 0x74, 0x74, 0x75, 0x62
};
const uint8_t ARP_UUID_CHARACTERISTIC[] = { //Characteristic UUID
0x00, 0x00, 0x6E, 0x6F, 0x69, 0x74, 0x61, 0x6D,
0x72, 0x6F, 0x66, 0x6E, 0x49, 0x54, 0x53, 0x56
};
BLEClientService Buttons = BLEClientService(BUTTONS_UUID_SERVICE); //Add UUID to service
BLEClientCharacteristic ArpeggiatorChr = BLEClientCharacteristic(ARP_UUID_CHARACTERISTIC); //Add UUID to characteristic
void setup() {
Serial.begin(115200);
Bluefruit.begin(0, MAX_CONNECTION_COUNT);
Bluefruit.setName("Bluefruit52 Central");
Buttons.begin(); //Begin service
ArpeggiatorChr.begin(); //Add characteristic to buttons service
Bluefruit.autoConnLed(true);
Bluefruit.Central.setDisconnectCallback(disconnect_callback);
Bluefruit.Central.setConnectCallback(connect_callback);
Bluefruit.Scanner.setRxCallback(scan_callback);
Bluefruit.Scanner.restartOnDisconnect(true);
Bluefruit.Scanner.setInterval(160, 80);
Bluefruit.Scanner.filterUuid(Buttons.uuid); //filter specifically for service UUID
Bluefruit.Scanner.useActiveScan(false);
Bluefruit.Scanner.start(0);
}
void loop() {
uint8_t randNumber[1];
randNumber[0] = random(100);
Serial.println(randNumber[0]); //generate random number, store in buffer, print out for own sake
if (Bluefruit.connected()) { //if connected to peripheral
if (ArpeggiatorChr.write(randNumber, 1)) { //write buffer to characteristic
Serial.println("Characteristic written to!"); //it's been written to!
} else {
Serial.println("Characteristic NOT written to!"); //it was not written to!
}
}
}
/**
* @param report
*/
void scan_callback(ble_gap_evt_adv_report_t* report) {
Bluefruit.Central.connect(report);
}
/**
*@param conn_handle
*/
void connect_callback(uint16_t conn_handle) {
Serial.println("Connecting"); //finds service and characteristic and initiates connection, otherwise drops connection if proper UUID's aren't found
Serial.print("Discovering Button Service ...");
if (!Buttons.discover(conn_handle)) {
Serial.println("Found None");
Bluefruit.disconnect(conn_handle);
return;
}
if (Buttons.discover(conn_handle)) {
Serial.println("Buttons Found!");
Serial.println("Discovering Characteristic ... ");
if (!ArpeggiatorChr.discover()) {
Serial.println("Arpeggiator Characteristic not found!");
Bluefruit.disconnect(conn_handle);
return;
} else {
Serial.println("Found Characteristic, ready to write to!");
}
}
}
/**
* @param conn_handle
* @param reason
*/
void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
(void)conn_handle;
(void)reason;
Serial.print("Disconnected, reason = 0x");
Serial.println(reason, HEX);
if (CURRENT_CONNECTION_COUNT = MAX_CONNECTION_COUNT) {
Bluefruit.Scanner.start(0);
}
CURRENT_CONNECTION_COUNT--;
}