Basic Library
Digital I/O
Analog I/O
Advanced I/O
Time
Math
Trigonometry
Random Numbers
Bits and Bytes
Interrupts
Serial Comm.
Standard Library
Camera
Servo Motor
Stepping Motor
Character LCD
SPI
I2C (Wire)
SD Card
SD (File Operations)
Periodic Operation
Clock (RTC)
Mbed Tips
BLE
This example uses the Bluetooth Low Energy (BLE) function of ESP32. Since there is no special library for BLE, BLE communication is performed using the AT parser. In ESP32's initial firmware, the following GATT profile is prepared.
GATT Profile
UUID | Access Property | Size (Bytes) | Characteristic Number |
---|---|---|---|
A002 | Read | 2 | - |
C300 | Read | 1 | 1 |
C301 | Read | 512 | 2 |
C302 | Write | 1 | 3 |
C303 | Write Without Response | 3 | 4 |
C304 | Write | 2 | 5 |
C305 | Notify | 5 | 6 |
C306 | Indicate | 5 | 7 |
Example
In this example, the GR-LYCHEE board is a server and a smartphone acts as a client. After executing the program, try using the iPhone application Light Blue.
#include <Arduino.h>
#include "ESP32.h"
BufferedSerial esp32(P7_1, P0_1, 1024);
ATParser_os esp_parser(esp32);
DigitalOut esp_en(P5_3);
DigitalOut esp_io0(P3_14);
DigitalOut led_green(LED1);
DigitalOut led_yellow(LED2);
DigitalOut led_orange(LED3);
DigitalOut led_red(LED4);
InterruptIn button0(USER_BUTTON0);
InterruptIn button1(USER_BUTTON1);
Semaphore event_sem(0);
const char ble_name[] = "GR-LYCHEE";
bool ble_advertizing;
bool ble_connected;
uint8_t ble_conn_index;
uint8_t ble_srv_index;
bool button0_flag = false;
bool button1_flag = false;
uint8_t ble_notification_on = false;
void esp32_event() {
event_sem.release();
}
void ble_client_read() {
uint8_t mac[6] = {0};
led_yellow = 1;
esp_parser.recv("%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\"", &ble_conn_index, &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
printf("%d, mac[%x:%x:%x:%x:%x:%x]\r\n", ble_conn_index, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
led_yellow = 0;
}
void ble_client_write() {
uint8_t char_index, desc_index;
led_orange = 1;
esp_parser.recv("%hhd,%hhd,%hhd,", &ble_conn_index, &ble_srv_index, &char_index);
printf("conn=%d srv=%d char=%d\r\n", ble_conn_index, ble_srv_index, char_index);
char c = esp_parser.getc();
if( c != ','){
desc_index = c;
esp_parser.getc(); // to read ',' after desc_index.
printf("desc=%d\r\n", desc_index);
}
uint16_t len;
esp_parser.recv("%hhd,", &len);
printf("length=%d\r\n", len);
for (int i = 0; i < len; i++) {
uint8_t value = esp_parser.getc();
printf("%x\r\n", value);
}
led_orange = 0;
}
void ble_client_disconn(){
led_green = 0;
ble_connected = false;
}
void ble_client_conn(){
uint8_t mac[6] = {0};
esp_parser.recv("%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\"", &ble_conn_index, &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
printf("connected client %d, mac[%x:%x:%x:%x:%x:%x]\r\n", ble_conn_index, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
led_green = 1;
ble_advertizing = false;
ble_connected = true;
}
void ub0_interrupt(){
if(button0_flag == false){
button0_flag = true;
event_sem.release();
}
}
void ub1_interrupt(){
if(button1_flag == false){
button1_flag = true;
event_sem.release();
}
}
void setup() {
printf("Bluetooth sample started\r\n");
led_green = 0;
led_yellow = 0;
led_orange = 0;
led_red = 0;
ble_advertizing = false;
ble_connected = false;
button0.fall(ub0_interrupt);
button1.fall(ub1_interrupt);
// Initializing esp32 access
esp32.baud(115200);
esp32.attach(Callback(esp32_event));
esp_io0 = 1;
esp_en = 0;
Thread::wait(10);
esp_en = 1;
esp_parser.setTimeout(1500);
if (esp_parser.recv("ready")) {
printf("ESP32 ready\r\n");
} else {
printf("ESP32 error\r\n");
led_red = 1;
while (1);
}
// Initializing esp32 as a server with GATT service
esp_parser.setTimeout(5000);
if (esp_parser.send("AT+BLEINIT=2") && esp_parser.recv("OK")
&& esp_parser.send("AT+BLENAME=\"%s\"", ble_name) && esp_parser.recv("OK")
&& esp_parser.send("AT+BLEGATTSSRVCRE") && esp_parser.recv("OK")
&& esp_parser.send("AT+BLEGATTSSRVSTART") && esp_parser.recv("OK")){
printf("GATT initialized\r\n");
} else {
printf("fail to initialize");
led_red = 1;
while (1);
}
esp_parser.oob("+READ:", ble_client_read);
esp_parser.oob("+WRITE:", ble_client_write);
esp_parser.oob("+BLEDISCONN:", ble_client_disconn);
esp_parser.oob("+BLECONN:", ble_client_conn);
while (1) {
if (esp_parser.send("AT+BLEADVSTART") && esp_parser.recv("OK")){
printf("Advertising started, please connect to any client\r\n");
} else {
printf("fail to start advertising");
led_red = 1;
while (1);
}
ble_advertizing = true;
uint8_t start, type;
uint16_t uuid;
esp_parser.send("AT+BLEGATTSSRV?");
if(esp_parser.recv("+BLEGATTSSRV:%hhd,%hhd,%hhx,%hhd\r\nOK", &ble_srv_index, &start, &uuid, &type)){
printf("srv_index=%d\r\n", ble_srv_index);
} else {
printf("fail to get service");
led_red = 1;
}
while (ble_connected || ble_advertizing) {
event_sem.wait();
esp_parser.setTimeout(5);
esp_parser.recv(" "); //dummy read for parser callback
if(button0_flag){
static uint8_t data = 1; // write data
esp_parser.setTimeout(5000);
if(esp_parser.send("AT+BLEGATTSSETATTR=%d,1,,1", ble_srv_index) && esp_parser.recv(">")){
if(esp_parser.putc(data) && esp_parser.recv("OK")){
printf("success to send\r\n");
} else {
printf("fail to send\r\n");
}
} else {
printf("fail to command AT");
}
esp_parser.flush();
button0_flag = false;
data++;
}
}
}
}
void loop() {
}