当前位置:文档之家› Arduino关于旋转编码器程序的介绍资料

Arduino关于旋转编码器程序的介绍资料

Arduino关于旋转编码器程序的介绍资料
Arduino关于旋转编码器程序的介绍资料

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 / https://www.doczj.com/doc/0d11204399.html,

* 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

void loop(){

// do some stuff here - the joy of interrupts is that they take care of themselves

}

void doEncoder() {

/* If pinA and pinB are both high or both low, it is spinning

* forward. If they're different, it's going backward.

*

* For more information on speeding up this process, see

* [Reference/PortManipulation], specifically the PIND register.

*/

if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {

encoder0Pos++;

} else {

encoder0Pos--;

}

Serial.println (encoder0Pos, DEC);

}

/* See this expanded function to get a better understanding of the

* meanings of the four possible (pinA, pinB) value pairs:

*/

void doEncoder_Expanded(){

if (digitalRead(encoder0PinA) == HIGH) { // found a low-to-high on channel A

if (digitalRead(encoder0PinB) == LOW) { // check channel B to see which way

// encoder is turning

encoder0Pos = encoder0Pos - 1; // CCW

}

else {

encoder0Pos = encoder0Pos + 1; // CW

}

}

else // found a high-to-low on channel A {

if (digitalRead(encoder0PinB) == LOW) { // check channel B to see which way

// encoder is turning encoder0Pos = encoder0Pos + 1; // CW

}

else {

encoder0Pos = encoder0Pos - 1; // CCW

}

}

Serial.println (encoder0Pos, DEC); // debug - remember to comment out

// before final program run

// you don't want serial slowing down your program if not needed

}

/* to read the other two transitions - just use another attachInterrupt()

in the setup and duplicate the doEncoder function into say,

doEncoderA and doEncoderB.

You also need to move the other encoder wire over to pin 3 (interrupt 1).

*/

BY:dskv 注意!!!

在中断程序中使用Serial.Print要特别注意,大多数情况下它会失败, 但是有时它会成功, 这是个程序比较糟糕的bugs. 下面连接是解释文档:

“https://https://www.doczj.com/doc/0d11204399.html,/a/https://www.doczj.com/doc/0d11204399.html,/forum/#!topic/developers/HKzEcN6gikM”

“https://www.doczj.com/doc/0d11204399.html,/index.php?topic=94459.0”

“https://www.doczj.com/doc/0d11204399.html,/node/1188.html”

中断例程(编码器中断主线程). 使用两个中断端口

读编码器,使用2个中断pin 2 & pin3

注意:下面的程序使用两个中断来使用编码器的最高精度(就像步进电机的细分. 上文的程序使用1个中断. 它仅仅读取一半精度,通过检测EncoderPin A的位置,但是它省一个中断程序。

#define encoder0PinA 2

#define encoder0PinB 3

volatile unsigned int encoder0Pos = 0;

void setup() {

pinMode(encoder0PinA, INPUT);

pinMode(encoder0PinB, INPUT);

// encoder pin on interrupt 0 (pin 2)

attachInterrupt(0, doEncoderA, CHANGE);

// encoder pin on interrupt 1 (pin 3)

attachInterrupt(1, doEncoderB, CHANGE);

Serial.begin (9600);

}

void loop(){ //Do stuff here }

void doEncoderA(){

// look for a low-to-high on channel A

if (digitalRead(encoder0PinA) == HIGH) {

// check channel B to see which way encoder is turning if (digitalRead(encoder0PinB) == LOW) {

encoder0Pos = encoder0Pos + 1; // CW

}

else {

encoder0Pos = encoder0Pos - 1; // CCW

}

}

else // must be a high-to-low edge on channel A

{

// check channel B to see which way encoder is turning if (digitalRead(encoder0PinB) == HIGH) {

encoder0Pos = encoder0Pos + 1; // CW

}

else {

encoder0Pos = encoder0Pos - 1; // CCW }

}

Serial.println (encoder0Pos, DEC);

// use for debugging - remember to comment out

}

void doEncoderB(){

// look for a low-to-high on channel B

if (digitalRead(encoder0PinB) == HIGH) {

// check channel A to see which way encoder is turning

if (digitalRead(encoder0PinA) == HIGH) {

encoder0Pos = encoder0Pos + 1; // CW

}

else {

encoder0Pos = encoder0Pos - 1; // CCW

}

}

// Look for a high-to-low on channel B

else {

// check channel B to see which way encoder is turning if (digitalRead(encoder0PinA) == LOW) {

encoder0Pos = encoder0Pos + 1; // CW

}

else {

encoder0Pos = encoder0Pos - 1; // CCW

}

}

}

中端例子(编码器中断主线程). 用一个中断端口, 将代码包装进C++类.

类包装by mikkoh [01/2010]

将上面的例子包装(一个中断的例程) 进类并且减少一点doEncoder 函数代码的体积(希望代码对你们还是可读的). 在这个类的文档中一个例子.

#ifndef __ENCODER_H__

#define __ENCODER_H__

#include "WProgram.h"

class Encoder {

/*

wraps encoder setup and update functions in a class

!!! NOTE : user must call the encoders update method from an

interrupt function himself! i.e. user must attach an interrupt to the

encoder pin A and call the encoder update method from within the

interrupt

uses Arduino pullups on A & B channel outputs

turning on the pullups saves having to hook up resistors

to the A & B channel outputs

// ------------------------------------------------------------------------------------------------

// Example usage :

// ------------------------------------------------------------------------------------------------ #include "Encoder.h"

Encoder encoder(2, 4);

void setup() {

attachInterrupt(0, doEncoder, CHANGE);

Serial.begin (115200);

Serial.println("start");

}

void loop(){

// do some stuff here - the joy of interrupts is that they take care of themselves }

void doEncoder(){

encoder.update();

Serial.println( encoder.getPosition() );

}

// ------------------------------------------------------------------------------------------------ // Example usage end

// ------------------------------------------------------------------------------------------------ */

public:

// constructor : sets pins as inputs and turns on pullup resistors

Encoder( int8_t PinA, int8_t PinB) : pin_a ( PinA), pin_b( PinB ) {

// set pin a and b to be input

pinMode(pin_a, INPUT);

pinMode(pin_b, INPUT);

// and turn on pullup resistors

digitalWrite(pin_a, HIGH);

digitalWrite(pin_b, HIGH);

};

// call this from your interrupt function

void update () {

if (digitalRead(pin_a)) digitalRead(pin_b) ? position++ : position--;

else digitalRead(pin_b) ? position-- : position++;

};

// returns current position

long int getPosition () { return position; };

// set the position value

void setPosition ( const long int p) { position = p; };

private:

long int position;

int8_t pin_a;

int8_t pin_b;

};

#endif // __ENCODER_H__

(译者上面的代码使用long int类型,关于Arduino 数据类型Arduino 数据类型)

中断例子(编码器中断主线程),使用两个中断

使用两个外部中断,仅仅计算一个方向的脉冲.

注意: 尽管代码感觉比较有效率, 但是由于使用了digitalRead()这个库函数,根据Pin I/O performance(译者地址Arduino 端口性能讲解)上说的它会比直接读端口要慢50倍。

最优效率的旋转编码器计数by m3tr0g33k

Paul Badger 的工作和原博客很有启发性并且很有用,在看代码之前,请理解他们是怎么说的(希望你能看明白)。

My project is a data loger where three analogue inputs are sampled each time a rotary encoder pulse steps clockwise. On an Arduino, time is of the essence to get this data sampled and saved somewhere (I have not included the …saving somewhere? part of this project yet.) (译者大体意思是当旋转编码器旋转一周将有3个输入量出现,但是在Arduino中处理器资源是有限的)为了节约一些处理器资源,我对终端系统做了稍微的修改,去维持在中断循环外的一对布尔声明。

