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 Transition Counter Mode

The Serial Wombat can count transitions on a pin. It can increment a counter on low-to-high, high-to-low, or both transitions. Software debouncing is optional to quiet down noisy sources like mechanical switches. The user can configure a maximum value, and if the counter rolls over to zero, or stays at maximum. The count is put in the pin's public data buffer.

This mode is useful for a variety of things, such as counting the number of button presses by a user. By allowing the Wombat to keep count, the host doesn't have to constantly poll the state of the pin.

Note that transitions which occur faster than the frame frequency may be missed.

Faster pulse counts for measurement of very fast events can be acheived with the hardware pulse measurement mode on capable pins.

Message format:

Data Sent to the Wombat: 200 Pin # 13 Debounce frames MSB Debounce frames LSB Transition type: Maximum MSB Maximum LSB
Meaning: Configure Pin First message Pin Number to be set to Counter Counter A transition must differ from the current state for this many frames in order to be detected 0: Count Low to High Transitions
1: Count High to low Transitions
2: Count both transitions.

Add 16 (0x10) to the value if the counter should NOT roll over after maximum.

The maximum value the counter can attain. Depending on the value of byte 5, the counter will either stop at this value, or roll over to zero.
This message is echoed back by the Wombat.

 

 

Example:

Pin 37 is tied to ground through a push-button switch. Internal pull-up resistors are enabled. When the button is pressed, it will transition from high to low. Configure channel 37 to count button presses. Require the switch to maintain a value for 30 frames (assume 1ms per frame) to debounce this value. Allow a maximum value of 65535, and stop rollover.

200 37 13 0x001E 0x111 0xFFFF ; Set pin 37 to counter mode,
                           ; 30 frame debounce (0x01E)
                           ; High to Low transitions, no rollover (0x11)
                           ; Maximum of 65535

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"
#pragma code APPLICATION
#pragma romdata APPLICATION_DATA


// rxbuffer[2] == INPUT_TRANSITION_COUNTER
// rxbuffer[3] == debounce frames high
// rxbuffer[4] == debounce frames low
// rxbuffer[5] == 0 = Count Transition high to low
//                1 = Count Transition low to high
//                2 = Count both transitions
// rxbuffer[5]   0x10 = prevent rollover
// rxbuffer[6,7]  max value

void init_counter(void)
{
        vpin_input();
        txbuffer[3] = HIGH_BYTE_16(tp.generic.buffer);
        txbuffer[4] = LOW_BYTE_16(tp.generic.buffer);
        tp.generic.buffer = 0;
        ASSIGN_RXBUFFER16(tp.counter.debounceframes,3);
        tp.counter.debouncecounter = 0;
        tp.counter.mode = rxbuffer[5] & 0x0F;
        tp.counter.freeze = ((rxbuffer[5] & 0x10) > 0);
        ASSIGN_RXBUFFER16(tp.counter.max,6);
        tp.counter.previous = vpin_read();
}

void update_counter(void)
{
     //printf("update called for pin %d\n", current_physical_pin);
     local_j = vpin_read();

     if (local_j != tp.counter.previous)
        {
            //Pin does not match last debounced value

            //Update 16 bit counter
            ++tp.counter.debouncecounter;
            tp.counter.increment_temp = 0;
            if (tp.counter.debouncecounter >= tp.counter.debounceframes)
            {
                //A debounced transition has occured.
                //reset counters.
               tp.counter.debouncecounter = 0;
                //Store new debounced value
                tp.counter.previous= local_j;
                //check to see if increment on this transition
                if (local_j == 0 && tp.counter.mode == 1)
                {
                        //printf("detected pin goes low...\n");
                       //Pin went low.  Update if mode == 0;
                       tp.counter.increment_temp = 1;
                }
                else if (local_j == 1 && tp.counter.mode == 0)
                {
                       //Pin went high.  Update if mode == 1;
                        //printf("detected pin goes high...\n");
                       tp.counter.increment_temp = 1;
                }
                else if (tp.counter.mode == 2)
                {
                        //printf("detected pin changed...\n");
                       //Pin changed.  Update if mode == 2;
                       tp.counter.increment_temp = 1;
                }
                if (tp.counter.increment_temp)
                {
                   if (tp.generic.buffer == 65535 && tp.counter.freeze)
                   {
                       // do nothing...
                   }
                   else
                   {
                            ++tp.generic.buffer;
                   }
                   if (tp.generic.buffer > tp.counter.max)
                   {
                           if (tp.counter.freeze)
                           {
                               tp.generic.buffer = tp.counter.max;
                           }
                           else
                           {
                               tp.generic.buffer = 0;
                           }
                   }
                }
            }
        }
        else
        {
                //pin matched last debounce value.  Reset counter.
                tp.counter.debouncecounter = 0;
        }
}



/////////////////////////////////////////////////////////////////////////
//  CODE FROM HERE DOWN IS TESTING CODE FOR USE ON PC, not FIRMWARE

#ifdef TEST_COUNTER
#define NUM_OF_DATA_INDEX 6

// Test 0, ___---___, count every change, 0 debounce
int const test0_data[] = {0,100,
                          1,100,
                          0,100};
//debounce frames, mode, freeze, max, initial_val,result, # of data
int const test0_init[] = {0,2,0,65535,0,2,sizeof(test0_data) / 8 };

// Test 1, _100_-100-_100_, count rising, 0 debounce

int const test1_data[] = {0,100,
                          1,100,
                          0,100};
//debounce frames, mode, freeze, max, result, # of data
int const test1_init[] = {0,1,0,65535,0,1,sizeof(test1_data) / 8 };

// Test 2, _100_-10-_100_, count rising, 10 debounce

