当前位置:网站首页>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 - checkbox (checkbox 23)
- Nacos作为服务注册中心
- 实战业务优化方案总结---主目录---持续更新
- Daily network security certification test questions (April 18, 2022)
- Daily network security certification test questions (April 15, 2022)
- 机器学习理论基础篇--关于机器学习的一些术语
- CISSP certified daily knowledge points (April 12, 2022)
- 14个py小游戏源代码分享第二弹
- 14 py games source code share the second bullet
- ESP32 LVGL8. 1 - label (style 14)
猜你喜欢
On iptables
listener. log
Excel intercept text
Druid SQL和Security在美团点评的实践
ESP32 LVGL8. 1 - input devices (input devices 18)
MVVM模型
The first leg of the national tour of shengteng AI developer creation and enjoyment day was successfully held in Xi'an
[popular science] CRC verification (I) what is CRC verification?
Setting up keil environment of GD single chip microcomputer
根据快递单号查询物流查询更新量
随机推荐
ESP32 LVGL8. 1 - slider slider (slider 22)
Actual combat of Nacos as service configuration center
In win10 system, all programs run as administrator by default
Machine learning theory (7): kernel function kernels -- a way to help SVM realize nonlinear decision boundary
Sentinel service fusing practice (sentinel integration ribbon + openfeign + fallback)
Ctfshow - web362 (ssti)
CISSP certified daily knowledge points (April 14, 2022)
Introduction to quantexa CDI syneo platform
Quantexa CDI(场景决策智能)Syneo平台介绍
深入理解 Golang 中的 new 和 make 是什么, 差异在哪?
迁移学习进阶
Creation and use of QT dynamic link library
Nacos作为服务配置中心实战
CANopen usage method and main parameters of object dictionary
Spark performance optimization guide
Seata处理分布式事务
解决:cnpm : 无法加载文件 ...\cnpm.ps1,因为在此系统上禁止运行脚本
机器学习理论之(7):核函数 Kernels —— 一种帮助 SVM 实现非线性化决策边界的方式
How to virtualize the video frame and background is realized in a few simple steps
Golang 语言实现TCP UDP通信