RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于Sensor API如何添加增量型旋轉(zhuǎn)編碼器的驅(qū)動(dòng)

ZephyrProject ? 來源:HalfCoder ? 作者:lgl88911 ? 2021-07-28 09:55 ? 次閱讀

增量型旋轉(zhuǎn)編碼器作為輸入器件廣泛用于各種設(shè)備,例如汽車音響的音量調(diào)節(jié),收音機(jī)頻率調(diào)節(jié),示波器上的旋鈕。但遺憾的是在Zephyr中并沒有增量型旋轉(zhuǎn)編碼器的驅(qū)動(dòng),本文將基于現(xiàn)有的Sensor API, 說明如何添加增量型旋轉(zhuǎn)編碼器的驅(qū)動(dòng),本文不對(duì)驅(qū)動(dòng)操作硬件的實(shí)現(xiàn)細(xì)節(jié)進(jìn)行說明。

增量型旋轉(zhuǎn)編碼器硬件要點(diǎn)

本文使用的是KY-040旋轉(zhuǎn)編碼器,詳細(xì)信息見文末參考

button引腳是一個(gè)對(duì)地的開關(guān),按壓時(shí)接地

旋轉(zhuǎn)時(shí)A/B輸出有相差的正交脈沖。

旋轉(zhuǎn)一圈產(chǎn)生固定數(shù)量的脈沖

旋轉(zhuǎn)時(shí)一個(gè)脈沖內(nèi)旋轉(zhuǎn)軸可以有多個(gè)停留位置,例如1,2,4.

驅(qū)動(dòng)

驅(qū)動(dòng)API選擇

比較好的做法是為旋轉(zhuǎn)編碼器抽象新的驅(qū)動(dòng)API,但新的API要進(jìn)入Zephyr的主分支過程是非常漫長的,同時(shí)旋轉(zhuǎn)編碼器抽象API需要涵蓋眾多類型。因此我選用了現(xiàn)有的Senser API來對(duì)增量類型旋轉(zhuǎn)編碼器的API。

增量類型旋轉(zhuǎn)編碼器的按壓就是一個(gè)簡(jiǎn)單的button,用gpio就可以處理,因此旋轉(zhuǎn)編碼器的驅(qū)動(dòng)就只處理旋轉(zhuǎn)。編碼器的旋轉(zhuǎn)理解為是一個(gè)角度的傳感器,正反轉(zhuǎn)為轉(zhuǎn)動(dòng)方向,轉(zhuǎn)動(dòng)的距離就是角度,這里使用sensor API的SENSOR_CHAN_ROTATION來對(duì)其進(jìn)行操控。

設(shè)備樹綁定

設(shè)備樹綁定是對(duì)旋轉(zhuǎn)編碼器的硬件進(jìn)行抽象,一個(gè)增量式旋轉(zhuǎn)編碼器與旋轉(zhuǎn)相關(guān)的的硬件特性有如下信息:

輸入引腳A/B

旋轉(zhuǎn)一圈產(chǎn)生的脈沖

一個(gè)脈沖周期的穩(wěn)妥數(shù)量

創(chuàng)建dts/bindings/sensor/rotary-encoder.yaml內(nèi)容如下

description: |

Sensor driver for the relative-axis rotary encoder

compatible: “rotary-encoder”

properties:

label:

type: string

required: true

a-gpios:

type: phandle-array

required: true

description: A pin for the encoder

b-gpios:

type: phandle-array

required: true

description: B pin for the encoder

ppr:

type: int

description: Pulse Per Revolution

required: false

spp:

type: int

description: |

Number of steps (stable states) per period

1: Full-period mode (default)

2: Half-period mode

4: Quarter-period mode

required: false

驅(qū)動(dòng)代碼

從設(shè)備樹中獲取硬件信息

創(chuàng)建管理數(shù)據(jù)變量和讀取硬件信息

struct encoder_config {

const char *a_label;

const uint8_t a_pin;

const uint8_t a_flags;

const char *b_label;

const uint8_t b_pin;

const uint8_t b_flags;

const uint8_t ppr;

const uint8_t spp;

};

