-
-
Save joshnuss/52a2dae98c4037ef70954432ee798fda to your computer and use it in GitHub Desktop.
/* | |
* Using digital hall effect sensor SENS-M-10 (purchased at Abra) | |
* | |
* MCU Board: ESP2-WROOM-32 | |
*/ | |
#include <BLEDevice.h> | |
#include <BLEUtils.h> | |
#include <BLEServer.h> | |
#define MEASURE_PIN 23 | |
#define LED_BUILTIN 2 | |
#define WHEEL_CIRCUMFERANCE 0.7 | |
#define SAMPLES 10 | |
#define SERVICE_UUID "5aad4ed0-a7dd-46b2-965b-7a5a159b07a2" | |
#define CHARACTERISTIC_RPM_UUID "69758442-6da8-497c-a29c-48b2c48d6ceb" | |
typedef struct { | |
uint16_t ms; | |
uint16_t revolutions; | |
} sample_t; | |
class RPMCallbacks : public BLECharacteristicCallbacks { | |
private: | |
double* pRps; | |
public: | |
RPMCallbacks(double* pRps) { | |
this->pRps = pRps; | |
} | |
void onRead(BLECharacteristic *pCharacteristic) { | |
double rpm = *pRps * 60; | |
pCharacteristic->setValue(std::to_string(rpm)); | |
} | |
}; | |
volatile uint8_t nextSample = 0; | |
volatile sample_t samples[SAMPLES] = {}; | |
hw_timer_t * timer = NULL; | |
// temp vars for computing totals | |
volatile sample_t* pSample; | |
uint8_t n; | |
uint8_t totalRevolutions; | |
uint8_t totalSamples; | |
uint16_t minMs; | |
uint16_t maxMs; | |
double rps; | |
// interrupt handler is triggered every 100ms | |
void IRAM_ATTR timer_interrupt() { | |
// compute total revolutions and revolutions per second | |
totalRevolutions = 0; | |
totalSamples = 0; | |
minMs = 0; | |
maxMs = 0; | |
rps = 0; | |
// iterate thru samples | |
for (int i=0;i<SAMPLES;i++) { | |
n = (nextSample+i) % SAMPLES; | |
pSample = &samples[n]; | |
if (pSample->ms > 0) { | |
// good sample | |
totalSamples++; | |
totalRevolutions += pSample->revolutions; | |
minMs = std::min(minMs, (uint16_t)pSample->ms); | |
maxMs = std::max(maxMs, (uint16_t)pSample->ms); | |
} | |
} | |
// compute rps | |
if (totalSamples > 0) { | |
rps = totalRevolutions * 1.0 / totalSamples; | |
} | |
// prepare for a new sample | |
if (nextSample >= SAMPLES-1) { | |
nextSample = 0; | |
} else { | |
nextSample++; | |
} | |
// clear old sample data | |
samples[nextSample].ms = millis(); | |
samples[nextSample].revolutions = 0; | |
} | |
// interrupt handler is triggered when magnet enters or leaves field | |
void magnet_detection_changed() { | |
// check if magnet is nearby | |
if (digitalRead(MEASURE_PIN) == HIGH) { | |
// increase revolutions | |
samples[nextSample].revolutions++; | |
// turn on built-in LED | |
digitalWrite(LED_BUILTIN, LOW); | |
} else { | |
// turn off built-in LED | |
digitalWrite(LED_BUILTIN, HIGH); | |
} | |
} | |
void setup() { | |
Serial.begin(115200); | |
pinMode(MEASURE_PIN, INPUT); | |
pinMode(LED_BUILTIN, OUTPUT); | |
// prescaler 80 is for 80MHz clock. One tick of the timer is 1us | |
timer = timerBegin(0, 80, true); | |
// attach interrupt handler | |
timerAttachInterrupt(timer, &timer_interrupt, true); | |
// trigger timer every 100ms (100,000us) | |
timerAlarmWrite(timer, 100000, true); | |
// enable the timer | |
timerAlarmEnable(timer); | |
// trigger function when hall effect sensor changes (goes low->high or high->low) | |
attachInterrupt(MEASURE_PIN, magnet_detection_changed, CHANGE); | |
// setup BLE device | |
BLEDevice::init("Speedometer"); | |
BLEServer *pServer = BLEDevice::createServer(); | |
BLEService *pService = pServer->createService(SERVICE_UUID); | |
// RPM characteristic | |
BLECharacteristic *pRPMCharacteristic = pService->createCharacteristic( | |
CHARACTERISTIC_RPM_UUID, | |
BLECharacteristic::PROPERTY_READ | |
); | |
pRPMCharacteristic->setCallbacks(new RPMCallbacks(&rps)); | |
pService->start(); | |
// BLEAdvertising *pAdvertising = pServer->getAdvertising(); // this still is working for backward compatibility | |
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); | |
BLEAdvertisementData advertisementData = BLEAdvertisementData(); | |
advertisementData.setName("Speedometer"); | |
pAdvertising->setAdvertisementData(advertisementData); | |
pAdvertising->addServiceUUID(SERVICE_UUID); | |
pAdvertising->setScanResponse(true); | |
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue | |
pAdvertising->setMinPreferred(0x12); | |
BLEDevice::startAdvertising(); | |
} | |
void loop() { | |
// output calculations for debug | |
Serial.print("samples="); | |
Serial.print(totalSamples); | |
Serial.print(", revolutions="); | |
Serial.print(totalRevolutions); | |
Serial.print(", rps="); | |
Serial.print(rps); | |
Serial.print(", rpm="); | |
Serial.print(rps * 60); | |
Serial.print(", speed="); | |
Serial.print(rps * 60 * WHEEL_CIRCUMFERANCE); | |
Serial.println(); | |
delay(1000); | |
} |
@Dim4ik1992 on Android, you can test it with the app Nordic nRF Connect, or write a program (I wrote one with Flutter)
@Dim4ik1992на Android вы можете протестировать его с помощью приложения Nordic nRF Connect или написать программу (я написал ее с помощью Flutter)
Так может вы просто поделитесь программой ? Я не спец в приложениях
This is nRF Connect, it is for testing Bluetooth devices:
https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp
Unfortunately, I can't share the program I wrote as it's part of a much bigger codebase, so I don't think it would help you.
You would probably need to write your own Android Bluetooth app to make use of this.
I would search for "esp32 Bluetooth flutter tutorials"
For example, maybe this would help:
https://github.com/martinloretzzz/flutter-esp32-bluetooth
I loaded this on my ESP-WROOM-32 and it worked to connect and read data fine (thanks for this). However it would not allow reconnecting after a disconnect without restarting the device. Found a suggestion on another forum to add a server callback for onDisconnect to start the advertising again which seems to resolve the problem:
class MyServerCallbacks: public BLEServerCallbacks {
public:
void onConnect(BLEServer* pServer) {
Serial.println("ble connect");
}
void onDisconnect(BLEServer* pServer) {
Serial.println("ble disconnect");
pServer->getAdvertising()->start();
}
};
and register the callback just after createServer():
pServer->setCallbacks(new MyServerCallbacks());
Как его подключить к телефону через ble ? На Android