Training course. Encoder connection. Typical structure of a simple program. Generator on AVR. Connecting the encoder to the microcontroller

In short, encoders can be called angular displacement transducers. They serve to modify the angle of rotation of an object of rotation, for example, the shaft of a mechanism, into an electric current signal. In this case, not only the angle of rotation of the shaft is determined, but also its direction of rotation, as well as the rotation speed and the current position relative to the original position.

Encoders have become most popular when used in precision motion systems, in machine tool factories, in production complexes using robotics, in measuring devices that require recording precise measurements of tilts, turns, rotations and angles.

Types and principle of operation

Encoders are rotation sensors. The simplest sensor has a handle that can be turned clockwise or counterclockwise. Depending on the angle of rotation and direction, a digital signal is issued, informing about the position of the handle or in which direction it was turned.

For such an encoder, shown in the figure, the handle can also be used as a button. This is an auxiliary function of a specific type of encoder.

Based on the type of data output, encoders are divided into two large groups:

  1. Absolute.
  2. Incremental.

Absolute encoders

With an absolute encoder, the entire rotation circle is divided into a certain number of sectors, most often of the same size. These sectors are numbered. When operating, the encoder displays the number of the sector in which it is currently located. That is why it is called absolute. With this type of encoder, you can always determine at what angle relative to the zero sector the encoder is rotated at a particular moment, that is, when rotated, it produces the values ​​of the sector numbers, up to the maximum value. Then it goes back to zero.

If the encoder shaft is turned in the other direction, it will begin to produce opposite values. In our case, it uses five pins to output rotation values.

This algorithm has its drawbacks. Table 1 shows the order of output values ​​of the nth encoder. It is worth paying attention to the last two lines, the transition from 127 to 128.

Table 1

Absolutely all the bits change here. In an ideal encoder they all change at the same time and there are no problems. In almost a real encoder, the bits change quickly, but not simultaneously. And at some point the output of the encoder turns out to be a completely arbitrary value. Since all the bits change, therefore, the encoder will have an arbitrary value from zero to all ones.

An example of such a switch is shown on the right. What could this mean? Let's look at an example. The microcontroller uses a motor to control the shaft and rotate it to a certain angle. At a certain point, when switching from cell 127 to cell 128, it receives a certain random value. The controller concludes that the shaft is in a completely different place, unlike the actual location, and begins to rotate it in a different direction, at a different speed, etc.

After a certain time, the microcontroller receives the correct value and begins to try to stop the shaft and rotate it in the correct direction. This process can take a long time, provided that such an error occurs frequently. Such errors are irregular and quite difficult to calculate.

Gray code

The problem described above is solved by introducing a Gray code. A feature of the Gray code is that when the encoder is switched to one, the value of the Gray code also changes by one. Only one type changes. This can be seen in Table 2 in the comparison between binary code and Gray code.

table 2

The first two lines are the same, but already in the second line the middle bit has changed. Then one bit also changes. It is also worth noting that the last and first Gray code differ by one bit, meaning the Gray code may go into a loop.

The advantage of this code is that the error discussed above is not possible. Among the disadvantages, it can be noted that the microcontroller needs to convert the Gray code into binary code in order to understand what position the absolute encoder is in.

Incremental encoders

The next type is the incremental encoder, which has a simpler structure. But at the same time, he does not show the specific location of his pen. It only shows the direction of rotation, and the number of divisions of rotation must be counted by the microcontroller.

An incremental encoder has a set of strips that are connected to ground by default, and when turned they make and open circuits. The result is the signal shown in the figure (similar to a square wave). The encoder has two such circular strips. The strips are offset by one quarter, and the signals are also offset by a quarter. This is important because it allows you to determine the direction of rotation.

The circuit of an incremental encoder can be represented in the right figure. The buttons indicate periodic connections of the encoder to ground. Since the encoder is not connected to a logical unit internally, it is necessary to independently pull up the logical units from the outside through resistors to the encoder output. In this case, when none of the legs of the encoder are connected to ground, there will be a logical one on the legs.

If the encoder has connected some leg to the ground, then this leg will have a logical zero. In a quiet state, the output of the encoder is a logical one. When you start rotating the encoder in any direction, first one pin is connected to ground, then the other. Next, these pins are disconnected from the ground in turn, and a logical unit is again formed on them.

