美文网首页
nRF52840 BLE Serial 通讯

nRF52840 BLE Serial 通讯

作者: T_K_233 | 来源:发表于2021-12-12 12:37 被阅读0次

Central Node


BLEClientBas  clientBas;  // battery client
BLEClientDis  clientDis;  // device information client
BLEClientUart clientUart; // bleuart client

void BLE_init(void) {
  // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
  // SRAM usage required by SoftDevice will increase dramatically with number of connections
  Bluefruit.begin(0, 1);
  
  Bluefruit.setName("CentralNode");

  // Configure Battyer client
  clientBas.begin();  

  // Configure DIS client
  clientDis.begin();

  // Init BLE Central Uart Serivce
  clientUart.begin();
  clientUart.setRxCallback(onBLE_UART_RXHandler);

  // Increase Blink rate to different from PrPh advertising mode
  Bluefruit.setConnLedInterval(250);

  // Callbacks for Central
  Bluefruit.Central.setConnectCallback(onConnectHandler);
  Bluefruit.Central.setDisconnectCallback(onDisconnectHandler);

  /* Start Central Scanning
   * - Enable auto scan if disconnected
   * - Interval = 100 ms, window = 80 ms
   * - Don't use active scan
   * - Start(timeout) with timeout = 0 will scan forever (until connected)
   */
  Bluefruit.Scanner.setRxCallback(scan_callback);
  Bluefruit.Scanner.restartOnDisconnect(true);
  Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms
  Bluefruit.Scanner.useActiveScan(false);
  Bluefruit.Scanner.start(0);                   // // 0 = Don't stop scanning after n seconds
}

/**
 * Callback invoked when scanner pick up an advertising data
 * @param report Structural advertising data
 */
void scan_callback(ble_gap_evt_adv_report_t* report) {
  // Check if advertising contain BleUart service
  if (Bluefruit.Scanner.checkReportForService(report, clientUart)) {
    Serial.print("BLE UART service detected. Connecting ... ");

    // Connect to device with bleuart service in advertising
    Bluefruit.Central.connect(report);
  }
  else {      
    // For Softdevice v6: after received a report, scanner will be paused
    // We need to call Scanner resume() to continue scanning
    Bluefruit.Scanner.resume();
  }
}

/**
 * Callback invoked when an connection is established
 * @param conn_handle
 */
void onConnectHandler(uint16_t conn_handle) {
  Serial.println("Connected");

  Serial.print("Dicovering Device Information ... ");
  if (clientDis.discover(conn_handle)) {
    Serial.println("Found it");
    char buffer[32+1];
    
    // read and print out Manufacturer
    memset(buffer, 0, sizeof(buffer));
    if (clientDis.getManufacturer(buffer, sizeof(buffer))) {
      Serial.print("Manufacturer: ");
      Serial.println(buffer);
    }

    // read and print out Model Number
    memset(buffer, 0, sizeof(buffer));
    if (clientDis.getModel(buffer, sizeof(buffer))) {
      Serial.print("Model: ");
      Serial.println(buffer);
    }

    Serial.println();
  }
  else {
    Serial.println("Found NONE");
  }

  Serial.print("Dicovering Battery ... ");
  if (clientBas.discover(conn_handle)) {
    Serial.println("Found it");
    Serial.print("Battery level: ");
    Serial.print(clientBas.read());
    Serial.println("%");
  }
  else {
    Serial.println("Found NONE");
  }

  Serial.print("Discovering BLE Uart Service ... ");
  if (clientUart.discover(conn_handle)) {
    Serial.println("Found it");

    Serial.println("Enable TXD's notify");
    clientUart.enableTXD();

    Serial.println("Ready to receive from peripheral");
  }
  else {
    Serial.println("Found NONE");
    
    // disconnect since we couldn't find bleuart service
    Bluefruit.disconnect(conn_handle);
  }  
}

/**
 * Callback invoked when a connection is dropped
 * @param conn_handle
 * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
 */
void onDisconnectHandler(uint16_t conn_handle, uint8_t reason) {
  (void) conn_handle;
  (void) reason;
  
  Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
}

/**
 * Callback invoked when uart received data
 * @param uart_svc Reference object to the service where the data 
 * arrived. In this example it is clientUart
 */
void onBLE_UART_RXHandler(BLEClientUart& uart_svc) {
  uart_svc.setTimeout(10);
  if (uart_svc.available()) {
    uint8_t buf[128];
    uint16_t size = uart_svc.readBytesUntil('\n', buf, 128);
    Serial.write(buf, size);
    Serial.write('\n');
  }
}

void setup() {
  Serial.begin(115200);
  while (!Serial) {}

  Serial.setTimeout(10);
  

  BLE_init();
}

void loop() {
  if (Bluefruit.Central.connected() && clientUart.discovered()) {
    // Discovered means in working state
    // Get Serial input and send to Peripheral
    if (Serial.available()) {
      uint8_t buf[128];
      uint16_t size = Serial.readBytesUntil('\n', buf, 128);
      clientUart.write(buf, size);
      //clientUart.write('\n');
    }
  }
}

