📜 ⬆️ ⬇️

Connecting a rotary encoder to a computer via USB

I have long wanted to adapt the volume control made from the encoder to the laptop. You will need to connect this regulator to USB so that everything will be “grown-up” (and you cannot connect an external device to the laptop anyway). Turn the encoder to the left - the volume should decrease, to the right - it should increase. We press down the encoder knob - run some useful program, or switch to timbre control.

For those who are not aware of what an encoder is, it’s such a twist, like a volume knob based on a conventional resistor, only this twist has no boundary positions — how many will fit in any direction. The encoder is spinning with nice soft clicks, and it looks like a normal variable resistor.

image

Such devices are not uncommon in modern car receivers and any household devices, the user interface of which is processed by the microcontroller (and this is what any household appliances), and where you need smooth adjustment or adjustment. A third contact that operates as a button on the handle is often built into the encoder - when we move the encoder handle down (along the axis), this button is triggered. It greatly enriches the possibilities of user interface - on one encoder you can build the entire control system of an electronic device (but a hemorrhoid is added to a programmer, but these are trifles). I just had such an encoder.
')
image

The principle of operation of the encoder is quite simple - there are only two contacts in it (the button on the handle does not count), which begin to close as soon as the user starts to turn the encoder handle. The contacts are connected to the two legs of the microcontroller (working as digital inputs), and when the encoder knob is rotated, impulses appear on these legs, out of phase and number of which the microcontroller determines the direction of rotation and the angle of rotation of the encoder knob.
image
In order for the volume control to work, you need to solve at least three engineering tasks:

Step 1 . Creating a low-speed USB device on a breadboard.
Step 2 . Connect an encoder to this USB device, ensure that the microcontroller performs it, and transmits information about the rotation of the encoder to the computer.
Step 3 . Understand how you can programmatically control the volume control. Surely there is any multimedia API that allows you to do this. Minimum program - you need to write a program that will receive signals from a USB device and control the volume. It would be nice, of course, to write a driver, but it's scary to take it. Better leave for later.

So, I will describe the process of creating a regulator in steps. I omit the details, otherwise it will be too boring. To whom it is interesting, see the source [6] and documentation links.

[ Step 1. Creating a low-speed USB device on a breadboard ]

This step was completed without even starting - somehow too simple and banal. Stupidly downloaded the sample project by reference [1]. Corrected a file usbconfig.h - for Ponte called my device ENCODER DEMO , for more fantasy was not enough. I checked in the Makefile the type of process (ATmega16), the frequency of quartz (16 MHz) - to match my AVR-USB-MEGA16 layout. I compiled the project in AVRStudio, flashed the mockup, connected it to the computer - it all started half a turn, my USB device worked properly as a virtual COM port - everything is exactly as written in article [1].

[ Step 2. Connect the encoder to the USB device ]

This step caused the greatest fear in me that everything would work as it should. That the encoder will be connected and I can read it - I did not doubt that. There were doubts that I would be able to read it qualitatively, when USB protocol processing also works in the background - after all, this is not an easy task for the microcontroller (as it turned out later - I was worried completely in vain).

As usual, I began to rummage through the Internet in search of ready-made subroutines for reading the encoder. I found very quickly what I needed - for AVR, a very simple C code [2], the files encoder.c and encoder.h. Say what you like, and open source is a cool thing.

He attached two indication LEDs - GREEN and YELLOW - to indicate the direction of rotation of the encoder. For convenience, I connected the encoder directly to the ISP connector, taking advantage of the fact that the MOSI, MISO and SCK signals are just the legs of PB5, PB6 and PB7 of the ATmega16 microcontroller (connected the A and B phases, as well as the encoder button).

image

Corrected the definition of the legs, added the initialization code. Attached the encoder.c module to the project. Added to the main loop the main control of green and yellow LEDs, when it comes from the encoder. The RED LED is tied to the encoder button - when you press it, the red LED lights up, release it - goes out. Compiled, flashed - it works. I twist the knob to the left, and the green LED flashes in time with the encoder clicks. I twist the knob to the right - the yellow LED flashes. Despite the fact that the encoder is read by the polling method, thanks to the effective code for reading the encoder, NO ANY criticism even when working simultaneously with the V-USB library (Respect, Pashgan!). Added the output of information from the encoder to the virtual COM-port (we turn the encoder to the left, I bring minusiki '-' to the console, I turn to the right, I bring plus sign '+' to the console). On the timer, every 10 ms, I display the status of the encoder button and indicate it with a red LED (the button is pressed - I transmit the symbol '1', released - '0'). Everything is working. Boredom.

image

In conclusion, I threw out the modules cmd.c, crc16.c, eepromutil.c, strval.c. The amount of code dropped to 3 kilobytes is excellent, now it will fit in the memory of ATtiny45 (you can use AVR-USB-TINY45 layout tool in the future, it is smaller and cheaper).

[ Step 3. Understand how you can programmatically control the volume control ]

As usual, googled the question. Weed out a bunch of garbage, and finally grabbed a pearl - [3]. Next thing technology. I take out the favorite children's designer - Visual Studio. Without thinking about anything, the wizard generates a dialog-based application. I throw a volume control slider on the panel, bind a variable to it, add a slider position handler. When the application starts, I tune the engine to a minimum of 0 and a maximum of 65535 (to match the bounds of the volume values ​​that the mixer control libraries manipulate). I read the mixerGetControlDetails function with the current volume value, and set the slider to the appropriate position. In the engine position handler, the opposite is true - I read the engine position and set the desired volume with the function MixSetControlDetails . Volume control is done exactly as written in article [3]. Checked - works.

Now it remains the case for small things - to read what comes from the virtual COM port (on it we have a freshly baked USB device with an encoder). If a minus (-) arrived, we move the slider to the left (decrease the volume), plus (+), then move the slider to the right (increase the volume). If the characters 0 and 1 arrive, then the checkbox state is controlled accordingly (just to indicate whether the encoder button is pressed or not). You can work with a COM port as you would with a regular file (see [4]). We initialize the connection to the COM port as opening a file (by calling :: CreateFile ) in blocking mode. We start a separate stream, we add a file reading to the infinite loop (with a blocking call :: ReadFile ) one character at a time, and we analyze this character. According to which character came, we turn the slider slider in the right direction (the volume will adjust the slider handler) or update the state of the checkbox. Checked - works.

image

That's all, actually. Then you can do endless (and probably useless) improvement. Make an automatic search for the desired virtual COM port (now, for simplicity, the COM port name is transmitted via the command line). Transform a USB device from a CDC class to HID - this can simplify the code of a USB device, as well as simplify software search and discovery of a device on a computer by VID and HID. Or write a service instead of the program (so that you do not need to run a separate program). Or even a driver. This is very interesting, but I do not know how (maybe, who of the habravchan will teach the mind? ..). Screw some action to the encoder button. Well, and so on to infinity.

I hope someone my research will be useful in their own development. If I missed something, I will be glad to hear comments in the comments.

[ UPD120803 ]

One competent person assembled on the AVR microcontroller a volume control - a USB HID device that emulates a standard multimedia keyboard (as suggested in the comments). This keyboard has the ability to adjust the volume without additional software, all the necessary work is performed by the operating system driver.

image

[ Links ]

1 . USB console for controlling amateur radio devices .
2 Here I found the code for the encoder . Here is the author's description of the algorithm .
3 Describes how to work with a sound card mixer via mixerSetControlDetails .
4 How to work with COM-port in Windows .
5 Video showing the operation of the volume control.
6 ENCODER DEMO project sources (AVRStudio project and Visual Studio project).

Source: https://habr.com/ru/post/98005/


All Articles