M5stackのbalaCをbluetoothで操作しようと思い、BLEのコードをBalaCのコードに追加したのですが、
Bluetoothでつながりますが、その後に、倒立振り子動作にはいらなくなります。
bluetooth接続が切れると、倒立振り子動作が復活します。どうも、notifycallbackが実行されると、loopが止まってしまうように思うのですが、どうでしょうか?どなたかご教授よろしくお願いいたします。
Arduino
1#include <BLEDevice.h> 2#include <BLEUtils.h> 3#include <BLEScan.h> 4#include <BLEAdvertisedDevice.h> 5 6 7 8#include <M5StickC.h> 9 10#define LED 10 11#define N_CAL1 100 12#define N_CAL2 100 13#define LCDV_MID 60 14 15boolean serialMonitor=true; 16boolean standing=false; 17int16_t counter=0; 18uint32_t time0=0, time1=0; 19int16_t counterOverPwr=0, maxOvp=20; 20float power, powerR, powerL, yawPower; 21float varAng, varOmg, varSpd, varDst, varIang; 22float gyroXoffset, gyroYoffset, gyroZoffset, accXoffset; 23float gyroXdata, gyroYdata, gyroZdata, accXdata, accZdata; 24float aveAccX=0.0, aveAccZ=0.0, aveAbsOmg=0.0; 25float cutoff=0.1; //~=2 * pi * f (Hz) 26const float clk = 0.01; // in sec, 27const uint32_t interval = (uint32_t) (clk*1000); // in msec 28float Kang, Komg, KIang, Kyaw, Kdst, Kspd; 29int16_t maxPwr; 30float yawAngle=0.0; 31float moveDestination, moveTarget; 32float moveRate=0.0; 33const float moveStep=0.2*clk; 34int16_t fbBalance=0; 35int16_t motorDeadband=0; 36float mechFactR, mechFactL; 37int8_t motorRDir=0, motorLDir=0; 38bool spinContinuous=false; 39float spinDest, spinTarget, spinFact=1.0; 40float spinStep=0.0; //deg per 10msec 41int16_t ipowerL=0, ipowerR=0; 42int16_t motorLdir=0, motorRdir=0; //0:stop 1:+ -1:- 43float vBatt, voltAve=3.7; 44int16_t punchPwr, punchPwr2, punchDur, punchCountL=0, punchCountR=0; 45byte demoMode=1; 46 47 48// UUID HID 49static BLEUUID serviceUUID("1812"); 50// UUID Report Charcteristic 51static BLEUUID charUUID("2a4d"); 52 53static boolean doConnect = false; 54static boolean connected = false; 55static boolean doScan = false; 56 57static BLEAdvertisedDevice *myDevice; 58 59std::vector<BLEAdvertisedDevice*> myDevices; 60 61 62static void notifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic,uint8_t *pData,size_t length, bool isNotify) { 63 // ボタンを押すなどしてNotifyが実行されると呼び出される 64 65 66} 67 68class MyClientCallback: public BLEClientCallbacks { 69 void onConnect(BLEClient *pclient) { 70 71 72 73 } 74 75 void onDisconnect(BLEClient *pclient) { 76 connected = false; 77 Serial.println("onDisconnect"); 78 } 79}; 80 81bool connectToServer() { 82 83 Serial.printf("myDevices=%d\n", myDevices.size()); 84 for (int i = 0; i < myDevices.size(); i++) { 85 Serial.print("Forming a connection to "); 86 Serial.println(myDevices.at(i)->getAddress().toString().c_str()); 87 88 BLEClient *pClient = BLEDevice::createClient(); 89 Serial.println(" - Created client"); 90 91 pClient->setClientCallbacks(new MyClientCallback()); 92 93 // Connect to the remove BLE Server. 94 pClient->connect(myDevices.at(i)); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private) 95 Serial.println(" - Connected to server"); 96 97 98 // Obtain a reference to the service we are after in the remote BLE server. 99 BLERemoteService *pRemoteService = pClient->getService(serviceUUID); 100 if (pRemoteService == nullptr) { 101 Serial.print("Failed to find our service UUID: "); 102 Serial.println(serviceUUID.toString().c_str()); 103 pClient->disconnect(); 104 return false; 105 } 106 Serial.println(" - Found our service"); 107 108 // 複数のCharacteristicを持つHIDの事は考慮されていないので 109 // 複数のCharacteristicに対応した処理をする 110 std::map<uint16_t, BLERemoteCharacteristic*> *pCharacteristicMap; 111 pCharacteristicMap = pRemoteService->getCharacteristicsByHandle(); 112 // 引数なしのgetCharacteristics()は複数のCharacteristicを返してこないのでこちらを利用する 113 if (pCharacteristicMap == nullptr) { 114 Serial.println("pCharacteristicMap=null"); 115 return false; 116 } 117 118 for (auto itr = pCharacteristicMap->begin(); itr != pCharacteristicMap->end(); ++itr) { 119 Serial.print("UUID: "); 120 Serial.println(itr->second->getUUID().toString().c_str()); 121 if (itr->second->getUUID().equals(charUUID)) { 122 Serial.print("CharUUID matched: "); 123 Serial.println(itr->second->getUUID().toString().c_str()); 124 if (itr->second->canNotify()) { 125 // ReportCharacteristicsはNotifyCallbackでデータを通信するため 126 // Notify属性を持っているCharacteristicをすべて登録する 127 Serial.print("Notify registerd: "); 128 Serial.println(itr->second->getUUID().toString().c_str()); 129 itr->second->registerForNotify(notifyCallback); 130 } 131 } 132 } 133 134 135 } 136 connected = true; 137 return true; 138} 139/** 140 * Scan for BLE servers and find the first one that advertises the service we are looking for. 141 */ 142class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { 143 /** 144 * Called for each advertising BLE server. 145 */ 146 void onResult(BLEAdvertisedDevice advertisedDevice) { 147 Serial.print("BLE Advertised Device found: "); 148 Serial.println(advertisedDevice.toString().c_str()); 149 150 // We have found a device, let us now see if it contains the service we are looking for. 151 if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) { 152 153// BLEDevice::getScan()->stop(); 154 myDevice = new BLEAdvertisedDevice(advertisedDevice); 155 myDevices.push_back(myDevice); 156 doConnect = true; 157 doScan = true; 158 159 } // Found our server 160 } // onResult 161}; 162 163 164void setup() { 165 166 pinMode(LED, OUTPUT); 167 digitalWrite(LED, HIGH); 168 Serial.begin(115200); 169 M5.begin(); 170 Wire.begin(0, 26); //SDA,SCL 171 imuInit(); 172 M5.Axp.ScreenBreath(11); 173 M5.Lcd.setRotation(2); 174 M5.Lcd.setTextFont(4); 175 M5.Lcd.fillScreen(BLACK); 176 M5.Lcd.setTextSize(1); 177 resetMotor(); 178 resetPara(); 179 resetVar(); 180 calib1(); 181 #ifdef DEBUG 182 debugSetup(); 183 #else 184 setMode(true); 185 #endif 186 187 BLEDevice::init(""); 188 BLEScan *pBLEScan = BLEDevice::getScan(); 189 pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); 190 pBLEScan->setInterval(1349); 191 pBLEScan->setWindow(449); 192 pBLEScan->setActiveScan(true); 193 pBLEScan->start(5, false); 194 195} 196 197void loop() { 198 199 checkButtonP(); 200 #ifdef DEBUG 201 if (debugLoop1()) return; 202 #endif 203 getGyro(); 204 if (!standing) { 205 dispBatVolt(); 206 aveAbsOmg = aveAbsOmg * 0.9 + abs(varOmg) * 0.1; 207 aveAccZ = aveAccZ * 0.9 + accZdata * 0.1; 208 M5.Lcd.setCursor(10,130); 209 M5.Lcd.printf("%5.2f ", -aveAccZ); 210 if (abs(aveAccZ)>0.9 && aveAbsOmg<1.5) { 211 calib2(); 212 if (demoMode==1) startDemo(); 213 standing=true; 214 } 215 } 216 else { 217 if (abs(varAng)>30.0 || counterOverPwr>maxOvp) { 218 resetMotor(); 219 resetVar(); 220 standing=false; 221 setMode(false); 222 } 223 else { 224 drive(); 225 } 226 } 227 counter += 1; 228 if (counter >= 100) { 229 counter = 0; 230 dispBatVolt(); 231 if (serialMonitor) sendStatus(); 232 } 233 do time1 = millis(); 234 while (time1 - time0 < interval); 235 time0 = time1; 236 237 238 // If the flag "doConnect" is true then we have scanned for and found the desired 239 // BLE Server with which we wish to connect. Now we connect to it. Once we are 240 // connected we set the connected flag to be true. 241 if (doConnect == true) { 242 if (connectToServer()) { 243 Serial.println("We are now connected to the BLE Server."); 244 } 245 else { 246 Serial.println("We have failed to connect to the server; there is nothin more we will do."); 247 } 248 doConnect = false; 249 } 250 251 // If we are connected to a peer BLE Server, update the characteristic each time we are reached 252 // with the current time since boot. 253 if (connected) { 254 255 // String newValue = "Time since boot: " + String(millis()/1000); 256 // Serial.println("Setting new characteristic value to \"" + newValue + "\""); 257 258 // // Set the characteristic's value to be the array of bytes that is actually a string. 259 // pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length()); 260 } 261 else if (doScan) { 262 BLEDevice::getScan()->start(0); // this is just eample to start scan after disconnect, most likely there is better way to do it in arduino 263 } 264 265} 266 267void calib1() { 268 calDelay(30); 269 digitalWrite(LED, LOW); 270 calDelay(80); 271 M5.Lcd.fillScreen(BLACK); 272 M5.Lcd.setCursor(0, LCDV_MID); 273 M5.Lcd.print(" Cal-1 "); 274 gyroYoffset=0.0; 275 for (int i=0; i <N_CAL1; i++){ 276 readGyro(); 277 gyroYoffset += gyroYdata; 278 delay(9); 279 } 280 gyroYoffset /= (float)N_CAL1; 281 M5.Lcd.fillScreen(BLACK); 282 digitalWrite(LED, HIGH); 283} 284 285void calib2() { 286 resetVar(); 287 resetMotor(); 288 digitalWrite(LED, LOW); 289 calDelay(80); 290 M5.Lcd.setCursor(0, LCDV_MID); 291 M5.Lcd.println(" Cal-2 "); 292 accXoffset=0.0; 293 gyroZoffset=0.0; 294 for (int i=0; i <N_CAL2; i++){ 295 readGyro(); 296 accXoffset += accXdata; 297 gyroZoffset += gyroZdata; 298 delay(9); 299 } 300 accXoffset /= (float)N_CAL2; 301 gyroZoffset /= (float)N_CAL2; 302 M5.Lcd.fillScreen(BLACK); 303 digitalWrite(LED, HIGH); 304} 305 306void checkButtonP() { 307 byte pbtn=M5.Axp.GetBtnPress(); 308 if (pbtn==2) calib1(); //short push 309 else if (pbtn==1) setMode(true); //long push 310} 311 312void calDelay(int n) { 313 for (int i=0; i<n; i++) { 314 getGyro(); 315 delay(9); 316 } 317} 318 319void setMode(bool inc) { 320 if (inc) demoMode=++demoMode%2; 321 M5.Lcd.fillScreen(BLACK); 322 M5.Lcd.setCursor(5, 5); 323 if (demoMode==0) M5.Lcd.print("Stand "); 324 else if (demoMode==1) M5.Lcd.print("Demo "); 325 326} 327 328void startDemo() { 329 moveRate=0.0; 330 spinContinuous=false; 331 spinStep=0.0*clk; 332 333} 334 335以下 略
提示のコードの動作の説明をしましょう。
どこが倒立振子のコードでしょうか
倒立振子のコードは以下です。よろしくお願いします。
//
// BalaC balancing robot (IMU:MPU6886)
// by Kiraku Labo
//
// 1. Lay the robot flat, and power on.
// 2. Wait until Gal-1 (Pitch Gyro calibration) completes.
// 3. Hold still the robot upright in balance until Cal-2 (Accel & Yaw Gyro cal) completes.
//
// short push of power button: Gyro calibration
// long push (>1sec) of power button: switch mode between standig and demo(circle)
//
#include <M5StickC.h>
#define LED 10
#define N_CAL1 100
#define N_CAL2 100
#define LCDV_MID 60
boolean serialMonitor=true;
boolean standing=false;
int16_t counter=0;
uint32_t time0=0, time1=0;
int16_t counterOverPwr=0, maxOvp=20;
float power, powerR, powerL, yawPower;
float varAng, varOmg, varSpd, varDst, varIang;
float gyroXoffset, gyroYoffset, gyroZoffset, accXoffset;
float gyroXdata, gyroYdata, gyroZdata, accXdata, accZdata;
float aveAccX=0.0, aveAccZ=0.0, aveAbsOmg=0.0;
float cutoff=0.1; //~=2 * pi * f (Hz)
const float clk = 0.01; // in sec,
const uint32_t interval = (uint32_t) (clk*1000); // in msec
float Kang, Komg, KIang, Kyaw, Kdst, Kspd;
int16_t maxPwr;
float yawAngle=0.0;
float moveDestination, moveTarget;
float moveRate=0.0;
const float moveStep=0.2*clk;
int16_t fbBalance=0;
int16_t motorDeadband=0;
float mechFactR, mechFactL;
int8_t motorRDir=0, motorLDir=0;
bool spinContinuous=false;
float spinDest, spinTarget, spinFact=1.0;
float spinStep=0.0; //deg per 10msec
int16_t ipowerL=0, ipowerR=0;
int16_t motorLdir=0, motorRdir=0; //0:stop 1:+ -1:-
float vBatt, voltAve=3.7;
int16_t punchPwr, punchPwr2, punchDur, punchCountL=0, punchCountR=0;
byte demoMode=1;
void setup() {
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
Serial.begin(115200);
M5.begin();
Wire.begin(0, 26); //SDA,SCL
imuInit();
M5.Axp.ScreenBreath(11);
M5.Lcd.setRotation(2);
M5.Lcd.setTextFont(4);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextSize(1);
resetMotor();
resetPara();
resetVar();
calib1();
#ifdef DEBUG
debugSetup();
#else
setMode(true);
#endif
}
void loop() {
checkButtonP();
#ifdef DEBUG
if (debugLoop1()) return;
#endif
getGyro();
if (!standing) {
dispBatVolt();
aveAbsOmg = aveAbsOmg * 0.9 + abs(varOmg) * 0.1;
aveAccZ = aveAccZ * 0.9 + accZdata * 0.1;
M5.Lcd.setCursor(10,130);
M5.Lcd.printf("%5.2f ", -aveAccZ);
if (abs(aveAccZ)>0.9 && aveAbsOmg<1.5) {
calib2();
if (demoMode==1) startDemo();
standing=true;
}
}
else {
if (abs(varAng)>30.0 || counterOverPwr>maxOvp) {
resetMotor();
resetVar();
standing=false;
setMode(false);
}
else {
drive();
}
}
counter += 1;
if (counter >= 100) {
counter = 0;
dispBatVolt();
if (serialMonitor) sendStatus();
}
do time1 = millis();
while (time1 - time0 < interval);
time0 = time1;
}
void calib1() {
calDelay(30);
digitalWrite(LED, LOW);
calDelay(80);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(0, LCDV_MID);
M5.Lcd.print(" Cal-1 ");
gyroYoffset=0.0;
for (int i=0; i <N_CAL1; i++){
readGyro();
gyroYoffset += gyroYdata;
delay(9);
}
gyroYoffset /= (float)N_CAL1;
M5.Lcd.fillScreen(BLACK);
digitalWrite(LED, HIGH);
}
void calib2() {
resetVar();
resetMotor();
digitalWrite(LED, LOW);
calDelay(80);
M5.Lcd.setCursor(0, LCDV_MID);
M5.Lcd.println(" Cal-2 ");
accXoffset=0.0;
gyroZoffset=0.0;
for (int i=0; i <N_CAL2; i++){
readGyro();
accXoffset += accXdata;
gyroZoffset += gyroZdata;
delay(9);
}
accXoffset /= (float)N_CAL2;
gyroZoffset /= (float)N_CAL2;
M5.Lcd.fillScreen(BLACK);
digitalWrite(LED, HIGH);
}
void checkButtonP() {
byte pbtn=M5.Axp.GetBtnPress();
if (pbtn==2) calib1(); //short push
else if (pbtn==1) setMode(true); //long push
}
void calDelay(int n) {
for (int i=0; i<n; i++) {
getGyro();
delay(9);
}
}
void setMode(bool inc) {
if (inc) demoMode=++demoMode%2;
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(5, 5);
if (demoMode==0) M5.Lcd.print("Stand ");
else if (demoMode==1) M5.Lcd.print("Demo ");
}
void startDemo() {
moveRate=0.0;
spinContinuous=false;
spinStep=0.0*clk;
}
void resetPara() {
Kang=37.0;
Komg=0.84;
KIang=800.0;
Kyaw=4.0;
Kdst=85.0;
Kspd=2.7;
mechFactL=0.45;
mechFactR=0.45;
punchPwr=20;
punchDur=1;
fbBalance=-3;
motorDeadband=10;
maxPwr=120;
punchPwr2=max(punchPwr, motorDeadband);
}
void getGyro() {
readGyro();
varOmg = (gyroYdata-gyroYoffset); //unit:deg/sec
yawAngle += (gyroZdata-gyroZoffset) * clk; //unit:g
varAng += (varOmg + ((accXdata-accXoffset) * 57.3 - varAng) * cutoff ) * clk; //complementary filter
}
void readGyro() {
float gX, gY, gZ, aX, aY, aZ;
M5.Imu.getGyroData(&gX,&gY,&gZ);
M5.Imu.getAccelData(&aX,&aY,&aZ);
gyroYdata=gX;
gyroZdata=-gY;
gyroXdata=-gZ;
accXdata=aZ;
accZdata=aY;
}
void drive() {
#ifdef DEBUG
debugDrive();
#endif
if (abs(moveRate)>0.1) spinFact=constrain(-(powerR+powerL)/10.0, -1.0, 1.0); //moving
else spinFact=1.0; //standing
if (spinContinuous) spinTarget += spinStep * spinFact;
else {
if (spinTarget < spinDest) spinTarget += spinStep;
if (spinTarget > spinDest) spinTarget -= spinStep;
}
moveTarget += moveStep * (moveRate +(float)fbBalance/100.0);
varSpd += power * clk;
varDst += Kdst * (varSpd * clk -moveTarget);
varIang += KIang * varAng * clk;
power = varIang + varDst + (Kspd * varSpd) + (Kang * varAng) + (Komg * varOmg);
if (abs(power) > 1000.0) counterOverPwr += 1;
else counterOverPwr =0;
if (counterOverPwr > maxOvp) return;
power = constrain(power, -maxPwr, maxPwr);
yawPower = (yawAngle - spinTarget) * Kyaw;
powerR = power - yawPower;
powerL = power + yawPower;
ipowerL = (int16_t) constrain(powerL * mechFactL, -maxPwr, maxPwr);
int16_t mdbn=-motorDeadband;
int16_t pp2n=-punchPwr2;
if (ipowerL > 0) {
if (motorLdir == 1) punchCountL = constrain(++punchCountL, 0, 100);
else punchCountL=0;
motorLdir = 1;
if (punchCountL<punchDur) drvMotorL(max(ipowerL, punchPwr2));
else drvMotorL(max(ipowerL, motorDeadband));
}
else if (ipowerL < 0) {
if (motorLdir == -1) punchCountL = constrain(++punchCountL, 0, 100);
else punchCountL=0;
motorLdir = -1;
if (punchCountL<punchDur) drvMotorL(min(ipowerL, pp2n));
else drvMotorL(min(ipowerL, mdbn));
}
else {
drvMotorL(0);
motorLdir = 0;
}
ipowerR = (int16_t) constrain(powerR * mechFactR, -maxPwr, maxPwr);
if (ipowerR > 0) {
if (motorRdir == 1) punchCountR = constrain(++punchCountR, 0, 100);
else punchCountR=0;
motorRdir = 1;
if (punchCountR<punchDur) drvMotorR(max(ipowerR, punchPwr2));
else drvMotorR(max(ipowerR, motorDeadband));
}
else if (ipowerR < 0) {
if (motorRdir == -1) punchCountR = constrain(++punchCountR, 0, 100);
else punchCountR=0;
motorRdir = -1;
if (punchCountR<punchDur) drvMotorR(min(ipowerR, pp2n));
else drvMotorR(min(ipowerR, mdbn));
}
else {
drvMotorR(0);
motorRdir = 0;
}
}
void drvMotorL(int16_t pwm) {
drvMotor(0, (int8_t)constrain(pwm, -127, 127));
}
void drvMotorR(int16_t pwm) {
drvMotor(1, (int8_t)constrain(-pwm, -127, 127));
}
void drvMotor(byte ch, int8_t sp) {
Wire.beginTransmission(0x38);
Wire.write(ch);
Wire.write(sp);
Wire.endTransmission();
}
void resetMotor() {
drvMotorR(0);
drvMotorL(0);
counterOverPwr=0;
}
void resetVar() {
power=0.0;
moveTarget=0.0;
moveRate=0.0;
spinContinuous=false;
spinDest=0.0;
spinTarget=0.0;
spinStep=0.0;
yawAngle=0.0;
varAng=0.0;
varOmg=0.0;
varDst=0.0;
varSpd=0.0;
varIang=0.0;
}
void sendStatus () {
Serial.print(millis()-time0);
Serial.print(" stand="); Serial.print(standing);
Serial.print(" accX="); Serial.print(accXdata);
Serial.print(" power="); Serial.print(power);
Serial.print(" ang=");Serial.print(varAng);
Serial.print(", ");
Serial.print(millis()-time0);
Serial.println();
}
void imuInit() {
M5.Imu.Init();
if (M5.Imu.imuType=M5.Imu.IMU_MPU6886) {
M5.Mpu6886.SetGyroFsr(M5.Mpu6886.GFS_250DPS); //250DPS 500DPS 1000DPS 2000DPS
M5.Mpu6886.SetAccelFsr(M5.Mpu6886.AFS_4G); //2G 4G 8G 16G
if (serialMonitor) Serial.println("MPU6886 found");
}
else if (serialMonitor) Serial.println("MPU6886 not found");
}
void dispBatVolt() {
M5.Lcd.setCursor(5, LCDV_MID);
vBatt= M5.Axp.GetBatVoltage();
M5.Lcd.printf("%4.2fv ", vBatt);
}
Ble 受信のコードは以下です。
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <M5StickC.h>
// UUID HID
static BLEUUID serviceUUID("1812");
// UUID Report Charcteristic
static BLEUUID charUUID("2a4d");
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLEAdvertisedDevice *myDevice;
std::vector<BLEAdvertisedDevice*> myDevices;
static void notifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic,uint8_t *pData,size_t length, bool isNotify) {
// ボタンを押すなどしてNotifyが実行されると呼び出される
}
class MyClientCallback: public BLEClientCallbacks {
void onConnect(BLEClient *pclient) {
}
void onDisconnect(BLEClient *pclient) {
connected = false;
Serial.println("onDisconnect");
}
};
bool connectToServer() {
Serial.printf("myDevices=%d\n", myDevices.size());
for (int i = 0; i < myDevices.size(); i++) {
Serial.print("Forming a connection to ");
Serial.println(myDevices.at(i)->getAddress().toString().c_str());
BLEClient *pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
pClient->connect(myDevices.at(i)); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
Serial.println(" - Connected to server");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService *pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// 複数のCharacteristicを持つHIDの事は考慮されていないので
// 複数のCharacteristicに対応した処理をする
std::map<uint16_t, BLERemoteCharacteristic*> *pCharacteristicMap;
pCharacteristicMap = pRemoteService->getCharacteristicsByHandle();
// 引数なしのgetCharacteristics()は複数のCharacteristicを返してこないのでこちらを利用する
if (pCharacteristicMap == nullptr) {
Serial.println("pCharacteristicMap=null");
return false;
}
for (auto itr = pCharacteristicMap->begin(); itr != pCharacteristicMap->end(); ++itr) {
Serial.print("UUID: ");
Serial.println(itr->second->getUUID().toString().c_str());
if (itr->second->getUUID().equals(charUUID)) {
Serial.print("CharUUID matched: ");
Serial.println(itr->second->getUUID().toString().c_str());
if (itr->second->canNotify()) {
// ReportCharacteristicsはNotifyCallbackでデータを通信するため
// Notify属性を持っているCharacteristicをすべて登録する
Serial.print("Notify registerd: ");
Serial.println(itr->second->getUUID().toString().c_str());
itr->second->registerForNotify(notifyCallback);
}
}
}
}
connected = true;
return true;
}
/**
* Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
* Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
// We have found a device, let us now see if it contains the service we are looking for.
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
// BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
myDevices.push_back(myDevice);
doConnect = true;
doScan = true;
} // Found our server
} // onResult
};
void setup() {
BLEDevice::init("");
BLEScan *pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
}
void loop() {
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
Serial.println("We are now connected to the BLE Server.");
}
else {
Serial.println("We have failed to connect to the server; there is nothin more we will do.");
}
doConnect = false;
}
// If we are connected to a peer BLE Server, update the characteristic each time we are reached
// with the current time since boot.
if (connected) {
// String newValue = "Time since boot: " + String(millis()/1000);
// Serial.println("Setting new characteristic value to \"" + newValue + "\"");
// // Set the characteristic's value to be the array of bytes that is actually a string.
// pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
}
else if (doScan) {
BLEDevice::getScan()->start(0); // this is just eample to start scan after disconnect, most likely there is better way to do it in arduino
}
}
あなたの回答
tips
プレビュー