Extracts BLE internals to a BLEAdvertising class
This commit is contained in:
parent
8d01cd3b7e
commit
6c4b57f2b0
5 changed files with 89 additions and 35 deletions
|
|
@ -2,8 +2,9 @@
|
||||||
A low power soil moisture sensor based on the nRF52840.
|
A low power soil moisture sensor based on the nRF52840.
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
* Implement BLE advertising with moisture, battery level
|
* Implement battery level monitoring
|
||||||
* Figure out how to calibrate the ADC when running from different voltages, as the battery discharges
|
* Figure out how to calibrate the ADC when running from different voltages, as the battery discharges
|
||||||
|
* Experiment with different TX power / battery tradeoff. Since we'll be deepsleeping most of the time, maybe we can get away with a lot of TX power.
|
||||||
* Implement deep sleep
|
* Implement deep sleep
|
||||||
* Measure current in deep sleep
|
* Measure current in deep sleep
|
||||||
* Measure current in operation (ADC + BLE adversiting)
|
* Measure current in operation (ADC + BLE adversiting)
|
||||||
|
|
@ -15,6 +16,7 @@ A low power soil moisture sensor based on the nRF52840.
|
||||||
* Design new board using the nrf52 instead of esp32
|
* Design new board using the nrf52 instead of esp32
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
|
* Implement BLE advertising with moisture
|
||||||
* Implement ADC for the parasitic capacitor; check out air/water range (using protoboard)
|
* Implement ADC for the parasitic capacitor; check out air/water range (using protoboard)
|
||||||
* Simple PWM square wave generator
|
* Simple PWM square wave generator
|
||||||
* Hook square wave generator to the protoboard sensor circuit
|
* Hook square wave generator to the protoboard sensor circuit
|
||||||
|
|
|
||||||
|
|
@ -1 +1,46 @@
|
||||||
#include "ble.h"
|
#include "ble.h"
|
||||||
|
|
||||||
|
#include <bluefruit.h>
|
||||||
|
|
||||||
|
namespace parasite {
|
||||||
|
namespace {}
|
||||||
|
|
||||||
|
void BLEAdvertiser::SetData(BLEAdvertisementData data) {
|
||||||
|
data_ = std::move(data);
|
||||||
|
if (is_running_) {
|
||||||
|
Bluefruit.Advertising.stop();
|
||||||
|
}
|
||||||
|
Bluefruit.Advertising.clearData();
|
||||||
|
Bluefruit.Advertising.setData(data_.GetRawData(), data_.GetDataLen());
|
||||||
|
if (is_running_) {
|
||||||
|
Bluefruit.Advertising.start(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLEAdvertiser::Init() {
|
||||||
|
ble_gap_addr_t addr;
|
||||||
|
addr.addr_id_peer = 1;
|
||||||
|
addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;
|
||||||
|
std::copy(std::begin(mac_addr_), std::end(mac_addr_), std::begin(addr.addr));
|
||||||
|
Bluefruit.begin(1, 1);
|
||||||
|
Bluefruit.setName("Parasite");
|
||||||
|
Bluefruit.setAddr(&addr);
|
||||||
|
is_initialized_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLEAdvertiser::Start() {
|
||||||
|
if (!is_initialized_) {
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
|
||||||
|
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
|
||||||
|
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
|
||||||
|
is_running_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLEAdvertiser::Stop() {
|
||||||
|
Bluefruit.Advertising.stop();
|
||||||
|
is_running_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace parasite
|
||||||
|
|
@ -1,13 +1,29 @@
|
||||||
#ifndef _PARASITE_BLE_H_
|
#ifndef _PARASITE_BLE_H_
|
||||||
#define _PARASITE_BLE_H_
|
#define _PARASITE_BLE_H_
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "parasite/ble_advertisement_data.h"
|
||||||
|
|
||||||
namespace parasite {
|
namespace parasite {
|
||||||
|
|
||||||
|
using MACAddr = std::array<uint8_t, 6>;
|
||||||
|
|
||||||
class BLEAdvertiser {
|
class BLEAdvertiser {
|
||||||
public:
|
public:
|
||||||
void Advertise(std::string name, double moisture) {}
|
explicit BLEAdvertiser(MACAddr mac_addr) : mac_addr_(std::move(mac_addr)) {}
|
||||||
|
void SetData(BLEAdvertisementData data);
|
||||||
|
void Start();
|
||||||
|
void Stop();
|
||||||
|
bool IsRunning() const { return is_running_; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool is_initialized_;
|
||||||
|
bool is_running_;
|
||||||
|
void Init();
|
||||||
|
BLEAdvertisementData data_;
|
||||||
|
MACAddr mac_addr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace parasite
|
} // namespace parasite
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,4 @@ void BLEAdvertisementData::SetRawSoilMoisture(int raw_soil_moisture) {
|
||||||
data_[kRawSoilMoistureOffset + 1] = packed_value & 0xff;
|
data_[kRawSoilMoistureOffset + 1] = packed_value & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace parasite
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <bluefruit.h>
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "parasite/ble.h"
|
#include "parasite/ble.h"
|
||||||
#include "parasite/ble_advertisement_data.h"
|
#include "parasite/ble_advertisement_data.h"
|
||||||
|
|
@ -14,53 +14,44 @@ constexpr int kSensAnalogPin = 4; // AIN2
|
||||||
constexpr int kDischargeEnablePin = 16;
|
constexpr int kDischargeEnablePin = 16;
|
||||||
constexpr double kPWMFrequency = 500000;
|
constexpr double kPWMFrequency = 500000;
|
||||||
|
|
||||||
ble_gap_addr_t kGAPAddr{
|
const parasite::MACAddr kMACAddr = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
|
||||||
1,
|
parasite::BLEAdvertiser advertiser(kMACAddr);
|
||||||
BLE_GAP_ADDR_TYPE_PUBLIC,
|
|
||||||
// This is the "reverse" order in comparison that the colon-separated
|
|
||||||
// human-readable MAC addresses.
|
|
||||||
{0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
|
|
||||||
};
|
|
||||||
|
|
||||||
void setupAdvertising() {
|
void updateAdvertisingData(parasite::BLEAdvertiser *advertiser,
|
||||||
Bluefruit.begin(1, 1);
|
int moisture_level) {
|
||||||
Bluefruit.setName("Parasite");
|
|
||||||
Bluefruit.setAddr(&kGAPAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateAdvertisingData(int moisture_level) {
|
|
||||||
parasite::BLEAdvertisementData data;
|
parasite::BLEAdvertisementData data;
|
||||||
data.SetRawSoilMoisture(moisture_level);
|
data.SetRawSoilMoisture(moisture_level);
|
||||||
Bluefruit.Advertising.stop();
|
|
||||||
Bluefruit.Advertising.clearData();
|
advertiser->SetData(data);
|
||||||
Bluefruit.Advertising.setData(data.GetRawData(), data.GetDataLen());
|
|
||||||
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
|
if (!advertiser->IsRunning()) {
|
||||||
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
|
advertiser->Start();
|
||||||
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
|
|
||||||
pinMode(kLED1Pin, OUTPUT);
|
pinMode(kLED1Pin, OUTPUT);
|
||||||
pinMode(kDischargeEnablePin, OUTPUT);
|
pinMode(kDischargeEnablePin, OUTPUT);
|
||||||
|
|
||||||
|
// Activate the PWM signal.
|
||||||
parasite::SetupSquareWave(kPWMFrequency, kPWMPin);
|
parasite::SetupSquareWave(kPWMFrequency, kPWMPin);
|
||||||
|
|
||||||
|
// Enable fast discharge cycle.
|
||||||
digitalWrite(kDischargeEnablePin, HIGH);
|
digitalWrite(kDischargeEnablePin, HIGH);
|
||||||
|
|
||||||
|
// We setup the analog reference to be VDD. This allows us to cancel out
|
||||||
|
// the effect of the battery discharge across time, since the RC circuit
|
||||||
|
// also depends linearly on VDD.
|
||||||
|
// TODO(rbaron): empirically prove/disprove this.
|
||||||
analogReference(AR_VDD4);
|
analogReference(AR_VDD4);
|
||||||
|
|
||||||
setupAdvertising();
|
|
||||||
|
|
||||||
Serial.println("Will advertise with MAC:");
|
|
||||||
for (const auto byte : kGAPAddr.addr) {
|
|
||||||
Serial.printf("0x%02x ", byte);
|
|
||||||
}
|
|
||||||
Serial.println();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
int sens_val = analogRead(kSensAnalogPin);
|
int sens_val = analogRead(kSensAnalogPin);
|
||||||
Serial.printf("Val: %d\n", sens_val);
|
Serial.printf("Val: %d\n", sens_val);
|
||||||
digitalToggle(kLED1Pin);
|
digitalToggle(kLED1Pin);
|
||||||
updateAdvertisingData(sens_val);
|
updateAdvertisingData(&advertiser, sens_val);
|
||||||
delay(500);
|
delay(500);
|
||||||
}
|
}
|
||||||
Loading…
Add table
Reference in a new issue