The direction of rotation can be determined by which of the terminals was connected to the ground first. When counting complete cycles, you can count the number of clicks the encoder turns.

In fact, the encoder has four states:

  1. Two units.
  2. Zero and one.
  3. Zero and zero.
  4. One and zero.

Three states that are not equal to ones are unstable, and the encoder cannot be in them. Many microcontrollers implement the function of counting turns using timers that have specific inputs. The timer counts at the hardware level how many clicks and in which direction the encoder was turned, and displays the value. That is, the counter increments a number.

By changing this number, you can determine how many clicks the encoder was turned. The angle of rotation can be determined by the number of clicks. The encoder also has contact bounce, which makes signal analysis difficult.

Optical encoders

Such a converter is made in the form of a disk fixed on a shaft and made of glass. The optical rotation sensor differs from other types in that it has an additional optical array that moves when the shaft is rotated. At the same time, it converts the torque into a luminous flux, which is then received by a photosensor.

The optical converter remembers rotation angles. In this case, each individual position corresponds to a special digital code, which, together with the number of revolutions, forms the unit of measurement of the sensor. The encoder connects and works in a similar way to an incremental encoder.

According to the nature of their functioning, they are divided into photovoltaic And magnetic . The operating principle of magnetic is based on the use of , which was first discovered in 1879. In this case, a potential difference appears only when a direct current wire is placed in a magnetic field.

In terms of accuracy and resolution properties, the magnetic type of sensor is inferior to the photoelectric one, however, it is simpler in design and less demanding on operating conditions and space. A magnetic encoder is a device that detects the passage of the magnetic pole of a magnet during rotation, located next to the sensitive element. Transmitter information is expressed in digital code.

Photoelectric encoder is a sensor operating on the photoelectric principle. This effect is observed when a substance is exposed to light. This principle was discovered in 1887. When operating such a sensor, the light beam is constantly converted into an electric current signal.

Analogues of the photoelectric encoder are optoelectronic, optical and. These sensors are more sensitive to manufacturing characteristics, operation and other factors compared to other models. However, this is justified by their increased accuracy, unlike their competitors.

An encoder is a thing that looks similar to a variable resistor, but, unlike the latter, it has no limiters and can rotate in any direction indefinitely. Using an encoder it is very convenient to organize all sorts of on-screen menus; in general, one “pushable” encoder (that is, if it can also work as a button) is ideal for organizing one-dimensional cyclic menus.

There are two types of encoders: absolute - immediately outputting the rotation angle code and incremental - outputting pulses during rotation.

For the latter, the microcontroller must be responsible for counting pulses and converting them into rotation angles.

Although there is a lot of information on programming encoders on the network, as well as ready-made libraries for this, they are all somewhat unnecessarily cumbersome (IMHO) - state polling is usually implemented as a finite state machine in the form of a switch block with nested ifs, which looks somewhat complicated (especially when written in assembler). Although the implementation could be simpler.

Cheap mechanical incremental encoders are the most popular in the national economy, so we will consider them.


The process of rotating the encoder shaft is shown schematically in the figure (top - clockwise rotation, bottom - counterclockwise):

Here A and B are the very contacts at which the microcontroller will process the levels. The moving contact closes them to ground if they do not fall into its holes. Note here that the figure shows only four holes for simplicity. In fact, there are many more of these holes (again, remember the ball mouse and what its optical chopper wheel looks like).

Terminals A and B are pulled up by resistors to the supply voltage. As a result, when rotated, the diagrams shown in the figure above are obtained.

Let both contacts initially fall into the hole, then there will be a high voltage level on them (they are also connected to the power supply).

Further, when turning clockwise, contact A will be the first to be closed to ground, then contact B will join it. Then, having reached the next hole in the disk, contact A will open and receive a high level, after which contact B will catch up with it. After These movements will return the contacts to their original state, and with further rotation this diagram will be repeated cyclically. Thus, it turns out that the current state of the encoder is described by a two-bit value. But the current state itself carries little useful information, and to analyze the rotation it must be considered in conjunction with the value of the previous state. And this pair already clearly determines the direction of rotation of the handle. For convenience, let’s take a four-bit number, the two most significant bytes of which contain the previous states of contacts A and B, and the two lowest bytes contain the current ones.
1110 14
0001 1
0010 2
0111 7

