Extracts BLE internals to a BLEAdvertising class

This commit is contained in:
rbaron 2021-02-13 17:11:36 +01:00
parent 8d01cd3b7e
commit 6c4b57f2b0
5 changed files with 89 additions and 35 deletions

View file

@ -2,8 +2,9 @@
A low power soil moisture sensor based on the nRF52840.
# 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
* 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
* Measure current in deep sleep
* 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
# Done
* Implement BLE advertising with moisture
* Implement ADC for the parasitic capacitor; check out air/water range (using protoboard)
* Simple PWM square wave generator
* Hook square wave generator to the protoboard sensor circuit

View file

@ -1 +1,46 @@
#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

View file

@ -1,13 +1,29 @@
#ifndef _PARASITE_BLE_H_
#define _PARASITE_BLE_H_
#include <array>
#include <string>
#include "parasite/ble_advertisement_data.h"
namespace parasite {
using MACAddr = std::array<uint8_t, 6>;
class BLEAdvertiser {
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

View file

@ -8,4 +8,4 @@ void BLEAdvertisementData::SetRawSoilMoisture(int raw_soil_moisture) {
data_[kRawSoilMoistureOffset + 1] = packed_value & 0xff;
}
}
} // namespace parasite

View file

@ -1,7 +1,7 @@
#include <Arduino.h>
#include <bluefruit.h>
#include <cstring>
#include <vector>
#include "parasite/ble.h"
#include "parasite/ble_advertisement_data.h"
@ -14,53 +14,44 @@ constexpr int kSensAnalogPin = 4; // AIN2
constexpr int kDischargeEnablePin = 16;
constexpr double kPWMFrequency = 500000;
ble_gap_addr_t kGAPAddr{
1,
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},
};
const parasite::MACAddr kMACAddr = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
parasite::BLEAdvertiser advertiser(kMACAddr);
void setupAdvertising() {
Bluefruit.begin(1, 1);
Bluefruit.setName("Parasite");
Bluefruit.setAddr(&kGAPAddr);
}
void updateAdvertisingData(int moisture_level) {
void updateAdvertisingData(parasite::BLEAdvertiser *advertiser,
int moisture_level) {
parasite::BLEAdvertisementData data;
data.SetRawSoilMoisture(moisture_level);
Bluefruit.Advertising.stop();
Bluefruit.Advertising.clearData();
Bluefruit.Advertising.setData(data.GetRawData(), data.GetDataLen());
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
advertiser->SetData(data);
if (!advertiser->IsRunning()) {
advertiser->Start();
}
}
void setup() {
Serial.begin(9600);
pinMode(kLED1Pin, OUTPUT);
pinMode(kDischargeEnablePin, OUTPUT);
// Activate the PWM signal.
parasite::SetupSquareWave(kPWMFrequency, kPWMPin);
// Enable fast discharge cycle.
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);
setupAdvertising();
Serial.println("Will advertise with MAC:");
for (const auto byte : kGAPAddr.addr) {
Serial.printf("0x%02x ", byte);
}
Serial.println();
}
void loop() {
int sens_val = analogRead(kSensAnalogPin);
Serial.printf("Val: %d\n", sens_val);
digitalToggle(kLED1Pin);
updateAdvertisingData(sens_val);
updateAdvertisingData(&advertiser, sens_val);
delay(500);
}