我的想法是改变一个A或B的布尔变量,当在A或B口收到一个有效的跳变沿. 当你因A 端口中断,并且是有效的,你将A_set=true. 然后检测B_set是不是false.如果是, 那么A 比B 的相位靠前,这表明是顺时针(计数++)。同理,当你收到有效的因端口B中断, 你会改变set B_set=true. 然后你检查A_set 是否是false. 如果是, 那么B 比A的相位靠前, 那么意味着是逆时针旋转(计数–)。

此代码与以前的代码不同的地方是:当A或B发生中断的时候(中断标志是CHANGE),检测A和B口的状态,如果A或B是0则设置A_set或B_set为false,其他的工作就不需要了,减少了中断的占用时间(因为以前在一次中断需要读取A和B口的状态,而这个仅仅需要读取一个口的状态)。

不管如何,在代码中有足够的解释,代码如下:

#define encoder0PinA 2

#define encoder0PinB 3

volatile unsigned int encoder0Pos = 0;

unsigned int tmp_Pos = 1;

unsigned int valx;

unsigned int valy;

unsigned int valz;

boolean A_set;

boolean B_set;

void setup() {

pinMode(encoder0PinA, INPUT);

pinMode(encoder0PinB, INPUT);

// encoder pin on interrupt 0 (pin 2)

attachInterrupt(0, doEncoderA, CHANGE);

// encoder pin on interrupt 1 (pin 3)

attachInterrupt(1, doEncoderB, CHANGE);

Serial.begin (9600);

}

void loop(){

//Check each second for change in position

if (tmp_Pos != encoder0Pos) {

Serial.print("Index:"); Serial.print(encoder0Pos, DEC); Serial.print(", Values: ");

Serial.print(valx, DEC); Serial.print(", ");

Serial.print(valy, DEC); Serial.print(", ");

Serial.print(valz, DEC); Serial.println();

tmp_Pos = encoder0Pos;

}

delay(1000);

}

// Interrupt on A changing state

void doEncoderA(){

// Low to High transition?

if (digitalRead(encoder0PinA) == HIGH) {

A_set = true;

if (!B_set) {

encoder0Pos = encoder0Pos + 1;

valx=analogRead(0);

valy=analogRead(1);

valz=analogRead(2);

}

}

// High-to-low transition?

if (digitalRead(encoder0PinA) == LOW) {

A_set = false;

}

}

// Interrupt on B changing state

void doEncoderB(){

// Low-to-high transition?

if (digitalRead(encoder0PinB) == HIGH) {

B_set = true;

if (!A_set) {

encoder0Pos = encoder0Pos - 1;

}

}

// High-to-low transition?

if (digitalRead(encoder0PinB) == LOW) {

B_set = false;

}

}

环绕中断代码的其他部分仅仅是为了展示它是怎么工作的。就像我说的,我仅仅希望演示电机正传(在我的电车例子中就是向前走)。当检测到电机是反转的时候,我仅仅是更新那个计数变量。在loop{} 循环体中,我们每一秒显示一次当前编码器的位置和相应引脚读数数据。但是仅当编码器位置发生改变的时候才去更新,如果位置没有发生变化,则就不更新。你可以试试一秒钟你能转你的编码器多少圈。我的记录是300步或者是1.5圈每秒。

这个代码有一个逻辑问题,如果你频繁改变方向,那么你也许会想知道在每步的中间位置是否改变了方向,而且在那个位置,你的计数参数是不发生改变的。这就是半步滞后现象。当然,在绝大多数情况下,这并不能观察得到或者是重要的,但是思考一下这个问题是比较重要的。

希望这个运行速度的提升能够帮助一些人!m3tr0g33k

中断例子(编码器中断主线程),使用两个中断,简化上面代码的中断响应函数

简化中断程序

按照A_set == B_set来判断滞后或提前,你可以简化相当一部分中断程序的代码。

中断程序变为:

// Interrupt on A changing state

void doEncoderA(){

// Test transition

A_set = digitalRead(encoderPinA) == HIGH;

// and adjust counter + if A leads B

encoderPos += (A_set != B_set) ? +1 : -1;

}

// Interrupt on B changing state

void doEncoderB(){

// Test transition

B_set = digitalRead(encoderPinB) == HIGH;

// and adjust counter + if B follows A

encoderPos += (A_set == B_set) ? +1 : -1;

}

其基本原理为:当当前的引脚的改变的状态和另一个引脚的状态一致,那么,这个引脚就比另一个引脚滞后。如果状态不一致,那么当前引脚就超前。

最终结果:两行代码便构成了中断程序。

全部代码为:

enum PinAssignments {

encoderPinA = 2,

encoderPinB = 3,

clearButton = 8

};

volatile unsigned int encoderPos = 0;

unsigned int lastReportedPos = 1;

boolean A_set = false;

boolean B_set = false;

void setup() {

pinMode(encoderPinA, INPUT);

pinMode(encoderPinB, INPUT);

pinMode(clearButton, INPUT);

digitalWrite(encoderPinA, HIGH); // turn on pullup resistor

digitalWrite(encoderPinB, HIGH); // turn on pullup resistor

digitalWrite(clearButton, HIGH);

// encoder pin on interrupt 0 (pin 2)

attachInterrupt(0, doEncoderA, CHANGE);

// encoder pin on interrupt 1 (pin 3)

attachInterrupt(1, doEncoderB, CHANGE);

Serial.begin(9600);

}

void loop(){

if (lastReportedPos != encoderPos) {

Serial.print("Index:");

Serial.print(encoderPos, DEC);

Serial.println();

lastReportedPos = encoderPos;

}

if (digitalRead(clearButton) == LOW) {

encoderPos = 0;

}

}

// Interrupt on A changing state

void doEncoderA(){

// Test transition

A_set = digitalRead(encoderPinA) == HIGH;

// and adjust counter + if A leads B

encoderPos += (A_set != B_set) ? +1 : -1;

}

// Interrupt on B changing state

void doEncoderB(){

// Test transition

B_set = digitalRead(encoderPinB) == HIGH;

// and adjust counter + if B follows A

encoderPos += (A_set == B_set) ? +1 : -1;

}

其他关于编码器的链接:

a good explanation of grey codes and absolute encoders

this code did work better for me than most others, with good explanation

中断例子(编码器中断主线程),使用两个外部中断,初始化读后,就不再读引脚的状态

更快读编码器:仅使用中断

我也在应用中使用到了读旋转编码器,经过多次尝试,我很高兴高速大家有一个新的方式处理他们。根据前任的建议,我在AMT旋转编码器上使用了它并且运行真的很好。不幸的是,其他的方法失败了,因为计数太快了。为了避免读Arduino引脚的,我想也许有更快的方法,通过仅仅使用中断。下面是它的代码:

//PIN's definition

#define encoder0PinA 2

#define encoder0PinB 3

volatile int encoder0Pos = 0;

volatile boolean PastA = 0;

volatile boolean PastB = 0;

void setup()

{

pinMode(encoder0PinA, INPUT);

//turn on pullup resistor

//digitalWrite(encoder0PinA, HIGH); //ONL Y FOR SOME ENCODER(MAGNETIC)!!!! pinMode(encoder0PinB, INPUT);

//turn on pullup resistor

//digitalWrite(encoder0PinB, HIGH); //ONL Y FOR SOME ENCODER(MAGNETIC)!!!! PastA = (boolean)digitalRead(encoder0PinA); //initial value of channel A;

PastB = (boolean)digitalRead(encoder0PinB); //and channel B

//To speed up even more, you may define manually the ISRs

// encoder A channel on interrupt 0 (arduino's pin 2)

attachInterrupt(0, doEncoderA, RISING);

// encoder B channel pin on interrupt 1 (arduino's pin 3)

attachInterrupt(1, doEncoderB, CHANGE);

}

void loop()

{

//your staff....ENJOY! :D

}

//you may easily modify the code get quadrature..

//..but be sure this whouldn't let Arduino back!

void doEncoderA()

{

PastB ? encoder0Pos--: encoder0Pos++;

}

void doEncoderB()

{

PastB = !PastB;

}

希望能帮助到大家!by carnevaledaniele [04/2010]

