32bits encoder counter using 16bits TIM and a 32bits software counter

Dependents:   v1 v2 v2bis GestionPixy ... more

Software 32 bits quadrature encoder interface for STM32 targets

This library is designed to help interface quadrature encoders with STM32 targets. The base idea is to use a timer as a counter with several inputs corresponding to the A and B channels of a quadrature encoder. This is easily done with the new STM32 chips from STMicro, and of course with the Nucleo Boards.

Almost every Nucleo Board has 4 or 5 of those interfaces, that can be routed to several pins (I still have to check with every board to this day). This library provides an easy way to use these quadrature decoders, with an added feature : using software 32 bits integers to stock the counter, allowing a more efficient way to use them. In deed, most of the timers of the Nucleo Boards are 16 bits counters, and thus can limit the possibilities in some projects.

The solution provided here uses the update interrupt of the timer, set when the counter over- or underflows, and updates an 32 bits integer accordingly, allowing to track the encoder activity on a range of -(2^31) to (2^31)-1, or -2147483648 to 2147483647.

Plus, this interface allows to use a simple object, easily instantiated.

Example code

#include "mbed.h"
#include "Nucleo_Encoder_16_bits.h"


Nucleo_Encoder_16_bits encoder1(TIM3);

void main (void)
{
    printf("Start of Nucleo Encoder test program");

    for(;;)
    {
        wait(1.0);
        printf("Encoder count : %l", encoder1.GetCounter());
    }
}

Please check the header file corresponding to your target to get the physical pins to which you have to connect the signals (EncoderMspInitxx.h)

Also, please do not mind the name of the files or objects/methods in this library. Some are named "16 bits", but everything runs using 32 bits soft counters, as said above.

