0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何设置用于旋转编码器的简单Arduino菜单

454398 来源:网络整理 作者:网络整理 2020-01-29 17:43 次阅读

步骤1:准备工作

如何设置用于旋转编码器的简单Arduino菜单

如果还没有,请参阅我的其他Instructable旋转编码器阅读,以了解如何设置硬件和Arduino IDE软件。

硬件

图片中显示了需要使用中心按钮的其他硬件连接。我使用Fritzing绘制了图表,但它没有代表最可能的引脚布局的旋转编码器组件,因此只需将该图表与注释结合使用,然后查看旋转编码器的照片,即可了解更多内容。可能正在寻找旋转编码器引脚布局方面的信息

旋转编码器一侧(与具有三个引脚的一侧相对)的两个引脚之一需要接地,而另一端则要连接到Arduino的数字引脚。我已将D4用于示例草图。如果您选择其他引脚,请不要忘记更改草图中的 buttonPin 的值。

接下来是步骤2中的代码。

步骤2:代码

这是代码。通过查看结构和评论,我希望您会发现很容易适应您的特定需求!

/*******Interrupt-based Rotary Encoder Menu Sketch*******

* by Simon Merrett, based on insight from Oleg Mazurov, Nick Gammon, rt and Steve Spence, and code from Nick Gammon

* 3,638 bytes with debugging on UNO, 1,604 bytes without debugging

*/

// Rotary encoder declarations

static int pinA = 2; // Our first hardware interrupt pin is digital pin 2

static int pinB = 3; // Our second hardware interrupt pin is digital pin 3

volatile byte aFlag = 0; // let‘s us know when we’re expecting a rising edge on pinA to signal that the encoder has arrived at a detent

volatile byte bFlag = 0; // let‘s us know when we’re expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)

volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255

volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)

volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent

// Button reading, including debounce without delay function declarations

const byte buttonPin = 4; // this is the Arduino pin we are connecting the push button to

byte oldButtonState = HIGH; // assume switch open because of pull-up resistor

const unsigned long debounceTime = 10; // milliseconds

unsigned long buttonPressTime; // when the switch last changed state

boolean buttonPressed = 0; // a flag variable

// Menu and submenu/setting declarations

byte Mode = 0; // This is which menu mode we are in at any given time (top level or one of the submenus)

const byte modeMax = 3; // This is the number of submenus/settings you want

byte setting1 = 0; // a variable which holds the value we set

byte setting2 = 0; // a variable which holds the value we set

byte setting3 = 0; // a variable which holds the value we set

/* Note: you may wish to change settingN etc to int, float or boolean to suit your application.

Remember to change “void setAdmin(byte name,*BYTE* setting)” to match and probably add some

“modeMax”-type overflow code in the “if(Mode == N && buttonPressed)” section*/

void setup() {

//Rotary encoder section of setup

pinMode(pinA, INPUT_PULLUP); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)

pinMode(pinB, INPUT_PULLUP); // set pinB as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)

attachInterrupt(0,PinA,RISING); // set an interrupt on PinA, looking for a rising edge signal and executing the “PinA” Interrupt Service Routine (below)

attachInterrupt(1,PinB,RISING); // set an interrupt on PinB, looking for a rising edge signal and executing the “PinB” Interrupt Service Routine (below)

// button section of setup

pinMode (buttonPin, INPUT_PULLUP); // setup the button pin

// DEBUGGING section of setup

Serial.begin(9600); // DEBUGGING: opens serial port, sets data rate to 9600 bps

}

void loop() {

rotaryMenu();

// carry out other loop code here

}