//創(chuàng)建管理數(shù)據(jù)和配置數(shù)據(jù)的宏

#define ENCODER_INST(n)

struct encoder_data encoder_data_##n;

const struct encoder_config encoder_cfg_##n = {

.a_label = DT_INST_GPIO_LABEL(n, a_gpios),

.a_pin = DT_INST_GPIO_PIN(n, a_gpios),

.a_flags = DT_INST_GPIO_FLAGS(n, a_gpios),

.b_label = DT_INST_GPIO_LABEL(n, b_gpios),

.b_pin = DT_INST_GPIO_PIN(n, b_gpios),

.b_flags = DT_INST_GPIO_FLAGS(n, b_gpios),

COND_CODE_0(DT_INST_NODE_HAS_PROP(n, ppr), (1), (DT_INST_PROP(n, ppr))),

COND_CODE_0(DT_INST_NODE_HAS_PROP(n, spp), (SPP_FULL), (DT_INST_PROP(n, spp))),

};

//根據(jù)設(shè)備樹對(duì)node進(jìn)行初始化,會(huì)從設(shè)備樹中讀取硬件信息放在struct encoder_config變量中

DT_INST_FOREACH_STATUS_OKAY(ENCODER_INST)

驅(qū)動(dòng)初始化

在啟動(dòng)的POST_KERNEL階段會(huì)調(diào)用encoder_init對(duì)驅(qū)動(dòng)進(jìn)行初始化

int encoder_init(const struct device *dev)

{

// GPIO的配置

// GPIO中斷安裝

// 旋轉(zhuǎn)編碼器GPIO初始化狀態(tài)讀取

// 驅(qū)動(dòng)初始化狀態(tài)設(shè)置

// 驅(qū)動(dòng)線程創(chuàng)建

// 使能中斷

}

//注冊(cè)驅(qū)動(dòng)

DEVICE_AND_API_INIT(encoder_##n, DT_INST_LABEL(n), encoder_init, &encoder_data_##n, &encoder_cfg_##n,

POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &encoder_driver_api);

驅(qū)動(dòng)流程

旋轉(zhuǎn)編碼器依靠脈沖觸發(fā)GPIO中斷,中斷通知thread進(jìn)行處理

static void encoder_a_gpio_callback(const struct device *dev, struct gpio_callback *cb,

uint32_t pins)

{

struct encoder_data *drv_data = CONTAINER_OF(cb, struct encoder_data, a_gpio_cb);

enable_int(drv_data-》dev, false);

drv_data-》intpin = 0b10;

//通知發(fā)生中斷

k_sem_give(&drv_data-》gpio_sem);

}

static void encoder_b_gpio_callback(const struct device *dev, struct gpio_callback *cb,

uint32_t pins)

{

struct encoder_data *drv_data = CONTAINER_OF(cb, struct encoder_data, b_gpio_cb);

enable_int(drv_data-》dev, false);

drv_data-》intpin = 0b01;

//通知發(fā)生中斷

k_sem_give(&drv_data-》gpio_sem);

}

static void encoder_thread(void *dev_ptr, void *p2, void *p3)

{

while (1) {

//等待中斷通知

k_sem_take(&drv_data-》gpio_sem, K_FOREVER);

//根據(jù)A/B GPIO level情況判斷正反旋轉(zhuǎn)

//更新旋轉(zhuǎn)數(shù)據(jù)

//通過trigger handle通過應(yīng)用層

if (drv_data-》handler) {

drv_data-》handler(dev, drv_data-》trigger);

}

//使能中斷

enable_int(dev, true);

}

}

驅(qū)動(dòng)接口實(shí)現(xiàn)

sensor的接口有5個(gè), 詳細(xì)參考旋轉(zhuǎn)編碼器只用實(shí)現(xiàn)其中的2個(gè)既可以。