Committer:
kkoichy
Date:
Thu May 26 16:21:43 2016 +0000
Revision:
1:e82009479b5c
Parent:
0:ebd170807e11
V1.1 :; - Added one constructor with only one parameter

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kkoichy 0:ebd170807e11 1 #include "mbed.h"
kkoichy 0:ebd170807e11 2 /*
kkoichy 0:ebd170807e11 3 * HAL_TIM_Encoder_MspInit()
kkoichy 0:ebd170807e11 4 * Overrides the __weak function stub in stm32f3xx_hal_tim.h
kkoichy 0:ebd170807e11 5 *
kkoichy 0:ebd170807e11 6 * Edit the below for your preferred pin wiring & pullup/down
kkoichy 0:ebd170807e11 7 * I have encoder common at 3V3, using GPIO_PULLDOWN on inputs.
kkoichy 0:ebd170807e11 8 * Encoder A&B outputs connected directly to GPIOs.
kkoichy 0:ebd170807e11 9 *
kkoichy 0:ebd170807e11 10 * http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00093333.pdf
kkoichy 0:ebd170807e11 11 * http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00097745.pdf
kkoichy 0:ebd170807e11 12 * http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00133117.pdf
kkoichy 0:ebd170807e11 13 * Table 14 has GPIO alternate function pinout mappings.
kkoichy 0:ebd170807e11 14 *
kkoichy 0:ebd170807e11 15 * TIM1_CH1: AF2 @ PC_0, PE_9; AF6 @ PA_8
kkoichy 0:ebd170807e11 16 * TIM1_CH2: AF2 @ PC_1, PE_11; AF6 @ PA_9
kkoichy 0:ebd170807e11 17 *
kkoichy 0:ebd170807e11 18 * (TIM2_CH1: AF1 @ PA_0, PA_5, PA_15; AF2 @ PD_3) TIM2 is the mbed system ticker, so unavailable as encoder.
kkoichy 0:ebd170807e11 19 * (TIM2_CH2: AF1 @ PA_1, PB_3; AF2 @ PD_4)
kkoichy 0:ebd170807e11 20 *
kkoichy 0:ebd170807e11 21 * TIM3_CH1: AF2 @ PA_6, PB_4, PC_6, PE_2 not for F302R8, OK @ F334R8
kkoichy 0:ebd170807e11 22 * TIM3_CH2: AF2 @ PA_4, PA_7, PB_5, PC_7, PE_3
kkoichy 0:ebd170807e11 23 *
kkoichy 0:ebd170807e11 24 * TIM4_CH1: AF2 @ PB_6, PD_12; AF10 @ PA_11 not for both F302R8 & F334R8
kkoichy 0:ebd170807e11 25 * TIM4_CH2: AF2 @ PB_7, PD_13; AF10 @ PA_12
kkoichy 0:ebd170807e11 26 *
kkoichy 0:ebd170807e11 27 */
kkoichy 0:ebd170807e11 28
kkoichy 0:ebd170807e11 29 #ifdef TARGET_STM32F3
kkoichy 0:ebd170807e11 30
kkoichy 0:ebd170807e11 31 void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim)
kkoichy 0:ebd170807e11 32 {
kkoichy 0:ebd170807e11 33 GPIO_InitTypeDef GPIO_InitStruct;
kkoichy 0:ebd170807e11 34
kkoichy 0:ebd170807e11 35 if (htim->Instance == TIM1) { //PA8 PA9 = Nucleo D7 D8
kkoichy 0:ebd170807e11 36 __TIM1_CLK_ENABLE();
kkoichy 0:ebd170807e11 37 __GPIOA_CLK_ENABLE();
kkoichy 0:ebd170807e11 38 GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
kkoichy 0:ebd170807e11 39 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
kkoichy 0:ebd170807e11 40 GPIO_InitStruct.Pull = GPIO_PULLDOWN;
kkoichy 0:ebd170807e11 41 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
kkoichy 0:ebd170807e11 42 GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;
kkoichy 0:ebd170807e11 43 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
kkoichy 0:ebd170807e11 44 }
kkoichy 0:ebd170807e11 45 #if 0 //TIM2 is the mbed system ticker
kkoichy 0:ebd170807e11 46 else if (htim->Instance == TIM2) { //PA0 PA1 = Nucleo A0 A1
kkoichy 0:ebd170807e11 47 __TIM2_CLK_ENABLE();
kkoichy 0:ebd170807e11 48 __GPIOA_CLK_ENABLE();
kkoichy 0:ebd170807e11 49 GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
kkoichy 0:ebd170807e11 50 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
kkoichy 0:ebd170807e11 51 GPIO_InitStruct.Pull = GPIO_PULLDOWN;
kkoichy 0:ebd170807e11 52 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
kkoichy 0:ebd170807e11 53 GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
kkoichy 0:ebd170807e11 54 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
kkoichy 0:ebd170807e11 55 }
kkoichy 0:ebd170807e11 56 #endif
kkoichy 0:ebd170807e11 57 #if defined TARGET_STM32F334R8
kkoichy 0:ebd170807e11 58 else if (htim->Instance == TIM3) { //PB4 PB5 = Nucleo D5 D4
kkoichy 0:ebd170807e11 59 __TIM3_CLK_ENABLE();
kkoichy 0:ebd170807e11 60 __GPIOB_CLK_ENABLE();
kkoichy 0:ebd170807e11 61 GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5;
kkoichy 0:ebd170807e11 62 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
kkoichy 0:ebd170807e11 63 GPIO_InitStruct.Pull = GPIO_PULLDOWN;
kkoichy 0:ebd170807e11 64 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
kkoichy 0:ebd170807e11 65 GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
kkoichy 0:ebd170807e11 66 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
kkoichy 0:ebd170807e11 67 }
kkoichy 0:ebd170807e11 68 #endif
kkoichy 0:ebd170807e11 69 #if 0
kkoichy 0:ebd170807e11 70 else if (htim->Instance == TIM4) { // PB6 PB7 = Nucleo D10 MORPHO_PB7
kkoichy 0:ebd170807e11 71 __TIM4_CLK_ENABLE();
kkoichy 0:ebd170807e11 72 __GPIOB_CLK_ENABLE();
kkoichy 0:ebd170807e11 73 GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
kkoichy 0:ebd170807e11 74 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
kkoichy 0:ebd170807e11 75 GPIO_InitStruct.Pull = GPIO_PULLDOWN;
kkoichy 0:ebd170807e11 76 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
kkoichy 0:ebd170807e11 77 GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;
kkoichy 0:ebd170807e11 78 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
kkoichy 0:ebd170807e11 79 }
kkoichy 0:ebd170807e11 80 #endif
kkoichy 0:ebd170807e11 81 }
kkoichy 0:ebd170807e11 82 #endif