繁体   English   中英

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

[英]Android + ESP32 send data over bluetooth (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. 从 Play 商店下载并安装 nRF Connect 应用程序。
  2. 启动 nRF Connect 应用程序并扫描设备。
  3. 如果找到,请连接到您的 ESP32。
  4. 浏览 GATT 表并找到控制 ESP32 的特性的 UUID 和句柄。 这很重要,因为它将在 B 部分中使用。
  5. 找到后,尝试将值 0、1、2、3 和 4 写入此特征,并确保一切正常。

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM