145 lines
3.9 KiB
C++
145 lines
3.9 KiB
C++
#include "Arduino.h"
|
|
#include "NoiselessTouchESP32.h"
|
|
|
|
#define struct_member_size(type, member) sizeof(((type *)0)->member)
|
|
|
|
NoiselessTouchESP32::NoiselessTouchESP32(uint8_t pin) {
|
|
NoiselessTouchESP32(pin, 6, 3);
|
|
}
|
|
|
|
NoiselessTouchESP32::NoiselessTouchESP32(uint8_t pin, uint8_t history_length, uint8_t hysteresis) {
|
|
Touchdata touch = {
|
|
pin : pin,
|
|
history : { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
hist_len : _max(_min((uint8_t)struct_member_size(Touchdata, history), history_length), 1),
|
|
hist_cur : 0,
|
|
hysteresis : _max(_min(hysteresis, 63), 1),
|
|
last : 0,
|
|
last_event : 0,
|
|
last_event_ms : 0
|
|
};
|
|
_data = touch;
|
|
for( _data.hist_cur = 0; _data.hist_cur < _data.hist_len; _data.hist_cur++ ) {
|
|
_data.history[_data.hist_cur] = touchRead(_data.pin);
|
|
}
|
|
_data.last = value_from_history();
|
|
}
|
|
|
|
int NoiselessTouchESP32::value_from_history() {
|
|
uint8_t minimum = _data.history[0];
|
|
uint8_t maximum = _data.history[0];
|
|
uint8_t mean = 0;
|
|
uint32_t sum = 0;
|
|
for( int i = 0; i < _data.hist_len; i++) {
|
|
minimum = _min(minimum, _data.history[i]);
|
|
maximum = _max(maximum, _data.history[i]);
|
|
sum += _data.history[i];
|
|
}
|
|
mean = sum / _data.hist_len;
|
|
//Serial.printf("mean: %d\n", mean);
|
|
while( mean - minimum > _data.hysteresis || maximum - mean > _data.hysteresis ) {
|
|
//Serial.printf("abs(%d - %d) = %d\n", maximum, minimum, abs(maximum - minimum));
|
|
uint8_t ldelta = abs(mean - minimum);
|
|
uint8_t udelta = abs(maximum - mean);
|
|
uint8_t lbound = minimum + (ldelta/2);
|
|
uint8_t ubound = maximum - (udelta/2);
|
|
if( ldelta < udelta ) {
|
|
lbound = minimum;
|
|
} else {
|
|
ubound = maximum;
|
|
}
|
|
//Serial.printf("Min: %d, Lower: %d, Mean: %d, Upper: %d, Max: %d\n", minimum, lbound, mean, ubound, maximum);
|
|
sum = 0;
|
|
uint8_t count = 0;
|
|
minimum = ubound;
|
|
maximum = lbound;
|
|
for( int i = 0; i < _data.hist_len; i++) {
|
|
if( lbound <= _data.history[i] && _data.history[i] <= ubound ) {
|
|
minimum = _min(minimum, _data.history[i]);
|
|
maximum = _max(maximum, _data.history[i]);
|
|
sum += _data.history[i];
|
|
count++;
|
|
}
|
|
}
|
|
if(count == 0) {
|
|
return mean;
|
|
}
|
|
mean = sum/count;
|
|
}
|
|
return mean;
|
|
}
|
|
|
|
int NoiselessTouchESP32::read_raw_mean() {
|
|
_data.hist_cur = (_data.hist_cur + 1) % _data.hist_len;
|
|
_data.history[_data.hist_cur] = touchRead(_data.pin);
|
|
return value_from_history();
|
|
}
|
|
|
|
int NoiselessTouchESP32::read_with_hysteresis() {
|
|
int val = read_raw_mean();
|
|
//Serial.printf("last: %d, hysteresis: %d, new value: %d\n", _data.last, _data.hysteresis, val);
|
|
if( val < _data.last - _data.hysteresis || _data.last + _data.hysteresis < val ) {
|
|
_data.last = val;
|
|
}
|
|
return _data.last;
|
|
}
|
|
|
|
int NoiselessTouchESP32::last_value() {
|
|
return _data.last;
|
|
}
|
|
|
|
int NoiselessTouchESP32::changed() {
|
|
int last = _data.last;
|
|
int val = read_with_hysteresis();
|
|
if( val > last ) {
|
|
_data.last_event = -1;
|
|
_data.last_event_ms = millis();
|
|
return -1;
|
|
}
|
|
if( val < last ) {
|
|
_data.last_event = 1;
|
|
_data.last_event_ms = millis();
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool NoiselessTouchESP32::touched() {
|
|
int last = _data.last;
|
|
int val = read_with_hysteresis();
|
|
if( val > last ) {
|
|
if( millis()-_data.last_event_ms < 5000 && _data.last_event == -1 ) {
|
|
return false;
|
|
}
|
|
_data.last_event = -1;
|
|
_data.last_event_ms = millis();
|
|
return false;
|
|
}
|
|
if( val < last ) {
|
|
if( millis()-_data.last_event_ms < 5000 && _data.last_event == 1 ) {
|
|
return false;
|
|
}
|
|
_data.last_event = 1;
|
|
_data.last_event_ms = millis();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool NoiselessTouchESP32::touching() {
|
|
int last = _data.last;
|
|
int val = read_with_hysteresis();
|
|
if( val > last ) {
|
|
_data.last_event = -1;
|
|
_data.last_event_ms = millis();
|
|
return false;
|
|
}
|
|
if( val < last ) {
|
|
_data.last_event = 1;
|
|
_data.last_event_ms = millis();
|
|
return true;
|
|
}
|
|
return _data.last_event == 1;
|
|
}
|
|
|