II.3.8. Adding Bluetooth Interface
Blackstomp core provide a very simple BLE (Bluetooth Low Energy) terminal interface for the easiest implementation. All you need to is just enabling the BLE terminal by calling enableBleTerminal() inside Arduino’s setup() and write the BLE terminal handler for the effectModule descendant class. Here is the example sketch code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
#include "blackstomp.h" class blePedal:public effectModule { private: float gain; public: void init(); void deInit(); void onControlChange(int controlIndex); void onButtonChange(int buttonIndex); void process(float* inLeft, float* inRight, float* outLeft, float* outRight, int sampleCount); void onBleTerminalRequest(const char* request, char* response); }; //////////////////////////////////////////////////////////////////////// void blePedal::init() { //select the appropriate device by uncommenting one of the following two lines: //setDeviceType(DT_ESP32_A1S_AC101); setDeviceType(DT_ESP32_A1S_ES8388); //define your effect name name = "BLE PEDAL"; //define the input mode (IM_LR or IM_LMIC) inputMode = IM_LR; //set up the controls control[0].name = "OUT LEVEL"; control[0].mode = CM_POT; control[0].levelCount = 128; //(0-127) control[0].slowSpeed = true; //set up the buttons button[0].mode = BM_TOGGLE; //do variable intitialization gain = 0; //do resource allocation (if needed).. //.. } //////////////////////////////////////////////////////////////////////// void blePedal::deInit() { //do resource deallocation (if needed).. //.. } //////////////////////////////////////////////////////////////////////// void blePedal::onControlChange(int controlIndex) { switch(controlIndex) { case 0: //control[0] { gain = (float)control[0].value/127.0; break; } } } void blePedal::onButtonChange(int buttonIndex) { switch(buttonIndex) { case 0: { if(button[0].value) { analogBypass(false); mainLed->turnOn(); } else { analogBypass(true); mainLed->turnOff(); } break; } } } //BLE terminal handler void blePedal::onBleTerminalRequest(const char* request, char* response) { strcpy(response,"Request has been received and processed"); } //////////////////////////////////////////////////////////////////////// void blePedal::process(float* inLeft, float* inRight, float* outLeft, float* outRight, int sampleCount) { for(int i=0;i<sampleCount;i++) { outLeft[i]=inLeft[i] * gain; outRight[i]=inRight[i] * gain; } } //declare an instance of your effect module blePedal myPedal; //setup the effect modules by calling blackstompSetup() inside arduino core's setup() void setup() { //SETTING UP THE EFFECT MODULE blackstompSetup(&myPedal); enableBleTerminal(); } //do repetitive task here (for debugging info only) void loop() { } |
You can see in the sketch code, the method enableBleTerminal() (at line #105) is called right after blackstompSetup() inside the Arduino’s setup function. The BLE terminal’s handler function onBleTerminalRequest() is defined in line #14, and implemented in line #83.
Customizing Some BLE Terminal Setup
The above sketch will run a pedal with BLE terminal enabled with some default setups:
- Device name: same name with the pedal name property but appended with unique device ID.
- Service UUID: “d11747ac-6172-4bb1-9b3a-20d58cc88f20”
- Characteristic UUID: “7a9fd763-04a5-4a17-b625-1fce28329f23”
- Pass Key: 123456;
It should be fine to leave the default setup untouched, but you can customize the service UUID, characteristic UUID, and the pass-key by manually set them up anywhere inside the init() function. Just copy and paste the following codes, paste into the init() function implementation, and edit their values with your own:
1 2 3 |
bleTerminal.servUuid = "d11747ac-6172-4bb1-9b3a-20d58cc88f20"; bleTerminal.charUuid = "7a9fd763-04a5-4a17-b625-1fce28329f23"; bleTerminal.passKey = 123456; |
Writing The BLE Terminal Handler
The BLE terminal handler function (line #83) is supplied with two parameters: (const char* request) and (char* response). You can read the request string pointed by request pointer, an do any action based on what we read. After that, we can send any text response to the connected BLE device by writing the response text to the memory pointed by response pointer (line #85).
Each time a connected Bluetooth device write the characteristic’s value, the system will call the handler function with the characteristic’s value as the request parameter. After the handler returns, the system will detect if the response memory content has changed, and if yes then the characteristic’s value will be update with the response text, and the connected Bluetooth device will be notified.
Developing BLE Client Device
In Bluetooth Low Energy (BLE) terms, Blackstomp sketch that enable the BLE terminal is a BLE server, that wait for incoming connection from the client. After getting connected, server will read the request and send the response. Here are what should be done when designing BLE client for Blackstomp BLE terminal:
- Scan the available BLE device with specific service and characteristic filter (either the default or custom characteristic and service uuids), so you’ll get the list of supported device.
- With list of supported device on scan, connect to the right BLE device name, and open the characteristic with read, write, and notification.
- To send a request, write the characteristic with the request string up to 517 bytes, always end the string with a carriage return (‘\n’ character), and make sure there no “carriage return” character before the end of your request string.
- Please keep in mind that shorter string would be faster to transfer, so keep your custom request-response protocol as short as possible for the best responsive link. Try to shorten the request string if it fails or too slow.
- After sending the request, wait a notification for that characteristic. After getting a notification, read the response by reading back the characteristic’s value.