Hi! I am trying to use a rotary encoder with my STM32F103C8t6 and it works, kinda, almost. I am using this library (the only one i could find with interrupt support for STM32):
https://github.com/enjoyneering/RotaryEncoder The issue i am getting is that in one direction things work pretty well, while in the other direction things barely work at all. If i add the 0.1uF caps to ground as suggested things work a lot worse.
I can get the encoders to work perfectly on a pro micro using Paul Stoffregens "Encoder" library. Any ideas whats going on ? any other libraries i should try instead ?
this is the code I am testing with:
Code: Select all
#include <USBComposite.h>
#include <RotaryEncoder.h>
#define PIN_A PB8 //ky-040 clk pin, add 100nF/0.1uF capacitors between pin & ground!!!
#define PIN_B PB9 //ky-040 dt pin, add 100nF/0.1uF capacitors between pin & ground!!!
#define BUTTON PB15 //ky-040 sw pin, add 100nF/0.1uF capacitors between pin & ground!!!
int16_t position = 0;
RotaryEncoder encoder(PIN_A, PIN_B, BUTTON);
void encoderISR()
{
encoder.readAB();
}
void encoderButtonISR()
{
encoder.readPushButton();
}
USBCompositeSerial CompositeSerial;
void setup() {
attachInterrupt(digitalPinToInterrupt(PIN_A), encoderISR, CHANGE); //call encoderISR() every high->low or low->high changes
attachInterrupt(digitalPinToInterrupt(BUTTON), encoderButtonISR, FALLING); //call pushButtonISR() every high->low changes
USBComposite.setProductId(0x0030);
CompositeSerial.registerComponent();
USBComposite.begin();
}
void loop()
{
if (position != encoder.getPosition())
{
position = encoder.getPosition();
CompositeSerial.println(position);
}
if (encoder.getPushButton() == true) CompositeSerial.println(F("PRESSED")); //(F()) saves string to flash & keeps dynamic memory free
}
by fredbox » Thu Apr 30, 2020 1:42 am
I made an example and tested today on a blue pill using the STM core.
Before running this code, remove any capacitors connected to the encoder pins.
Code: Select all
// test a KY-040 style rotary encoder module on a blue pill board
// uncomment either LIBMAPLE_CORE or STM32DUINO_CORE
//#define LIBMAPLE_CORE
#define STM32DUINO_CORE
// for STM32DUINO_CORE be sure to select a serial port in the tools menu
// define encoder pins
// clock and data are from the silkscreen on the encoder module
#define ENC_CLK PB8
#define ENC_DATA PB9
#define LEDPIN PC13
volatile uint32_t encoderCount;
// call this from the systick interrupt every millisecond
// modified from the original code by dannyf
// at https://github.com/dannyf00/My-MCU-Libraries---2nd-try/blob/master/encoder1.c
void encoder1_read(void)
{
volatile static uint8_t ABs = 0;
ABs = (ABs << 2) & 0x0f; //left 2 bits now contain the previous AB key read-out;
ABs |= (digitalRead(ENC_CLK) << 1) | digitalRead(ENC_DATA);
switch (ABs)
{
case 0x0d:
encoderCount++;
break;
case 0x0e:
encoderCount--;
break;
}
}
void led_blink()
{
static uint8_t led_state = 0;
led_state = 1 - led_state;
digitalWrite(LEDPIN, led_state);
}
void setup()
{
Serial.begin(9600);
pinMode(ENC_CLK, INPUT);
pinMode(ENC_DATA, INPUT);
pinMode(LEDPIN, OUTPUT);
encoderCount = 10000;
#ifdef LIBMAPLE_CORE
systick_attach_callback(&encoder1_read);
#endif
}
void loop()
{
static uint32_t count;
static uint32_t prevCount;
count = encoderCount;
if (count != prevCount)
{
prevCount = count;
Serial.print("Count: ");
Serial.println(count);
led_blink();
}
}
#ifdef STM32DUINO_CORE
void HAL_SYSTICK_Callback()
{
encoder1_read();
}
#endif
Expected results:
At each click of the encoder, the LED toggles.
On the serial port:
Code: Select all
Clockwise:
Count: 10001
Count: 10002
Count: 10003
Count: 10004
Count: 10005
Counterclockwise:
Count: 10004
Count: 10003
Count: 10002
Count: 10001
Count: 10000
This also compiles on the Libmaple core by changing the define but I did not test it.
Go to full post