Arduino关于旋转编码器程序的介绍资料
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Arduino关于旋转编码器程序的介绍介绍
旋转或编码器是一个角度测量装置. 他用作精确测量电机的旋转角度或者用来控制控制轮子(可以无限旋转,而电位器只能旋转到特定位置)。其中有一些还安装了一个可以在轴上按的按钮,就像音乐播放器的控制按钮。Some of them are also equipped with a pushbutton when you press on the axis (like the ones used for navigation on many music controllers). 它们的精度多种多样,有每圈16步到1024步的各种,价格也从2到200欧元不等。
我写了一个小例子去读旋转编码器,并且使将读数通过RS232显示。我们很容易实现当编码器每走一步更新一下计数,并且将它通过串口显示在电脑上(通过串口监视器)。这个程序在ALPS STEC12E08编码器(每圈有24步)上运行良好。但是我认为当它使用在一个有更高精度的编码器上时有可能就会失效或者当电机旋转很快,或者你拓展这个程序以适应多个编码器。请先试试他吧。
我在Arduino distribution(A VRLib的一部分)的encoder.h中学会了怎样操作编码器。谢谢作者:Pascal Stang,感谢他对每一个函数友好而详细的解释。如下:
Example 1
/* Read Quadrature Encoder
* Connect Encoder to Pins encoder0PinA, encoder0PinB, and +5V.
*
* Sketch by max wolf /
* v. 0.1 - very basic functions - mw 20061220
*
*/
int val;
int encoder0PinA = 3;
int encoder0PinB = 4;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;
void setup() {
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
Serial.begin (9600);
}
void loop() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {//上升沿
if (digitalRead(encoder0PinB) == LOW) {
encoder0Pos--;
} else {
encoder0Pos++;
}
Serial.print (encoder0Pos);
Serial.print ("/");
}
encoder0PinALast = n;
}
要注意的几点:
encoder0Pos会一直记数,那也就意味着如果电机一直向一个方向进行旋转,那么串口消息会变的很长(最多6个字符),这样的话就会画更多的时间去转换。你需要保证当encoder0Pos 溢出的时候,在你的PC端不会发生bugs-如果它的值大于INT的最大值(32,767)时,它会突变为-32,768!反之亦然。改进建议: 仅当上位机需要读数的时候,将计数相加,即只计数发送周期之间的数据。当然,如果你在loop()中添加更多的代码,或者使用更高精度的编码器,就有可能丢失某一步(少计数)。更好的解决办法是使用中断(当检测到信号的突变时)。我上面提到库文件就是这么去做的,但是现在(2006-12) 无法再Arduino环境下编译,或者我不知道怎么去做……。
更深的解释, 包括编码器时序图
我对于编码器的时序的原理不怎么确定,但是还是将这些内容添加到这里吧. Paul Badger
下图,是编码器A & B两通道的时序图。
下面的描述会更好的解释编码器是怎么运行的。当代码检测到A通道一个上升沿的时候,他会接着去检查B通道是高电平或者是低电平,因为方向不同,接着它会将计数增加或者减少。为了检测到波形,编码器必须旋转。
上面代码的优势是,他只检测了关于编码器的一种可能性(共4种分别是检测A(上升沿,下降沿)(B+,B-),检测B(上升沿,下降沿)(A+,A-))。为了方便解释,不管红色还是绿色虚线标注的变换,都是根据编码器的旋转方向变化而变化的。
中断的例子
使用一个中断的例子
下面是使用中断的代码. 当Arduino检测到A通道有变化(上升沿或下降沿), 它立刻跳转到“doEncoder”函数, 中断函数会在上升沿和下降沿都会被调用,所以每个一步都会被计两次。我不想使用另一个中断去检查B通道的2个变换( 上图紫色和青色线标注处),但是即使调用了,也不会很麻烦.
使用中断去操作旋转编码器比较不错,因为中断响应时间很快,因为它不用操作很多任务。
I used the encoder as a “mode selector”on a synthesizer made solely from an Arduino chip(译者作者可能是说他将这个旋转编码器用作一个模式选择用途,就是如同按钮形式的东西). 这是一个比较随意的程序,因为用户对单片机丢失一些脉冲并不在意. 中断方法比较重要的应用是在伺服电机或者机器人的轮子上,在这些应用中,单片机不能丢失任何一个脉冲,不然运动的精度就无法保证了。
要注意的另一点是: I used the Arduino’s pullup resistors to “steer”the inputs high when they were not engaged by the encoder. Hence the encoder common pin is connected to ground. (译者作者使用Arduino内部上拉电阻使输入端的常态是高电平,因此编码器的公共端是连接到地上)上面的程序没有提到的一点是:输入端需要串联上拉电阻(10K欧就好),因为编码器的公共端连接是+5V.
/* read a rotary encoder with interrupts
Encoder hooked up with common to GROUND,
encoder0PinA to pin 2, encoder0PinB to pin 4 (or pin 3 see below)
it doesn't matter which encoder pin you use for A or B
uses Arduino pullups on A & B channel outputs
turning on the pullups saves having to hook up resistors
to the A & B channel outputs
*/
#define encoder0PinA 2
#define encoder0PinB 4
volatile unsigned int encoder0Pos = 0;
void setup() {
pinMode(encoder0PinA, INPUT);
digitalWrite(encoder0PinA, HIGH); // turn on pullup resistor
pinMode(encoder0PinB, INPUT);
digitalWrite(encoder0PinB, HIGH); // turn on pullup resistor
attachInterrupt(0, doEncoder, CHANGE); // encoder pin on interrupt 0 - pin 2
Serial.begin (9600);
Serial.println("start"); // a personal quirk