|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Did you know...
|
Serial Wombat Debounce Channel ModeThe Serial Wombat can debounce a digital input. The user supplies a number of frames over which the input must remain the same to be considered valid. This technique also works with some channel modes which output values other than 1 or 0. The source of the signal to be debounced by this mode can be the pin being assigned, or can be the digital input or public data from any other pin. If the assigned pin is not the input source , it can be used to output the debounced signal as a digital or analog output (PWM or driving an off-board D/A or digital pot). The debounced value will be provided as the pin's public data. Message format:
Example:Pin 37 is connected to a cheap pushbutton switch. Study of this switch with an oscilloscope shows that it will "bounce" for up to 15ms when pressed. Configure pin 19 to output the debounced state of this switch, based on a time period of 20ms. 200 19 12 37 0 0x0020 0x55 ; Set pin 19 to debounce mode,
; Based on pin 37's digital input
; With a debounce period of 20ms
; Read pin 16's data (this pin) for position
201 19 12 1 1 0 0x55 0x55 ; Second configuration message, pin 19 to debounce mode
; Digital output,
; Output high when pin 37 is debounced high
; Output low when pin 37 is debounced low
Background:Check out Jack Ganssle's awsome articles on debouncing switches on embedded.com. Debouncing Algorithms (The Serial Wombat uses the Counting Algorithm) Pin Mode Source CodeThe following code is what creates the pin mode for this function inside of the Wombat. You don't need to know this to use the pin mode, but some people find it interesting. See the SDK for some insight into how pin modes work. Hold your mouse over various words and variables for definitions.#ifndef COMPILING_FIRMWARE #include <stdio.h> #endif #include "types.h" #include "utilities.h" #include "global_data.h" #ifdef COMPILING_FIRMWARE #pragma code APPLICATION #pragma romdata APPLICATION_DATA #endif void init_debounce(void) { if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_0) { tp.generic.buffer = vpin_read(); tp.debounce.source = map_pin(rxbuffer[3]); tp.debounce.usepublic = (rxbuffer[4] > 0); tp.debounce.debounceframes = RXBUFFER16(5); tp.debounce.debouncecounter = tp.debounce.debounceframes; tp.debounce.outputmode = 0; if (tp.debounce.source == virtual_pin) { tp.debounce.sourceisvpin = 1; } else { tp.debounce.sourceisvpin = 0; } if (tp.debounce.sourceisvpin) { vpin_input(); } } if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_1) { tp.debounce.outputmode = rxbuffer[3]; tp.debounce.activemode = rxbuffer[4]; tp.debounce.inactivemode = rxbuffer[5]; } } void update_debounce(void) { if (tp.debounce.usepublic) { local_temp16_1.u = get_buffer( tp.debounce.source); } else { if (tp.debounce.sourceisvpin) { local_temp16_1.u = vpin_read(); } else { local_temp16_1.u = (uint16)read_pin(tp.debounce.source); } } if (tp.debounce.previous == local_temp16_1.u) { ++tp.debounce.debouncecounter; } else { tp.debounce.debouncecounter = 0; } if (tp.debounce.debouncecounter >= tp.debounce.debounceframes) { tp.generic.buffer = local_temp16_1.u; tp.debounce.debouncecounter = 0; } tp.debounce.previous = local_temp16_1.u; if (tp.debounce.outputmode == 1) { if (tp.generic.buffer) { vpin_set(tp.debounce.activemode); } else { vpin_set(tp.debounce.inactivemode); } } else if (tp.debounce.outputmode == 2) { vset_pwm(tp.generic.buffer); update_pwm(); } executive_settings.buffer_dirty = 1; } ///////////////////////////////////////////////////////////////////////// // CODE FROM HERE DOWN IS TESTING CODE FOR USE ON PC, not FIRMWARE #ifdef TEST_DEBOUNCE uint8 debounce_frames = 4; #define PIN 33 int test = 1; int run_tests(void); int main (void) { int overall_return = 0; system_init(); debounce_frames = 0; test = 1; rxbuffer[0] = CONFIGURE_CHANNEL_MODE_0; rxbuffer[1] = PIN; rxbuffer[2] = PIN_MODE_DEBOUNCE; rxbuffer[3] = PIN; rxbuffer[4] = 0; //Don't use public rxbuffer[5] = (debounce_frames ) / 256; rxbuffer[6] = (debounce_frames ) % 256; rxbuffer[7] = 0x55; process_rxbuffer(); rxbuffer[0] = CONFIGURE_CHANNEL_MODE_1; rxbuffer[1] = PIN; rxbuffer[2] = PIN_MODE_DEBOUNCE; rxbuffer[3] = 0; //Don't output rxbuffer[4] = 0x55; rxbuffer[5] = 0x55; rxbuffer[6] = 0x55; rxbuffer[7] = 0x55; process_rxbuffer(); overall_return |= run_tests(); test = 2; debounce_frames = 1; rxbuffer[0] = CONFIGURE_CHANNEL_MODE_0; rxbuffer[1] = PIN; rxbuffer[2] = PIN_MODE_DEBOUNCE; rxbuffer[3] = PIN; rxbuffer[4] = 0; //Don't use public rxbuffer[5] = (debounce_frames ) / 256; rxbuffer[6] = (debounce_frames ) % 256; rxbuffer[7] = 0x55; process_rxbuffer(); rxbuffer[0] = CONFIGURE_CHANNEL_MODE_1; rxbuffer[1] = PIN; rxbuffer[2] = PIN_MODE_DEBOUNCE; rxbuffer[3] = 0; //Don't output rxbuffer[4] = 0x55; rxbuffer[5] = 0x55; rxbuffer[6] = 0x55; rxbuffer[7] = 0x55; process_rxbuffer(); overall_return |= run_tests(); if (overall_return == 0) { printf("Passed!\n"); } return (overall_return); } int run_tests() { int i; int same_counter; int last; int temp; int output = 0; int returnval = 0; test_set_pin(map_pin(PIN),0); last = 0; same_counter = 0; for(i = 0; i < 10000 ; ++i) { temp = random(); temp &= 0x00000001; if (temp == last) { ++ same_counter; } else { same_counter = 0; } if (same_counter >= ((debounce_frames ) )) { output = temp; } test_set_pin(map_pin(PIN),temp); process_pins(); // printf ("%d%d%d\n",temp,output,get_buffer(map_pin(PIN))); if (get_buffer(map_pin(PIN) )!= output) { printf ("Error at %d, %d\n",test ,i); returnval = 1; } last = temp; } return (returnval); } #endif |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Copyright Wombat Interface Products, 2005-2008. All Rights Reserved.