当前位置:网站首页>Esp32 drive encoder -- siq-02fvs3 (vscade + IDF)
Esp32 drive encoder -- siq-02fvs3 (vscade + IDF)
2022-04-23 18:40:00 【Please call me Xiao Peng】
Tips : This blog serves as a learning note , If there are mistakes, I hope to correct them
List of articles
One 、 Encoder Introduction
Encoder is generally divided into hall encoder and grating encoder , The formula I use here SIQ-02FVS3 This mini encoder , and EC11 The driving method is similar , But this encoder is small , But the price is more expensive . The following is the physical picture of the encoder .SIQ-02FVS3 It also has a press button , To achieve multi-function .

So how do we use this encoder , From the given data book, we can see a waveform , We use this waveform to judge whether the encoder rotates and the direction of encoder rotation , It can be seen from the figure that when CW When the direction turns ,A Rising edge ratio of waveform B The rising edge of the waveform is fast , How fast is it , The data book here gives 24±3°, When from CCW The direction of rotation is exactly the opposite at this time ,B The rising edge of phase is faster than A The rising edge of . In this way, the direction of the encoder can be determined by capturing the order of rising edges .

After understanding the working mechanism of the encoder, we can have the following methods to realize the state capture of the encoder , With CW Direction, for example .
- 1、 When detected A At the rising edge of the term , testing B Status of the item , Sure A The rising edge breaks , Detect in interrupt B The level state of .
- 2、 Simultaneous detection A、B The rising edge of the item , Then judge the direction according to the order of rising edges .
- 3、 You can capture an item ( for example A term ) The edge of , And then determine A Get when the first edge of the item breaks B and A Level of item , Capture when the second edge triggers an interrupt B and A Level of item , Based on two captures B and A The value of the term can know the direction of rotation .
Two 、 Hardware design
The hardware design should be noted that if it is detected by interrupt , It's best to use... In hardware 0.1uF Filter capacitor filter , Otherwise, there will be some burrs and starting interruption when rotating , Or use software filtering , But it's more troublesome , Detect the interval time between two rising edges to judge the effective value of receiving and processing interrupt signal .
The following two pictures capture the level at the time of rotation through the logic analyzer , The first one looks good, with obvious interruption , But after zooming in, it is found that there are burrs in the second picture , This is a circuit without hardware filtering .


Schematic diagram

3、 ... and 、 Implementation code
Here I use the third method to capture the encoder state , Plus hardware filtering , At present, it is more accurate to use , Use queues to send data out of interrupts . From the third case, there are two cases of capturing edges , With A Edge break , And then in A Capture in interrupt A、B The state of . Two cases .
CW Direction, for example , First capture A The rising edge of the edge bit of the item , here A = 1,B = 0; Then the second time you have to capture the falling edge ,A = 0,B = 1. If A The first time you don't catch a rising edge at the edge , What is captured is the falling edge , The second time, you must catch the rising edge .CCW The direction is the same , So we can judge these four situations , Don't worry about anything else , This can filter out interference , So as to achieve more accurate control .
Encoder.c file
#include "Encoder.h"
#define ESP_INTR_FLAG_DEFAULT 0
xQueueHandle encoder_gpio_event_queue = NULL; // Encoder queue
static unsigned int Value_count = 0; // State count
static int Encoder_A_Last_Value = 0; // for the first time A Item value
static int Encoder_B_Last_Value = 0; // for the first time B Item value
static int Encoder_A_Value = 0; // The second time A Item value
static int Encoder_B_Value = 0; // The second time B Item value
#define TAG "Encoder"
/***************************************** * @brief GPIO Interrupt handling * @author wsp * @date 2022-2-21 * ***************************************/
static void IRAM_ATTR encoder_gpio_isr_handler(void * arg)
{
uint32_t GPIO_Queue_Data = 0; // Send queue variables
if(Value_count == 0){
// Edge count value , Count the edge value twice
Encoder_A_Last_Value = gpio_get_level(Encoder_A); // Capture A Item value
Encoder_B_Last_Value = gpio_get_level(Encoder_B); // Capture B Item value
Value_count = 1; // Start the first count
}else if(Value_count == 1){
// Complete an edge capture
Encoder_A_Value = gpio_get_level(Encoder_A); // Capture A Item value
Encoder_B_Value = gpio_get_level(Encoder_B); // Capture B Item value
// State judgment processing
if(((Encoder_A_Last_Value == 0 && Encoder_A_Value == 1) && (Encoder_B_Last_Value == 1 && Encoder_B_Value == 0)) || ((Encoder_A_Last_Value == 1 && Encoder_A_Value == 0) && (Encoder_B_Last_Value == 0 && Encoder_B_Value == 1))){
// Clockwise rotation
GPIO_Queue_Data = 1; // The right one
}else if(((Encoder_A_Last_Value == 0 && Encoder_A_Value == 1) && (Encoder_B_Last_Value == 0 && Encoder_B_Value == 1)) || ((Encoder_A_Last_Value == 1 && Encoder_A_Value == 0) && (Encoder_B_Last_Value == 1 && Encoder_B_Value == 0))){
// Counter clockwise rotation
GPIO_Queue_Data = 2; // Second left
}
Encoder_B_Last_Value = 2; // Clear the status value , Not initialized 0 The reason is that the first global initialization is 0, To distinguish
Encoder_A_Last_Value = 2; // Clear the status value
Value_count = 0; // Clear the status value
}
if(GPIO_Queue_Data != 0) // When the state changes Sending queue
xQueueSendFromISR(encoder_gpio_event_queue, &GPIO_Queue_Data, NULL);
}
/***************************************** * @brief Encoder initialization * @author wsp * @date 2022-2-21 * ***************************************/
void Encoder_init(void)
{
gpio_config_t io_conf; // To configure GPIO Structure
io_conf.intr_type = GPIO_INTR_DISABLE; // Do not enable GPIO interrupt
io_conf.mode = GPIO_MODE_INPUT; //GPIO The input mode
io_conf.pull_down_en = 0; // Pull down enable
io_conf.pull_up_en = 1; // Pull up does not enable
io_conf.pin_bit_mask = Encoder_CHB_GPIO_INPUT_PIN_SEL; //GPIO Input pin selection
gpio_config(&io_conf); // To configure IO Parameters
io_conf.intr_type = GPIO_INTR_ANYEDGE; // Edge triggered interrupt
io_conf.pin_bit_mask = Encoder_CHA_GPIO_INPUT_PIN_SEL; //GPIO Input pin selection
gpio_config(&io_conf); // To configure IO Parameters
io_conf.intr_type = GPIO_INTR_DISABLE; // Do not enable GPIO interrupt
io_conf.pin_bit_mask = Encoder_KEY_GPIO_INPUT_PIN_SEL; //GPIO Input pin selection
gpio_config(&io_conf); // To configure IO Parameters
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); // install GPIO Interruption of service
gpio_isr_handler_add(Encoder_A,encoder_gpio_isr_handler,(void * )Encoder_A);// Add interrupt service
encoder_gpio_event_queue = xQueueCreate(1,sizeof(uint32_t)); // Create a queue
}
void Encoder_Test(void)
{
char Capure_Enconder_State = 0;
while(1){
// Get queue information
if (pdTRUE == xQueueReceive(encoder_gpio_event_queue, & Capure_Enconder_State, (portTickType)portMAX_DELAY)){
printf("Capure_Enconder_State:%d\n\r",Capure_Enconder_State);
}
}
}
Encoder.h file
#ifndef _Encoder_H_
#define _Encoder_H_
#include "lvgl/lvgl.h"
#include <stdio.h>
#include "lv_port_indev_Key.h"
#include "lvgl_function.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#include "esp_err.h"
#include "sdkconfig.h"
#define Encoder_A 34 // Encoder channel 1
#define Encoder_B 35 // Encoder channel 2
#define Encoder_K 13 // Encoder key channel
#define Encoder_CHA_GPIO_INPUT_PIN_SEL ((1ULL<<Encoder_A))
#define Encoder_CHB_GPIO_INPUT_PIN_SEL ((1ULL<<Encoder_B))
#define Encoder_KEY_GPIO_INPUT_PIN_SEL ((1ULL<<Encoder_K))
extern xQueueHandle encoder_gpio_event_queue;
void Encoder_init(void);
void Encoder_Test(void);
#endif
main function
void app_main(void)
{
Encoder_init();
Encoder_Test();
}
Four 、 Show results
The final display result is quite accurate , There will be no problems when rotating quickly .

