Android+ESP32通过蓝牙(BLE)发送数据



我正试图通过蓝牙(BLE(将数据从我的android应用程序发送到esp32,但我找不到正确的方法。我现在所能做的就是扫描并找到BLE设备。我的arduino代码按照我的意愿工作(它正确地接收数据(,因为我使用了另一个应用程序,它可以让我向ble设备发送数据,所以我知道arduino码很好。

我已经在这里搜索了好几天,并在谷歌上搜索了如何实现它,但我仍然被卡住了。这是我现在的代码:

扫描仪:

class BluetoothFragment : Fragment() {
private lateinit var binding: FragmentBluetoothBinding
private var list : MutableList<BluetoothDevice> = ArrayList()
private lateinit var  bluetoothAdapter : BluetoothAdapter
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
Log.d("DeviceListActivity", "onCreate()")
return inflater.inflate(R.layout.fragment_bluetooth, container, false)
}
// TODO: 19/05/2021 implementar listener en el recycler view para crear la conexión con el ble
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentBluetoothBinding.bind(view)
if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
val permissions = arrayOf(
android.Manifest.permission.ACCESS_COARSE_LOCATION,
)
ActivityCompat.requestPermissions(requireActivity(), permissions, 0)
}
setRecyclerView(list)
}
private val bleScanner = object :ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult?) {
super.onScanResult(callbackType, result)
Log.d("pepe","onScanResult: ${result?.device?.address} - ${result?.device?.name}")
if(result?.device?.name?.isNotEmpty() == true){
var bluetoothDevice = result?.device?.name?.let { BluetoothDevice(it) }
if (bluetoothDevice != null) {
list.add(bluetoothDevice)
bluetoothAdapter.notifyDataSetChanged()
}
}
}
override fun onBatchScanResults(results: MutableList<ScanResult>?) {
super.onBatchScanResults(results)
Log.d("DeviceListActivity","onBatchScanResults:${results.toString()}")
}
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
Log.d("DeviceListActivity", "onScanFailed: $errorCode")
}
}
private val bluetoothLeScanner: BluetoothLeScanner
get() {
val bluetoothManager = requireActivity().getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val bluetoothAdapter = bluetoothManager.adapter
return bluetoothAdapter.bluetoothLeScanner
}
class ListDevicesAdapter(context: Context?, resource: Int) : ArrayAdapter<String>(context!!, resource)

override fun onStart() {
Log.d("DeviceListActivity","onStart()")
super.onStart()
bluetoothLeScanner.startScan(bleScanner)
}
override fun onStop() {
bluetoothLeScanner.stopScan(bleScanner)
super.onStop()
}
private fun setRecyclerView(allCategories: List<BluetoothDevice>) {
val layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(context)
binding.rvBluetooth.layoutManager = layoutManager
bluetoothAdapter = BluetoothAdapter(allCategories)
binding.rvBluetooth.adapter = bluetoothAdapter
}
}

Arduino代码(我用它控制一辆小车,所以这就是为什么我有5个不同的值(:

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
// Motor 1
int motor1Pin1 = 23;
int motor1Pin2 = 22;
int enable1Pin = 21;
// Motor 2
int motor2Pin1 = 18;
int motor2Pin2 = 19;
int enable2Pin = 5;
const int freq = 30000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 200;
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
if (value[0] == '1') {
dutyCycle = 200;
Serial.println("Moving Forward");
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
while (dutyCycle <= 255) {
ledcWrite(pwmChannel, dutyCycle);
dutyCycle = dutyCycle + 5;
delay(500);
}
}
if (value[0] == '4') {
dutyCycle = 200;
Serial.println("Moving Backwards");
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
while (dutyCycle <= 255) {
ledcWrite(pwmChannel, dutyCycle);
dutyCycle = dutyCycle + 5;
delay(500);
}
}
if (value[0] == '2') {
dutyCycle = 100;
Serial.println("Motor right");
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
}
if (value[0] == '3') {
dutyCycle = 100;
Serial.println("Motor left");
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
}
if (value[0] == '0') {
Serial.println("Motor stopped");
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, LOW);
}
}
}
};

void setup() {
Serial.begin(115200);
BLEDevice::init("Andruino");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(enable1Pin, OUTPUT);
pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);
pinMode(enable2Pin, OUTPUT);
ledcSetup(pwmChannel, freq, resolution);
ledcAttachPin(enable1Pin, pwmChannel);
ledcAttachPin(enable2Pin, pwmChannel);

ledcWrite(pwmChannel, dutyCycle);
}
void loop() {
}

我如何通过蓝牙将数据从我的android应用程序发送到esp32?

如果我是你,我会做以下事情:-

第A部分:使用现有的Android应用程序(例如nRF Connect-也许你已经完成了这一部分(

  1. 从游戏商店下载并安装nRF Connect应用程序
  2. 启动nRF Connect应用程序并扫描设备
  3. 如果找到,请连接到您的ESP32
  4. 浏览GATT表,找到控制ESP32的特性的UUID和句柄。这一点很重要,因为它将在B部分中使用
  5. 找到后,尝试将值0、1、2、3和4写入此特性,并确保一切正常

如果以上部分对您来说是新的,请查看下面的链接。如果你已经成功地完成了以上所有操作,那么转到第B部分:-

  • nRF Connect For Mobile-入门
  • 蓝牙低能耗特性-入门指南
  • BLE-GATT简介

第B部分:使用您的Android应用程序进行此操作:-

  1. 与nRF Connect应用程序类似,您的应用程序需要扫描并连接到ESP32。你可以在这里找到如何做到这一点的例子
  2. 连接后,您需要浏览GATT表并找到正确的特征。你可以在这里找到这样的例子
  3. 一旦找到了正确的特征及其句柄(这就是您在上面步骤4中注意到的那个(,就可以继续向该特征写入值。你可以在这里、这里和这里找到例子

如果所有这些都已到位,但仍然不起作用,请检查以下内容:-

  • 您正在等待GATT写入完成回调吗?还要检查这个
  • 你使用的是正确的Android写入操作吗
  • 您是否可能使用可靠的写入而不是正常的写入
  • 您发送的是整数数据而不是字符串数据吗?应用程序需要整数数据才能正常工作

您可以在以下链接中找到有关上述步骤的示例和解释:-

  • 如何通过BLE链接发送数据
  • 使用BLE连接到Android应用程序中的设备
  • Android BLE开发的终极指南
  • Android低能耗蓝牙入门
  • 如何使用Android BLE与设备通信

我认为最好的方法是从本文开始——让android ble成为工作的一部分。

您的数据无法传递到设备的原因有很多:

  1. 设备固件(使用nRF Connect应用程序进行检查(
  2. Android代码中的逻辑错误(查看文章以尝试修复它们(

最新更新