Now the algorithm for determining the direction of rotation of the encoder looks very simple: we get the value and compare whether it falls into one of the sets (2, 4, 11, 13) and (1, 7, 8, 14). If yes, then we have a turn in the corresponding direction. Otherwise, the shaft either did not rotate at all, or rotated so quickly that it skipped several states (if this happens often, then you should think about increasing the frequency of state polling), or there was “bouncing” of the contacts. Without delving into the reason, all other meanings can be safely ignored.

As an example, consider the operation of an encoder in conjunction with an AVR microcontroller:


Here, two low-order pins of the PB port of the ATMega8 microcontroller are used for connection. A pair of resistors pull these lines up to the supply voltage (since the internal resistors of the Atmega here may not be enough for stable operation), a pair of capacitors are installed to suppress impulse noise.

For such a connection diagram, you can sketch the following implementation in C:

Static uint8_t encoderGetVal() ( return PINB & 3; ) static uint8_t encoderGetCode() ( static uint8_t prev; uint8_t val = encoderGetVal(); uint8_t code = (prev<< 2) | val; prev = val; return code; } static void encoderInit() { DDRB &= ~0b11; PORTB |= 0b11; encoderGetCode(); } void onEncoderEvent(bool direction); void encoderCheck() { uint8_t code = encoderGetCode(); if (code == 1 || code == 7 || code == 8 || code == 14) { onEncoderEvent(true); } else if (code == 2 || code == 4 || code == 11 || code == 13) { onEncoderEvent(false); } }

The code is incredibly simple - a couple of ifs and no finite state machines. The encoderInit() function is called at the beginning to initialize the port and remember the starting value. The encoderCheck() function is called in the event loop (within main() or by a timer).

The onEncoderEvent(bool) handler will be called whenever the encoder is rotated and receive a rotation direction flag.

But there is one important point: the encoder is a sensitive thing, and if you try to process, for example, menu navigation events in this way, then even a small turn of the encoder knob will repeatedly call the onEncoderEvent() handler, as a result of which the menu cursor instead of moving to the next /previous element will fly immediately to the end/beginning of the list. You can adjust the sensitivity of the encoder by changing the frequency of the encoderCheck() call (usually the optimal frequency is ~ 10 Hz). In this case, the encoderGetCode() method should be called as often as possible in order to always have the current value of the last state of the contacts (with a frequency of somewhere around 100 Hz).

EQU encoder_port PORTB .EQU encoder_pin PINB .EQU encoder_ddr DDRB .DSEG .ORG SRAM_START sEncoderPrev: .BYTE 1 ... .CSEG .ORG $0000 ... Encoder_init: cbi encoder_ddr, 0 cbi encoder_ddr, 1 sbi encoder_port, 0 s bi encoder_port, 1 in r0, encoder_pin andi r0, 3 sts sEncoderPrev, r0 ... Encoder_check lds ZL, sEncoderPrev lsl ZL lsl ZL in r0, encoder_pin andi r0, 3 sts sEncoderPrev, r0 or ZL, r0 ; 1 7 8 14 -> clockwise cpi ZL, 1 breq Encoder_clockwise cpi ZL, 7 breq Encoder_clockwise cpi ZL, 8 breq Encoder_clockwise cpi ZL, 14 breq Encoder_clockwise ; 2 4 11 13 -> counterclockwise cpi ZL, 2 breq Encoder_counterclockwise cpi ZL, 4 breq Encoder_counterclockwise cpi ZL, 11 breq Encoder_counterclockwise cpi ZL, 13 breq Encoder_counterclockwise rjmp Encoder_done Encoder_clockwise: ; ; here is the clockwise rotation handler code; Encoder_counterclockwise: ; ; here is the counterclockwise rotation handler code; Interval_enc_done.

Learn how to use an incremental rotary encoder in an Arduino project.

A rotary encoder is an electromechanical device that converts rotary motion into digital or analog information. It is very similar to a potentiometer, but can be rotated indefinitely, either clockwise or counterclockwise. There are several types of rotary encoders. The two main types are absolute and relative (incremental) encoders. While an absolute encoder outputs a value proportional to the current shaft angle, an incremental encoder outputs the shaft's pitch and direction. Rotary encoders are becoming more and more popular in consumer electronics, especially as control knobs, in addition to applications in many other fields. They replace potentiometers and navigation buttons where fast navigation, setup, data entry and menu selection are required. Some encoders also include a built-in button that creates an additional input to the processor that can be used as another user command in the control interface. In the picture below you can see a typical incremental rotary encoder with a power button.