void rotaryMenu() { //This handles the bulk of the menu functions without needing to install/include/compile a menu library

//DEBUGGING: Rotary encoder update display if turned

if(oldEncPos != encoderPos) { // DEBUGGING

Serial.println(encoderPos);// DEBUGGING. Sometimes the serial monitor may show a value just outside modeMax due to this function. The menu shouldn‘t be affected.

oldEncPos = encoderPos;// DEBUGGING

}// DEBUGGING

// Button reading with non-delay() debounce - thank you Nick Gammon!

byte buttonState = digitalRead (buttonPin);

if (buttonState != oldButtonState){

if (millis () - buttonPressTime 》= debounceTime){ // debounce

buttonPressTime = millis (); // when we closed the switch

oldButtonState = buttonState; // remember for next time

if (buttonState == LOW){

Serial.println (“Button closed”); // DEBUGGING: print that button has been closed

buttonPressed = 1;

}

else {

Serial.println (“Button opened”); // DEBUGGING: print that button has been opened

buttonPressed = 0;

}

} // end if debounce time up

} // end of state change

//Main menu section

if (Mode == 0) {

if (encoderPos 》 (modeMax+10)) encoderPos = modeMax; // check we haven’t gone out of bounds below 0 and correct if we have

else if (encoderPos 》 modeMax) encoderPos = 0; // check we haven‘t gone out of bounds above modeMax and correct if we have

if (buttonPressed){

Mode = encoderPos; // set the Mode to the current value of input if button has been pressed

Serial.print(“Mode selected: ”); //DEBUGGING: print which mode has been selected

Serial.println(Mode); //DEBUGGING: print which mode has been selected

buttonPressed = 0; // reset the button status so one press results in one action

if (Mode == 1) {

Serial.println(“Mode 1”); //DEBUGGING: print which mode has been selected

encoderPos = setting1; // start adjusting Vout from last set point

}

if (Mode == 2) {

Serial.println(“Mode 2”); //DEBUGGING: print which mode has been selected

encoderPos = setting2; // start adjusting Imax from last set point

}

if (Mode == 3) {

Serial.println(“Mode 3”); //DEBUGGING: print which mode has been selected

encoderPos = setting3; // start adjusting Vmin from last set point

}

}

}

if (Mode == 1 && buttonPressed) {

setting1 = encoderPos; // record whatever value your encoder has been turned to, to setting 3

setAdmin(1,setting1);

//code to do other things with setting1 here, perhaps update display

}

if (Mode == 2 && buttonPressed) {

setting2 = encoderPos; // record whatever value your encoder has been turned to, to setting 2

setAdmin(2,setting2);

//code to do other things with setting2 here, perhaps update display

}

if (Mode == 3 && buttonPressed){

setting3 = encoderPos; // record whatever value your encoder has been turned to, to setting 3

setAdmin(3,setting3);

//code to do other things with setting3 here, perhaps update display

}

}

// Carry out common activities each time a setting is changed

void setAdmin(byte name, byte setting){

Serial.print(“Setting ”); //DEBUGGING

Serial.print(name); //DEBUGGING

Serial.print(“ = ”); //DEBUGGING

Serial.println(setting);//DEBUGGING

encoderPos = 0; // reorientate the menu index - optional as we have overflow check code elsewhere

buttonPressed = 0; // reset the button status so one press results in one action

Mode = 0; // go back to top level of menu, now that we’ve set values

Serial.println(“Main Menu”); //DEBUGGING

}

//Rotary encoder interrupt service routine for one encoder pin

void PinA(){

cli(); //stop interrupts happening before we read pin values

reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB‘s values

if(reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin’s rising edge

encoderPos --; //decrement the encoder‘s position count

bFlag = 0; //reset flags for the next turn

aFlag = 0; //reset flags for the next turn

}

else if (reading == B00000100) bFlag = 1; //signal that we’re expecting pinB to signal the transition to detent from free rotation

sei(); //restart interrupts

}

//Rotary encoder interrupt service routine for the other encoder pin

void PinB(){

cli(); //stop interrupts happening before we read pin values

reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB‘s values

if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin’s rising edge

encoderPos ++; //increment the encoder‘s position count

bFlag = 0; //reset flags for the next turn

aFlag = 0; //reset flags for the next turn

}

else if (reading == B00001000) aFlag = 1; //signal that we’re expecting pinA to signal the transition to detent from free rotation

sei(); //restart interrupts

}

// end of sketch!

在任何对菜单执行操作都不重要的行的每个注释的开头,我都使用了“ DEBUGGING”。如果您对菜单功能满意,则可能需要注释掉或删除这些行以缩小编译的草图尺寸。

请注意,菜单导航的关键部分是在用户滚动浏览选项和设置时反馈给用户。因此,如果您选择不包括DEBUGGING行,则可能应该使用另一个可视指示器(例如LCD文本显示器,LED),编码器输入正在导航菜单并更改设置。

如果我注释掉DEBUGGING行(注意,菜单导航仍需要一些视觉反馈),Arduino Uno的编译后代码约为1,650字节,希望在ATMEGA328P上留出足够的空间以容纳草图中更令人兴奋的部分!

转到步骤3,了解菜单系统的工作原理

步骤3:操作和结论

操作

如果上传此草图后在Arduino中打开串行监视器,并开始转动编码器轴,则应该看到顶层菜单在子菜单/选项数中旋转您拥有(使用 modeMax 变量进行限制)。如果按中间的按钮,您会看到已选择要滚动到的模式/子菜单,现在可以自由选择要滚动浏览该子菜单中的0-255值。现在,如果您按下中央按钮,则将其设置为 setting1 或 setting2 或 setting3 等。Arduino自动并立即返回

上电后,Arduino会记住您将每个设置设置为什么,并且如果您返回子菜单以获取设置,则您已经设置了一个值到此为止,它将从您选择的最后一个值开始进行编码器调整!

结论

我着手编写一些基于草图的代码,旋转编码器导航Arduino的基本菜单。我还尝试使其具有可读性,以便与某些替代方案不同,有人可以看到菜单结构,并知道他们需要进行哪些更改才能根据自己的需要定制菜单。

此代码是基本的和通用的,专门用于演示功能,同时易于适应您自己的应用程序。它使用串行监视器作为基本的调试工具,如果您想查看代码的工作原理,也不需要单独显示。希望您发现它有用,并受到启发进行编辑,修改和改进!

