Compare commits

...

4 Commits
v0.1 ... main

Author SHA1 Message Date
485f7c3b09 removed .vscode folder 2024-12-08 19:14:54 +01:00
a686daaa44 modified: .gitignore 2024-12-08 19:11:36 +01:00
f1629b7327 added limit to maximum value of button
added basic LED support
2024-12-08 19:10:39 +01:00
e27bc0d3e0 Added threshold for activation point of buttons
Added filters for smoothing results of sensors
2024-09-05 03:17:57 +02:00
5 changed files with 103 additions and 126 deletions

5
.gitignore vendored
View File

@ -1,5 +1,2 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
.vscode

View File

@ -1,10 +0,0 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

78
.vscode/settings.json vendored
View File

@ -1,78 +0,0 @@
{
"files.associations": {
"optional": "cpp",
"istream": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"system_error": "cpp",
"array": "cpp",
"functional": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"*.tcc": "cpp",
"chrono": "cpp",
"ctime": "cpp",
"iomanip": "cpp",
"limits": "cpp",
"numeric": "cpp",
"streambuf": "cpp"
},
"C_Cpp_Runner.cCompilerPath": "gcc",
"C_Cpp_Runner.cppCompilerPath": "g++",
"C_Cpp_Runner.debuggerPath": "gdb",
"C_Cpp_Runner.cStandard": "",
"C_Cpp_Runner.cppStandard": "",
"C_Cpp_Runner.msvcBatchPath": "",
"C_Cpp_Runner.useMsvc": false,
"C_Cpp_Runner.warnings": [
"-Wall",
"-Wextra",
"-Wpedantic",
"-Wshadow",
"-Wformat=2",
"-Wcast-align",
"-Wconversion",
"-Wsign-conversion",
"-Wnull-dereference"
],
"C_Cpp_Runner.msvcWarnings": [
"/W4",
"/permissive-",
"/w14242",
"/w14287",
"/w14296",
"/w14311",
"/w14826",
"/w44062",
"/w44242",
"/w14905",
"/w14906",
"/w14263",
"/w44265",
"/w14928"
],
"C_Cpp_Runner.enableWarnings": true,
"C_Cpp_Runner.warningsAsError": false,
"C_Cpp_Runner.compilerArgs": [],
"C_Cpp_Runner.linkerArgs": [],
"C_Cpp_Runner.includePaths": [],
"C_Cpp_Runner.includeSearch": [
"*",
"**/*"
],
"C_Cpp_Runner.excludeSearch": [
"**/build",
"**/build/**",
"**/.*",
"**/.*/**",
"**/.vscode",
"**/.vscode/**"
],
"C_Cpp_Runner.useAddressSanitizer": false,
"C_Cpp_Runner.useUndefinedSanitizer": false,
"C_Cpp_Runner.useLeakSanitizer": false,
"C_Cpp_Runner.showCompilationTime": false,
"C_Cpp_Runner.useLinkTimeOptimization": false,
"C_Cpp_Runner.msvcSecureNoWarnings": false
}

View File

@ -13,4 +13,5 @@ platform = raspberrypi
board = adafruit_kb2040
framework = arduino
upload_protocol = picotool
monitor_speed = 115200
monitor_speed = 115200
lib_deps = fastled/FastLED@^3.9.4

View File

