button bounce profiler
i'm working on usb macro keyboard project , wanted button bounce handling right. think knowing expect button useful optimally debouncing it.
bounce profiler accumulates bounce recordings repeated button presses , outputs serial csv formatted report can graphed in spreadsheet program.
i'm starting programming please don't hold critique.
*edit: reduced default sample size resolve out of memory bug on uno
*edit: added configuration constant simplify changes input or switch polarity
*edit: found , fixed error in overflow handler (last_run). also moved declarations better spots.
bounce profiler accumulates bounce recordings repeated button presses , outputs serial csv formatted report can graphed in spreadsheet program.
i'm starting programming please don't hold critique.
code: [select]
// configuration values block
const byte test_pin = 5;
const byte pressed_value = 0; //set appropriately account input_pullup or nc switches
const byte test_count = 42; //gather many button presses @ time
const word sample_size = 512; //sample resolution .. requires twice amount of memory (1000 much)
const word sample_millis = 20; //preferred monitoring window in milliseconds (+- 1ms)
const byte clock_mhz = 16; //mcu clock speed , sample code run time ...
const byte sample_clocks = 100; //... used setdelay() calculate required delay between samples
// these arrays accumulate bounce data button repeatedly pressed
byte press_data[sample_size] = {};
byte release_data[sample_size] = {};
word set_delay = 0;
word setdelay(){
unsigned long sm = sample_millis;
unsigned long mh = clock_mhz;
unsigned long ss = sample_size;
unsigned long sc = sample_clocks;
unsigned long sd;
sd = (sm * 1000 * mh - sc * ss) / (ss * mh);
return sd;
}
void setup() {
pinmode(test_pin, input_pullup);
serial.begin(9600);
set_delay = setdelay();
while(!serial.available()); // waits here until something, anything, sent via serial
}
void loop() {
static boolean data_full = false;
static word loop_counter = 1;
unsigned long time_profile;
if (loop_counter == 1){
serial.print("bounce profiler :- press , release button ");
serial.print(test_count);
serial.print(" times gather data.");
}
byte state_previous = !pressed_value;
for (byte i=0; < test_count * 2 && !data_full; i++) {
byte state_initial;
while (state_previous == (state_initial = digitalread(test_pin)));
state_previous = state_initial;
unsigned long time_start = micros();
for (word i=0; < sample_size && !data_full; i++) {
delaymicroseconds(set_delay);
if (digitalread(test_pin) != state_initial) {
if (state_initial ^ pressed_value) {
press_data[i]++;
if (press_data[i] > 254) {
data_full = true;
}
}
else {
release_data[i]++;
if (release_data[i] > 254) {
data_full = true;
}
}
}
}
if (i==2) {
time_profile = micros() - time_start;
}
serial.print('.');
}
serial.println();
serial.print("press bounce on ");
serial.print(sample_millis);
serial.print("ms,");
for (word i=0; < sample_size; i++) {
serial.print(press_data[i]);
serial.print(',');
}
serial.println();
serial.print("release bounce on ");
serial.print(sample_millis);
serial.print("ms,");
for (word i=0; < sample_size; i++) {
serial.print(release_data[i]);
serial.print(',');
}
serial.println();
serial.print("button cycle count,");
serial.println(loop_counter * test_count);
serial.print("profile duration,");
serial.println(sample_millis);
//serial.println(time_profile); //useful debugging setdelay or other timing stuff
serial.print("moment please... ");
delay(3000);
if (data_full == false) {
serial.println("this process can optionally repeated accumulate more sample data.");
loop_counter++;
}
else {
while (serial.read() >= 0);
serial.println("maximum data accumulated. send key reset data , start over.");
while(!serial.available());
for (int i=0; < sample_size; i++) {
press_data[i] = 0;
release_data[i] = 0;
}
loop_counter = 1;
data_full = false;
}
}
*edit: reduced default sample size resolve out of memory bug on uno
*edit: added configuration constant simplify changes input or switch polarity
*edit: found , fixed error in overflow handler (last_run). also moved declarations better spots.
the results attached show short 'make' bounce followed 2ms later larger 'break' bounce. the poles close symmetrical in behaviour. there fair bit of measured noise due hurried connection twisted wire bounce signal seen.
code: [select]
// configuration values block
const byte test_pin = 5;
const boolean two_pole = true; // double size of data set ... reduce sample size
const byte test_pin_2 = 11; // second pin double pole profiling
const byte pressed_value = 0; // set appropriately account input_pullup or nc switches
const byte test_count = 42; // gather many button presses @ time
const word sample_size = 256; // sample resolution .. requires twice amount of memory (1000 much)
const word sample_millis = 20; // preferred monitoring window in milliseconds (+- 1ms)
const byte clock_mhz = 16; // mcu clock speed , sample code run time ...
const byte sample_clocks = 100; // ... used setdelay() calculate required delay between samples
word set_delay;
// array accumulates bounce data button repeatedly pressed
byte sample_data[4][sample_size] = {};
void setup() {
pinmode(test_pin, input_pullup);
pinmode(test_pin_2, input_pullup);
serial.begin(9600);
set_delay = setdelay();
while(!serial.available()); // wait here until something, anything, sent via serial
}
word loop_counter = 1;
void loop() {
static boolean data_full = false;
unsigned long time_profile;
if (loop_counter == 1){
serial.print("bounce profiler :- press , release button ");
serial.print(test_count);
serial.print(" times gather data.");
}
byte button_state = !pressed_value;
for (byte i=0; < test_count * 2 && !data_full; i++) {
while (button_state == digitalread(test_pin) && (!two_pole || button_state != digitalread(test_pin_2)));
button_state = !button_state;
unsigned long time_start = micros();
for (word i=0; < sample_size && !data_full; i++) {
delaymicroseconds(set_delay);
if (digitalread(test_pin) != button_state) {
if (sample_data[button_state ^ pressed_value][i]++ > 253)
data_full = true;
}
if (digitalread(test_pin_2) == button_state) {
if (sample_data[(button_state ^ pressed_value) + 2][i]++ > 253)
data_full = true;
}
}
if (i==2) {
time_profile = micros() - time_start;
}
//serial.print('.'); //visual feedback each button press
}
//serial.println(time_profile); //useful debugging setdelay or other timing stuff
printreport();
serial.println("moment please... ");
delay(3000);
if (data_full == false) {
serial.println("this process can optionally repeated accumulate more sample data.");
loop_counter++;
}
else {
while (serial.read() >= 0);
serial.println("maximum data accumulated. send key reset data , start over.");
while(!serial.available());
for (int i=0; < sample_size; i++) {
sample_data[0][i] = 0;
sample_data[1][i] = 0;
}
loop_counter = 1;
data_full = false;
}
}
word setdelay(){
unsigned long sm = sample_millis;
unsigned long mh = clock_mhz;
unsigned long ss = sample_size;
unsigned long sc = sample_clocks;
unsigned long sd;
sd = (sm * 1000 * mh - sc * ss) / (ss * mh);
return sd;
}
void printreport(){
serial.println();
serial.print("press bounce on ");
serial.print(sample_millis);
serial.print("ms,");
for (word i=0; < sample_size; i++) {
serial.print(sample_data[0][i]);
serial.print(',');
}
serial.println();
serial.print("release bounce on ");
serial.print(sample_millis);
serial.print("ms,");
for (word i=0; < sample_size; i++) {
serial.print(sample_data[1][i]);
serial.print(',');
}
serial.println();
serial.print("pole 2 press bounce on ");
serial.print(sample_millis);
serial.print("ms,");
for (word i=0; < sample_size; i++) {
serial.print(sample_data[2][i]);
serial.print(',');
}
serial.println();
serial.print("pole 2 release bounce on ");
serial.print(sample_millis);
serial.print("ms,");
for (word i=0; < sample_size; i++) {
serial.print(sample_data[3][i]);
serial.print(',');
}
serial.println();
serial.print("button cycle count,");
serial.println(loop_counter * test_count);
serial.print("profile duration,");
serial.println(sample_millis);
}
Arduino Forum > Community > Exhibition / Gallery > button bounce profiler
arduino
Comments
Post a Comment