旋转编码器库,在loop()中使用,没有示例代码

下面是完整的旋转编码器操作库代码(译者下面的代码没有使用中断,将占用较多的处理器资源):

#include

#include "HardwareSerial.h"

// 12 Step Rotary Encoder with Click //

// https://www.doczj.com/doc/0d11204399.html,/products/9117 //

#define EncoderPinA 20 // Rotary Encoder Left Pin //

#define EncoderPinB 19 // Rotary Encoder Right Pin //

#define EncoderPinP 21 // Rotary Encoder Click //

//

====================================================================== ================= //

class Encoder

{

public:

Encoder()

{

pinMode(EncoderPinA, INPUT);

digitalWrite(EncoderPinA, HIGH);

pinMode(EncoderPinB, INPUT);

digitalWrite(EncoderPinB, HIGH);

pinMode(EncoderPinP, INPUT);

digitalWrite(EncoderPinP, HIGH);

Position = 0;

Position2 = 0;

Max = 127;

Min = 0;

clickMultiply = 10;

}

void Tick(void)

{

Position2 = (digitalRead(EncoderPinB) * 2) + digitalRead(EncoderPinA);;

if (Position2 != Position)

{

isFwd = ((Position == 0) && (Position2 == 1)) || ((Position == 1) && (Position2 == 3)) ||

((Position == 3) && (Position2 == 2)) || ((Position == 2) && (Position2 ==

0));

if (!digitalRead(EncoderPinP)) { if (isFwd) Pos += clickMultiply; else Pos -= clickMultiply; }

else { if (isFwd) Pos++; else Pos--; }

if (Pos < Min) Pos = Min;

if (Pos > Max) Pos = Max;

}

Position = Position2;

}

int getPos(void)

{

return (Pos/4);

}

void setMinMax(int _Min, int _Max)

{

Min = _Min*4;

Max = _Max*4;

if (Pos < Min) Pos = Min;

if (Pos > Max) Pos = Max;

}

void setClickMultiply(int _clickMultiply)

{

clickMultiply = _clickMultiply;

}

private:

int clickMultiply;

int Max;

int Min;

int Pos;

int Position;

int Position2;

int isFwd;

};

中断例子(编码器中断主线程)–>这个没看

使用两个外部中断端口,主要根据Circuits@home代码,不防抖动。注意:Serial.print()函数会占用几毫秒,所以此代码中的中断程序运行时间会相对比较长,当将这些声明去掉的时候,那么就会提升程序的性能。(因为当中断程序占用足够长的时间,那么信号抖动甚至一些信号将会被丢失)。-ED

代码:

/*

RotaryInterrupts - a port-read and interrupt based rotary encoder sketch

Created by Joshua Layne (w15p), January 4, 2011.

based largely on: https://www.doczj.com/doc/0d11204399.html,/mcu/reading-rotary-encoder-on-arduino Released into the public domain.

*/

#define ENC_A 2

#define ENC_B 3

#define ENC_PORT PIND

uint8_t bitShift = 2; // change to suit your pins (offset from 0,1 per port)

// Note: You need to choose pins that have Interrupt capability.

int counter;

boolean ticToc;

void setup()

{

pinMode(ENC_A, INPUT);

digitalWrite(ENC_A, HIGH);

pinMode(ENC_B, INPUT);

digitalWrite(ENC_B, HIGH);

Serial.begin (115200);

Serial.println("Start");

counter = 0;

ticToc = false;

// Attach ISR to both interrupts

attachInterrupt(0, read_encoder, CHANGE);

attachInterrupt(1, read_encoder, CHANGE);

}

void loop()

{

// do some stuff here - the joy of interrupts is that they take care of themselves

}

void read_encoder()

{

int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};

static uint8_t encoderState = 0;

static uint8_t stateIndex = 0;

static uint8_t filteredPort = 0;

uint8_t filter = 0x03; // base filter: 0b00000011

filter <<= bitShift;

Serial.print("raw port value: ");

Serial.println(ENC_PORT, BIN);

Serial.print("filter bitmask: ");

Serial.println(filter, BIN);

filteredPort = ENC_PORT & filter;

Serial.print("filtered port state: ");

Serial.println(filteredPort, BIN);

Serial.print("old encoder state: ");

Serial.println(encoderState, BIN);

encoderState &= filter; // filter out everything except the rotary encoder pins Serial.print("filtered old encoder state: ");

Serial.println(encoderState, BIN);

encoderState <<= 2; // shift existing value two bits to the left

Serial.print("filtered and shifted (<<2) old encoder state: ");

Serial.println(encoderState, BIN);

encoderState |= filteredPort; // add filteredport value

Serial.print("old encoder state + port state: ");

Serial.println(encoderState, BIN);

stateIndex = encoderState >> bitShift;

Serial.print("encoder state index: ");

Serial.println(stateIndex, DEC);

if (ticToc) {

Serial.print("counter tic: ");

Serial.println(enc_states[stateIndex], DEC);

counter += enc_states[stateIndex];

Serial.print("counter: ");

Serial.println(counter, DEC);

}

ticToc = !ticToc;

Serial.println("----------");

}

中断例子(旋转编码器中断主线程)

