Обмен данными датчиков ESP32C6 с BLE 5.0 для каждого кода Arduino и кода Android Studio (JAVA)JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Обмен данными датчиков ESP32C6 с BLE 5.0 для каждого кода Arduino и кода Android Studio (JAVA)

Сообщение Anonymous »

У меня есть проект, в котором я хочу прочитать данные датчика из ESP32C6 с помощью BLE 5.0
и я действительно запутался и не знаю, как кодировать настоящий BLE 5.0, но это мое задание. Не могли бы вы мне с этим помочь?
Проблема:
Я хочу прочитать данные датчика моего ESP32C6, но код Android Studio не подключается. с моим устройством и поэтому не обмениваюсь нужными мне данными и не отображаю их в моем приложении. Не могли бы вы мне с этим помочь?
Код Arduino

Код: Выделить всё

#include 
#include 
#include 
#include 
#include 
#include 
#include "MAX30105.h"  // Korrigierte Bibliothek
#include "heartRate.h" // Zusätzliche Bibliothek für Herzfrequenzberechnung

// BLE UUIDs
#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

// Pin Definitions
#define OPA344_PIN A0

// Task handles for core management
TaskHandle_t Task1;
TaskHandle_t Task2;

// Mutex for protecting shared resources
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
SemaphoreHandle_t xMutex = NULL;

// Sensor objects
Adafruit_MPU6050 mpu;
MAX30105 particleSensor;

// Variables für Herzfrequenzberechnung
const byte RATE_SIZE = 4; // Größe des Arrays für die Mittelwertbildung
byte rates[RATE_SIZE]; // Array zur Speicherung der letzten Herzfrequenzen
byte rateSpot = 0;
long lastBeat = 0; // Zeit seit dem letzten Herzschlag
float beatsPerMinute;
int beatAvg;

// BLE objects
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;

// Shared data structure
struct SensorData {
// MPU6050 data
float accX, accY, accZ;
float gyroX, gyroY, gyroZ;
// MAX30102 data
uint32_t red, ir;
float heartRate;
int avgHeartRate;
// OPA344 data
float soundLevel;
} sensorData;

class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
Serial.println("Device connected!");
}

void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
Serial.println("Device disconnected!");
}
};

// Core 0: Sensor data acquisition
void SensorTask(void * parameter) {
for(;;) {
if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
// Read MPU6050
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);

sensorData.accX = a.acceleration.x;
sensorData.accY = a.acceleration.y;
sensorData.accZ = a.acceleration.z;
sensorData.gyroX = g.gyro.x;
sensorData.gyroY = g.gyro.y;
sensorData.gyroZ = g.gyro.z;

// Read MAX30102 and calculate heart rate
sensorData.ir = particleSensor.getIR();

if (checkForBeat(sensorData.ir)) {
long delta = millis() - lastBeat;
lastBeat = millis();

beatsPerMinute = 60 / (delta / 1000.0);

if (beatsPerMinute < 255 && beatsPerMinute > 20) {
rates[rateSpot++] = (byte)beatsPerMinute;
rateSpot %= RATE_SIZE;

// Durchschnitt berechnen
beatAvg = 0;
for (byte x = 0; x < RATE_SIZE; x++)
beatAvg += rates[x];
beatAvg /= RATE_SIZE;

sensorData.heartRate = beatsPerMinute;
sensorData.avgHeartRate = beatAvg;
}
}

// Read OPA344
int rawValue = analogRead(OPA344_PIN);
sensorData.soundLevel = (rawValue * 3.3) / 4095.0;

xSemaphoreGive(xMutex);
}
vTaskDelay(pdMS_TO_TICKS(10)); // 100Hz sampling rate
}
}

// Core 1: BLE and data processing
void ProcessingTask(void * parameter) {
for(;;) {
if (deviceConnected && xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
// Format data for BLE transmission
String sensorDataStr =
"ACC:" + String(sensorData.accX) + "," +
String(sensorData.accY) + "," +
String(sensorData.accZ) +
";GYRO:" + String(sensorData.gyroX) + "," +
String(sensorData.gyroY) + "," +
String(sensorData.gyroZ) +
";HR:"  + String(sensorData.heartRate) +
";AVG_HR:" + String(sensorData.avgHeartRate) +
";SND:" + String(sensorData.soundLevel);

// Send via BLE
pCharacteristic->setValue(sensorDataStr.c_str());
pCharacteristic->notify();

xSemaphoreGive(xMutex);
}
vTaskDelay(pdMS_TO_TICKS(100)); // 10Hz update rate for BLE
}
}

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

// Create mutex
xMutex = xSemaphoreCreateMutex();

// Initialize MPU6050
if (!mpu.begin()) {
Serial.println("MPU6050 not found!");
while (1) delay(10);
}
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);

// Initialize MAX30102
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
Serial.println("MAX30102 not found!");
while (1) delay(10);
}

// Konfiguration für den MAX30102
particleSensor.setup();
particleSensor.setPulseAmplitudeRed(0x0A);
particleSensor.setPulseAmplitudeGreen(0);
particleSensor.setPulseAmplitudeIR(0x0A);
particleSensor.setSampleRate(200); // Setzt die Sample Rate auf 200Hz
particleSensor.setFIFOAverage(4);  // Setzt den Durchschnitt auf 4 Samples

// Initialize BLE
BLEDevice::init("ESP32C6");
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());

BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY
);

pService->start();
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06);
pAdvertising->setMaxPreferred(0x12);
BLEDevice::startAdvertising();

