Arduino Uno 简单使用旋转增量式编码器(E6B2 |
您所在的位置:网站首页 › 编码器如何测量好坏的方法 › Arduino Uno 简单使用旋转增量式编码器(E6B2 |
目录 实验效果使用Arudino Uno 的中断引脚实现旋转增量式编码器的A,B相实现正反方向计数,Z相的归零修正。 编码器作用是测量速度、方向、位移,可以应用在步进电机丢步补偿,米轮测距等等。 元件说明在本示例中使用的旋转增量式编码器是 欧姆龙的E6B2-CWZ6C 输出相: A、 B、 Z相 输出相位差: A相、 B相的相位差90±45° (1/4±1/8T) 输出形式: NPN集电极开路输出 输出容量: 施加电压: DC30V以下 负载电流: 35mA以下 残留电压:0.4V以下 (负载电流35mA时)最高响应频率: 100kHz 输出上升、 下降时间: 1μs以下 控制输出电压:5V 负载电阻1kΩ、起动转矩: 0.98mN·m以下 惯性力矩: 1×10−6 kg·m2 以下 (600 P/R以下为3×10−7kg·m2以下) 最大轴负载: 径向 30N 轴向 20N允许最高转速:6,000r/min 保护回路:负载短路保护、电源反接保护 ― 环境温度范围:工作时:−10~+70°C、保存时:−25~+85°C (无结冰) 环境湿度范围:工作时、保存时:各35~85%RH (无结露) 绝缘电阻:20MΩ以上 (DC500V兆) 导线端整体与外壳间 耐电压:AC500V 50/60Hz 1min 导线端整体与外壳间 振动:(耐久) 10~500Hz 上下振幅 2mm或150m/s2 X、 Y、 Z各方向 扫频11min/次 扫频3次 冲击:(耐久) 1,000m/s2 X、 Y、 Z各方向 3次 保护结构:IEC标准 IP50 连接方式:导线引出型 (标准导线长500mm) 材质: 外壳 ABS 本体 铝 轴 SUS420J2详细中文说明: https://www.fa.omron.com.cn/data_pdf/cat/e6b2-c_ds_c_6_1.pdf?id=487 BOM表 名称 数量 Arduino Uno x1 E6B2-CWZ6C 编码器 x1 跳线(杜邦线) 若干 引脚说明5to24VDC :供电,5-24V GND :地线GND OUT A :A相输出 OUT B :B相输出,根据A相和B相的高低电平可以判断编码器的旋转方向。 OUT Z :Z相输出,当编码器回到一圈的原点时触发,一般用于修正。 接线方式 Arduino Uno 引脚 E6B2-CWZ6C 引脚 5V 褐色 Brown GND 蓝色 Blue 2 黑色 Black 3 橙色 Orange 4 白色 White 提点 attachInterrupt() 说明attachInterrupt()函数是用于为Arduino开发板设置和执行ISR(中断服务程序)用的 ISR(中断服务程序)顾名思义就是中断Arduino当前正在处理的事情而优先去执行中断服务程序。当中断服务程序完成以后,再回来继续执行刚才执行的事情。中断服务程序对监测Arduino输入有很大的用处。 我们可以使用attachInterrupt()函数,利用Arduino的引脚触发中断程序。以下列表说明支持中断的引脚有哪些: Arduino控制板 支持中断的引脚 Uno, Nano, Mini 2, 3 Mega, Mega2560, MegaADK 2, 3, 18, 19, 20, 21 Micro, Leonardo 0, 1, 2, 3, 7 Zero 除4号引脚以外的所有数字引脚 MKR1000 Rev.1 0, 1, 4, 5, 6, 7, 8, 9, A1, A2 Due 所有数字引脚 注意在ISR(中断服务程序)函数中,delay()函数是不工作的,而且millis()函数返回值也不再增长。在ISR(中断服务程序)运行期间Arduino开发板接收到的串口数据也可能丢失。另外ISR函数里所使用的变量应声明为volatile类型。详情请见以下”关于ISR(中断服务程序)”部分。 使用中断中断很适合执行那些需要不断检查的工作,比如检查一个引脚上连接的按键开关是否被按下。中断更适用于很快就会消失的信号检查,比如某一个引脚用于检测脉冲信号,这个脉冲信号的持续时间可能十分短暂。如果不使用中断,那么假如Arduino开发板正在执行其它任务时,突然这个脉冲信号来了,还不等Arduino开发板完成正在执行的工作,这个脉冲信号可能就已经消失了。而使用中断,就可以确保这个转瞬即逝的脉冲信号可以很好的被Arduino开发板检测到并执行相应任务。 关于ISR(中断服务程序)对于Arduino开发板来说,ISR(中断服务程序)是一种特殊的函数。它的特殊意味着它具有其它类型函数所不具备的限制和特点。 ISR函数不能有任何参数。ISR也没有任何返回值。 通常ISR需要越短小精悍越好!另外如果您的代码中有多个ISR函数,那么每次Arduino只能运行一个ISR函数,其它ISR函数只有在当前的ISR函数执行结束以后,才能按照其优先级别顺序执行。 millis()函数的运行依赖Arduino开发板的中断功能,因此ISR函数中的millis()函数是无法正常运行的。micros() 也是类似的情况,它只能在初始的1-2毫秒中可以运行,但是过了这1-2毫秒后就开始出现问题了。 delayMicroseconds() 不需要任何计数器就可以运行,所以delayMicroseconds() 运行是不会受到影响的。 一般情况下,ISR函数与主程序之间传递数据是依靠全局变量来实现的。为了确保全局变量在ISR函数中可以正常的工作,应该将可能被ISR函数中使用的全局变量声明为volatile类型。如需更多有关中断方面的知识,请参考 Nick Gammon’s notes. 语法 attachInterrupt(digitalPinToInterrupt(pin), ISR, mode); 参数pin: 中断引脚号 ISR: 中断服务程序名 mode:中断模式 中断模式(mode)有以下几种形式: LOW: 当引脚为低电平时触发中断服务程序 CHANGE: 当引脚电平发生变化时触发中断服务程序 RISING: 当引脚电平由低电平变为高电平时触发中断服务程序 FALLING: 当引脚电平由高电平变为低电平时触发中断服务程序 返回值无 示例 const byte ledPin = 13; //用2号引脚作为中断触发引脚 const byte interruptPin = 2; volatile byte state = LOW; void setup() { pinMode(ledPin, OUTPUT); //将中断触发引脚(2号引脚)设置为INPUT_PULLUP(输入上拉)模式 pinMode(interruptPin, INPUT_PULLUP); //设置中断触发程序 attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE); } void loop() { digitalWrite(ledPin, state); } //中断服务程序 void blink() { state = !state; } 注意 在中断服务程序中,不能使用delay()函数和millis()函数。因为他们无法在中断服务程序中正常工作。delayMicroseconds()可以在中断服务程序中正常工作。 中断服务程序应尽量保持简单短小。否则可能会影响Arduino工作。 中断服务程序中涉及的变量应声明为volatile类型。 中断服务程序不能返回任何数值。所以应尽量在中断服务程序中使用全局变量。参考引用: http://www.taichi-maker.com/homepage/reference-index/arduino-code-reference/attachinterrupt/ 程序代码 // By lingshunlab.com #define ENCODER_A_PIN 2 // BLack 黑线 #define ENCODER_Z_PIN 3 // Orange 橙线 #define ENCODER_B_PIN 4 // White 白线 volatile long counter = 0; // 定义 counter 计数器,用于计数 void setup() { // put your setup code here, to run once: Serial.begin(115200); pinMode(ENCODER_A_PIN, INPUT_PULLUP);// 将中断的引脚设置为输入PULLUP模式 pinMode(ENCODER_B_PIN, INPUT_PULLUP);// 将引脚设置为输入PULLUP模式 pinMode(ENCODER_Z_PIN, INPUT_PULLUP);// 将中断的引脚设置为输入PULLUP模式 // 使用attachInterrupt设定绑定中断功能的引脚、触发时要执行的函式、以及执行方式 attachInterrupt(digitalPinToInterrupt(ENCODER_A_PIN), interrupt_a_change, CHANGE); attachInterrupt(digitalPinToInterrupt(ENCODER_Z_PIN), interrupt_z_change, CHANGE); } void loop() { Serial.println(counter); // 串口显示 计数器数值 } // 引脚A中断时,调用的函数 void interrupt_a_change() { int temp_a = digitalRead(ENCODER_A_PIN); int temp_b = digitalRead(ENCODER_B_PIN); // 判断编码器的选择方向 if (temp_a == temp_b) { counter--; // 向后转 计数器-1 } else { counter++; // 向前转 计数器+1 } } // 引脚Z中断时,调用的函数 void interrupt_z_change() { counter = 0; // 归零 } |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |