Jump to content

Rotary Encoder and the LP

Recommended Posts

So here is my final (for now) encoder implementation, most reliable 2 pin so far.

1. Increased capacitors to 1uF electrolytic (did try to debounce in software with WDT, but results were not so good.)

2. Encoder A is P1.6, B is P1.7

3. No other pins will use interrupts on P1

4. Only one switch can interrupt at any time, this eliminates most of the problems with rocking and bouncing

5. I really need to get something better than PEC11, about 90-120 deg of the turn produces horrible results.





#include "msp430g2553.h"
//required funct.asm

#define APIN BIT6
#define BPIN BIT7
#define DPINT P1IE = 0;
#define CLRPFG P1IFG = 0;


#define sendData(data) send(data, 1)
#define sendInstruction(data) send(data, 0)
#define initDisplay() sendInstruction(0x3C); sendInstruction(0x0C); clearDisplay(); sendInstruction(0x06)
#define clearDisplay() sendInstruction(0x01); _delay_cycles(2000)

void binaryToASCIIScale(unsigned int n, unsigned char * digits, unsigned int scale);	// asm prototype

unsigned char d[5] = {0,0,0,0,0};

void sendDataArray(unsigned char data[], char length);
void send(unsigned char data, unsigned char registerSelect);

char charIndex = 0;
char valueIndex = 0;

int counter = 500;

void main(void) {



   P2SEL &= ~(BIT6|BIT7);

   P1IES = BPIN;

   _delay_cycles(10000); // delay to allow display to settle down, might not be needed
   P1IE = BPIN;

   while(1) {
       binaryToASCIIScale(counter>>1, d, 0);
       sendDataArray(d, 5);

void sendDataArray(unsigned char data[], char length) {
   charIndex = 0;
   while(charIndex < length) {

void send(unsigned char data, unsigned char registerSelect) {
   P1OUT &= 0xF0;
   P1OUT |= data & 0x0F;
   P2OUT &= 0x0F;
   P2OUT |= data & 0xF0;

// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void) {
   DPINT;                  // disable interrupts on port 1
   if(P1IFG & APIN) { // interrupt came from switch A
       CLRPFG;           // clear interrupt flags
       if((P1IES & APIN) ^ (P1IN & BPIN)) { // XOR IES of A with level of B to determine dir
       } else {
       (P1IN & BPIN) ? (P1IES |= BPIN) : (P1IES &= ~BPIN); // set IES of B based on it's current level, safer than toggling
       P1IE = BPIN; // enable interrupts for switch B
   } else {                  // interrupt came from switch A
       CLRPFG;           // clear interrupt flags
       if((P1IES & BPIN) ^ (P1IN & APIN)) { // XOR IES of B with level of A to determine dir
       } else {
       (P1IN & APIN) ? (P1IES |= APIN) : (P1IES &= ~APIN); // set IES of A based on it's current level
       P1IE = APIN; // enable interrupts for switch A

Link to post
Share on other sites
  • Replies 46
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

Fixed some misalignment and increased pad sizes to be comparable to the LP pads. TI_launchpad.zip

My code (above) do it.   For this I also use RC debouncing. It's work perfectly. A----[ 4k7 ]---------> (internal pullup in MSP430) | | = 10nF

That method looks pretty good too. Another method uses quadrature direction = new A ^ old B = ~(new B ^ old A).   I've used this method in the past. I would poll the encoder at some debounce int

Posted Images

... you've come up with simplest and most elegant solution I've seen.

@Mac: Please don't heap praise on me. I stand on the shoulders of others on this topic. In this case, I located the sample code on this blog entry. I only adapted it to CSS from mspgcc.

Then thank you (Zeke) for passing along a good idea. I implemented it (on the circuit below) by adding a few lines of code to my parallel switch state logic and it's working surprisingly well. Since the switch state logic is designed to filter out all but a "new press" switch state, it works extremely well for filtering out all but a single A or B encoder transition between detents. Check out this excerpt from my test program (a small eight line mux' routine fills the 'swnew' sample variable);


    /*                                                                  *
    *  Mike McLaren's parallel switch state logic (plus encoder)       *
    *                                                                  *
    *  swnew  ___---___---___---___   inverted active lo sample        *
    *  swold  ____---___---___---__   switch state latch               *
    *  swnew  ___-__-__-__-__-__-__   changes, press or release        *
    *  swnew  ___-_____-_____-_____   filter out 'release' bits        *
    *  flags  ____------______-----   toggle flag bits for main        *
    *                                                                  */
       swnew ^= swold;             // changes, press or release
       swold ^= swnew;             // update switch state latch
       swnew &= swold & 0xEF;      // filter out 'release' bits

       if(swnew & 0x20)            // if encoder B "new press"
       { if(swold & 0x10)          // if opposite direction
           swnew ^= 0x30;          // toggle up/dn switch flags
       }                           //
   /*                                                                  *
    *  test for encoder "new press" and bump "count" accordingly       *
    *                                                                  */
       if(swnew & 0x20)            // increment 'count'
         count = _bcd_add_short(count,0x01);
       if(swnew & 0x10)            // decrement 'count'
         count = _bcd_add_short(count,0x99);

I'll post a demo' program in a new thread. That is, if anyone is interested.


Cheerful regards, Mike


Link to post
Share on other sites
  • 1 month later...

Good work to everyone on all of this. I have a question about simplifying the debouncing of a rotary encoder... Could a hardware debouncer such as the Maxim MAX6817 be used to get a pure, clean digital signal from a rotary encoder?



I got a few of the 6817s as samples for a device I'm working on after seeing this post http://dangerousprototypes.com/2011/09/25/debounced-breadboard-keypad/ on dangerousprototypes' blog. Tonight, I was thinking it might work on a rotary as well.

Link to post
Share on other sites

@zeke thanks, man. It should probably work with the MAX6817 then with no issues and less parts count.


@bluehash That's a great idea. I have a few of the MAX6818 octal debouncers as well. Maybe a shield that has a the 6818, one or two rotary encoders and a few buttons all hardware debounced?

---- Honestly, I'm still struggling through making my own schematics and boards in Eagle. Is there a file or post somewhere that contains a blank shield template to start with? I've already created the part and footprint for the 6817 if anyone wants it.

Link to post
Share on other sites

Here's a quick one. Haven't even made a printout to compare to the device, so quick one :). Should be more or less OK, though. Includes the main LaunchPad obstacles on tDocu, might come handy if you plan populating the bottom as well.


I'll eventually add a reduced 5cm x 5cm package as well, as it is a popular cheap option.


(BH: .lbr is still not allowed)


Edit: the current version can be found at viewtopic.php?f=10&t=1684#p11477

Link to post
Share on other sites
design a booster 'shield'. (or Sword as I read it in another thread :lol: )

I thought we called them Payloads :shh:


There are tiny bits of enhancements still to come. I did them already, now waiting for SugarAddict to come around, check them then post the updated lib (I'll probably be fast asleep the whole weekend); you may want to wait for that :).

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...