@ -2,27 +2,45 @@
#include <pico.h>
#include <hardware/pwm.h>
#include <Keyboard.h>
#include <FastLED.h>
#define PORT 2
#define PORT2 3
#define THRESHOLD 10
#define LEDPORT 5
CRGB leds[2];
class HallButton
{
public:
uint64_t firstPulseStart;
uint64_t firstPulseLength;
bool isDataReadyToRead;
uint8_t counter = 0;
uint64_t firstPulseLength[3]; // value of button
int64_t value;
uint64_t _median;
int64_t maxValue;
bool isFirstClick = true;
bool isDataReadyToRead = false;
bool isButtonPressed = false;
uint64_t nextTogglePoint = 0; // value when to toggle state of button
size_t ledId;
HallButton(uint8_t gpioNum, char buttonOnKeyboard)
HallButton(uint8_t gpioNum, char buttonOnKeyboard, size_t ledId)
{
this->gpioNum = gpioNum;
this->buttonOnKeyboard = buttonOnKeyboard;
this->ledId = ledId;
}
void HandleISR(bool gpioState, uint64_t currentTime)
{
if (gpioState)
{
firstPulseLength = currentTime - firstPulseStart;
firstPulseLength[counter] = currentTime - firstPulseStart;
isDataReadyToRead = true;
if (++counter >= 3)
counter = 0;
}
else
{
@ -31,24 +49,84 @@ public:
}
void HandleButton()
{
if (!buttonPressed && firstPulseLength > 310)
if (!isDataReadyToRead)
return;
_median = median(firstPulseLength[0], firstPulseLength[1], firstPulseLength[2]);
value = filtered((float)_median);
if (value > maxValue)
if (isFirstClick)
maxValue = value;
else
value = maxValue;
if (isButtonPressed)
{
Keyboard.press(buttonOnKeyboard);
buttonPressed = true;
if (value < nextTogglePoint)
{
Release();
if (isFirstClick)
isFirstClick = false;
}
if ((int64_t)value - (int64_t)nextTogglePoint > THRESHOLD)
nextTogglePoint = value - THRESHOLD;
}
else if (buttonPressed && firstPulseLength < 300)
else
{
Keyboard.release(buttonOnKeyboard);
buttonPressed = false;
if (value >= nextTogglePoint)
{
Press();
}
if ((int64_t)nextTogglePoint - (int64_t)value > THRESHOLD)
nextTogglePoint = value + THRESHOLD;
}
isDataReadyToRead = false;
}
uint64_t median(uint64_t a, uint64_t b, uint64_t c)
{
return (a < b) ? ((b < c) ? b : ((c < a) ? a : c)) : ((a < c) ? a : ((c < b) ? b : c));
}
float filtered(float value)
{
float _kalman_gain, _current_estimate;
_kalman_gain = _err_estimate / (_err_estimate + _err_measure);
_current_estimate = _last_estimate + _kalman_gain * (value - _last_estimate);
_err_estimate = (1.0 - _kalman_gain) * _err_estimate + fabs(_last_estimate - _current_estimate) * _q;
_last_estimate = _current_estimate;
return _current_estimate;
}
private:
bool buttonPressed;
float _err_measure = 15;
float _err_estimate = 15;
float _q = 0.1;
float _last_estimate = 0.0;
uint8_t gpioNum;
char buttonOnKeyboard;
void Press()
{
if (isButtonPressed)
return;
Keyboard.press(buttonOnKeyboard);
isButtonPressed = true;
LEDTick(isButtonPressed, ledId);
}
void Release()
{
if (!isButtonPressed)
return;
Keyboard.release(buttonOnKeyboard);
isButtonPressed = false;
LEDTick(isButtonPressed, ledId);
}
static void LEDTick(bool status, size_t ledId)
{
leds[ledId] = status ? CRGB::Red : CRGB::Black;
FastLED.show();
}
};
HallButton btn[2] = {HallButton(PORT, 't'), HallButton(PORT2, 'y')};
HallButton btn[2] = {HallButton(PORT, 't', 1), HallButton(PORT2, 'y', 0)};
void isr(uint gpio, uint32_t events)
{
uint64_t currentTime = time_us_64();
@ -66,8 +144,6 @@ void isr(uint gpio, uint32_t events)
void setup()
{
Keyboard.begin();
Serial.begin(115200);
gpio_init(PORT);
gpio_set_dir(PORT, false);
gpio_pull_up(PORT);
@ -76,29 +152,20 @@ void setup()
gpio_set_dir(PORT2, false);
gpio_pull_up(PORT2);
gpio_set_irq_enabled_with_callback(PORT2, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, isr);
// Serial.begin(9600);
Keyboard.begin();
FastLED.addLeds<NEOPIXEL, LEDPORT>(leds, 2);
}
#define printf Serial.printf
byte counter = 0;
void printDebugInfo()
{
if (counter < 1 && btn[0].isDataReadyToRead)
static uint32_t lastTime = 0;
uint32_t time = millis();
if (time - lastTime >= 1)
{
btn[0].isDataReadyToRead = false;
printf("BTN1: %lu", btn[0].firstPulseLength);
counter++;
}
if (btn[1].isDataReadyToRead)
{
btn[1].isDataReadyToRead = false;
if (counter > 0)
printf("\t");
printf("BTN2: %lu", btn[1].firstPulseLength);
counter++;
}
if (counter > 1)
{
printf("\n");
counter = 0;
Serial.printf("%d,%d,%llu,%llu,%i,", btn[0].isFirstClick, btn[0].maxValue, btn[0].value, btn[0].nextTogglePoint, btn[0].isButtonPressed);
Serial.printf("%d,%d,%llu,%llu,%i\n", btn[1].isFirstClick, btn[1].maxValue, btn[1].value, btn[1].nextTogglePoint, btn[1].isButtonPressed);
lastTime = time;
}
}
void loop()