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

 

Pulse on Change Channel Mode

Note: The following documentation applies to version 2.0 and up. For previous version documentation, download the appropriate web site image from the download page.

A frequent need when designing a product is to provide user feedback of an event. Common examples are blinking an LED to indicate communications traffic, or powering a tone generator to acknowledge a button press.

The Serial Wombat can generate a short pulse when any pin's public data changes, increases, or decreases, or when any of a variety of system parameters change, increase, or decrease. This frees the host from the chore of sending commands to pulse an output as a result of a change. Pulses can be active high, or active low. As of version 2.0, the pulse function can also set a pin high, low, or input if another pin's public data is equal to an arbitrary value, or not equal to an arbitrary value. By setting the active time to 1 frame and the inactive time to 0 frames the two equality tests can be used to set a pin as long as some public value is/isn't equal to a value.

Message Format:

There are two messages needed to set up a pulse on change pin:

Data Sent to the Wombat: 200 Pin # 0x10 Active Pulse Time Inactive Pulse Time Active State Inactive State Trigger Mode
Meaning: Configure Pin First message The Wombat Pin which will generate the pulse. Channel Mode for Pulse on Change Mode Length in frames of pulse active period Time in frames which must elapse between pulses The pin state while the pulse is active: 0 = low, 1 = high, 2 = Input/High Impedence The pin state while the pulse is inactive: 0 = low, 1 = high, 2 = Input/High Impedence 0 = selected data source changes

1= selected data source increases

2 = Selected data source decreases

3 = Selected data source not equal to some constant

4 = Selected data source equal to some constant

This message is echoed back by the Wombat.

 

Data Sent to the Wombat: 201 Pin # 0x10 Data Source Toggle Compare Value High Compare Value Low Unused
Meaning: Configure Pin Second message The Wombat Pin which will generate the pulse. Channel Mode for Pulse on Change Mode The Public Data Index which is monitored for change If non zero, then the output pin will toggle between active and inactive during the pulse period. Used to generate simple tones. The initial 16 bit value to be compared against in trigger modes 0 through 2, and the fixed value to be compared against in modes 3 and 4.  
This message is echoed back by the Wombat.

Example 1: Blink an LED on Serial Receive

An led is connected to +5 volts through a current limiting resistor, and attached to Wombat Pin 21. Make the LED light for 10 frames when a byte is received.

200 21 16 10 0 0 2 0;  Pulse pin 21 low 10 ms on change, input idle 
201 21 16 246 0 0 0 0x55; Based on rx_interrupts.  No toggle, 0 initial val

Example 2: Configure a rotary encoder and beep on change:

A rotary encoder is connected to pins 36 and 37. A piezo buzzer is attached to pin 20 and ground. Make the buzzer sound for 50 frames (50 ms in default configuration) every time the rotary encoder count changes.

200 36 11 37 0 0 0xFF 0xFF; Rotary encoder on pins 36 and 37, min 0, max 65535
201 36 11 36 0 1 0 0      ; Increment/decrement pin 36's public data by 1 on change
200 20 16 50 0 1 0 0;  Pulse pin 20 high 50 ms on change, low idle 
201 20 16 36 0 0 0 0x55; Based pin 36.  No toggle, 0 initial val

 

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. #include "types.h"
#include "utilities.h"
#include "global_data.h"
#pragma code APPLICATION
#pragma romdata APPLICATION_DATA
//pin_register_t tp;

#define PULSE_STATE_IDLE 0
#define PULSE_STATE_ACTIVE 1
#define PULSE_STATE_DELAY 2

#define PULSE_TRIGGER_CHANGE 0
#define PULSE_TRIGGER_INCREASE 1
#define PULSE_TRIGGER_DECREASE 2
#define PULSE_TRIGGER_NE 3
#define PULSE_TRIGGER_EQ 4

void init_pulse (void)
{
        if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_0)
        {       tp.pulse.activetime = rxbuffer[3];
                tp.pulse.inactivetime = rxbuffer[4];
                tp.pulse.activestate = rxbuffer[5];
                tp.pulse.inactivestate = rxbuffer[6];
                tp.pulse.trigger = rxbuffer[7];
                tp.pulse.commandpin = 255;
                if (rxbuffer[7] == PULSE_TRIGGER_EQ ||
                                rxbuffer[7] == PULSE_TRIGGER_NE)
                {
                                tp.pulse.fixedvalue = 1;
                }
                else
                {
                        tp.pulse.fixedvalue = 0;
                }
              vpin_set(tp.pulse.inactivestate);
        }
       else if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_1)
        {
              tp.pulse.commandpin = map_pin(rxbuffer[3]);
              tp.pulse.toggle = rxbuffer[4];
              tp.pulse.lastval = RXBUFFER16(5);
              tp.generic.buffer = 0;
              tp.pulse.counter = 0;
              tp.pulse.state = PULSE_STATE_IDLE;
              vpin_set(tp.pulse.inactivestate);
        }
        else
        {
                error();
        }
        
}

void update_pulse()
{
       if (tp.pulse.commandpin == 255)
       {
               return;
       }
       tp2.pulse.bufferval = get_buffer(tp.pulse.commandpin);
        
       switch (tp.pulse.state)
       {
               case PULSE_STATE_IDLE:
               {
                       local_j = tp.pulse.trigger;
                       if ( ((local_j == PULSE_TRIGGER_CHANGE || local_j == PULSE_TRIGGER_NE) && tp2.pulse.bufferval != tp.pulse.lastval) ||
                                       (local_j == PULSE_TRIGGER_EQ && tp2.pulse.bufferval == tp.pulse.lastval)||
                            (local_j == PULSE_TRIGGER_INCREASE && tp2.pulse.bufferval > tp.pulse.lastval) ||
                            (local_j == PULSE_TRIGGER_DECREASE && tp2.pulse.bufferval < tp.pulse.lastval)
                          )
                       {
                               tp.pulse.counter = 0;
                                       vpin_set(tp.pulse.activestate);
                               tp.generic.buffer = 1;
                               tp.pulse.state = PULSE_STATE_ACTIVE;
                        }
                       else
                       {
                                       vpin_set(tp.pulse.inactivestate);
                       }

               }
               break;
      
               case PULSE_STATE_ACTIVE:
               {
                       if (tp.pulse.counter == tp.pulse.activetime  )
                       {
                               tp.pulse.counter = 0;
                               if (tp.pulse.inactivetime > 0)
                               {
                                       tp.pulse.state = PULSE_STATE_DELAY;
                                       vpin_set(tp.pulse.inactivestate);
                               }
                               else
                               {
                                       tp.pulse.state = PULSE_STATE_IDLE;
                               }
                            }
                            else
                            {
                                    ++tp.pulse.counter;
                            }
                }
               break;
               case PULSE_STATE_DELAY:
               {
                       if (tp.pulse.counter == tp.pulse.inactivetime  )
                       {
                                       tp.pulse.state = PULSE_STATE_IDLE;
                                       if (!tp.pulse.fixedvalue)
                                       {
                                       tp.pulse.lastval = tp2.pulse.bufferval;
                                       }
                       }
                       else
                       {
                               ++tp.pulse.counter;
                       }
                    }
               break;
               default:
               {
                       tp.pulse.state = PULSE_STATE_IDLE;
                       tp.pulse.counter = 0;
               }
               break;
       }      
       if (!tp.pulse.fixedvalue)
       {
               tp.pulse.lastval = tp2.pulse.bufferval;
       }
       executive_settings.buffer_dirty = 1;
                
                      
                      
}
 

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