责任编辑:wv

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编码器
    +关注

    关注

    45

    文章

    3643

    浏览量

    134525
  • Arduino
    +关注

    关注

    188

    文章

    6469

    浏览量

    187093
收藏 人收藏

    评论

    相关推荐

    二进制编码器与绝对编码器的区别

    编码器是工业自动化和机器人威廉希尔官方网站 中不可或缺的组件,用于将机械位置或运动转换为电信号。二进制编码器和绝对编码器是两种常见的编码器类型,它们各自有
    的头像 发表于 11-06 09:54 491次阅读

    旋转编码器的类型以及选择与设计注意要点

    应用中,需要准确测量旋转物体的角度,旋转编码器可以提供高精度的角度信息,用于导航、定位和控制系统。此外,通过监测旋转
    的头像 发表于 10-02 16:52 343次阅读
    <b class='flag-5'>旋转</b><b class='flag-5'>编码器</b>的类型以及选择与设计注意要点

    旋转编码器可以收集并发出什么信号,旋转编码器信号异常怎么处理

    旋转编码器是一种精密的测量装置,主要用于旋转运动转换为可测量的电信号。它可以收集并发出多种信号,但主要的是与旋转运动相关的位置、速度或角度
    的头像 发表于 10-01 16:55 586次阅读

    增量旋转编码器

    电子发烧友网站提供《增量旋转编码器.pdf》资料免费下载
    发表于 09-03 11:51 0次下载
    增量<b class='flag-5'>旋转</b><b class='flag-5'>编码器</b>

    编码器有什么分类?

    编码器本质是一种用于运动控制的传感,作用在于测量机械旋转的位移。
    的头像 发表于 08-10 14:47 580次阅读

    Arduino旋转编码器设计 旋转编码器的工作原理和特点

    旋转编码器(Rotary Encoder),也称为轴编码器,是一种将旋转的机械位移量转换为电气信号的传感。这些电气信号经过处理后,可以
    的头像 发表于 07-04 17:17 2630次阅读
    带<b class='flag-5'>Arduino</b>的<b class='flag-5'>旋转</b><b class='flag-5'>编码器</b>设计 <b class='flag-5'>旋转</b><b class='flag-5'>编码器</b>的工作原理和特点

    旋转编码器控制电机速度

    旋转编码器控制电机速度
    发表于 06-24 09:16 4次下载

    怎么看编码器上的参数?

    编码器是一种用于测量运动和位置的设备,常用于工业控制、机器人和自动化设备等领域。编码器的工作原理基于数码信号与机械旋转之间的特定关系,可以将
    的头像 发表于 06-23 16:16 1563次阅读
    怎么看<b class='flag-5'>编码器</b>上的参数?

    变频编码器参数怎么设置方法

    变频编码器参数设置是确保变频编码器正常工作的关键步骤。本文将详细介绍变频
    的头像 发表于 06-17 14:36 2207次阅读

    s120编码器参数设置在哪里

    S120编码器是一种高精度的旋转编码器,广泛应用于工业自动化、机器人、数控机床等领域。S120编码器具有多种型号,不同型号的
    的头像 发表于 06-17 14:33 1379次阅读

    旋转编码器在PLC中怎么编程

    在工业自动化领域,旋转编码器与可编程逻辑控制(PLC)的结合应用极为广泛。旋转编码器通过提供精确的旋转
    的头像 发表于 06-17 09:24 1672次阅读

    旋转编码器的常见类型

    在工业自动化和精密测量领域中,旋转编码器是一种不可或缺的设备。它能够将旋转位置或旋转量转换成模拟或数字信号,为控制系统提供精确的位置和速度信息。随着威廉希尔官方网站 的不断发展,
    的头像 发表于 05-29 15:59 934次阅读

    旋转编码器的种类和接线方法

    旋转编码器,作为现代工业领域中不可或缺的重要传感,广泛应用于各种机械设备、自动化系统以及测量仪器中。它能够准确测量物体的转速、角度等参数,并转换成相应的电信号输出,为控制系统提供精确
    的头像 发表于 05-24 14:50 1721次阅读

    如何将增量旋转编码器Arduino连接

    在本教程中,您将学习如何将增量旋转编码器Arduino连接,以读取旋钮的运动。这对于在机器人和其他应用程序中创建用户界面或读取机械位置非常有用。
    的头像 发表于 02-11 10:00 1440次阅读
    如何将增量<b class='flag-5'>旋转</b><b class='flag-5'>编码器</b>与<b class='flag-5'>Arduino</b>连接

    旋转编码器的工作原理,旋转编码器的作用功能及应用

    旋转编码器用于测量轴或轴旋转的组件。它们通常用于音频设备、DIY 游戏控制中的音量旋钮,或用
    的头像 发表于 02-11 09:53 5737次阅读
    <b class='flag-5'>旋转</b><b class='flag-5'>编码器</b>的工作原理,<b class='flag-5'>旋转</b><b class='flag-5'>编码器</b>的作用功能及应用