使用1个中断,这样就丢失了一半的精度,作者说速度比较快但是却用了digitalRead()函数而不是直接去操作引脚。(具体请看:https://www.doczj.com/doc/0d11204399.html,/2010/01/06/pin-io-performance/))<< 2011/06 >>

通过尝试所有的例子,我觉得我的代码对于SaprkFun的旋转编码器(SaprkFunRotary encoder)操作地比较快了。但是请注意:需要在编码器的中间引脚和B引脚之间串连一个电容(译者就是在输出口和GND之间串联一个电容)。

程序:

#include

LiquidCrystal lcd(12,11,5,4,8,7);

#define encoder0PinA 2

#define encoder0PinB 3

volatile int encoder0Pos = 0;

volatile boolean PastB = 0;

volatile boolean update = false;

void setup()

{

lcd.begin(16,2);

lcd.print("Pos:");

pinMode(encoder0PinA, INPUT);

//turn on pullup resistor

digitalWrite(encoder0PinA, HIGH);

pinMode(encoder0PinB, INPUT);

//turn on pullup resistor

digitalWrite(encoder0PinB, HIGH);

attachInterrupt(1, doEncoderB, FALLING);

}

void loop()

{

if (update){

update = false;

PastB? encoder0Pos++:encoder0Pos--;

lcd.setCursor(7,0);

lcd.print(" ");

lcd.setCursor(7,0);

lcd.print(encoder0Pos,DEC);

}

}

void doEncoderB()

{

PastB=(boolean)digitalRead(encoder0PinA);

update = true;

}

去抖动电路

去抖动电路1

7.8.2011 deif

通过许多尝试,我建立了一个电路消除大多数的抖动。

下面是我最简形式的代码:

ISR(INT0_vect){

int a;

a = PIND & 0x0c;

if ((a == 0x0c) || (a == 0)){

encoderCount++;

}

else {

encoderCount--;

}

}

void setupPinInterrupt(){

EICRA = 0x01; //int0 on pinchange

EIMSK = 0x01; //enable interrupt 0

EIFR = 0; //clear flags

}

旋转编码器原理及其应用

旋转编码器的原理及其应用 摘要:本文介绍了常用编码器的原理、分类以及其应用的注意事项,并以德国P+F公司的编码器产品为参照,重点介绍了增量型编码器和绝对值型编码器的原理及应用,其中绝对值型编码器中以格雷码为主作了详细的介绍。 关键词:编码器增量型绝对值格雷码 一、前言 在自动化领域,旋转编码器是用来检测角度、速度、长度、位移和加速度的传感器。依靠轴杆、齿轮、测量轮或绳缆的控制,线性的移动能被检测。编码器也把实际的机械参数值转换成电气信号,这些电气信号可以被计数器、转速表、PLC和工业PC处理。 二、功能原理 由玻璃或塑料制成的圆盘被分成透明和非透明的区域,如果一个光源固定在圆盘的一侧,光敏元件固定在另一侧,旋转的移动没有接触就可获得。如果一束光打在透明的区域,接收器接收到,产生脉冲,当光束被 黑色区域隔断式,不产生脉冲。发光二极管 通常用作光源,发光范围在红外线范围内, 光敏二极管或光敏晶体管作为接收器。(见 右图) 如果按照此原理没有其它功能加入的 话,仅能推论出圆盘在转动,旋转的感应或 绝对值位置不能被确定。 编码器根据它们的功能原理和机械形式 和安装系统有不同的区别。 1、功能原理 1.1增量型旋转编码器 轴的每圈转动,增量型编码器提供一定数量的脉冲,周期性的测量或者单位时间内的脉冲数可以用来测量移动的速度。如果在一个参考点后面脉冲数被累加,计算值就代表了转动角度或行程的参数。双通道编码器输出脉冲之间相差900。能使接收脉冲的电子设备接收轴的旋转感应信号,因此可用来实现双向的定位控制。另外,三通道增量型编码器每一圈产生一个称之为零位信号的脉冲。 旋转增量型编码器以转动时输出脉冲,通过计数设备来计算其位置,当编码器不动或停电时,依靠计数设备的内部记忆来记住位置。这样,当停电后,编码器不能有任何的移动,当来电工作时,编码器输出脉冲过程中,也不能有干扰而丢失脉冲,不然,计数设备计算并记忆的零点就会偏移,而且这种偏移的量是无从知道的,只有错误的产生结果出现后才能知道。 解决的方法是增加参考点,编码器每经过参考点,将参考位置修正进计数设备的记忆位置。在参考点以前,是不能保证位置的准确性的。为此,在工控中就有每次操作先找参考点,开机找零等方法。 这样的方法对有些工控项目比较麻烦,甚至不允许开机找零(开机后就要知道准确位置),于是就有了绝对编码器的出现。 1.2绝对值旋转编码器 绝对编码器光码盘上有许多道光通道刻线,每道刻线依次以2线、4线、8线、16线编排,这样,在编码器的每一个位置,通过读取每道刻线的通、暗,获得一组从2的零次方到2的n-1次方的唯一的2进制编码(格雷码),这就称为n位绝对编码器。这样的编码器是由光电码盘的机械位置决定的,它不受停电、干扰的影响。特别是在定位控制应用中,绝对值编码器减轻了电子接收设备的计算任务,从而省去了复杂的和昂贵

编码器详细介绍与编程指导

增量型编码器与绝对型编码器的区分 编码器如以信号原理来分,有增量型编码器,绝对型编码器。 增量型编码器 (旋转型) 工作原理: 由一个中心有轴的光电码盘,其上有环形通、暗的刻线,有光电发射和接收器件读取,获得四组正弦波信号组合成A、B、C、D,每个正弦波相差90度相位差(相对于一个周波为360度),将C、D信号反向,叠加在A、B两相上,可增强稳定信号;另每转输出一个Z相脉冲以代表零位参考位。 由于A、B两相相差90度,可通过比较A相在前还是B相在前,以判别编码器的正转与反转,通过零位脉冲,可获得编码器的零位参考位。 编码器码盘的材料有玻璃、金属、塑料,玻璃码盘是在玻璃上沉积很薄的刻线,其热稳定性好,精度高,金属码盘直接以通和不通刻线,不易碎,但由于金属有一定的厚度,精度就有限制,其热稳定性就要比玻璃的差一个数量级,塑料码盘是经济型的,其成本低,但精度、热稳定性、寿命均要差一些。 分辨率—编码器以每旋转360度提供多少的通或暗刻线称为分辨率,也称解析分度、或直接称多少线,一般在每转分度5~10000线。 信号输出: 信号输出有正弦波(电流或电压),方波(TTL、HTL),集电极开路(PNP、NPN),推拉式多种形式,其中TTL为长线差分驱动(对称A,A-;B,B-;Z,Z-),HTL 也称推拉式、推挽式输出,编码器的信号接收设备接口应与编码器对应。 信号连接—编码器的脉冲信号一般连接计数器、PLC、计算机,PLC和计算机连接的模块有低速模块与高速模块之分,开关频率有低有高。 如单相联接,用于单方向计数,单方向测速。 A.B两相联接,用于正反向计数、判断正反向和测速。 A、B、Z三相联接,用于带参考位修正的位置测量。 A、A-, B、B-,Z、Z-连接,由于带有对称负信号的连接,电流对于电缆贡献的电磁场为0,衰减最小,抗干扰最佳,可传输较远的距离。 对于TTL的带有对称负信号输出的编码器,信号传输距离可达150米。 对于HTL的带有对称负信号输出的编码器,信号传输距离可达300米。

编码器的工作原理及分类

编码器的工作原理及分类 编码器的工作原理及作用:它是一种将旋转位移转换成一串数字脉冲信号的旋转式传感器,这些脉冲能用来控制角位移,如果编码器与齿轮条或螺旋丝杠结合在一起,也可用于测量直线位移。 编码器产生电信号后由数控制置CNC、可编程逻辑控制器PLC、控制系统等来处理。这些传感器主要应用在下列方面:机床、材料加工、电动机反馈系统以及测量和控制设备。在ELTRA编码器中角位移的转换采用了光电扫描原理。读数系统是基于径向分度盘的旋转,该分度由交替的透光窗口和不透光窗口构成的。此系统全部用一个红外光源垂直照射,这样光就把盘子上的图像投射到接收器表面上,该接收器覆盖着一层光栅,称为准直仪,它具有和光盘相同的窗口。接收器的工作是感受光盘转动所产生的光变化,然后将光变化转换成相应的电变化。一般地,旋转编码器也能得到一个速度信号,这个信号要反馈给变频器,从而调节变频器的输出数据。 故障现象:旋转编码器坏(无输出)时,变频器不能正常工作,变得运行速度很慢,而且一会儿变频器保护,显示“PG断开”。。。联合动作才能起作用。要使电信号上升到较高电平,并产生没有任何干扰的方波脉冲,这就必须用电子电路来处理。编码器pg接线与参数矢量变频器与编码器pg之间的连接方式,必须与编码器pg的型号相对应。一般而言,编码器pg型号分差动输出、集电极开路输出和推挽输出三种,其信号的传递方式必须考虑到变频器pg卡的接口,因此选择合适的pg卡型号或者设置合理。 编码器一般分为增量型与绝对型,它们存着最大的区别:在增量编码器的情况下,位置是从零位标记开始计算的脉冲数量确定的,而绝对型编码器的位置是由输出代码的读数确定的。在一圈里,每个位置的输出代码的读数是唯一的;因此,当电源断开时,绝对型编码器并不与实际的位置分离。如果电源再次接通,那么位置读数仍是当前的,有效的;不像增量编码器那样,必须去寻找零位标记。 现在编码器的厂家生产的系列都很全,一般都是专用的,如电梯专用型编码器、机床专用

旋转编码器详解

增量式编码器的A.B.Z 编码器A、B、Z相及其关系

TTL编码器A相,B相信号,Z相信号,U相信号,V相信号,W相信号,分别有什么关系? 对于这个问题的回答我们从以下几个方面说明: 编码器只有A相、B相、Z相信号的概念。 所谓U相、V相、W相是指的电机的主电源的三相交流供电,与编码器没有任何关系。“A相、B相、Z相”与“U相、V相、W相”是完全没有什么关系的两种概念,前者是编码器的通道输出信号;后者是交流电机的三 相主回路供电。 而编码器的A相、B相、Z相信号中,A、B两个通道的信号一般是正交(即互差90°)脉冲信号;而Z相是零脉冲信号。详细来说,就是——一般编码器输出信号除A、B两相(A、B两通道的信号序列相位差为90度)外,每转一圈还输出一个零位脉冲Z。 当主轴以顺时针方向旋转时,输出脉冲A通道信号位于B通道之前;当主轴逆时针旋转时,A通道信号则位于B通道之后。从而由此判断主轴是正转还是反转。 另外,编码器每旋转一周发一个脉冲,称之为零位脉冲或标识脉冲(即Z相信号),零位脉冲用于决定零位置或标识位置。要准确测量零位脉冲,不论旋转方向,零位脉冲均被作为两个通道的高位组合输出。由于通道之间的相位差的存在,零位脉冲仅为脉冲长度的一半。 带U、V、W相的编码器,应该是伺服电机编码器 A、B相是两列脉冲,或正弦波、或方波,两者的相位相差90度,因此既可以测量转速,还可以测量电机的旋转方向Z相是参考脉冲,每转一圈输出一个脉冲,脉冲宽度往往只占1/4周期,其作用是编码器自我校正用的,使得编码器在断电或丢失脉冲的 时候也能正常使用。 ABZ是编码器的位置信号,UVW是电机的磁极信号,一般用于同步电机; AB对于TTL/HTL编码器来说,AB相根据编码器的细分度不同,每圈有很多个,但Z相每圈只有一个; UVW磁极信号之间相位差是120度,随着编码器的角度转动而转动,与ABZ 之间可以说没有直接关系。 /#############################################################

Arduino关于旋转编码器程序的介绍资料

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 / https://www.doczj.com/doc/0d11204399.html, * 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)) {//上升沿

旋转编码器的原理及应用

旋转编码器的原理及应用 旋转编码器是用来测量转速的装置。它分为单路输出和双路输出两种。技术参数主要有每转脉冲数(几十个到几千个都有),和供电电压等。单路输出是指旋转编码器的输出是一组脉冲,而双路输出的旋转编码器输出两组相位差90度的脉冲,通过这两组脉冲不仅可以测量转速,还可以判断旋转的方向。 什么是光电编码器? 工作原理:当光电编码器的轴转动时A、B两根线都产生脉冲输出,A、B两相脉冲相差90度相位角,由此可测出光电编码器转动方向与电机转速。如果A相脉冲比B相脉冲超前则光电编码器为正转,否则为反转.Z 线为零脉冲线,光电编码器每转一圈产生一个脉冲.主要用作计数。A线用来测量脉冲个数,B线与A线配合可测量出转动方向. N为电机转速Δn=ND测-ND理 例如:我们车的速度为1.5m/s,轮子的直径220mm,C=D*Pi,电机控制在21.7转/秒,根据伺服系统的指标, 设电机转速为1500转/分,故可求得当ND=21.7*60=130转/分时,光码盘每秒钟输出的脉冲数为: PD=130×600/60=1300个脉冲 当测出的脉冲个数与计算出的标准值有偏差时,可根据电压与脉冲 个数的对应关系计算出输出给伺服系统的增量电压△U,经过D/A转换,再计算出增量脉冲个数,等下减去。 当运行时间越长路线越长,离我们预制的路线偏离就多了。这时系统起动位置环,通过不断测量光电编码器每秒钟输出的脉冲个数,并与标准值PD(理想值)进行比较,计算出增量△P并将之转换成对应的D/A 输出数字量,通过控制器减少输个电机的脉冲个数,在原来输出电压的基础上减去增量,迫使电机转速降下来,当测出的△P近似为零时停止调节,这样可将电机转速始终控制在允许的范围内。

绝对值旋转编码器程序

绝对值旋转编码器程序 #include // 寄存器头文件包含 #include // 寄存器头文件包含 #include // 空操作函数,移位函数头文件包含 #define uchar unsigned char #define uint unsigned int /* sbit SH_CP = P1^1; //移位时钟脉冲端口 sbit DS = P1^2; // 串行数据输入端口 sbit ST_CP = P3^7; //锁存端口 */ int inc_data=0; //每刷新一次的增量值 int jms=0; //累计增量 int m_iPrvSSI = 0; int m_bIsSPI = 0; uchar uPrvState = 0; sbit AA = P3^3;// sbit BB = P3^4;//这个是时钟 sbit ZZ = P3^5;//这个是数据 sbit BEEP=P1^5; //正反判断 bit t_bFang = 1; int a; int iSSI = 0;

int temp,num,j; uchar led_buf[12]; /*定义LED显示缓冲区*/ uchar code table[]="0123456789"; void delay (int t) { int i,j; for(i=1;i for (j=1;j } void GetSSI(void) { uchar ix = 0; // uchar uState = 0; //状态位数据 int iSSI = 0;//当前的角度数据(0-1023) bit bCrc = 0; // 奇数或偶数标志位 int ire = 0; //增量数据,表示上次正确读的数据,和这次正确读的位置差 AA = 0; //CSN _nop_();_nop_(); BB = 0;//CLK _nop_();_nop_(); BB = 1;//CLK _nop_();_nop_(); for(ix = 0; ix { BB = 0;//CLK

旋转编码器的输出电路以及常用术语介绍

旋转编码器的输出电路以及常用术语介绍 来源:互联网 旋转编码器是用来测量转速的装置,光电式旋转编码器通过光电转换,可将输出轴的角位移、角速度等机械量转换成相应的电脉冲以数字量输出(REP)。当旋转编码器轴带动光栅盘旋转时,经发光元件发出的光被光栅盘狭缝切割成断续光线,并被接收元件接收产生初始信号。该信号经后继电路处理后,输出脉冲或代码信号。旋转编码器的特点是体积小,重量轻,品种多,功能全,频响高,分辨能力高,力矩小,耗能低,性能稳定,可靠使用寿命长等特点。其主要种类有增量式编码器、绝对值编码器、正弦波编码器。 输出电路图解 1、NPN电压输出和NPN集电极开路输出线路 PNP开路集电极输出

电压输出 此线路仅有一个NPN型晶体管和一个上拉电阻组成,因此当晶体管处于静态时,输出电压是电源电压,它在电路上类似于TTL逻辑,因而可以与之兼容。在有输出时,晶体管饱和,输出转为0VDC的低电平,反之由零跳向正电压。 随着电缆长度、传递的脉冲频率、及负载的增加,这种线路形式所受的影响随之增加。因此要达到理想的使用效果,应该对这些影响加以考虑。集电极开路的线路取消了上拉电阻。这种方式晶体管的集电极与编码器电源的反馈线是互不相干的,因而可以获得与编码器电压不同的电流输出信号。 2、PNP和PNP集电极开路线路 该线路与NPN线路是相同,主要的差别是晶体管,它是PNP型,其发射极强制接到正电压,如果有电阻的话,电阻是下拉型的,连接到输出与零伏之间。 3、推挽式线路 这种线路用于提高线路的性能,使之高于前述各种线路。事实上,NPN电压输出线路的主要局限性是因为它们使用了电阻,在晶体管关闭时表现出比晶体管高得多的阻抗,为克服些这缺点,在推挽式线路中额外接入了另一个晶体管,这样无论是正方向还是零方向变换,输出都是低阻抗。推挽式线路提高了频率与特性,有利于更长的线路数据传输,即使是高速率时也是如此。信号饱和的电平仍然保持较低,但与上述的逻辑相比,有时较高。任何情况下推挽式线路也都可应用于NPN或PNP线路的接收器。

案例五旋转编码器的安装与应用

案例五旋转编码器的安装与应用 1.项目训练目的 掌握旋转编码器的安装与使用方法。 2.项目训练设备 旋转编码器及相应耦合器一套。 3.项目训练内容 先熟悉旋转编码器的使用说明书。 (1)旋转编码的安装步骤及注意事项 ①安装步骤: 第一步:把耦合器穿到轴上。不要用螺钉固定耦合器和轴。 第二步:固定旋转编码器。编码器的轴与耦合器连接时,插入量不能超过下列值。 E69-C04B型耦合器,插入量 5.2mm;E69-C06B型耦合器,插人量 5.5mm;E69-Cl0B型耦合器,插入量7.lmm。 第三步:固定耦合器。紧固力矩不能超过下列值。E69-C04B型耦合器,紧固力矩2.0kfg?cm;E69-C06B型耦合器,紧固力矩 2.5kgf?cm;E69B-Cl0B型耦合器,紧固力矩4.5kfg?cm。 第四步:连接电源输出线。配线时必须关断电源。 第五步:检查电源投入使用。 ②注意事项: 采用标准耦合器时,应在允许值内安装。如图5-1所示。 图5-1 标准耦合器安装 连接带及齿轮结合时,先用别的轴承支住,再将旋转编码器和耦合器结合起来。如图 5-2所示。 图5-2 旋转编码器安装 齿轮连接时,注意勿使轴受到过大荷重。 用螺钉紧固旋转编码器时,应用5kfg?cm左右的紧固力矩。 固定本体进行配线时,不要用大于3kg的力量拉线。 可逆旋转使用时,应注意本体的安装方向和加减法方向。 把设置的装置原点和编码器的Z相对准时,必须边确定Z相输出边安装耦合器。 使用时勿使本体上粘水滴和油污。如浸入内部会产生故障。 (2)配线及连接

①配线应在电源0FF状态下进行。电源接通时,若输出线接触电源线,则有时会损坏输出回路。 ②若配线错误,则有时会损坏内部回路,所以配线时应充分注意电源的极性等。 ③若和高压线、动力线并行配线,则有时会受到感应造成误动作或损坏。 ④延长电线时,应在10m以下。还由于电线的分布容量,波形的上升、下降时间会延长,所以有问题时,应采用施密特回路等对波形进行整形。 还有为了避免感应噪声等,也要尽量用最短距离配线。集成电路输人时,要特别注意。 ⑤电线延长时,因导体电阻及线间电容的影响。波形的上升、下降时间变长,容易产 生信号间的干扰(串音),因此应使用电阻小、线间电容低的电线(双绞线、屏蔽线)。

编码器编程

我用的是三菱PLC的FX2N,这里有A、B、Z相的HK38系列的增量式旋转编码器,将PLC 的X0,X1,X2分别接编码器的A相和B相及Z相,用PLC的双相计数器C252计数,虽然我知道A相超过B相90°为顺时针转,滞后就逆时针转,但不知道如何具体编程,我的目的是达到测旋转轴的角度,从-135°~-30°~-10°~10°~+30°~-135°,正反转旋转 多谢各位,我改了一下,但仍旧没找到问题原因,但测试中发现,接X2和X5都能使C252复位,尽管手册上说只有X2复位,但由于以上提到的Z相接入任何一个输入端都使之ON,所以我就避开了接X2和X5端子,改接其他的端子,比如X3,这并不是因为它是高速输入端的一种才选,其他端也一样,因此我采用了软件复位,也没办法了,效果倒是达到了想要的,

DHSZ D200 K8 C235 M8130 HSZ是高速区间比较指令,前面加D是32位的。运作如下: D200 > C235 M8130 ON D200<=C235>=k8 M8131 ON D200 < C235 M8132 ON

将旋转编码器的A相或B相的输出信号连接至X0~X5,(使用不同的计数器,接不同的输入点)然后用高速计数器对编码器的脉冲信号进行计数。以C235为例,只进行加计数,脉冲编码器的A相或B相需要接入PLC的X0,当设备带动编码器旋转,则X0就有信号输入,C235就会进行计数。使用很简单。 需求一段三菱PLC+旋转编码器+变频器实行多段距离控制,例如:上升总距离为50cm,0-15cm 实行20hz运行、16-25 cm 实行35HZ运行、26-35cm实行40HZ 运行、36-46cm实行20HZ 运行、47-50cm实行10HZ运行;下降反之! 程序中的数字,是按每厘米100个脉冲设计的,在实际中还要经过计算。

2013.7-多摩川编码器总结

2013.7 多摩川编码器总结 一、摘要 基于CPLD 和DSP 实现CPLD 与多摩川编码器的通讯,通过对编码器发送请求,得到编码器发回的数据并进行解码,得到绝对位置值。 二、学习步骤: 1、熟悉工作环境,掌握Modelsim 以及Quartus 的使用。 2、阅读多摩川编码器的通讯协议。 3、根据协议编写testbench ,并在Modelsim 上进行仿真调试。 4、仿真通过后,通过Quartus 编译后下载到CPLD 上并与编码器通讯,实际情况下运行。 5、完成各项要求的功能。 6、对代码进行优化,尽可能减少资源占用。 7、验收。 三、总体结构 双绞线,差分式,串行 地址/数据总线接口 RO,DI,DIR逻辑信号 结构分三部分:多摩川编码器,CPLD ,DSP 。 1、编码器跟CPLD 之间通过MAX485电平转换进行连接。 2、CPLD 与DSP 则通过总线进行连接(这一部分结构编写学长已经完成并且提供了端口连接) 3、主要工作是CPLD 的解码部分。 四、通讯协议 1、TS5668的技术指标:(物理层) 精度:单圈精度: 17位(131 072) 多圈精度: 16位(65 536) 最高转速/ ( r ·min - 1 ): 6 000】 输出:差分NRZ 编码二进制 传输速度/Mbp s : 2. 5 发送、接收电路:差分形式 通信方式:主从模式 接口:3FG ,4sig+ ,5sig -,7VCC ,8DGND 。4和5为差分信号接口。 2、通信步骤如下图:(逻辑链路层) 1)CPLD 向编码器发送一个控制字CF 2)3us 后编码器返回数据包。 3)CPLD 对数据包进行解码,并将得到的数据放在总线上,等待DSP 获取。 具体流程如下图:

旋转编码器在S7-200的应用

运行工作方式,机器大概情况, 机器共18个工位,每个工位为一个机器过程,一个工件为5米(误差1CM)要求用2000线的轴式旋转编码器通过PLC协调控制完成每个工件。 每个工位都有一个人,1个绿启动按钮。一个绿灯,1个红色急停按钮,1个红灯。当1号工人按1号启动按钮后1号指示灯亮,2号工人按2号启动按钮后2号指示灯亮,直到第18个工人都按启动按钮后18灯全亮,机器开始运转,自动运转到5米后停止。绿灯全灭(记米自动复位)等待18个工人下一次继续给18个运行信号后运行。(红色按钮为紧急停车按钮:当工件工作到一半时紧急停车,手动不复位情况下,8个工人动启动后机器可继续当前的米数运转。手动复位则重新开始) 当18个工人无论哪个工人按红色按钮时机器立即停机(此时红色指示灯全亮,红色按钮释放后指示灯全灭)机器再次启动需18个工人都给启动信号才能运行。18个红色按钮共用PLC一个点。如果点富裕的话18个红按钮分为3组,一组6个共用一个点,用3个点实现这个功能。变频器运行过程,当给变频器运行信号时变频器缓慢启动逐渐加速到高速,指定记米到达时变频器缓慢减速到低速运行,记米到达后变频器立即停止刹车,18个工位如果少几个工位的把那几个工位短接,要不影响工作。

程序分为3部分,主程序,指示灯输出,初始化。初始化中有两个中断程序,分别为当前值=设定值时中断以及复位时产生的中断。高速计数器HDEF的通道是HSC0,意思为编码器的A、B相接I0.0、I0.1,复位接在I0.2。事件号是10,意思是选择A/B正交计数器。中断ATCH的事件号12代表当前值=设定值时中断。事件号28代表HSC0当I0.2高电平时产生中断。 主程序:

旋转编码器工作原理

增量式旋转编码器工作原理 增量式旋转编码器通过内部两个光敏接受管转化其角度码盘的时序和相位关系,得到其角度码盘角度位移量增加(正方向)或减少(负方向)。在接合数字电路特别是plc后,增量式旋转编码器在角度测量和角速度测量较绝对式旋转编码器更具有廉价和简易的优势。增量式编码器是直接利用光电转换原理输出三组方波脉冲A、B和Z相;A、B两组脉冲相位差90o,从而可方便地判断出旋转方向,而Z相为每转一个脉冲,用于基准点定位。它的优点是原理构造简单,机械平均寿命可在几万小时以上,抗干扰能力强,可靠性高,适合于长距离传输。其缺点是无法输出轴转动的绝对位置信息。 增量式旋转编码器的内部工作原理(附图) 增量式编码器是直接利用光电转换原理输出三组方波脉冲A、B和Z相;A、B两组脉冲相位差90o,从而可方便地判断出旋转方向,而Z相为每转一个脉冲,用于基准点定位。它的优点是原理构造简单,机械平均寿命可在几万小时以上,抗干扰能力强,可靠性高,适合于长距离传输。其缺点是无法输出轴转动的绝对位置信息。 A,B两点对应两个光敏接受管,A,B两点间距为 S2 ,角度码盘的光栅间距分别为S0和S1。 当角度码盘以某个速度匀速转动时,那么可知输出波形图中的S0:S1:S2比值与实际图的S0:S1:S2比值相同,同理角度码盘以其他的速度匀速转动时,输出波形图中的S0:S1:S2比值与实际图的S0:S1:S2比值仍相同。如果角度码盘做变速运动,把它看成为多个运动周期(在下面定义)的组合,那么每个运动周期中输出波形图中的S0:S1:S2比值与实际图的S0:S1:S2比值仍相同。 通过输出波形图可知每个运动周期的时序为

曳引机使用说明书

曳引机使用说明书 安全可靠人性创新 永磁同步无齿轮曳引机 MTA50000AB

序言 感谢您使用该系列永磁同步无齿轮曳引机产品! 永磁同步电机技术作为一种电动机新技术应用于电梯曳引机领域开始于二十世纪九十年代,它带来了一次电梯公司形式上的革命。该系列永磁同步无齿轮曳引机采用盘式制动器、内转子型式。 本公司研发的永磁同步无齿轮曳引机的各项指标设计均符合国家相关规定,每台曳引机出厂前都经过严格的质量检验,对制动力、绝缘耐压、振动、噪音等各项指标进行了全面的检测,从而保证产品的质量和性能符合标准规定。 此手册为产品的一部分,旨在为用户正确使用无齿轮曳引机并提供曳引机安装、保养方面的指导,请务必妥善保管于安全的地方,以方便服务人员使用。在对机器进行安装、调试、使用、维修前,请务必阅读并理解此手册的内容。对不按此手册或不按我公司工程人员指导进行违规操作所产生的所有后果,我公司有权不予承担。 我公司拥有对本手册及其所包含信息的所有权,并有权对手册内容进行版本更新,而不另行通知。 严禁任何单位和个人,不经本公司同意复制部分或全部内容,用于同行业产品的说明和介绍。

目录 序言 一安全 ........................................................................................................ - 1 -二产品说明 ................................................................................................ - 1 -2.1曳引机介绍 (1) 2.2曳引机工作条件 (1) 2.3防护等级 (1) 2.4产品型号 (2) 2.5外形安装尺寸 (2) 2.6备件 (3) 三运输、仓储及吊装 ................................................................................. - 3 -四安装 ........................................................................................................ - 4 -4.1使用前检查 (4) 4.2安装注意事项 (4) 4.3远程松闸手动装置的安装及使用说明 (4) 4.3.1 安装 ................................................................................................ - 4 - 4.3.2 使用说明 ........................................................................................ - 5 -

旋转编码器在线速度检测控制中的应用

在电缆生产线上,通常需要检测电缆的走线速度,用来控制收线电机的转速和计算线缆的长度。成缆工艺参数的稳定,直接关系到电线电缆的质量。 该项目是为某电缆厂的技术改造项目,要改造的设备是利用束线原理制造的盘绞式成缆机,改造的内容是更换全部电气控制系统。这种成缆机的放线盘固定,而收线盘固定在盘绞架上同时完成绞合和收线的双重运动。工作时,在线缆盘直流电机的带动下,完成电缆的收线运动,在排线电机的带动下实现电缆在收线盘的整齐排列。在大盘电机的带动下,通过齿轮箱带动盘绞架实现轴向旋转,完成电缆绞合运动,是保证节距的关键。线速度是由收线盘的旋转速度决定的,如果收线电机的转速恒定,收线盘随着收线轴的变粗,线速度会增大,因此,为保证收线速度恒定,要逐渐降低收线电机的转速。 1 系统设计原理 根据电缆的生产工艺要求,不同型号的电缆,其走线速度是恒定的。通常,电缆的运行速度是由电缆带动旋转编码器来检测的。电缆线速度测速示意图如图1所示。 该项目中,采用的旋转编码器的型号是TRDJ1000系列,旋转一周输出1 000个脉冲。因此,根据在一定时间内检测到的脉冲数,就可以计算出电缆的走线速度。实际应用中,将其与一加工精度极高、周长为500 mm的旋转编码器测量主动轮与旋转编码器同轴安装,主动轮与电缆接触。在电缆生产运动过程中,依靠摩擦力拉动测量轮旋转,这样就把电缆的直线位移(长度)转化为旋转编码器的脉冲数字信号输出。

设旋转编码器每旋转一周,其计数脉冲个数为NP(脉冲个数/转),则旋转编码器角分辨率(单位:(°)/个)为: P=360/NP 假定固定在旋转编码器转轴上的主动导向轮半径为r m,则旋转编码器位移分辨率(单位:m/个)为: Ps=27πr/NP 这时,若计数脉冲个数为N(个),则由旋转编码器测量的位移量S(单位:m)为: S=Ps·N 线缆走线速度V(单位:m/s)为: V=S/T 式中:T为接收N个脉冲所用的时间(单位:s)。 2 硬件电路设计原理 该检测电路以AT89C51单片机为控制核心,如图2所示,旋转编码器输出的脉冲,经过电平转换,变成O~5 V的TTL电平脉冲,送到AT89 C51单片机的外部中断INT0端。每收到

旋转编码器应用注意事项

旋转编码器应用注意事项 有网友问:增量旋转编码器选型有哪些注意事项? 应注意三方面的参数: 1.械安装尺寸,包括定位止口,轴径,安装孔位;电缆出线方式;安装空间体积; 工作环境防护等级是否满足要求。 2.分辨率,即编码器工作时每圈输出的脉冲数,是否满足设计使用精度要求。 3.电气接口,编码器输出方式常见有推拉输出(F型HTL格式),电压输出(E), 集电极开路(C,常见C为NPN型管输出,C2为PNP型管输出),长线驱动器输出。其输出方式应和其控制系统的接口电路相匹配。 ■二.※有网友问:请教如何使用增量编码器? 1,增量型旋转编码器有分辨率的差异,使用每圈产生的脉冲数来计量,数目从 6到5400或更高,脉冲数越多,分辨率越高;这是选型的重要依据之一。 2,增量型编码器通常有三路信号输出(差分有六路信号):A,B和Z,一般采用 TTL电平,A脉冲在前,B脉冲在后,A,B脉冲相差90度,每圈发出一个Z脉冲,可作为参考机械零位。一般利用A超前B或B超前A进行判向,我公司增量型编码器定义为轴端看编码器顺时针旋转为正转,A超前B为90°,反之逆时针旋转为反转B超前A为90 °。也有不相同的,要看产品说明。 3,使用PLC采集数据,可选用高速计数模块;使用工控机采集数据,可选用高 速计数板卡;使用单片机采集数据,建议选用带光电耦合器的输入端口。 4,建议B脉冲做顺向(前向)脉冲,A脉冲做逆向(后向)脉冲,Z原点零位脉冲。 5,在电子装置中设立计数栈。 ■三.※关于户外使用或恶劣环境下使用 有网友来email问,他的设备在野外使用,现场环境脏,而且怕撞坏编码器。 我公司有铝合金(特殊要求可做不锈钢材质)密封保护外壳,双重轴承重载型 编码器,放在户外不怕脏,钢厂、重型设备里都可以用。 不过如果编码器安装部分有空间,我还是建议在编码器外部再加装一防护壳,以加 强对其进行保护,必竟编码器属精密元件,一台编码器和一个防护壳的价值比较还 是有一定差距的。 ■四.※从接近开关、光电开关到旋转编码器: 工业控制中的定位,接近开关、光电开关的应用已经相当成熟了,而且很好用 。可是,随着工控的不断发展,又有了新的要求,这样,选用旋转编码器的应用优 点就突出了: 信息化:除了定位,控制室还可知道其具体位置; 柔性化:定位可以在控制室柔性调整; 现场安装的方便和安全、长寿:拳头大小的一个旋转编码器,可以测量从几个 μ到几十、几百米的距离,n个工位,只要解决一个旋转编码器的安全安装问题,可 以避免诸多接近开关、光电开关在现场机械安装麻烦,容易被撞坏和遭高温、水气 困扰等问题。由于是光电码盘,无机械损耗,只要安装位置准确,其使用寿命往往 很长。 多功能化:除了定位,还可以远传当前位置,换算运动速度,对于变频器,步 进电机等的应用尤为重要。 经济化:对于多个控制工位,只需一个旋转编码器的成本,以及更主要的安装 、维护、损耗成本降低,使用寿命增长,其经济化逐渐突显出来。

欧姆龙PLC与旋转编码器的应用

旋转编码器的应用 例:E6C-N绝对型多旋转高精度型旋转编码器与CPM1A PLC连接进行定位控制 一、连接示意图 型号E6C-NN5C 型号CPM1A-40CD□-□ 二、配线表 【型号E6C-NN5C和型号CPM1A的配线】 型号E6C-NN5C输出信号型号CPM1A 输入信号 单旋转导线外皮褐(20) 00000 数据颜色橙(21) 00001 (灰)黄(22) 00002 绿(23) 00003 蓝(24) 00004 紫(25) 00005 灰(26) 00006 白(27) 00007 粉红(28) 00008 多旋转导线外皮茶(20) 00100 数据颜色橙(21) 00101 (黑)黄(22) 00102 绿(23) 00103 蓝(24) 00104 紫(25) 00105 符号+=0 灰(26) 00106 -=1 白(27) 00107 三、输出时间 【输出时间】 型号E6C-NN5C的绝对值数据 1旋转 2旋转 127旋转 63999

四、梯形图程序 000通道的0 接点,输送到 (单旋转数 BIN) BIN BCD 001通道的 0~7接点,输送 到DM0003(多旋转 数据BIN) BIN 转换到BCD BCD)× 500(单旋转分辨率) 的结果存入 DM0005~6 比较带在DM0010/11的值与DM0012/13 的值间在线性绝对值数据时,输出01000 接点。(限正旋转时进行带域比较)

五、DM设定 【DM设定】 DM0000 0001 0002 0000 数据程序用工作区域 0003 0004 0005 0006 0007 线性绝对值数据 0008 0009 比较数据 0010 9000 0011 0000 上限值设定 0012 0500 0013 0001 下限值设定 注:上述梯形程序为参考例,有时会因程序控制器的数据读入时间而产生数据读取错误。这时,比较上次读入的数据与当前读入的数据。若超过100以上,则该数据作废。(多旋转数据变化时,同时读入单旋转数据与多旋转数据,则错误的数据也被读入。

多摩川产品资料说明

陀螺仪: 可应用于航空、航天、航海、兵器、汽车、生物医学、环境监控等领域。 1、体积小、重量轻。适合于对安装空间和重量要求苛刻的场合,例如弹载测量等。 2、低成本。 3、高可靠性。内部无转动部件,全固态装置,抗大过载冲击,工作寿命长。 4、低功耗。 5、大量程。适于高转速大g值的场合。 6、易于数字化、智能化。可数字输出,温度补偿,零位校正等。 测速发电机: 输出电动势与转速成比例的微特电机。测速发电机的绕组和磁路经精确设计,其输出电动势 E 和转速 n 成线性关系,即 E=Kn,K 是常数。改变旋转方向时输出电动势的极性即相应改变。在被测机构与测速发电机同轴联接时,只要检测出输出电动势,就能获得被测机构的转速,故又称速度传感器。 测速发电机广泛用于各种速度或位置控制系统。在自动控制系统中作为检测速度的元件,以调节电动机转速或通过反馈来提高系统稳定性和精度;在解算装置中可作为微分、积分元件,也可作为加速或延迟信号用或用来测量各种运动机械在摆动或转动以及直线运动时的速度。 电子凸轮: 利用角度位置传感器来模拟机械凸轮各控制点的角度范围,并能独立输出各自的控制信号,此种设备称为电子凸轮,包含“机械凸轮+微动开关”的基本功能。 ?可以输出多路控制开关量(ON/OFF),且每路都可以独立预设起始、终止角度。 ?可以动态检测和显示实际运行角度,对设备运行和再调整实时检测。 ?可以随时修改预设角度,且每一路均有 LED 状态指示,“开态”点亮,“关态”熄灭。 ?各路输出信号在电气上相互隔离,抗干扰能力强,可靠性高。 ?动作精度可达到1°typical 轨迹球: 外型尺寸:1、1.4、2、3英寸 输出方式:PS2、USB、方波、脉冲输出

旋转编码器(光电编码)c程序

/*----------------------------------------------- 名称:外部中断0边沿触发 内容:通过中断接口P3.2连接的旋转编码器脉冲输出端,用数码管显示旋转圈数,INT0设置为下降沿触发。 ------------------------------------------------*/ #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义/*------------------------------------------------ 主程序 ------------------------------------------------*/ #define uint unsigned int #define uchar unsigned char uint a=0,b=0; uchar Duma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//段码 uchar Wema[]={0,1,2,3,4,5,6,7};//位码 uchar Qushu[4]={0,0,0,0}; main() { uint x; uchar i; EA=1; //全局中断开 EX0=1; //外部中断0开 IT0=1; //边沿触发 P3=0xff; while(1) { for(i=0;i<4;i++) { P2=Wema[i]; P0=Duma[Qushu[i]]; //在此添加其他程序 for(x=0;x<1000;x++); } } } /*------------------------------------------------ 外部中断程序 ------------------------------------------------*/ void in0(void) interrupt 0 using 1 { a++; if(a>=500) {a=0; b++; if(b>9999) b=0; Qushu[0]=b/1000;

360旋转编码器

360°编码电位器原理 在音频功率放大器中,音量控制是必不可少的环节,尤其是现在用微电脑控制的多通道AV 功放,一般都采用一枚多通道音量控制芯片进行音量调节,而且根据标准要求:每个通道音量既需要总调又需要单独微调。因此,对音量控制手段提出了特殊要求。过去常用的普通多联碳膜电位器(手动或马达遥控)已无法适应这种要求,于是脉冲电位器或称数码电位器就应运而生。脉冲电位器能够360 度旋转,音量调节速度可编程控制,它寿命长、不产生噪声、,电路简单,这都是碳膜电位器无法比拟的。但其结构工作原理使用方法与普通电位器截然不同,本文讨论脉冲电位器原理及与单片机接口编程方法,旨在起到抛砖引玉的作用。 脉冲电位器的工作原理 从外观看,脉冲电位器与普通电位器一样都是三个引脚,但在其内部与引脚1、2相连的是两个长短不一的金属静片,与引脚3相连的是一周有12或24个齿的金属动片。当脉冲电位器旋转时可出现四种状态:即引脚3与引脚1相连,引脚3与引脚2及引脚1全相连;引脚3与引脚2相连,引脚3与引脚2及引脚1全断开。

在实际使用中,一般将引脚3接地作为数据输入端。而引脚1、2作为数据输出端与单片机I/O 口相连。如图2中所示,将引脚1与单片机的P1.0相连,引脚2与单片机的P1.1相连。当脉冲电位器左旋或右旋时,P1.0和P1.1就会周期性地产生图1所示的波形,如果是12点的脉冲电位器旋转一圈就会产生12组这样的波形,24点的脉冲电位器就会产生24组这样的波形;一组波形(或一个周期)包含了4个工作状态。因此只要检测出P1.0和P1.1的波形,就能识别脉冲电位器是否旋转是左旋还是右旋。 脉冲电位器接口编程方法

相关主题
文本预览
相关文档 最新文档