int const test2_data[] = {0,100,
                          1,10,
                          0,100};
//debounce frames, mode, freeze, max, result, # of data
int const test2_init[] = {10, //Debounce frames
                        1,   // MODE
                        0, //Freeze
                        65535,//  Max
                        0, //Initial_val
                        1, //EXPECTED result
                        sizeof(test2_data) / 8 };

// Test 3, _100_-9-_100_, count rising, 10 debounce

int const test3_data[] = {0,100,
                          1,9,
                          0,100};
//debounce frames, mode, freeze, max, result, # of data
int const test3_init[] = {10, //Debounce frames
                        1,   // MODE
                        0, //Freeze
                        65535,//  Max
                        0, //Initial_val
                        0, //EXPECTED result
                        sizeof(test3_data) / 8 };
// Test 4, _100_-9-_100_, count falling, 10 debounce

int const test4_data[] = {0,100,
                          1,9,
                          0,100};
//debounce frames, mode, freeze, max, result, # of data
int const test4_init[] = {10, //Debounce frames
                        0,   // MODE
                        0, //Freeze
                        65535,//  Max
                        0, //Initial_val
                        0, //EXPECTED result
                        sizeof(test4_data) / 8 };

// Test 5, _1_-1-_1_-1-, count rising, 0 debounce

int const test5_data[] = {0,1,
                          1,1,
                          0,1,
                          1,1};
//debounce frames, mode, freeze, max, result, # of data
int const test5_init[] = {0, //Debounce frames
                        0,   // MODE
                        0, //Freeze
                        65535,//  Max
                        0, //Initial_val
                        2, //EXPECTED result
                        sizeof(test5_data) / 8 };

// Test 6, _1_-1-_1_-1-, count falling, 0 debounce

int const test6_data[] = {0,1,
                          1,1,
                          0,1,
                          1,1};

int const test6_init[] = {0, //Debounce frames
                        1,   // MODE
                        0, //Freeze
                        65535,//  Max
                        0, //Initial_val
                        1, //EXPECTED result
                        sizeof(test6_data) / 8 };

// Test 7, _1_-1-_1_-1-, count both, 0 debounce

int const test7_data[] = {0,1,
                          1,1,
                          0,1,
                          1,1};

int const test7_init[] = {0, //Debounce frames
                        2,   // MODE
                        0, //Freeze
                        65535,//  Max
                        0, //Initial_val
                        3, //EXPECTED result
                        sizeof(test7_data) / 8 };

// Test 8, _1_-1-_1_-1-, count both, 0 debounce, rollover

int const test8_data[] = {0,1,
                          1,1,
                          0,1,
                          1,1};

int const test8_init[] = {0, //Debounce frames
                        2,   // MODE
                        0, //Freeze
                        65535,//  Max
                        65535, //Initial_val
                        2, //EXPECTED result
                        sizeof(test8_data) / 8 };

// Test 9, _1_-1-_1_-1-, count both, 0 debounce, rollover, freeze

int const test9_data[] = {0,1,
                          1,1,
                          0,1,
                          1,1};

int const test9_init[] = {0, //Debounce frames
                        2,   // MODE
                        1, //Freeze
                        65535,//  Max
                        65534, //Initial_val
                        65535, //EXPECTED result
                        sizeof(test9_data) / 8 };

int const*  test_vectors[]= {test0_init,test0_data,
                             test1_init,test1_data,
                             test2_init,test2_data,
                             test3_init,test3_data,
                             test4_init,test4_data,
                             test5_init,test5_data,
                             test6_init,test6_data,
                             test7_init,test7_data,
                             test8_init,test8_data,
                             test9_init,test9_data
                            };

#define NUMBER_OF_TESTS (sizeof(test_vectors) / 8)
   int data_point;
   int test = 0;
   int iteration = 0;
   int vpin_data_counter = 0;
   int const* vpin_data_vector;
   uint8 test_pin;

int main(void)
{
   int i;
   int const* init_data;
   int data_points;
   int returnval = 0;

   test_pin = 2;
   system_init();

   for (test = 0;test < NUMBER_OF_TESTS; ++test)
   {
      vpin_data_vector = test_vectors[test * 2 + 1];
      vpin_data_counter = 0;
      init_data = test_vectors[test *2];
      data_points = init_data[NUM_OF_DATA_INDEX];
    
      rxbuffer[0] = CONFIGURE_CHANNEL_MODE_0;
      rxbuffer[1] = test_pin;
      rxbuffer[2] = PIN_MODE_COUNTER;

      rxbuffer[3] = init_data[0]/256;
      rxbuffer[4] = init_data[0]%256;

      rxbuffer[5] = init_data[1];
      if (init_data[2])
      {
         rxbuffer[5] |= 0x10;
      }
      rxbuffer[6] = init_data[3]/256;
      rxbuffer[7] = init_data[3]%256;
      set_pin(map_pin(test_pin),vpin_data_vector[0]);

      process_rxbuffer();


      set_buffer(map_pin(test_pin), init_data[4]);
      for (data_point = 0; data_point <  data_points; ++ data_point)
      {
         for (iteration = 0; iteration < vpin_data_vector[data_point * 2 + 1]; ++iteration)
         {
            set_pin(map_pin(test_pin),vpin_data_vector[data_point * 2]);  
                 process_pins();
         }


      }
         if (get_buffer(map_pin(test_pin)) == init_data[5])
         {
            printf ("Test %d passed\n", test);
         }
         else
         {
            printf("Test %d expected %d, got %d\n",test, init_data[5],get_buffer(map_pin(test_pin)) );
            returnval = 1 ;
         }


   }
   return (returnval);
}
#endif
 

Copyright Wombat Interface Products, 2005-2008. All Rights Reserved.