版权声明
本文为[Please call me Xiao Peng]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204210609450036.html
边栏推荐
- ESP32 LVGL8. 1 - input devices (input devices 18)
- Chondroitin sulfate in vitreous
- Multifunctional toolbox wechat applet source code
- In shell programming, the shell file with relative path is referenced
- Analysez l'objet promise avec le noyau dur (Connaissez - vous les sept API communes obligatoires et les sept questions clés?)
- [mathematical modeling] - analytic hierarchy process (AHP)
- 昇腾 AI 开发者创享日全国巡回首站在西安成功举行
- Ionic instruction set order from creation to packaging
- Nacos集群搭建和mysql持久化配置
- Daily CISSP certification common mistakes (April 15, 2022)
猜你喜欢

ESP32 LVGL8. 1 - input devices (input devices 18)

Use bitnami / PostgreSQL repmgr image to quickly set up PostgreSQL ha

使用 bitnami/postgresql-repmgr 镜像快速设置 PostgreSQL HA

硬核解析Promise對象(這七個必會的常用API和七個關鍵問題你都了解嗎?)

STM32学习记录0008——GPIO那些事1

Analysez l'objet promise avec le noyau dur (Connaissez - vous les sept API communes obligatoires et les sept questions clés?)

Druid SQL和Security在美团点评的实践

Halo 开源项目学习(七):缓存机制

Introduction to quantexa CDI syneo platform

ctfshow-web361(SSTI)
随机推荐
Chondroitin sulfate in vitreous
Database computer experiment 4 (data integrity and stored procedure)
Machine learning practice - naive Bayes
Daily network security certification test questions (April 18, 2022)
Nacos作为服务配置中心实战
关于unity文件读取的操作(一)
QT error: no matching member function for call to ‘connect‘
CISSP certified daily knowledge points (April 18, 2022)
Halo open source project learning (VII): caching mechanism
实战业务优化方案总结---主目录---持续更新
ctfshow-web362(SSTI)
[popular science] CRC verification (I) what is CRC verification?
使用 bitnami/postgresql-repmgr 镜像快速设置 PostgreSQL HA
How to virtualize the video frame and background is realized in a few simple steps
ESP32 LVGL8. 1 - arc (arc 19)
Mysqldump backup database
机器学习理论之(8):模型集成 Ensemble Learning
ctfshow-web362(SSTI)
Seata handles distributed transactions
纠结