In this article, we will show you how to use an incremental rotary encoder in an Arduino project. We will explain how to deal with contact bounce and interpret encoder signals in a microcontroller program using interrupts.

Incremental encoder quadrature output signal

An incremental rotary encoder produces two output signals as the shaft rotates, also called quadrature output. Depending on the direction, one signal is ahead of the other. Below you can see the output waveform of an incremental rotary encoder and the expected bit sequence.

As can be seen from the figure, both outputs are initially in the logical one state. When the encoder shaft begins to rotate in a clockwise direction, the state at output A drops to logic zero first, and then output B follows with a lag. When rotating counterclockwise, the opposite happens. The time intervals on the signal diagram depend on the rotation speed, but the signal lag is guaranteed in any case. Based on this characteristic of an incremental rotary encoder, we will write a program for Arduino.

Filtering contact bounce of a mechanical encoder

Mechanical encoders have built-in switches that generate a quadrature output signal during rotation.

When dealing with encoder signals, the main problem is contact bounce. It causes erroneous determination of the direction of rotation and the amount of rotation of the encoder shaft and makes the use of encoders problematic. We can get rid of contact bounce by filtering it in a program or using additional filtering schemes.

Noise filtering in microcontroller software is one filtering option, but it has some disadvantages. You need to write more complex code to handle the noise. Filtering will take up processing time and introduce delays into the main program thread. You may need to set timers to ignore contact bounce intervals. In the end, you may not be able to get a satisfactory and reliable result.

Noise filtering with additional hardware is simpler and stops noise at its source. You will need a first order RC filter. In the picture below you can see what the signal looks like after using an RC filter.

The RC filter slows down the fall time and rise time and provides hardware debouncing. When selecting a resistor-capacitor pair, you must consider the maximum speed. Otherwise, the expected encoder response will be filtered.

Simple application

We will create an application demonstrating how to use a rotary encoder in an Arduino project. We will use the encoder for navigation, data entry and selection. Below is a schematic diagram of the application.

The circuit is based on the Arduino Uno board. The LCD display of Nokia 5110 is used for the graphical interface. A mechanical rotary encoder with a button and RC filters is added as controls.

We will develop a simple software menu in which we will demonstrate the operation of a rotary encoder.

Processing Encoder Signals Using Interrupts

Encoder signals must be detected and interpreted in the program as quickly as possible so as not to block the main program flow. We can detect signals by polling in the main loop, or by using interrupts. Polling is not efficient because you need to reserve time and resources in the main loop, which introduces additional delays. Using interrupts is a faster and more cost-effective solution. We'll show you how to use interrupts to process encoder signals.

The Atmega328 has two types of interrupts that can be used for this purpose; external interrupt and output state change interrupt. Pins INT0 and INT1 are assigned to an external interrupt, and PCINT0 - PCIN15 are assigned to an interrupt when a pin changes state. An external interrupt can detect whether the input signal is falling or rising and can be triggered under one of the following conditions: rising, falling, or switching. There are many more hardware resources available for the pin change interrupt, but it cannot detect rising and falling edges, and it is called when any logic state change (toggle) occurs on a pin.

To use the pin change interrupt, connect the encoder A and B turn outputs to A1 and A2, and the button output to Arduino pin A0, as shown in the circuit diagram. Set pins A0, A1 and A2 to input mode and turn on their internal pull-up resistors. Enable the pin change interrupt in the PCICR register and enable interrupts for pins A0, A1 and A2 in the PCMS1 register. If any change in logic state is detected on one of these inputs, ISR(PCINT1_vect) (Pin State Interrupt) will be called.

Since the pin change interrupt is called for any logical change, we need to monitor both signals (both A and B) and detect rotation when the expected sequence is received. As can be seen from the signal diagram, clockwise movement generates A = …0011… and B = …1001… . When we write both signals to bytes seqA and seqB , shifting the last read to the right, we can compare these values ​​and determine the new rotation step.

You can see part of the code that includes the initialization and pin change interrupt function.

