Skip to content

Commit dd69de8

Browse files
committed
Add support for ArduinoBLE devices to StandardFirmataBLE
1 parent 4bd508a commit dd69de8

File tree

3 files changed

+291
-7
lines changed

3 files changed

+291
-7
lines changed

examples/StandardFirmataBLE/bleConfig.h

+32-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
/*==================================================================================================
22
* BLE CONFIGURATION
33
*
4-
* If you are using an Arduino 101, you do not need to make any changes to this file (unless you
5-
* need a unique ble local name (see below). If you are using another supported BLE board or shield,
6-
* follow the instructions for the specific board or shield below.
7-
*
8-
* Make sure you have the Intel Curie Boards package v2.0.2 or higher installed via the Arduino
9-
* Boards Manager.
4+
* If you are using a device supported by the ArduinoBLE library or an Arduino 101, you do not need
5+
* to make any changes to this file (unless you need a unique ble local name (see below)). If you
6+
* are using another supported BLE board or shield, follow the instructions for the specific board
7+
* or shield below.
108
*
119
* Supported boards and shields:
12-
* - Arduino 101 (recommended)
10+
* - Devices supported by the ArduinoBLE library, including the Arduino MKR WiFi 1010,
11+
* Arduino UNO WiFi Rev.2, Arduino Nano 33 IoT, and Arduino Nano 33 BLE
12+
* - Arduino 101
1313
* - RedBearLab BLE Shield (v2) ** to be verified **
1414
* - RedBearLab BLE Nano ** works with modifications **
1515
* - Adafruit Feather M0 Bluefruit LE
@@ -20,6 +20,25 @@
2020
// within the same physical space
2121
#define FIRMATA_BLE_LOCAL_NAME "FIRMATA"
2222

23+
/*
24+
* ArduinoBLE devices
25+
*
26+
* Be sure to install the ArduinoBLE library via the Arduino Library Manager.
27+
*
28+
*/
29+
#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_ARDUINO_NANO33BLE)
30+
#define ARDUINO_BLE
31+
32+
// Value is specified in units of 0.625 ms
33+
#define FIRMATA_BLE_ADVERTISING_INTERVAL 32 // 20ms (20 / 0.625)
34+
35+
// These values are specified in units of 1.25 ms and must be between
36+
// 0x0006 (7.5ms) and 0x0c80 (4s).
37+
#define FIRMATA_BLE_MIN_INTERVAL 0x000c // 15ms (15 / 1.25)
38+
#define FIRMATA_BLE_MAX_INTERVAL 0x0018 // 30ms (30 / 1.25)
39+
#endif
40+
41+
2342
/*
2443
* Arduino 101
2544
*
@@ -107,6 +126,12 @@
107126
* END BLE CONFIGURATION - you should not need to change anything below this line
108127
*================================================================================================*/
109128

129+
#ifdef ARDUINO_BLE
130+
#include "utility/ArduinoBLE_UART_Stream.h"
131+
ArduinoBLE_UART_Stream stream;
132+
#endif
133+
134+
110135
#ifdef _VARIANT_ARDUINO_101_X_
111136
#include "utility/BLEStream.h"
112137
BLEStream stream;

utility/ArduinoBLE_UART_Stream.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/*
2+
* Implementation is in ArduinoBLE_UART_Stream.h to avoid linker issues.
3+
*/

utility/ArduinoBLE_UART_Stream.h

