Author Topic: State Machine for Rotary Encoder AVR ASM  (Read 12031 times)

0 Members and 1 Guest are viewing this topic.

Offline DaveHardyTopic starter

  • Regular Contributor
  • *
  • Posts: 103
State Machine for Rotary Encoder AVR ASM
« on: February 06, 2013, 08:51:39 pm »
I'm interested in creating a state machine in AVR ASM for a project that I am working on.  I understand the theory behind state machines but I have trouble with the actual execution and design of code associated with them.   I've scoured the internet and have found several postings related to Gray Code, etc.  I found this post but I can't figure out how the code works.   

http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html

Can someone help me out with this?  I would like to set up one rotary encoder and turn some leds on and off.  What is the next logical step for me?  I'm fairly good at Assembly but not at C yet. 
 

Offline mazurov

  • Frequent Contributor
  • **
  • Posts: 524
  • Country: us
Re: State Machine for Rotary Encoder AVR ASM
« Reply #1 on: February 06, 2013, 09:07:17 pm »
State machine is too heavy for such a simple task. Take a look at this technique (link below) , it is short and simple enough to re-implement in ASM, even though you won't be able to make it faster or smaller in ASM, for the same reason:

http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino
With sufficient thrust, pigs fly just fine - RFC1925
 

Online bingo600

  • Super Contributor
  • ***
  • Posts: 1970
  • Country: dk
Re: State Machine for Rotary Encoder AVR ASM
« Reply #2 on: February 06, 2013, 09:51:55 pm »
have a look at this german thread (via google xlate) ... 2 pages

peter starts with C , but also have this in avr asm.
http://www.mikrocontroller.net/topic/drehgeber-auslesen?page=1#42046

Another one from same author
http://www.mikrocontroller.net/topic/112603#new

/Bingo
 

Offline croberts

  • Regular Contributor
  • *
  • Posts: 94
  • Country: us
Re: State Machine for Rotary Encoder AVR ASM
« Reply #3 on: February 06, 2013, 10:15:49 pm »
Hello DaveHardy

Please have a look at my post in this same section "A Simple State Machine". I have programmed some fairly complex tasks using this method.

https://www.eevblog.com/forum/microcontrollers/a-simple-state-machine/

 

Offline DaveHardyTopic starter

  • Regular Contributor
  • *
  • Posts: 103
Re: State Machine for Rotary Encoder AVR ASM
« Reply #4 on: February 06, 2013, 10:44:47 pm »
State machine is too heavy for such a simple task. Take a look at this technique (link below) , it is short and simple enough to re-implement in ASM, even though you won't be able to make it faster or smaller in ASM, for the same reason:

http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino

Thank you for this link.  I am studying it right now.   I'm assuming that this is as easy as it gets with rotary encoders.  So there really isn't a way to incorporate one of these into a design without at least 30 lines of complex logic and a data table?  It appears that ASM is almost out of the question.
 

Offline DaveHardyTopic starter

  • Regular Contributor
  • *
  • Posts: 103
Re: State Machine for Rotary Encoder AVR ASM
« Reply #5 on: February 06, 2013, 10:54:13 pm »
Hello DaveHardy

Please have a look at my post in this same section "A Simple State Machine". I have programmed some fairly complex tasks using this method.

https://www.eevblog.com/forum/microcontrollers/a-simple-state-machine/

I looked at it.  The theory was fun.  You've got a nice PIC template. 

I can't figure out how to apply your theory to a rotary encoder though.
 

Offline mazurov

  • Frequent Contributor
  • **
  • Posts: 524
  • Country: us
Re: State Machine for Rotary Encoder AVR ASM
« Reply #6 on: February 06, 2013, 11:15:09 pm »
State machine is too heavy for such a simple task. Take a look at this technique (link below) , it is short and simple enough to re-implement in ASM, even though you won't be able to make it faster or smaller in ASM, for the same reason:

http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino

Thank you for this link.  I am studying it right now.   I'm assuming that this is as easy as it gets with rotary encoders.  So there really isn't a way to incorporate one of these into a design without at least 30 lines of complex logic and a data table?  It appears that ASM is almost out of the question.

Where did you find complex logic? One shift, one OR and a couple of ANDs.

This technique is more clever than it looks. One, there is no branching so the code always takes the same (and very small) amount of time. Second, you don't need to debounce the encoder since any bounce would result in invalid state.

The lookup table is constant so you can place it in the ROM. You don't need 30 lines either - write it in C, compile and look at compiler-generated assembly.

With sufficient thrust, pigs fly just fine - RFC1925
 

Offline DaveHardyTopic starter

  • Regular Contributor
  • *
  • Posts: 103
Re: State Machine for Rotary Encoder AVR ASM
« Reply #7 on: February 07, 2013, 12:35:57 am »
State machine is too heavy for such a simple task. Take a look at this technique (link below) , it is short and simple enough to re-implement in ASM, even though you won't be able to make it faster or smaller in ASM, for the same reason:

http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino

Thank you for this link.  I am studying it right now.   I'm assuming that this is as easy as it gets with rotary encoders.  So there really isn't a way to incorporate one of these into a design without at least 30 lines of complex logic and a data table?  It appears that ASM is almost out of the question.

Where did you find complex logic? One shift, one OR and a couple of ANDs.

This technique is more clever than it looks. One, there is no branching so the code always takes the same (and very small) amount of time. Second, you don't need to debounce the encoder since any bounce would result in invalid state.

The lookup table is constant so you can place it in the ROM. You don't need 30 lines either - write it in C, compile and look at compiler-generated assembly.

I just assumed it would be 30 lines when I converted it to ASM.  I meant complex compared to an ADC read.   Don't worry, It's the best code I've seen after a day on the net.  I'm probably going to use the ISR modification that he posted. 

Thanks again.
 

Offline jeroen74

  • Frequent Contributor
  • **
  • Posts: 396
  • Country: nl
Re: State Machine for Rotary Encoder AVR ASM
« Reply #8 on: February 07, 2013, 01:35:19 pm »
State machine is too heavy for such a simple task. Take a look at this technique (link below) , it is short and simple enough to re-implement in ASM, even though you won't be able to make it faster or smaller in ASM, for the same reason:

http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino

you realize that code is a state machine?
 

Offline mazurov

  • Frequent Contributor
  • **
  • Posts: 524
  • Country: us
Re: State Machine for Rotary Encoder AVR ASM
« Reply #9 on: February 07, 2013, 06:43:47 pm »
State machine is too heavy for such a simple task. Take a look at this technique (link below) , it is short and simple enough to re-implement in ASM, even though you won't be able to make it faster or smaller in ASM, for the same reason:

http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino

you realize that code is a state machine?

No it is not. This is a definition of a state machine -> http://en.wikipedia.org/wiki/Finite-state_machine . According to this, an encoder could be seen as is a state machine. What my code does is it merely tracks this first state machine, you can treat it as a piece of paper  with a Gray code written to it.
With sufficient thrust, pigs fly just fine - RFC1925
 

Offline jeroen74

  • Frequent Contributor
  • **
  • Posts: 396
  • Country: nl
Re: State Machine for Rotary Encoder AVR ASM
« Reply #10 on: February 07, 2013, 07:56:17 pm »
Yes, it is.