旋轉(zhuǎn)編碼器是主動(dòng)輸出型設(shè)備,無需軟件觸發(fā),因此可以不必實(shí)現(xiàn)channel_fetch,只用實(shí)現(xiàn)trigger_set用于注冊(cè)觸發(fā)時(shí)的callback,實(shí)現(xiàn)channel_get用于在callback時(shí)從driver獲取旋轉(zhuǎn)的角度既可以。

12static int encoder_trigger_set(const struct device *dev, const struct sensor_trigger *trig,

sensor_trigger_handler_t handler)

{

struct encoder_data *drv_data = dev-》data;

enable_int(dev, false);

drv_data-》trigger = trig;

drv_data-》handler = handler;

enable_int(dev, true);

return 0;

}

static int encoder_channel_get(const struct device *dev, enum sensor_channel chan,

struct sensor_value *val)

{

struct encoder_data *drv_data = dev-》data;

const struct encoder_config *drv_cfg = dev-》config;

int32_t acc;

if (chan != SENSOR_CHAN_ROTATION) {

return -ENOTSUP;

}

acc = drv_data-》pulses;

val-》val1 = acc * FULL_ANGLE / (drv_cfg-》ppr * drv_cfg-》spp);

val-》val2 = acc * FULL_ANGLE - val-》val1 * (drv_cfg-》ppr * drv_cfg-》spp);

if (val-》val2) {

val-》val2 *= 1000000;

val-》val2 /= (drv_cfg-》ppr * drv_cfg-》spp);

}

return 0;

}

static const struct sensor_driver_api encoder_driver_api = {

.trigger_set = encoder_trigger_set,

.channel_get = encoder_channel_get,

};

驅(qū)動(dòng)使用

添加設(shè)備樹節(jié)點(diǎn)

在板子的dts中添加旋轉(zhuǎn)編碼器的設(shè)備樹節(jié)點(diǎn):

gpio1.22和gpio1.23是旋轉(zhuǎn)編碼器連接旋轉(zhuǎn)編碼器的A/B引腳。旋轉(zhuǎn)編碼器旋轉(zhuǎn)一圈有15個(gè)脈沖,每個(gè)脈沖下有2個(gè)穩(wěn)定狀態(tài)。

input_encoder: rotary_encoder {

compatible = “rotary-encoder”;

status = “okay”;

label = “INPUT_ENCODER”;

a-gpios = 《&gpio1 22 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)》;

b-gpios = 《&gpio1 23 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)》;

ppr = 《15》;

spp = 《2》;

};

使用代碼

void encoder_callback(const struct device *dev,

struct sensor_trigger *trigger)

{

struct sensor_value val;

//旋轉(zhuǎn)編碼器旋轉(zhuǎn)發(fā)生,從驅(qū)動(dòng)讀出旋轉(zhuǎn)過的角度

sensor_channel_get(dev, SENSOR_CHAN_ROTATION, &val);

printk(“current %d.%d

”, val.val1, val.val2);

}

void main(void)

{

struct device *dev;

//獲取旋轉(zhuǎn)編碼器device

dev = device_get_binding(“INPUT_ENCODER”);

//注冊(cè)trigger callback,當(dāng)旋轉(zhuǎn)發(fā)生時(shí)將調(diào)用encoder_callback

sensor_trigger_set(dev, NULL, encoder_callback);

}

以上測(cè)試測(cè)序編譯完后跑起來的效果

current 12.0

current 24.0

current 36.0

current 48.0

current 36.0

current 24.0

current 12.0

current 0.0

current -12.0

current -24.0

current -36.0

current -48.0

參考

https://zh.wikipedia.org/wiki/%E6%97%8B%E8%BD%89%E7%B7%A8%E7%A2%BC%E5%99%A8

https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/input/rotary-encoder.txt

https://www.epitran.it/ebayDrive/datasheet/25.pdf

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Zephyr
    +關(guān)注

    關(guān)注

    0

    文章

    21

    瀏覽量

    5963

原文標(biāo)題:Zephyr添加旋轉(zhuǎn)編碼器驅(qū)動(dòng)

