Extracts soil reading to SoilMonitor

This commit is contained in:
rbaron 2021-02-14 12:43:00 +01:00
parent 4c30ff3549
commit 9c2d95569d
3 changed files with 104 additions and 27 deletions

View file

@ -0,0 +1,48 @@
#include "parasite/adc.h"
#include <Arduino.h>
#include <algorithm>
namespace parasite {
namespace {
// Resultion in bits. ADC read values will be mapped to [0, 2^reference].
constexpr int kResolution = 10;
/*
* Battery monitoring
*/
// Use the internal 0.6 reference with a gain of 1/2.
// This lets us read values in the range [0, 1.2V].
constexpr eAnalogReference kBattADCReference = AR_INTERNAL_1_2;
constexpr double kMaxVoltage = 1.2;
// How many samples will be averaged out.
constexpr uint32_t kOversampling = 32;
// Voltage divider.
constexpr double kBattDividerR1 = 1470;
constexpr double kBattDividerR2 = 470;
constexpr double kBattDividerFactor =
(kBattDividerR1 + kBattDividerR2) / kBattDividerR2;
} // namespace
double BatteryMonitor::Read() {
analogOversampling(kOversampling);
analogReference(kBattADCReference);
int batt_val = analogRead(pin_);
double v_in = kMaxVoltage * batt_val / (1 << kResolution);
return kBattDividerFactor * v_in;
}
soil_reading_t SoilMonitor::Read() {
analogOversampling(kOversampling);
// Set up 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.
analogReference(AR_VDD4);
int raw = analogRead(pin_);
double percentage =
static_cast<double>(raw - air_val_) / (water_val_ - air_val_);
return {raw, std::max(0.0, std::min(1.0, percentage))};
}
} // namespace parasite

View file

@ -0,0 +1,35 @@
#ifndef _PARASITE_ADC_H_
#define _PARASITE_ADC_H_
namespace parasite {
class BatteryMonitor {
public:
explicit BatteryMonitor(int pin) : pin_(pin) {}
double Read();
private:
const int pin_;
};
struct soil_reading_t {
int raw;
double parcent;
};
class SoilMonitor {
public:
explicit SoilMonitor(int air_val, int water_val, int pin)
: air_val_(air_val), water_val_(water_val), pin_(pin) {}
soil_reading_t Read();
private:
// Referencce values for estimating the soil moisture percentage.
const int air_val_, water_val_;
// Pin the analog signal is connected to.
const int pin_;
};
} // namespace parasite
#endif // _PARASITE_ADC_H_

View file

@ -1,8 +1,8 @@
#include <Arduino.h>
#include <cstring>
#include <vector>
#include "parasite/adc.h"
#include "parasite/ble.h"
#include "parasite/ble_advertisement_data.h"
#include "parasite/pwm.h"
@ -10,22 +10,25 @@
constexpr int kLED1Pin = 17;
constexpr int kLED2Pin = 18;
constexpr int kPWMPin = 19;
constexpr int kSensAnalogPin = 4; // AIN2
constexpr int kSoilAnalogPin = 4; // AIN2
constexpr int kBattAnalogPin = 3; // AIN3
constexpr int kDischargeEnablePin = 16;
constexpr double kPWMFrequency = 500000;
constexpr double kBattDividerR1 = 1470;
constexpr double kBattDividerR2 = 470;
constexpr double kBattDividerFactor = (kBattDividerR1 + kBattDividerR2) / kBattDividerR2;
constexpr int kSoilMonitorAirVal = 680;
constexpr int kSoilMonitorWaterVal = 60;
const parasite::MACAddr kMACAddr = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
parasite::BLEAdvertiser advertiser(kMACAddr);
void updateAdvertisingData(parasite::BLEAdvertiser *advertiser,
int moisture_level) {
parasite::BatteryMonitor batt_monitor(kBattAnalogPin);
parasite::SoilMonitor soil_monitor(kSoilMonitorAirVal, kSoilMonitorWaterVal,
kSoilAnalogPin);
void updateAdvertisingData(parasite::BLEAdvertiser* advertiser,
const parasite::soil_reading_t& soil_reading) {
parasite::BLEAdvertisementData data;
data.SetRawSoilMoisture(moisture_level);
data.SetRawSoilMoisture(soil_reading.raw);
advertiser->SetData(data);
@ -48,25 +51,16 @@ void setup() {
}
void loop() {
// With a gain of 1/2, we can read the range of [0, 1.2V].
// I'm using a voltage divider with R1 = 1470, R2 470, so
// We can read 0 - ~5V.
// This seems to be working okay, but I need to investigate if making it
// stiffer (lower R1 and R2) work better.
analogOversampling(32);
analogReference(AR_INTERNAL_1_2);
int batt_val = analogRead(kBattAnalogPin);
double v_in = 1.2 * batt_val / (1<<10);
double batt_voltage = kBattDividerFactor * v_in;
Serial.printf("Batt val: %d, voltage: %f\n", batt_val, batt_voltage);
double batt_voltage = batt_monitor.Read();
Serial.printf("Batt voltage: %f\n", batt_voltage);
parasite::soil_reading_t soil_reading = soil_monitor.Read();
Serial.printf("Moisture val: %d, %f%%\n", soil_reading.raw,
100 * soil_reading.parcent);
// 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.
analogReference(AR_VDD4);
int sens_val = analogRead(kSensAnalogPin);
// Serial.printf("Moisture val: %d\n", sens_val);
digitalToggle(kLED1Pin);
updateAdvertisingData(&advertiser, sens_val);
updateAdvertisingData(&advertiser, soil_reading);
delay(500);
}