Some battery saving improvements

Got it working on the nrf52840 breakout board!
This commit is contained in:
rbaron 2021-02-17 22:40:03 +01:00
parent 972f5507f4
commit 5b3c6a471d
4 changed files with 56 additions and 22 deletions

View file

@ -16,20 +16,24 @@ namespace {
constexpr unsigned long kPWMFrequencyPrescale = PWM_PRESCALER_PRESCALER_DIV_1;
} // namespace
void SetupSquareWave(double frequency, int pin_number) {
// In conjunction with the PWM clock frequency, kPWMMaxCounter defines the
SquareWaveGenerator::SquareWaveGenerator(double frequency, int pin_number)
: frequency_(frequency), pin_number_(pin_number) {
// In conjunction with the PWM clock frequency, max_count defines the
// frequency of the square wave.
const int max_count = 16e6 / frequency;
// Since we want a duty cycle of 0.5, we flip the PVM output when the counter
// reaches kPWMMaxCounter / 2;
// reaches max_count / 2;
const int flip_at_count = max_count / 2;
HwPWM0.addPin(pin_number);
HwPWM0.setClockDiv(kPWMFrequencyPrescale);
HwPWM0.setMaxValue(max_count);
HwPWM0.writePin(pin_number, flip_at_count);
HwPWM0.begin();
}
void SquareWaveGenerator::Start() { HwPWM0.begin(); }
void SquareWaveGenerator::Stop() { HwPWM0.stop(); }
} // namespace parasite

View file

@ -10,5 +10,16 @@ namespace parasite {
// and reusable.
void SetupSquareWave(double frequency, int pin_number);
class SquareWaveGenerator {
public:
SquareWaveGenerator(double frequency, int pin_number);
void Start();
void Stop();
private:
double frequency_;
int pin_number_;
};
} // namespace parasite
#endif // _PARASITE_PWM_H_

View file

@ -7,16 +7,19 @@
#include "parasite/ble_advertisement_data.h"
#include "parasite/pwm.h"
constexpr int kLED1Pin = 17;
constexpr int kLED2Pin = 18;
constexpr int kPWMPin = 19;
constexpr int kSoilAnalogPin = 4; // AIN2
constexpr int kBattAnalogPin = 3; // AIN3
constexpr int kDischargeEnablePin = 16;
// variants/feather_nrf52840_express/variant.cpp
constexpr int kLED1Pin = 17; // P0.28
constexpr int kLED2Pin = 18; // P0.02
constexpr int kPWMPin = 33; // 0.09
constexpr int kSoilAnalogPin = 21; // P0.31, AIN7
constexpr int kBattAnalogPin = 15; // P0.05, AIN3
constexpr int kDischargeEnablePin = 16; // P0.30;
constexpr double kPWMFrequency = 500000;
constexpr int kSoilMonitorAirVal = 680;
constexpr int kSoilMonitorWaterVal = 60;
// parasite::SquareWaveGenerator square_wave_generator(kPWMFrequency, kPWMPin);
const parasite::MACAddr kMACAddr = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
parasite::BLEAdvertiser advertiser(kMACAddr);
@ -49,21 +52,31 @@ void updateAdvertisingData(parasite::BLEAdvertiser* advertiser,
* #define configTIMER_TASK_STACK_DEPTH (1024)
*/
void timer_cb(TimerHandle_t timer_handle) {
Serial.println("timer!");
parasite::SquareWaveGenerator square_wave_generator(kPWMFrequency, kPWMPin);
digitalToggle(kLED1Pin);
double battery_voltage = batt_monitor.Read();
Serial.printf("Batt voltage: %f\n", battery_voltage);
square_wave_generator.Start();
digitalWrite(kDischargeEnablePin, HIGH);
parasite::soil_reading_t soil_reading = soil_monitor.Read();
Serial.printf("Moisture val: %d, %f%%\n", soil_reading.raw,
100 * soil_reading.parcent);
// Serial.printf("Moisture val: %d, %f%%\n", soil_reading.raw,
// 100 * soil_reading.parcent);
square_wave_generator.Stop();
digitalWrite(kDischargeEnablePin, LOW);
double battery_voltage = batt_monitor.Read();
// Serial.printf("Batt voltage: %f\n", battery_voltage);
updateAdvertisingData(&advertiser, soil_reading, battery_voltage);
// Keep adversiting for 1 second.
delay(1000);
advertiser.Stop();
// TODO(rbaron): stop PWM; stop everything to save battery.
// TODO(rbaron): what else can we turn off to save battery?
}
void setup() {
@ -71,12 +84,6 @@ void setup() {
pinMode(kLED1Pin, OUTPUT);
pinMode(kDischargeEnablePin, OUTPUT);
// Activate the PWM signal.
parasite::SetupSquareWave(kPWMFrequency, kPWMPin);
// Enable fast discharge cycle.
digitalWrite(kDischargeEnablePin, HIGH);
timer.begin(2000, timer_cb, /*timerID=*/nullptr, /*repeating=*/true);
timer.start();

View file

@ -132,6 +132,18 @@ int sens_val = analogRead(kSensAnalogPin);
```
I'm getting ~680 when in the air; ~65 while holding the sensor. The default resolution is 10 bits, so 1024 -> 3.3V. On the scope, I'm reading the sensor output value to be 2.16V. This matches the value I'm reading: 1024/3.3 * 2.15 = 667. Nice.
The Vcc voltage seems to have an impact though (with nrf52840):
Vcc = 3.5 => Moisture Air: 668; Hand: 65
Vcc = 3.0 => Moisture Air: 640; Hand: 53
Vcc = 2.5 => Moisture Air: 605; Hand: 32
Vcc = 2.0 => Moisture Air: 547; Hand: 23
Possible issues:
* Fast discharging circuit is not fully open with lower voltage?
Possible fixes:
* Hack a software interpolation
# Battery
* [CR2032 datasheet](https://data.energizer.com/pdfs/cr2032.pdf)
* 235 mAh (from 3.0V to 2.0V)