Archivi categoria: STM32

STM32 Mbed Quadrature encoder input

How to use a quadrature encoder with STM32/Mbed online compiler? This code is how I’ve solved it.

At first, surfing the net searching for a solution I’ve found this forum post: POST

Then I’ve found a working example program HERE

The following code is that one modified by me  for my needs:

  • Obtain a number: positive for clockwise turning, negative for conterclockwise.
  • The number must be proportional of the turning speed
  • I’m using the EC11 encoder that outputs 4 pulses each click

Please nothe that in this code I’ve activated the CPU internal pullups on input lines/pins PC_10 and PC_12. You can change the pins according with your needs and cpu or board used.

#include "mbed.h"

// Pin declarations
DigitalIn phA1(PC_10); // phase a of the quadrature encoder 1
DigitalIn phB1(PC_12); // phase b of the quadrature encoder 1

// Global variables declaration
int encoderClickCountA    = 0; // hold the signed value corresponding to the number of clicks left or right since last sample
int previousEncoderStateA = 0; // keep a record of the last actioned sample state of the Qb+Qa outputs for comparison on each interrupt

// Rotation accumulator for the quadrature encoder
void quadratureDecoder1( void )
{
    int currentEncoderStateA = (phB1.read() << 1) + phA1.read(); // create a two bit value out of phaseB and phaseA
    
    if( currentEncoderStateA == previousEncoderStateA )
    {
        return;
    }
    
    switch( previousEncoderStateA )
    {
        case 0:
            if( currentEncoderStateA == 1 )
            {
                encoderClickCountA--;
            }
            else if( currentEncoderStateA == 2 )
            {
                encoderClickCountA++;
            }
            break;
            
        case 1:
            if( currentEncoderStateA == 3 )
            {        
                encoderClickCountA--;
            }
            else if( currentEncoderStateA == 0 )
            {
                encoderClickCountA++;
            }
            break;
            
        case 2:
            if( currentEncoderStateA == 0 )
            {
                encoderClickCountA--;
            }
            else if( currentEncoderStateA == 3 )
            {
                encoderClickCountA++;
            }
            break;
            
        case 3:
            if( currentEncoderStateA == 2 )
            {
                encoderClickCountA--;
            }
            else if( currentEncoderStateA == 1 )
            {
                encoderClickCountA++;
            }
            break;

        default:
            break;
    }
    previousEncoderStateA = currentEncoderStateA;
}

 // read the rotation accumulator, and once read, reset it to zero
int getClicksA( void )
{
   int res = encoderClickCountA; // this allows the knob to be rotated "while im not looking at it' and still return the    
    encoderClickCountA = 0;      // actual number of clicks that have been rotated since last time I was checking it.
    return res;
}
int main()
{
    Serial pc( USBTX, USBRX );
    pc.baud(115200);
    Ticker sampleTicker;                                // create a timer to sample the encoder
    int    ClicksA;                                     // Click encoder A
    
    phA1.mode(PullUp);
    phB1.mode(PullUp);
    
    sampleTicker.attach_us( &quadratureDecoder1, 1000 ); // make the quadrature decoder function check the knob once every 1000us = 1ms
    
    pc.printf("test started\r\n");
    
    //Loop principale infinito
    while( 1 )
    {
        ClicksA = getClicksA()/4;
        
        if(ClicksA != 0 ) // If there is some movement on encoders I display it
        {
      pc.printf("clicks %d\r\n", ClicksA);
        }
        
    }