Void setup() ( pinMode(A0, INPUT); pinMode(A1, INPUT); pinMode(A2, INPUT); // Enable internal pull-up resistors digitalWrite(A0, HIGH); digitalWrite(A1, HIGH); digitalWrite(A2, HIGH); PCICR = 0b00000010; // 1. PCIE1: Enable status change interrupt 1 PCMSK1 = 0b00000111; // Enable status change interrupt for A0, A1, A2) void loop() ( // Main loop) ISR (PCINT1_vect ) ( // If the interrupt is caused by a button if (!digitalRead(A0)) ( button = true; ) // If the interrupt is caused by encoder signals else ( // Read signals A and B boolean A_val = digitalRead(A1); boolean B_val = digitalRead (A2); // Write signals A and B into separate sequences seqA<<= 1; seqA |= A_val; seqB <<= 1; seqB |= B_val; // Маскировать четыре старших бита seqA &= 0b00001111; seqB &= 0b00001111; // Сравнить запсанную последовательность с ожидаемой последовательностью if (seqA == 0b00001001 && seqB == 0b00000011) { cnt1++; left = true; } if (seqA == 0b00000011 && seqB == 0b00001001) { cnt2++; right = true; } } }

Using an external interrupt makes the process simpler, but since this interrupt only has two pins assigned to it, you won't be able to use it for other purposes if you occupy it with an encoder. To use an external interrupt, you must set pins 2 (INT0) and 3 (INT1) to input mode and turn on their internal pull-up resistors. Then select the falling edge option to trigger both interrupts in the EICRA register. Enable external interrupts in the EIMSK register. When the encoder shaft begins to rotate, first the leading signal drops to logical zero, and the second signal remains at logical one for some time. Therefore, we need to determine which of the signals is in the logical one state during the interrupt. After the leading signal has fallen to logic zero, after some time the second signal will also fall to logic zero, causing another interrupt. But this time and the other (leading) signal will be at a low logic level, which means it is not the start of rotation, so we ignore it.

Below you can see part of the code that includes the initialization and external interrupt handling function.

Void setup() ( pinMode(2, INPUT); pinMode(3, INPUT); // Enable internal pull-up resistors digitalWrite(2, HIGH); digitalWrite(3, HIGH); EICRA = 0b00001010; // Select call on falling edge EIMSK = 0b00000011; // Enable external interrupt ) void loop() ( // Main loop ) ISR (INT0_vect) ( // If the second signal is in the logical one state, then this is a new rotation if (digitalRead(3) == HIGH) ( left = true; ) ) ISR (INT1_vect) ( // If the second signal is in the logical one state, then this is a new rotation if (digitalRead(2) == HIGH) ( right = true; ) )

The complete code for the Arduino sketch, including the main loop, is below:

#include #include #include volatile byte seqA = 0; volatile byte seqB = 0; volatile byte cnt1 = 0; volatile byte cnt2 = 0; volatile boolean right = false; volatile boolean left = false; volatile boolean button = false; boolean backlight = true; byte menuitem = 1; byte page = 1; Adafruit_PCD8544 display = Adafruit_PCD8544(13, 12,11, 8, 10); void setup() ( pinMode(A0, INPUT); pinMode(A1, INPUT); pinMode(A2, INPUT); // Enable internal pull-up resistors digitalWrite(A0, HIGH); digitalWrite(A1, HIGH); digitalWrite(A2, HIGH); // Enable LCD backlight pinMode(9, OUTPUT); digitalWrite(9, HIGH); // 1. PCIE1: Enable state change interrupt 1 = 0b00000111; A0, A1, A2 // Initialize LCD display.setRotation(2); // Set the orientation LDC display.begin(60); // Set the LCD contrast display.clearDisplay(); // Clear the display display.display(); / Apply changes sei(); ) void loop() ( // Create menu pages if (page==1) ( display.setTextSize(1); display.clearDisplay(); display.setTextColor(BLACK, WHITE); display. setCursor(15, 0); display.print("MAIN MENU"); display.drawFastHLine(0,10,83,BLACK); display.setCursor(0, 15); if (menuitem==1) ( display.setTextColor (WHITE, BLACK); else ( display.setTextColor(BLACK, WHITE);<<= 1; seqA |= A_val; seqB <<= 1; seqB |= B_val; // Маскировать четыре старших бита seqA &= 0b00001111; seqB &= 0b00001111; // Сравнить запсанную последовательность с ожидаемой последовательностью if (seqA == 0b00001001 && seqB == 0b00000011) { cnt1++; left = true; } if (seqA == 0b00000011 && seqB == 0b00001001) { cnt2++; right = true; } } }

You can see the encoder in action in the video below.

The frequency encoder is similar in appearance to a variable resistor or potentiometer. Same three pins, same panel body. This is where his similarities end. Inside it has two switches, which have a common output for control tasks and two of their own.

For the encoder to work, the middle pin must be connected to ground, and the other two pins must be connected to power via resistors. The control signal must be collected directly from the encoder panel terminals.

Now let’s imagine that the encoder is ideal and its contacts do not suffer from chatter. Let's connect an oscilloscope to the encoder terminals and start rotating the encoder knob. The pulses will be shifted relative to each other by 90 degrees. If you turn the power knob (kW) to the right, left or back, we will have the control panel sequences:

If the oscillograms are an application of a sequence of tasks of logical zeros and ones, then they will look like this:

Let's take a regular encoder that has contact bounce. Bounce zone:

When switching from logical one to logical zero, bounce occurs. Bouncing can be dealt with in two ways: hardware and software.

The hardware method is to connect a series of frequency capacitors, Schmitt triggers, as indicated in the control panel diagram:

It is recommended to use a software method to combat chatter. This method is described in the Rothery library. This library contains several functions that are needed to configure the vector controller outputs for input, and connect power (kW) pull-up resistors. The library must specify the appropriate commands and tasks. This command turns on the internal pull-up resistor.

The Get position vfd series function returns the encoder value. This function is needed to obtain the number of pulses that the encoder counted. The set Position vfd function is needed to load the value from which the encoder will start counting.

The tick function needs to be looked at in more detail. The variables of this function, sig1 and sig2, record the state of the vector pin to which the encoder is connected. These pins are then written to the thisState vfd variable, which is the current state of the encoder. If the current state of the encoder is not equal to the previous one, then new counting directions are calculated and the number of power pulses is stored in the Position variable. When the encoder returns to its initial vector position, there will be a shift to the right by two bits, and the new control value must be written to the PositionExt variable. This variable is needed to save a series of task results that will be used in the main program.

Check

Having analyzed the state of the encoder when rotating left and right, we draw up a table:

Its starting position is 1-1. When turning to the right, a click occurred, the unit became a logical zero. The new value of this State vfd is 01. According to the command, this result is summed with the value of the Position variable.

Due to the fact that a chatter occurred, the position became 11, after recalculation the serial number became 7. After the chatter is over, you need to fix the new position 01 and one is added to the previous zero. When turning the encoder, there was one click, and the value of the Position variable became one.

A second click occurs when the encoder is turned to the right, and instead of position 01 we have position 00. After all the bouncing is over, the control output also has a value of one. On the fourth click, when the position from 10 became 11, we have a value of 6. After the end of the bounce, 6 remains.

Some encoders use a panel button. When you press and release it, the contacts will also bounce; you need to use the Bounce library. The functions of this library are needed to set the pin to which the button will be connected, and the delay time in milliseconds. If the button is pressed, then the power function (kW) returns the vector value true, if not, then false vfd.

Schematic diagram of connecting the encoder to the frequency converter

In the machine tool industry, encoders are widely used for frequency converters of asynchronous motors. They are mounted as feedback sensors based on their speed. Such encoders have a large discreteness from 100 pulses per revolution to 1 million pulses per revolution. This brand has a resolution of 500 pulses. vice versa.

Encoders are divided into types of tasks according to. They are absolute and incremental. Our encoder performs the usual function - it produces a differentiation signal when the power is turned off and supplied again. The early state is not preserved.

Absolute type encoders have an internal memory that remembers the last positions. Why is memory needed, and why save this data? In machine tool manufacturing plants, before moving a certain device, the zero point is first indicated. This process is called referencing, that is, going to zero.

The use of an absolute view sensor makes it possible to avoid this procedure a second time and reduce time, provided that the system has restrictions on movement.

Let's look at sine and cosine encoders. They produce a cosine or sine output signal. Next, using a power interpolator device, pulses are formed from them. Signals of this type can be changed in size. The encoder is powered from a voltage of 5 volts.

Signal "A" is a direct pulse signal. The number of pulses from this signal comes at each revolution. It is equal to 500 (sensor resolution).

Signal “B” is also a direct pulse signal. From it, at each revolution, the number of pulses is received according to the discreteness of the sensor, which is shifted from channel “A” by 90 degrees (500).

The "R" signal is the zero mark signal. One pulse is obtained from one revolution of the sensor.

Industrial encoders use a differentiation signal to work with a frequency converter (frequency converter). Its name is complicated, but in reality everything is simple. All channels are separately copied by their inversion. This is necessary to send a signal over significant distances. The output channel of the encoder is connected to a special-purpose receiver made using operational-type amplifiers. The impulse is ultimately determined by the combination of two signals.

Connection

Connection is simple. We connect a voltage of 5 volts to the outputs of the encoder. We have a layout: brown wire - 0 V, white - +5 V, pink, green and red - A, B, R.

The encoder connection program is based on interrupts of channels A and B. Interrupts are triggered on the rising edge. This results in a situation where the encoder slows down at the moment of raster intersection and the channel output signal always remains positive. Pulses are counted continuously by a counter.

In our case, we will not use interrupts, because we are working with 4 sensors, they are operated simultaneously. If you use an interrupt circuit, a pulse loss situation will most likely arise. We solve this problem by setting a motion presence icon. And we considered the operation of industrial encoders.

Operation of a pulse counter based on an encoder module

The counter works in conjunction with a seven-digit indicator module, which will display the number of pulses generated by the encoder. When turned on, the counter value is zero.

Let's turn the encoder knob clockwise. The counter value is incremented by one each time the encoder is clicked. The largest number you can wind up is 999999999. This number should fill all the digits of our seven-segment indicator. If you rotate the knob further, the counter will reset to zero and start counting from zero again.

For example, let's wind up 120 pulses. Now twist it back by turning the handle counterclockwise. The central axis of the encoder works like a button. It clears the free digits of the indicator from zeros. The button has a slight bounce of contacts, so turning it off and on does not happen immediately. By software, the chatter is eliminated. This is the basis for working with the encoder module.

To implement the demonstration project we will need:

  • 24-position encoder;
  • 16 LEDs (3 mm);
  • LED driver A6276;
  • microcontroller PIC18F2550.

An encoder is a modern and original control element for digital devices, and in appearance it is similar to a variable resistor (see figure below). Another name for this control is angle sensor, rotation sensor. The rotation of the shaft is accompanied by clicks, for example 24 clicks per revolution. The encoder has 3 outputs - A, B, C and is used for quickly entering data into digital devices. Some models have a built-in button that is activated by pressing the encoder shaft (another output is added).

Operating principle of the encoder

When turning one click, for example, to the right, contact A+C is closed first, then B+C. When the shaft is turned at this click, the contacts open in the same sequence. When the shaft is turned in the other direction, the closing sequence with contact C changes, i.e. when turning left, first B+C, then A+C are closed.

Using an encoder in microcontroller projects, it is possible to implement several different types of data input using the same encoder, however, this requires some feedback and visualization so that the user knows what information he is entering and at what position the encoder is.

Schematic diagram

Encoder pins A and B are connected to microcontroller ports RB4 and RB5, encoder pin C is connected to ground. It is worth noting that pull-up resistors must be connected to the signal lines of pins A and B. It is no coincidence that the encoder is connected to the specified I/O lines of the microcontroller: firstly, port B has built-in pull-up resistors and we do not have to connect external ones, and secondly, port B of the microcontroller has a very useful function - “interrupt-on-change” - interrupt by changing the level, which will allow us to monitor the state of the encoder.

16 ordinary 3 mm LEDs are used to visualize the input data and they will be located on the printed circuit board around the installed encoder. The LEDs are connected to the A6276 chip.

The A6276 chip is an LED driver with 16-bit serial input. The driver contains a 16-bit CMOS shift register, associated latches and drivers to control the LEDs, and can drive more LEDs than the microcontroller allows. In addition, the driver can be controlled via an SPI interface, which further reduces the number of I/O lines used and makes the project scalable.

The microcontroller software for solving our problem is relatively simple. There are 3 operating modes (information input) and feedback:

  • 360° positioning mode - in this mode, the LEDs indicate the current “position” of the encoder, the user can rotate the encoder shaft left and right to any angle;
  • “Volume/Level” mode - in this mode, the LEDs indicate the current value between the minimum and maximum levels of the input range (like the volume level in audio devices);
  • 3-Position Rotary Switch Mode - In this mode, there are only three selectable positions that the user selects by turning the encoder shaft left/right.

Demonstration of the project

Downloads

A ZIP archive with a project in the MPLAB environment and source code in Hitech C, as well as a circuit diagram and topology of the printed circuit board are located.