First of all, I wanna explain what is my objective and then I'll show my code and the issue i'm having.
In sumary, I need to send a keyboard caracter from ESP32 to my pc when the wire is touched.
For the touch part, I'm not using the ESP32 touch pins beacause they will not be available on the final project. Instead, I'm using an open wire connected to the analog input with a 10k pullup resistor. Every loop, I calculate an average of the last 'N' values, to filter noise.
For the keyboard part, I'm using the BleKeyboard library, witch handles all the BLE communication and the keyboard character codes.
The problem is that it is sending mutiple character per touch. In fact, I discovered the number of caracters sent is exactly the number of values taken on the average calculation (N). I don't understand how 'N' is influencing the keyboard part.
Even when I add a delay after the reading or the caracter sending, it still sends as much caracter as values on the average.
// Evans Picolo
// Asthor Barden
// dec/2022
// Library link : https://github.com/T-vK/ESP32-BLE-Keyboard
// Library
#include <BleKeyboard.h>
// Sensibility setting
#define TOUCH_THRESHOLD 4095
#define RELEASE_THRESHOLD 4094
#define N 3
// Array to save last N values
int series0[N];
// Flag to avoid redundance
bool charSent = false;
// Object to be my ble keyboard
BleKeyboard bleKeyboard;
// ------ SETUP -----------------------------
void setup()
{
// Start ble keyboard
bleKeyboard.begin();
// Start serial communication (for debug)
Serial.begin(9600);
}
// ---- MAIN PROGRAM ----------------------------------
void loop()
{
// Read analog input
int touch0 = analogRead(A0);
// Variable to save average
long average0 = 0;
// Move array values to the right, so the older value is discarded
// Add up all the array values, except for the first position (which will be the new value)
for(int i = N - 1; i > 0; i--)
{
series0[i] = series0[i-1];
average0 += series0[i];
}
// Insert new value in the first position of the array
series0[0] = touch0;
// Add the new value to the sum
average0 += touch0;
// Calculate the average
average0 /= N;
// Send average to serial (debug)
Serial.print(average0);
// Check if there is a bluetooth client connected
if(bleKeyboard.isConnected())
{
// Check if wire was touched
// Average lower than TOUCH_THRESHOLD means touch
if(average0 < TOUCH_THRESHOLD)
{
// Check flag to avoid redundance
if(charSent == false)
{
bleKeyboard.print("A");
Serial.print("\tTOUCH");
charSent == true;
}
}
// Check if wire is not touched anymore
// Value above RELEASE_THRESHOLD means wire released
if(average0 > RELEASE_THRESHOLD)
{
charSent = false;
}
}
// Delay stabilization
delay(10);
Serial.println();
}
I determined the threshold values by watching the serial monitor/plotter. When not touched, average value is precisely 4095. Never changes until the wire is touched.
// Evans Picolo
// Asthor Barden
// dec/2022
// Library link : https://github.com/T-vK/ESP32-BLE-Keyboard
// Library
#include <BleKeyboard.h>
// Sensibility setting
#define TOUCH_THRESHOLD 4095
#define RELEASE_THRESHOLD 4094
#define N 3
// Array to save last N values
int series0[N];
// Flag to avoid redundance
bool charSent = false;
// Object to be my ble keyboard
BleKeyboard bleKeyboard;
// ------ SETUP -----------------------------
void setup()
{
// Start ble keyboard
bleKeyboard.begin();
// Start serial communication (for debug)
Serial.begin(9600);
}
// ---- MAIN PROGRAM ----------------------------------
void loop()
{
static int seriesIndex = 0;
// Read analog input
int touch0 = analogRead(A0);
// Variable to save average
long average0 = 0;
// Insert new value in the next available position of the array
series0[seriesIndex] = touch0;
seriesIndex++;
if (seriesIndex >= N) seriesIndex = 0;
// Add up all the array values
for (int i = 0; i < N; i++)
{
average0 += series0[i];
}
// Calculate the average
average0 /= N;
// Send average to serial (debug)
Serial.print(average0);
// Check if there is a bluetooth client connected
if (bleKeyboard.isConnected())
{
// Check if wire was touched
// Average lower than TOUCH_THRESHOLD means touch
if (average0 < TOUCH_THRESHOLD)
{
// Check flag to avoid redundance
if (charSent == false)
{
bleKeyboard.print("A");
Serial.print("\tTOUCH");
charSent == true;
}
}
// Check if wire is not touched anymore
// Value above RELEASE_THRESHOLD means wire released
if (average0 > RELEASE_THRESHOLD)
{
charSent = false;
}
}
// Delay stabilization
delay(10);
Serial.println();
}
Thanks for the code sample. I did some tests here and it dind't work properly. The average values are extremely near the máximum value, even when the wire is touched. That's why my thresholds values wore so near from each other. Also, it's not reporting any touch on the serial ("on/off"). Here's a pic of the the serial plotter running your code.
I tried different values for the thresholds already. If they are to low, the touch can't be detected. If it's high enough for the touch to be detected, the problem of redunce appears.
The touch pins will not be available because I'm using a third part board powered by ESP32 developed by the company I work for. This board has only two touch, while I need at least five.
Are you sure this will work in every environment? This isn't capacitive touch, it's mains electricity capacitively coupling into the input pin. The performance characteristics thus depend on the electrical environment of the device. With true capacitive touch, the device generates a signal, so there is always a constant sense voltage available. The hardware signal conditioning also screens out interference. Your arrangement has none except your attempt to filter it in software.
At least, run a test program to capture a burst of readings, dump them to a spreadsheet and have a good analysis of it before you decide how to code for it.
Guys, a think you are missing the point. The touch part on my code does work. I've tested it apart from the main code before trying it all together. What I'm failing to do is to ignore redudant readings. I need the code to ignore redundant readings. Like a debug for a button.
Also, I wanted to figure out why the bluetooth keyboard part is redundant, even when the serial monitor indicates only one touch and what it has to do with the number of samples I get for the average.
I feel like I'm realy close to the solution, but missed something. Like a bug or something like.
What is a "redundant reading"? What is a "debug for a button"? What do you mean, "the bluetooth keyboard part is redundant"? Perhaps if we missed the point, it is because it wasn't presented clearly. Your last post didn't help to clarify it.
You say the touch part works. So what exactly is the problem? In detail, please...
The main problem is: esp32 is sending several characters for a single touch. I need it to be exactly one character for one touch.
When i say "redundant reading", I'm refering to reding a touch that was already read. Like it was reading several times the same touch singnal. If I touch the wire and realease it, I keep receiving characters for a while, like I was still touching. It has to stop sending characters as soon as I release the wire.
For "debug for button" i intended to write "debounce". When we press a button, it has a mechanical bouncing that produces several highs and lows utill it stabilizes. There's a plenty of technics to avoid that. I tried to adapt some os them to my case, but didn't solve the problem.
Now, the most interesting part of the problem is that, for some reason, the number of character sent over bluetooth is the same of the number of samples taken for the average calculation. But when i read the code, I don't see any relation with these two numbers. Maybe if I understand this relation, I can find the source of the problem.
Am I misunderstanding your plot? Why are you averaging the readings? It doesn't look like there's any noise at all - or at least not anywhere near enough to interfere with the result when the touch readings are so different from the baseline readings.
Define a touch. Such as how long is a touch period. Say if I touch for 1 milli second that is a touch, if I touch for 1.3 milli seconds that is a single touch, but if I touch for 2 milli seconds that is 2 touches. How long is a single touch supposed to be? Then a debounce or ignore thingy can be had.
And you did read post#13? That this device may work on the bench where the code has been tuned to make it work but move the device to an open field or next to a motor-generator and the device does not work as expected.
Acctualy, there is no noise from the environment. This filter is already a try to "debounce" the touch. Should I remove it and work directly with input values?
Wel, so maybe the problem are the delays? Sloud I try to use millis to check the duration of the touch?
Also, yes, I'm aware that it might not work on every environment. In fact, I'm counting on some eletromagnetic inteference to work (a good dose of inteference on my body does make this tpe of touch work better). But since it's intended to be used on school classes, i believe it won't be a big problem.