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