Serial Wombat
a general-purpose digital interface device for hobbyists, engineers and students

 


Home
Overview
Protocol
Documentation
Channel Modes
Direct Control
Controlled Pin
Raw A/D
A/D Averaging
A/D 1st Order Filtering
Matrix Keypad
Servo Control
Analog Direct
Analog Follow
Rotary Encoder
Debouncing
Counter
Hysteresis
Morse Code
Pulse
Unipolar Stepper
LCD Driver 1
LCD Driver 2
HW Pulse Meas.
2D Lookup
SPI Master
HD44780 Generic
Remote Control
DataLogger
Min-Max
Public Data
Timed IO
Getting Started
Connectivity
Pin Mode SDK Beta
Sample Projects
Downloads
Contact Us
Purchase
Forum

Did you know...

 

Serial Wombat Debounce Channel Mode

The 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:

Data Sent to the Wombat: 200 Pin # 12 Source pin Data source Debounce Period MSB Debounce Period LSB 0x55
Meaning: Configure Pin First message Pin Number to be set to Debounce Mode Debounce Mode The pin providing signal to be debounced (can be pin being assigned to debounce mode) 0: read the current digital input of the pin

1: get the pin's public data (should not be used if source pin is pin being assigned)

Number of frames that the input must remain the same to be passed on as output Unused
This message is echoed back by the Wombat.

 

Data Sent to the Wombat: 201 Pin # 12 Pin Output Mode Active State Inactive State 0x55 0x55
Meaning: Configure Pin Second message Pin Number to be set to Debounce Mode Debounce Mode 0: Do nothing (use this if the assigned pin is also the source)

1: Output a digital signal corresponding to the debounced value

2: Output the debounced value as an analog value

If Pin Output mode == 1, then this state will be driven if the debounced value is greater than zero. Valid values are:
0: Low
1: High
2: Input (high impedance)
If Pin Output mode == 1, then this state will be driven if the debounced value is zero. Valid values are:
0: Low
1: High
2: Input (high impedance)
Unused. Unused.
This message is echoed back by the Wombat.

 

 

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.

Studying switch bounce

Solving bounce with hardware

Debouncing Algorithms (The Serial Wombat uses the Counting Algorithm)

Pin Mode Source Code

The 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.