// Create tasks for each core
xTaskCreatePinnedToCore(
SensorTask,    // Task function
"SensorTask",  // Name
10000,         // Stack size
NULL,          // Parameters
1,            // Priority
&Task1,        // Task handle
0             // Core ID (0)
);

xTaskCreatePinnedToCore(
ProcessingTask,
"ProcessingTask",
10000,
NULL,
1,
&Task2,
1            // Core ID (1)
);

Serial.println("Setup complete!");
}

void loop() {
// Empty loop as tasks handle all the work
vTaskDelay(pdMS_TO_TICKS(1000));
}
Код Android Studio:

Код: Выделить всё

package com.example.project;

import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.util.UUID;

public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST_CODE = 1;
private static final String DEVICE_NAME = "ESP32C6";
private static final UUID SERVICE_UUID = UUID.fromString("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
private static final UUID CHARACTERISTIC_UUID = UUID.fromString("beb5483e-36e1-4688-b7f5-ea07361b26a8");

private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private BluetoothLeScanner bluetoothLeScanner;
private BluetoothGatt bluetoothGatt;

private Button btnScan;
private TextView tvConnectionStatus, tvAccData, tvGyroData, tvHeartRate, tvSoundLevel;
private boolean scanning = false;
private Handler handler = new Handler();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

initializeViews();
setupBluetooth();
checkPermissions();
}

private void initializeViews() {
btnScan = findViewById(R.id.btnScan);
tvConnectionStatus = findViewById(R.id.tvConnectionStatus);
tvAccData = findViewById(R.id.tvAccData);
tvGyroData = findViewById(R.id.tvGyroData);
tvHeartRate = findViewById(R.id.tvHeartRate);
tvSoundLevel = findViewById(R.id.tvSoundLevel);

btnScan.setOnClickListener(v ->  {
if (!scanning) {
startScan();
} else {
stopScan();
}
});
}

private void setupBluetooth() {
bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager != null) {
bluetoothAdapter = bluetoothManager.getAdapter();
bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
}
}

private void checkPermissions() {
String[] permissions = {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT
};

for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE);
return;
}
}
}

@SuppressLint("MissingPermission")
private void startScan() {
if (bluetoothLeScanner != null) {
scanning = true;
btnScan.setText("Stop Scan");
bluetoothLeScanner.startScan(scanCallback);
handler.postDelayed(this::stopScan, 10000); // Stop scanning after 10 seconds
}
}

@SuppressLint("MissingPermission")
private void stopScan() {
if (bluetoothLeScanner != null) {
scanning = false;
btnScan.setText("Start Scan");
bluetoothLeScanner.stopScan(scanCallback);
}
}

private final ScanCallback scanCallback = new ScanCallback() {
@SuppressLint("MissingPermission")
@Override
public void onScanResult(int callbackType, ScanResult result) {
BluetoothDevice device = result.getDevice();
if (DEVICE_NAME.equals(device.getName())) {
stopScan();
connectToDevice(device);
}
}
};

private void connectToDevice(BluetoothDevice device) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
return;
}
bluetoothGatt = device.connectGatt(this, false, gattCallback);
}

private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (status == BluetoothGatt.GATT_SUCCESS) {
if (newState == BluetoothGatt.STATE_CONNECTED) {
runOnUiThread(() -> tvConnectionStatus.setText("Status: Connected"));
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
return;
}
bluetoothGatt.discoverServices();
} else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
runOnUiThread(() ->  tvConnectionStatus.setText("Status: Disconnected"));
}
}
}

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService service = gatt.getService(SERVICE_UUID);
if (service != null) {
BluetoothGattCharacteristic characteristic = service.getCharacteristic(CHARACTERISTIC_UUID);
if (characteristic != null) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
return;
}
gatt.setCharacteristicNotification(characteristic, true);
}
}
}
}

@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
if (CHARACTERISTIC_UUID.equals(characteristic.getUuid())) {
final String data = new String(characteristic.getValue());
parseAndUpdateUI(data);
}
}
};

private void parseAndUpdateUI(final String data) {
runOnUiThread(() -> {
try {
String[] sections = data.split(";");
for (String section : sections) {
String[] parts = section.split(":");
if (parts.length == 2) {
String type = parts[0];
String values = parts[1];

switch (type) {
case "ACC":
String[] accValues = values.split(",");
String accText = String.format("X: %.2f\nY: %.2f\nZ: %.2f",
Float.parseFloat(accValues[0]),
Float.parseFloat(accValues[1]),
Float.parseFloat(accValues[2]));
tvAccData.setText(accText);
break;

case "GYRO":
String[] gyroValues = values.split(",");
String gyroText = String.format("X: %.2f\nY: %.2f\nZ: %.2f",
Float.parseFloat(gyroValues[0]),
Float.parseFloat(gyroValues[1]),
Float.parseFloat(gyroValues[2]));
tvGyroData.setText(gyroText);
break;

case "HR":
tvHeartRate.setText(values + " BPM");
break;

case "SND":
tvSoundLevel.setText(String.format("%.2f V", Float.parseFloat(values)));
break;
}
}
}
} catch (Exception e) {
Toast.makeText(MainActivity.this, "Error parsing data", Toast.LENGTH_SHORT).show();
}
});
}

@Override
protected void onDestroy() {
super.onDestroy();
if (bluetoothGatt != null) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
return;
}
bluetoothGatt.close();
}
}
}
Манифест:
Это также есть в моем манифесте: Я уже пытался спросить Клода или ChatGpt, потому что я ничего не знаю о протоколе BLE и у меня нет на это много времени из-за других моих занятий, пожалуйста, помогите мне

Подробнее здесь: https://stackoverflow.com/questions/792 ... -android-s
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»