-
-
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); | |
| } |
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());
Так может вы просто поделитесь программой ? Я не спец в приложениях