文章出處:【微信號(hào):ZephyrProject,微信公眾號(hào):ZephyrProject】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    增量編碼器與絕對(duì)值編碼器的區(qū)別

    增量編碼器與絕對(duì)值編碼器的區(qū)別:增量編碼器與絕對(duì)值編碼器在精度特點(diǎn)對(duì)比
    的頭像 發(fā)表于 11-18 16:38 ?491次閱讀
    <b class='flag-5'>增量</b><b class='flag-5'>編碼器</b>與絕對(duì)值<b class='flag-5'>編碼器</b>的區(qū)別

    增量編碼器單圈和多圈怎么知道,如何分辯?

    增量編碼器單圈和多圈怎么知道,如何分辯? 單圈編碼器特點(diǎn): ? 單圈編碼器只能測(cè)量一圈內(nèi)的旋轉(zhuǎn)角度或位移。一旦
    的頭像 發(fā)表于 10-21 09:42 ?397次閱讀
    <b class='flag-5'>增量</b>式<b class='flag-5'>編碼器</b>單圈和多圈怎么知道,如何分辯?

    旋轉(zhuǎn)編碼器可以收集并發(fā)出什么信號(hào),旋轉(zhuǎn)編碼器信號(hào)異常怎么處理

    旋轉(zhuǎn)編碼器是一種精密的測(cè)量裝置,主要用于將旋轉(zhuǎn)運(yùn)動(dòng)轉(zhuǎn)換為可測(cè)量的電信號(hào)。它可以收集并發(fā)出多種信號(hào),但主要的是與旋轉(zhuǎn)運(yùn)動(dòng)相關(guān)的位置、速度或角度等物理量的信號(hào)。具體來說,
    的頭像 發(fā)表于 10-01 16:55 ?541次閱讀

    如何實(shí)現(xiàn)比較以提高工業(yè)驅(qū)動(dòng)應(yīng)用中旋轉(zhuǎn)編碼器的性能

    電子發(fā)燒友網(wǎng)站提供《如何實(shí)現(xiàn)比較以提高工業(yè)驅(qū)動(dòng)應(yīng)用中旋轉(zhuǎn)編碼器的性能.pdf》資料免費(fèi)下載
    發(fā)表于 09-19 13:09 ?0次下載
    如何實(shí)現(xiàn)比較<b class='flag-5'>器</b>以提高工業(yè)<b class='flag-5'>驅(qū)動(dòng)</b>應(yīng)用中<b class='flag-5'>旋轉(zhuǎn)</b><b class='flag-5'>編碼器</b>的性能

    增量旋轉(zhuǎn)編碼器

    電子發(fā)燒友網(wǎng)站提供《增量旋轉(zhuǎn)編碼器.pdf》資料免費(fèi)下載
    發(fā)表于 09-03 11:51 ?0次下載
    <b class='flag-5'>增量</b><b class='flag-5'>旋轉(zhuǎn)</b><b class='flag-5'>編碼器</b>

    帶Arduino的旋轉(zhuǎn)編碼器設(shè)計(jì) 旋轉(zhuǎn)編碼器的工作原理和特點(diǎn)

    旋轉(zhuǎn)編碼器(Rotary Encoder),也稱為軸編碼器,是一種將旋轉(zhuǎn)的機(jī)械位移量轉(zhuǎn)換為電氣信號(hào)的傳感。這些電氣信號(hào)經(jīng)過處理后,可以用于
    的頭像 發(fā)表于 07-04 17:17 ?2492次閱讀
    帶Arduino的<b class='flag-5'>旋轉(zhuǎn)</b><b class='flag-5'>編碼器</b>設(shè)計(jì) <b class='flag-5'>旋轉(zhuǎn)</b><b class='flag-5'>編碼器</b>的工作原理和特點(diǎn)

    旋轉(zhuǎn)編碼器控制電機(jī)速度

    旋轉(zhuǎn)編碼器控制電機(jī)速度
    發(fā)表于 06-24 09:16 ?4次下載

    伺服電機(jī)編碼器的型號(hào)怎么看

    伺服電機(jī)編碼器是伺服電機(jī)的重要組成部分,它能夠?qū)㈦姍C(jī)的旋轉(zhuǎn)角度、速度等信息轉(zhuǎn)換為電信號(hào),為控制系統(tǒng)提供精確的位置和速度反饋。 一、伺服電機(jī)編碼器的分類 1.1 增量
    的頭像 發(fā)表于 06-17 11:07 ?1886次閱讀

    旋轉(zhuǎn)編碼器在PLC中怎么編程

    在工業(yè)自動(dòng)化領(lǐng)域,旋轉(zhuǎn)編碼器與可編程邏輯控制(PLC)的結(jié)合應(yīng)用極為廣泛。旋轉(zhuǎn)編碼器通過提供精確的旋轉(zhuǎn)
    的頭像 發(fā)表于 06-17 09:24 ?1626次閱讀

    增量編碼器結(jié)構(gòu)應(yīng)用與工作原理

    增量編碼器的工作原理:增量編碼器的核心部分是碼盤,它通過旋轉(zhuǎn)來產(chǎn)生脈沖信號(hào)。碼盤上有一系列的條紋,這些條紋會(huì)依據(jù)
    的頭像 發(fā)表于 06-04 10:15 ?1771次閱讀
    <b class='flag-5'>增量</b>式<b class='flag-5'>編碼器</b>結(jié)構(gòu)應(yīng)用與工作原理

    增量編碼器和絕對(duì)值編碼器的區(qū)別

    在工業(yè)自動(dòng)化和精密測(cè)量領(lǐng)域,編碼器是不可或缺的關(guān)鍵設(shè)備。編碼器能夠?qū)C(jī)械位移轉(zhuǎn)換為電信號(hào),以便于計(jì)算機(jī)或其他數(shù)字系統(tǒng)進(jìn)行處理。在編碼器的眾多類型中,增量
    的頭像 發(fā)表于 06-03 15:40 ?2789次閱讀

    旋轉(zhuǎn)編碼器的常見類型

    詳細(xì)介紹旋轉(zhuǎn)編碼器的常見類型,包括增量編碼器和絕對(duì)式編碼器兩大類,并對(duì)它們的特點(diǎn)、工作原理、應(yīng)用場(chǎng)合等進(jìn)行深入探討。
    的頭像 發(fā)表于 05-29 15:59 ?915次閱讀

    光纖絕對(duì)式和光纖增量編碼器的區(qū)別

    絕對(duì)式編碼器增量編碼器二者有什么區(qū)別呢?分別有什么特征,適合什么樣的應(yīng)用呢?歡迎閱讀文章了解~
    的頭像 發(fā)表于 05-15 10:43 ?425次閱讀
    光纖絕對(duì)式和光纖<b class='flag-5'>增量</b>式<b class='flag-5'>編碼器</b>的區(qū)別

    如何將增量旋轉(zhuǎn)編碼器與Arduino連接

    在本教程中,您將學(xué)習(xí)如何將增量旋轉(zhuǎn)編碼器與Arduino連接,以讀取旋鈕的運(yùn)動(dòng)。這對(duì)于在機(jī)器人和其他應(yīng)用程序中創(chuàng)建用戶界面或讀取機(jī)械位置非常有用。
    的頭像 發(fā)表于 02-11 10:00 ?1424次閱讀
    如何將<b class='flag-5'>增量</b><b class='flag-5'>旋轉(zhuǎn)</b><b class='flag-5'>編碼器</b>與Arduino連接

    永磁同步電機(jī)的矢量控制 帶編碼器的電機(jī)-AB增量編碼器應(yīng)用指南

    電子發(fā)燒友網(wǎng)站提供《永磁同步電機(jī)的矢量控制 帶編碼器的電機(jī)-AB增量編碼器應(yīng)用指南.pdf》資料免費(fèi)下載
    發(fā)表于 01-30 09:37 ?3次下載
    永磁同步電機(jī)的矢量控制 帶<b class='flag-5'>編碼器</b>的電機(jī)-AB<b class='flag-5'>增量</b><b class='flag-5'>型</b><b class='flag-5'>編碼器</b>應(yīng)用指南
    RM新时代网站-首页