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

Posted

技术标签:

【中文标题】Android + ESP32 通过蓝牙 (BLE) 发送数据【英文标题】:Android + ESP32 send data over bluetooth (BLE) 【发布时间】:2021-08-16 21:51:39 【问题描述】:

我正在尝试通过蓝牙 (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?

【问题讨论】:

到底是什么问题?有很多关于这个主题的教程,例如this ble guide 解释了如何通过 ble 发送数据。 【参考方案1】:

如果我是你,我会执行以下操作:-

A 部分:使用现有的 Android 应用(例如 nRF Connect - 也许您已经完成了这部分)

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

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

nRF Connect For Mobile - Get Started Bluetooth Low Energy Characteristics - A Beginner's Guide Introduction to BLE - GATT

B 部分:使用您的 Android 应用程序来完成这项工作:-

    与 nRF Connect 应用类似,您的应用需要扫描并连接到 ESP32。您可以在here 找到有关如何执行此操作的示例。 连接后,您需要浏览 GATT 表并找到正确的特征。您可以找到此 here 的示例。 一旦找到正确的特征及其句柄(这是您在上面第 4 步中记下的那个),继续向该特征写入值。您可以找到示例here、here 和here。

如果所有这些都到位但仍然无法正常工作,请检查以下几点:-

Are you waiting for the GATT write completion callback? 还要检查this。 Are you using the right Android write operation? Are you maybe using reliable writes instead of normal write? 您发送的是整数数据而不是字符串数据吗?该应用需要整数数据才能正常工作。

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

How to Send Data over a BLE Link Use BLE to connect to devices in an Android app The Ultimate Guide to Android BLE Development Getting Started with Bluetooth Low Energy on Android How to Use Android BLE to Communicate with Devices

【讨论】:

【参考方案2】:

我认为最好的方法是从这篇文章开始 - making-android-ble-work-part。

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

    设备固件(使用 nRF Connect 应用检查) Android 代码中的逻辑错误(查看文章尝试修复它们)

【讨论】:

以上是关于Android + ESP32 通过蓝牙 (BLE) 发送数据的主要内容,如果未能解决你的问题,请参考以下文章

低功耗蓝牙(ESP32 和 Android 智能手机之间):数据传输很慢

Arduino ESP32 BLE蓝牙串口通讯实验

ESP32 BLE蓝牙 微信小程序通信发送大于20字符数据

ESP32 使用BLE蓝牙透传

Arduino ESP32 BLE蓝牙和安卓端蓝牙数据交互实验

esp32不使用蓝牙助手连接蓝牙