Client

#include <bluefr#include <bluefruit.h>

// BLE Service
BLEDfu  bledfu;  // OTA DFU service
BLEDis  bledis;  // device information
BLEUart bleuart; // uart over ble
BLEBas  blebas;  // battery

// callback invoked when central connects
void onConnectHandler(uint16_t conn_handle) {
  // Get the reference to current connection
  BLEConnection* connection = Bluefruit.Connection(conn_handle);

  char central_name[32] = { 0 };
  connection->getPeerName(central_name, sizeof(central_name));

  Serial.print("Connected to ");
  Serial.println(central_name);
}

/**
 * Callback invoked when a connection is dropped
 * @param conn_handle connection where this event happens
 * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
 */
void onDisconnectHandler(uint16_t conn_handle, uint8_t reason) {
  (void) conn_handle;
  (void) reason;

  Serial.println();
  Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
}

void BLE_init(void) {
  // Setup the BLE LED to be enabled on CONNECT
  // Note: This is actually the default behavior, but provided
  // here in case you want to control this LED manually via PIN 19
  Bluefruit.autoConnLed(true);

  // Config the peripheral connection with maximum bandwidth 
  // more SRAM required by SoftDevice
  // Note: All config***() function must be called before begin()
  Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);

  Bluefruit.begin();
  Bluefruit.setTxPower(4);    // Check bluefruit.h for supported values
  Bluefruit.setName("ClientNode"); // useful testing with multiple central connections

  Bluefruit.Periph.setConnectCallback(onConnectHandler);
  Bluefruit.Periph.setDisconnectCallback(onDisconnectHandler);

  // To be consistent OTA DFU should be added first if it exists
  bledfu.begin();

  // Configure and Start Device Information Service
  bledis.setManufacturer("RATH");
  bledis.setModel("nRF52840");
  bledis.begin();

  // Configure and Start BLE Uart Service
  bleuart.begin();

  // Start BLE Battery Service
  blebas.begin();
  blebas.write(100);
  
}

void BLE_startAdvertising(void) {
  // Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();

  // Include bleuart 128-bit uuid
  Bluefruit.Advertising.addService(bleuart);

  // Secondary Scan Response packet (optional)
  // Since there is no room for 'Name' in Advertising packet
  Bluefruit.ScanResponse.addName();
  
  /* Start Advertising
   * - Enable auto advertising if disconnected
   * - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
   * - Timeout for fast mode is 30 seconds
   * - Start(timeout) with timeout = 0 will advertise forever (until connected)
   * 
   * For recommended advertising interval
   * https://developer.apple.com/library/content/qa/qa1931/_index.html   
   */
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds  
}

void setup() {
  Serial.begin(115200);

  while (!Serial) {}
  
  Serial.setTimeout(10);
  bleuart.setTimeout(10);

  BLE_init();

  // Set up and start advertising
  BLE_startAdvertising();

  Serial.println("Please use Adafruit's Bluefruit LE app to connect in UART mode");
  Serial.println("Once connected, enter character(s) that you wish to send");
}


void loop() {
  if (Serial.available()) {
    uint8_t buf[128];
    uint16_t size = Serial.readBytesUntil('\n', buf, 128);
    bleuart.write(buf, size);
    //bleuart.write('\n');
  } 

  if (bleuart.available()) {
    uint8_t buf[128];
    uint16_t size = bleuart.readBytesUntil('\n', buf, 128);
    Serial.write(buf, size);
    Serial.write('\n');
  }
}

测试用的 Python 代码:

import random

import serial

ser = serial.Serial("COM20", 115200, timeout=0.01)

prev_t = time.time()

count = 0
counter = 0
while True:

    t = time.time()
    buf = "%s\n" % t
    #buf = "hi\n"
    counter += 1
    ser.write(buf.encode())

    time.sleep(0.005)
    buf = b""
    c = ser.read()

    while c and c != b"\n":
        buf += c
        c = ser.read()

    buf += c

    count += len(buf)

    #print(buf)
    try:
        prev_t = float(buf.decode().replace("\n", ""))
        print(t, "\t", time.time() - prev_t)
    except:
        pass


    if count > 100:
        print(count / (time.time() - prev_t), " wd/s")
        count = 0    
        prev_t = time.time()

另一端用个 echo client


import serial

ser = serial.Serial("COM23", 115200, timeout=0.1)

count = 0
while True:

    buf = b""
    c = ser.read()

    while c and c != b"\n":
        buf += c
        c = ser.read()

    buf += c


    #print(buf)
    
    ser.write(buf)

    
    count += 1

相关文章

网友评论

      本文标题:nRF52840 BLE Serial 通讯

      本文链接:https://www.haomeiwen.com/subject/arsrfrtx.html