If it 'tracks' something it means it has to have a 'state'. The state it transitions to depends on the presented inputs. What you have implemented is just an efficient way to encode a simple state machine, just like the old-school hardware method of a EPROM with some address inputs being the current state remembered in some flipflops, some address lines use as input, and the EPROM data outputs as the output of the state machine and the new state (that get's fed back to the input again).

Even a simple binary counter is basically a state machine.

Your code would not work without the 'static' qualifier. And you could rewrite it as a big if/switch statement.

Here's an excerpt of some code I wrote long ago that basically achieves more or less the same as your code, just written in another way that most people would qualify as a state machine ;) It handles an encoder that goes through the whole cycle per detent.

Code: [Select]
void handle_encoder(void)
{
 if (state==0)
  {
  if (encoder_a) state=1;
  if (encoder_b) state=4;
  }
 else if (state==1)
       {
       if (encoder_b) state=2;
        else if (!encoder_a) state=0;
       }      
 else if (state==2) 
       {
       if (!encoder_a) state=3;
       }         
 else if (state==3)
       {
       if (!encoder_b)
        {
        encoder_flag=2;
        state=0;
        }
       }
 else if (state==4)
       {
       if (encoder_a) state=5;
        else if (!encoder_b) state=0;
       }
 else if (state==5)
       {
       if (!encoder_b) state=6;
       }
 else if (state==6) 
       {
       if (!encoder_a)
        { 
        encoder_flag=1;
        state=0;
        }
       }
 else state=0;
}

It could be rewritten as a table driven state machine and would likely be exactly like your code ;)
 

Offline mazurov

  • Frequent Contributor
  • **
  • Posts: 524
  • Country: us
Re: State Machine for Rotary Encoder AVR ASM
« Reply #11 on: February 07, 2013, 10:57:34 pm »
I suggest reading the Wikipedia article about state machines once again paying particular attention to the phrase "A particular FSM is defined by a list of its states, and the triggering condition for each transition" (it's at the end of the first paragraph).

To make my code a state machine a lookup table needs to be changed to store pointers to functions returning 1, -1, or 0 - this will give it both "state" and "transition" attributes.


With sufficient thrust, pigs fly just fine - RFC1925
 

Offline jeroen74

  • Frequent Contributor
  • **
  • Posts: 396
  • Country: nl
Re: State Machine for Rotary Encoder AVR ASM
« Reply #12 on: February 07, 2013, 11:22:19 pm »
All the concepts of a FSM are in your code, maybe not in plain sight, but they are there ;) The transition attributes are in that table. The state is remembered in the static variable. How you exactly code things is immaterial. Function pointers, table driven, hard coded or some fancy OO method.
 

Offline baljemmett

  • Supporter
  • ****
  • Posts: 665
  • Country: gb
Re: State Machine for Rotary Encoder AVR ASM
« Reply #13 on: February 07, 2013, 11:55:55 pm »
I suggest reading the Wikipedia article about state machines once again paying particular attention to the phrase "A particular FSM is defined by a list of its states, and the triggering condition for each transition" (it's at the end of the first paragraph).

Yes -- defined, not implemented.  You can translate that code into a list of states and triggering conditions trivially, but even if it wasn't implemented in such a direct correspondence to such a list it would still be a FSM.

The definition of your FSM is encapsulated in the enc_states array, with the array index representing the current state (top two bits) and trigger condition (bottom two bits).  Then for each index you can read it as 'from state=(top two bits) with input=(bottom two bits), output=(array entry) and move to state=(bottom two bits)'.  It's an absolutely classic way to implement a FSM (textbook, in fact, and almost certainly literally so.)
 

Offline mazurov

  • Frequent Contributor
  • **
  • Posts: 524
  • Country: us
Re: State Machine for Rotary Encoder AVR ASM
« Reply #14 on: February 08, 2013, 12:49:03 am »
That is one way to interpret the algorithm. However, I think it can more accurately be described as "lookup table with a history". The difference is start state which is necessary in FSM but not necessary in my case - here I initialize old_AB to zero just because I know that this particular encoder reads zero at detent so the first read is always correct.

It's an absolutely classic way to implement a FSM (textbook, in fact, and almost certainly literally so.)

Can you please point me to a particular textbook where I can read this?
With sufficient thrust, pigs fly just fine - RFC1925
 

Offline jeroen74

  • Frequent Contributor
  • **
  • Posts: 396
  • Country: nl
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf