Mirror of espurna firmware for wireless switches and more
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

167 lines
4.6 KiB

// -----------------------------------------------------------------------------
// Analog Sensor
// Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
//
// Scaling support by Carlos Iván Conde Martín <ivan dot conde at gmail dot com>
// (original sensor was just the analogRead output)
// -----------------------------------------------------------------------------
#pragma once
#include <algorithm>
#include "../espurna.h"
#include "../sensor.h"
#include "BaseSensor.h"
#include "BaseAnalogSensor.h"
class AnalogSensor : public BaseAnalogSensor {
public:
static constexpr int RawBits { 10 };
static constexpr double RawMax { (1 << RawBits) - 1 };
static constexpr double RawMin { 0.0 };
static constexpr size_t SamplesMin { 1 };
static constexpr size_t SamplesMax { 16 };
using Delay = espurna::duration::critical::Microseconds;
static constexpr auto DelayMin = Delay{ 200 };
static constexpr auto DelayMax = Delay::max();
unsigned char id() const override {
return SENSOR_ANALOG_ID;
}
unsigned char count() const override {
return 1;
}
void setDelay(Delay delay) {
_delay = std::clamp(delay, DelayMin, DelayMax);
}
void setDelay(uint16_t delay) {
setDelay(Delay{delay});
}
void setSamples(size_t samples) {
_samples = std::clamp(samples, SamplesMin, SamplesMax);
}
void setFactor(double factor) {
_factor = factor;
}
void setOffset(double offset) {
_offset = offset;
}
// ---------------------------------------------------------------------
size_t getSamples() const {
return _samples;
}
espurna::duration::Microseconds getDelay() const {
return _delay;
}
double getFactor() const {
return _factor;
}
double getOffset() const {
return _offset;
}
// ---------------------------------------------------------------------
// Sensor API
// ---------------------------------------------------------------------
// Initialization method, must be idempotent
void begin() override {
_ready = true;
}
// Descriptive name of the sensor
String description() const override {
return F("ANALOG @ TOUT");
}
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char) const override {
return F("A0");
}
// Type for slot # index
unsigned char type(unsigned char index) const override {
if (index == 0) {
return MAGNITUDE_ANALOG;
}
return MAGNITUDE_NONE;
}
// Current value for slot # index
double value(unsigned char index) override {
if (index == 0) {
return this->analogRead();
}
return 0;
}
double analogRead() const {
return _withFactor(_rawRead());
}
protected:
static unsigned int _rawRead(uint8_t pin, size_t samples, Delay delay) {
// TODO: system_adc_read_fast()? current implementation is using system_adc_read()
// (which is even more sampling on top of ours)
unsigned int last { 0 };
unsigned int result { 0 };
for (size_t sample = 0; sample < samples; ++sample) {
const auto value = ::analogRead(pin);
result = result + value - last;
last = value;
if (sample > 0) {
espurna::time::critical::delay(delay);
yield();
}
}
return result;
}
unsigned int _rawRead() const {
return _rawRead(0, _samples, _delay);
}
double _withFactor(double value) const {
return _factor * value + _offset;
}
double _minWithFactor() const {
return _withFactor(RawMin);
}
double _maxWithFactor() const {
return _withFactor(RawMax);
}
Delay _delay { DelayMin };
size_t _samples { SamplesMin };
double _factor { 1.0 };
double _offset { 0.0 };
};
constexpr double AnalogSensor::RawMin;
constexpr double AnalogSensor::RawMax;
constexpr AnalogSensor::Delay AnalogSensor::DelayMin;
constexpr AnalogSensor::Delay AnalogSensor::DelayMax;