+256
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
/*
2+
ArduinoBLE_UART_Stream.h
3+
4+
Based on BLEStream.h and the HardwareBLESerial library:
5+
https://github.com/Uberi/Arduino-HardwareBLESerial
6+
*/
7+
8+
#ifndef _ARDUINO_BLE_UART_STREAM_H_
9+
#define _ARDUINO_BLE_UART_STREAM_H_
10+
11+
#include <ArduinoBLE.h>
12+
13+
#define BLE_ATTRIBUTE_MAX_VALUE_LENGTH 20
14+
15+
16+
class ArduinoBLE_UART_Stream : public Stream
17+
{
18+
public:
19+
ArduinoBLE_UART_Stream();
20+
21+
void setLocalName(const char *localName);
22+
void setAdvertisingInterval(unsigned short advertisingInterval);
23+
void setConnectionInterval(unsigned short minConnInterval, unsigned short maxConnInterval);
24+
void setFlushInterval(int flushInterval);
25+
26+
void begin();
27+
bool poll();
28+
void end();
29+
30+
// Print overrides
31+
size_t write(uint8_t byte);
32+
using Print::write; // Expose other write variants
33+
34+
// Stream overrides
35+
int available();
36+
int read();
37+
int peek();
38+
void flush();
39+
40+
private:
41+
void dataReceived(const unsigned char *data, size_t size);
42+
43+
static void connectedHandler(BLEDevice central);
44+
static void disconnectedHandler(BLEDevice central);
45+
46+
static void rxWrittenHandler(BLEDevice central, BLECharacteristic characteristic);
47+
48+
static void txSubscribedHandler(BLEDevice central, BLECharacteristic characteristic);
49+
static void txUnsubscribedHandler(BLEDevice central, BLECharacteristic characteristic);
50+
51+
BLEService uartService;
52+
BLECharacteristic rxCharacteristic;
53+
BLECharacteristic txCharacteristic;
54+
55+
String localName;
56+
unsigned short advertisingInterval;
57+
unsigned short minConnInterval;
58+
unsigned short maxConnInterval;
59+
int flushInterval;
60+
61+
bool connected;
62+
63+
unsigned char rxBuffer[256];
64+
size_t rxHead;
65+
size_t rxTail;
66+
67+
bool txSubscribed;
68+
unsigned char txBuffer[BLE_ATTRIBUTE_MAX_VALUE_LENGTH];
69+
size_t txCount;
70+
unsigned long lastFlushTime;
71+
72+
static ArduinoBLE_UART_Stream *instance;
73+
};
74+
75+
76+
ArduinoBLE_UART_Stream::ArduinoBLE_UART_Stream() :
77+
uartService("6E400001-B5A3-F393-E0A9-E50E24DCCA9E"),
78+
rxCharacteristic("6E400002-B5A3-F393-E0A9-E50E24DCCA9E", BLEWriteWithoutResponse | BLEWrite, BLE_ATTRIBUTE_MAX_VALUE_LENGTH),
79+
txCharacteristic("6E400003-B5A3-F393-E0A9-E50E24DCCA9E", BLENotify, BLE_ATTRIBUTE_MAX_VALUE_LENGTH),
80+
advertisingInterval(0),
81+
minConnInterval(0),
82+
maxConnInterval(0),
83+
flushInterval(100), // Default flush interval is 100ms
84+
connected(false),
85+
rxHead(0),
86+
rxTail(0),
87+
txSubscribed(false),
88+
txCount(0),
89+
lastFlushTime(0)
90+
{
91+
instance = this;
92+
}
93+
94+
void ArduinoBLE_UART_Stream::setLocalName(const char *localName)
95+
{
96+
this->localName = localName;
97+
}
98+
99+
void ArduinoBLE_UART_Stream::setAdvertisingInterval(unsigned short advertisingInterval)
100+
{
101+
this->advertisingInterval = advertisingInterval;
102+
}
103+
104+
void ArduinoBLE_UART_Stream::setConnectionInterval(unsigned short minConnInterval, unsigned short maxConnInterval)
105+
{
106+
this->minConnInterval = minConnInterval;
107+
this->maxConnInterval = maxConnInterval;
108+
}
109+
110+
void ArduinoBLE_UART_Stream::setFlushInterval(int flushInterval)
111+
{
112+
// The minimum allowed connection interval is 7.5ms, so don't try to flush
113+
// more frequently than that
114+
this->flushInterval = max(flushInterval, 8);
115+
}
116+
117+
void ArduinoBLE_UART_Stream::begin()
118+
{
119+
BLE.begin();
120+
121+
if (localName.length() > 0) {
122+
BLE.setLocalName(localName.c_str());
123+
}
124+
if (advertisingInterval > 0) {
125+
BLE.setAdvertisingInterval(advertisingInterval);
126+
}
127+
if (minConnInterval > 0 && maxConnInterval > 0) {
128+
BLE.setConnectionInterval(minConnInterval, maxConnInterval);
129+
}
130+
131+
BLE.setEventHandler(BLEConnected, connectedHandler);
132+
BLE.setEventHandler(BLEDisconnected, disconnectedHandler);
133+
134+
rxCharacteristic.setEventHandler(BLEWritten, rxWrittenHandler);
135+
uartService.addCharacteristic(rxCharacteristic);
136+
137+
txCharacteristic.setEventHandler(BLESubscribed, txSubscribedHandler);
138+
txCharacteristic.setEventHandler(BLEUnsubscribed, txUnsubscribedHandler);
139+
uartService.addCharacteristic(txCharacteristic);
140+
141+
BLE.addService(uartService);
142+
BLE.setAdvertisedService(uartService);
143+
BLE.advertise();
144+
}
145+
146+
bool ArduinoBLE_UART_Stream::poll()
147+
{
148+
if (millis() - lastFlushTime > flushInterval) {
149+
flush(); // Always calls BLE.poll()
150+
} else {
151+
BLE.poll();
152+
}
153+
return connected;
154+
}
155+
156+
void ArduinoBLE_UART_Stream::end()
157+
{
158+
flush();
159+
txCharacteristic.setEventHandler(BLEUnsubscribed, NULL);
160+
txCharacteristic.setEventHandler(BLESubscribed, NULL);
161+
txSubscribed = false;
162+
163+
rxCharacteristic.setEventHandler(BLEWritten, NULL);
164+
rxHead = 0;
165+
rxTail = 0;
166+
167+
BLE.setEventHandler(BLEDisconnected, NULL);
168+
BLE.setEventHandler(BLEConnected, NULL);
169+
connected = false;
170+
171+
BLE.end();
172+
}
173+
174+
size_t ArduinoBLE_UART_Stream::write(uint8_t byte)
175+
{
176+
if (!txSubscribed) {
177+
return 0;
178+
}
179+
txBuffer[txCount] = byte;
180+
txCount++;
181+
if (txCount == sizeof(txBuffer)) {
182+
flush();
183+
}
184+
return 1;
185+
}
186+
187+
int ArduinoBLE_UART_Stream::available()
188+
{
189+
return (rxHead - rxTail + sizeof(rxBuffer)) % sizeof(rxBuffer);
190+
}
191+
192+
int ArduinoBLE_UART_Stream::read()
193+
{
194+
if (rxTail == rxHead) {
195+
return -1;
196+
}
197+
uint8_t byte = rxBuffer[rxTail];
198+
rxTail = (rxTail + 1) % sizeof(rxBuffer);
199+
return byte;
200+
}
201+
202+
int ArduinoBLE_UART_Stream::peek()
203+
{
204+
if (rxTail == rxHead) {
205+
return -1;
206+
}
207+
return rxBuffer[rxTail];
208+
}
209+
210+
void ArduinoBLE_UART_Stream::flush()
211+
{
212+
if (txCount > 0) {
213+
txCharacteristic.setValue(txBuffer, txCount);
214+
txCount = 0;
215+
}
216+
lastFlushTime = millis();
217+
BLE.poll();
218+
}
219+
220+
void ArduinoBLE_UART_Stream::dataReceived(const unsigned char *data, size_t size)
221+
{
222+
for (size_t i = 0; i < size; i++) {
223+
rxBuffer[rxHead] = data[i];
224+
rxHead = (rxHead + 1) % sizeof(rxBuffer);
225+
}
226+
}
227+
228+
void ArduinoBLE_UART_Stream::connectedHandler(BLEDevice central)
229+
{
230+
instance->connected = true;
231+
}
232+
233+
void ArduinoBLE_UART_Stream::disconnectedHandler(BLEDevice central)
234+
{
235+
instance->connected = false;
236+
}
237+
238+
void ArduinoBLE_UART_Stream::rxWrittenHandler(BLEDevice central, BLECharacteristic characteristic)
239+
{
240+
instance->dataReceived(characteristic.value(), characteristic.valueLength());
241+
}
242+
243+
void ArduinoBLE_UART_Stream::txSubscribedHandler(BLEDevice central, BLECharacteristic characteristic)
244+
{
245+
instance->txSubscribed = true;
246+
}
247+
248+
void ArduinoBLE_UART_Stream::txUnsubscribedHandler(BLEDevice central, BLECharacteristic characteristic)
249+
{
250+
instance->txSubscribed = false;
251+
}
252+
253+
ArduinoBLE_UART_Stream * ArduinoBLE_UART_Stream::instance = NULL;
254+
255+
256+
#endif // _ARDUINO_BLE_UART_STREAM_H_

0 commit comments

Comments
 (0)