📜 ⬆️ ⬇️

IP KVM DIY 2.0

At this time, I will present a kind of "bugfix" for the device from the previous article . Another version of the implementation, see the following .

Having looked at the resulting bike, an idea came to correct how badly it could be. Namely:


I’ll just say something from the video that didn’t come up, I’m going to have to be content with what we have, but let's not talk about sad things.
')
And so proceed, with clean hands, a cold head and a warm heart. The components have changed dramatically instead of the Raspberry PI, we will use the Orange PI and instead of the Arduino UNO only the very microcircuit (Atmega16u2) that was discussed in the last article.

The number of components has not changed:

1. UVC video capture card:



2. VGA to AV Converter:



Experimented with another converter, here with this:



But the miracle did not happen, the video quality did not improve, but on the contrary.

3. Atmega16u2:



4. Orange PI in my case Orange pi PC model:



A few words about this micro computer. It is based on the Allwinner H3 processor (a good cheap 4-core processor on the AWP architecture), 1 GB of RAM 3 USB, HDMI, and so on, a full description is not difficult to find on the Internet.

Preparatory stage


Install the operating system on Orangepi


Here is a link to the forum, in this forum thread there is a lot of useful information, but of course everything is in English, we are interested in the OrangePI-PC_Ubuntu_Vivid_Mate.img distribution, you can download it from mega.nz or Google Drive. We find the Download from Mega or Google Drive line in the header, click on the desired link, download it.

The procedure for transferring an image to a USB flash drive is the same as for a flash drive; on Windows, you can use win32 disk imager writer on Linux with the dd command.

A small digression. Orange pi and similar microcomputers built on Chinese Allwinner processors are pretty much inferior to hardware not by hardware (hardware), but by software (software), more precisely by capabilities and OS "completeness", so to speak. A trimmed kernel, an un-optimized file system, a huge number of bugs, these are not all problems. This situation arose due to the fact that the processor manufacturer initially focused on tablets (maybe even smart phones) running Android, and from the manufacturer’s point of view, there wasn’t any economic expediency in a full-fledged Linux distribution. The Linux kernel was trimmed to the very tomatoes, from a full life turned into a vegetable, capable only of primitive actions. For a long time there were Linux distributions on the core of the android, probably a kind of cheap marketing ploy, and so it would have continued if not for the enthusiasts.

But back to our sheep. Distribution recorded, the system is running.

Adjust the motion


Go to the console. orangepi root or root orangepi password

Update packages:

 sudo apt-get update && sudo apt-get upgrade –y 

Set Motion


All settings as in the previous article:

Fragment of the article
 sudo apt-get install motion -y 

We edit the autorun config:

 sudo nano /etc/default/motion 

In the line start_motion_daemon set 'yes'. Save changes Ctrl + x, y, Enter.

We edit the config of the motion itself (a):

 sudo nano /etc/motion/motion.conf 

Change the parameter values ​​as follows:

The parameter defines the launch of the application as a service:

 daemon on 

These parameters determine the resolution of the transmitted image, there is no sense in setting a higher resolution, since video capture is limited to PAL or SECAM standards, the resolution of which is 720x576. This is by the way an annoying flaw, but more on that later.

 width 800 height 600 

Frame rate:

 framerate 25 

Disable screenshots saving:

 output_normal off 

Image transfer quality:

 webcam_quality 100 

Frame rate:

 webcam_maxrate 25 

Cancel restrictions on connections from other ip

 webcam_localhost off 

Save changes Ctrl + x, y, Enter.

The console is not closing yet.

Preparing to compile


For the transfer of control, we will write a program, everything will be described below in more detail, in the meantime, we will make basic preparations.

Install everything you need to compile, our program will be in C:

 sudo apt-get install build-essential -y 

Install the ncurses library, using it we will capture the key values:

 sudo apt-get install ncurses -y 

We make ourselves the owner of the serial port so that we can record:

 sudo chown orangepi /dev/ttyS2 

Open the kernel module loading config in the editor:

 sudo nano /etc/modules 

Uncomment the gpio-sunxi . With this action we activate gpio, more precisely, the module for working with it, why I’ll tell you later.

Editing autorun:

 sudo nano /etc/rc.local 

Add in front of the exit line the following chown -R orangepi /sys/devices/platform/* . This command will make the orangepi user own the virtual files that are responsible for interacting with the GPIO port.

In theory, it would be better to create a group, assign rights, add a user to the group, but this is all a demonstration model (therefore, a character from a famous cartoon is recalled), and so it will come down. Of course, I do not in any way forbid you to do everything as it should.

Save the changes and reboot:

 sudo reboot 

Let's digress a bit on the hardware.

Atmega16u2


To transfer control, it was decided to use the Atmega16u2 microcircuit directly without the participation of unnecessary microcontrollers and ArduinoIDE, and run the executable code, you guessed it, right on the microcomputer.

Let us analyze the logic of the Arduin in the previous article.

The key values ​​were received via the serial port on the Atmega328p microcontroller (large oblong chip on Arduino UNO) which of the arrays specified in HIDKeyboard.h passed the key codes, so-called “USB HID keyboard keycodes” to the Atmega16u2 microcontroller (again on the serial port), which in turn sent via USB to the target computer. Serial → Atmega328p → Serial → Atmega16u2 → USB

In general, Atmega328p played the role of intermediary, and of course it is logical to remove it, which we will do, for this we will rewrite the code that was for Arduin under Orangepi, and connect Atmega16u2 directly.

Naturally bare chip will not work, you need at least a minimum binding.
I advise you to read the review at this link. For our purposes, the USB powered version is perfect


As you can see, the scheme is very simple, even a beginner can cope with it, not a lot of elements can be managed with hinged mounting, only it is better to fix the crystal oscillator so as not to dangle in the air. The generator by the way should be 16 megahertz if suddenly it is not clear from the scheme. And do not pay attention to the fact that the circuit for ATmega32u2 is suitable for ATmega16u2 and for ATmega8u2 too.

If there is an Arduino UNO board you can use it, you should connect to the tx contacts - № 0, rx -№ 1 and preferably remove the Atmega328p mikruha so that it doesn’t consume any power and does not clog the serial port air.

I don’t need to remind you about the logical levels, everything is the same as in the previous article, the serial port Orange PI is similar to Raspberry PI running at 3.3 volts and matching of voltages is necessary.

For ATmega16u2 firmware, you need to close the Reset leg with the ground for a second and fill the firmware with the Flip program

I will not describe in detail, it was already the last time. At this training is over let's get to the point.

We write the program


For the transfer of keys and remote control of the converter, we will write a small program.

Theory


At first there was a rush to simply port the sources from UNO-HIDKeyboard-Library, this is the library for the Arduino IDE (files HIDKeyboard.cpp and HIDKeyboard.h) that was used last time, but the functionality was not enough for the idea, so why not write your own program.

I present to your attention the Linux-Remote-HIDKeyboard, the name is so-so, but you also need to call it something, hereinafter referred to as LRHIDKeyboard.cpp or rkeysend (compiled binary).

The source will consist of 2 files LRHIDKeyboard.cpp and HIDKeyboard.h. HIDKeyboard.h is the same header file from the UNO-HIDKeyboard-Library library. Arrays are stored in this file to convert to “USB HID keyboard keycodes”, but I took the liberty of correcting errors and expanding arrays, compatibility with HIDKeyboard.cpp is preserved, so if needed, you can also use it for arduin.

USB HID keyboard keycodes are key codes delivered via USB, you can read more here (pdf).

In the HIDKeyboard.h header file, two arrays are the first to define regular keys, the second is for keys with the shift pressed. The decimal number obtained when capturing from the terminal is compared with the number of the array element and is replaced with this element that looks something like “0x7f” (hexadecimal number). Example key "a" has the value "4" in decimal notation or "04" in hexadecimal, key "ESCAPE" "41" in decimal or "29" in hexadecimal, a hexadecimal number indicating the press of any key is sent to the chip.

Practice


Open the console Orangepi create a directory where the program will be stored like this:

 cd ~ mkdir PROG cd PROG 

We create the files HIDKeyboard.h and LRHIDKeyboard.cpp :

 touch HIDKeyboard.h touch LRHIDKeyboard.cpp 

Open in the editor HIDKeyboard.h:

 nano HIDKeyboard.h 

Copy the contents of the listing:

Listing HIDKeyboard.h
 #ifndef HIDKeyboard_h #define HIDKeyboard_h //#include "Arduino.h" /**************************************************************************** * SPECIAL CHARACTER DEFINES * * These are the HID values for keys that do not output characters * ****************************************************************************/ // HID Values of Function Keys #define F1 0x3a #define F2 0x3b #define F3 0x3c #define F4 0x3d #define F5 0x3e #define F6 0x3f #define F7 0x40 #define F8 0x41 #define F9 0x42 #define F10 0x43 #define F11 0x44 #define F12 0x45 // HID Values of Special Keys #define ENTER 0x28 #define ESCAPE 0x29 #define BACKSPACE 0x2a #define TAB 0x2b #define SPACEBAR 0x2c #define CAPSLOCK 0x39 #define PRINTSCREEN 0x46 #define SCROLLLOCK 0x47 #define PAUSE 0x48 #define INSERT 0x49 #define HOME 0x4a #define PAGEUP 0x4b #define DELETE 0x4c #define END 0x4d #define PAGEDOWN 0x4e #define RIGHTARROW 0x4f #define LEFTARROW 0x50 #define DOWNARROW 0x51 #define UPARROW 0x52 // HID Values of Keypad Keys #define NUMLOCK 0x53 #define KEYPADSLASH 0x54 #define KEYPADSTAR 0x55 #define KEYPADMINUS 0x56 #define KEYPADPLUS 0x57 #define KEYPADENTER 0x58 #define KEYPAD1 0x59 #define KEYPAD2 0x5a #define KEYPAD3 0x5b #define KEYPAD4 0x5c #define KEYPAD5 0x5d #define KEYPAD6 0x5e #define KEYPAD7 0x5f #define KEYPAD8 0x60 #define KEYPAD9 0x61 #define KEYPAD0 0x62 #define KEYPADPERIOD 0x63 // HID Values of System Keys #define KEYBOARDAPPLICATION 0x65 #define KEYBOARDPOWER 0x66 #define VOLUMEMUTE 0x7f #define VOLUMEUP 0x80 #define VOLUMEDOWN 0x81 // Common-use modifiers #define LCTRL 0x01 #define SHIFT 0x02 #define ALT 0x04 #define GUI 0x08 /**************************************************************************** * * ASCII->HID LOOKUP TABLE * * Taken from the HID Table definition at * http://www.usb.org/developers/devclass_docs/Hut1_11.pdf * * This array maps the ASCII value of a type-able character to its * corresponding HID value. * * Example: * 'a' = ASCII value 97 = HID value 0x04 * HIDTable['a'] = HIDTable[97] = 0x04 * * NOTE: * "Shift Modified" HID values are the same as the non Shift-Modified values * for any given character, eg the HID value for '2' is equal to the * HID value for '@'. The Shift-Modified value is sent by setting the * modifier value (buf[0]) to the corresponding modifier value in the * modifier table. * ****************************************************************************/ const static uint8_t HIDTable[] = { 0x00, // 0 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x2b, 0x28, // 10 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, // 30 0x00, 0x2c, 0x1e, 0x34, 0x20, 0x21, 0x22, 0x24, 0x34, 0x26, // 40 0x27, 0x25, 0x2e, 0x36, 0x2d, 0x37, 0x38, 0x27, 0x1e, 0x1f, // 50 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x33, 0x33, 0x36, // 60 0x2e, 0x37, 0x38, 0x1f, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, // 70 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // 80 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, // 90 0x2f, 0x31, 0x30, 0x23, 0x2d, 0x35, 0x04, 0x05, 0x06, 0x07, // 100 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // 110 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, // 120 0x1c, 0x1d, 0x2f, 0x31, 0x30, 0x35, 0x4c, 0x00, 0x00, 0x00, // 130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x52, 0x50, // 260 0x4f, 0x4a, 0x2a, 0x00, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, // 270 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x00, 0x00, 0x00, 0x00, // 280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, // 330 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x4b, 0x00, // 340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, // 360 }; /**************************************************************************** * * ASCII->MODIFIER LOOKUP TABLE * * Looks up whether or not the HID report should use the SHIFT modifier. * * Example: * The character '2' and the character '@' have different ASCII values but * the same HID value. This table uses the ASCII value to determine if * we should hold shift while sending the key. eg: * * HIDTable['2'] = 0x1f and modifierTable['2'] = 0 * HIDTable['@'] = 0x1f and modifierTable['@'] = SHIFT * * There's probaly a better way to do this, but it's functional. * ****************************************************************************/ const static uint8_t modifierTable[] = { 0x00, // 0 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 10 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 30 0x00, 0x00, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, 0x00, SHIFT, // 40 SHIFT, SHIFT, SHIFT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, SHIFT, 0x00, SHIFT, // 60 0x00, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 70 SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 80 SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 90 0x00, 0x00, 0x00, SHIFT, SHIFT, 0x00, 0x00, 0x00, 0x00, 0x00, // 100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 120 0x00, 0x00, SHIFT, SHIFT, SHIFT, SHIFT, 0x00 // 127 }; class HIDKeyboard { public: // Constructor HIDKeyboard(); // Public functions void begin(); // Starts the required serial communication (9600 baud) void pressKey(uint8_t modifier, uint8_t key); // Looks up key in HIDTable and sends with a modifier void pressKey(uint8_t key); // Sends key report without modifier (modifier = 0) void pressSpecialKey(uint8_t modifier, uint8_t specialKey); // Sends specialKey with a modifier void pressSpecialKey(uint8_t specialKey); // Sends specialKey without modifier void releaseKey(); // Releases keys (clears key and modifier) void print(char* sequence); // Prints string <sequence> void println(char* sequence); // Prints string <sequence> followed by a carriage return private: // HID report buffer uint8_t buf[8]; // In report, buf[0] = modifier and buf[2] = key HID value }; #endif 


save Ctrl + x, y, Enter

And again:

 nano LRHIDKeyboard.cpp 

Copy the contents of the listing:

Listing LRHIDKeyboard.cpp
 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <termios.h> #include <time.h> #include <ncurses.h> #include "HIDKeyboard.h" char myport[] = "/dev/ttyS2"; //  serial port     //        char nul[] = ""; char menu[] = "/sys/class/gpio_sw/PA14/data"; // char zoom[] = "/sys/class/gpio_sw/PD14/data"; // char kup[] = "/sys/class/gpio_sw/PC4/data"; // char kdn[] = "/sys/class/gpio_sw/PC7/data"; // char klf[] = "/sys/class/gpio_sw/PG8/data"; // char krt[] = "/sys/class/gpio_sw/PA21/data"; // uint8_t buf[8] = { 0 }; /* Keyboard report buffer */ int open_port(char *devname) // serial port { int fd; fd = open(devname, O_RDWR | O_NOCTTY | O_NDELAY); if(fd == -1) // { printw("Port is not open! %s" , devname); return -1; } else { fcntl(fd, F_SETFL, 0); printw("Open port %s", devname); } //  struct termios port_settings; cfsetispeed(&port_settings, B9600); cfsetospeed(&port_settings, B9600); port_settings.c_cflag &= ~PARENB; port_settings.c_cflag &= ~CSTOPB; port_settings.c_cflag &= ~CSIZE; port_settings.c_cflag |= CS8; tcsetattr(fd, TCSANOW, &port_settings); return(fd); } int alt_check(int check) //   ALT,     ALT,   "0" { if(check == 27) { nodelay(stdscr,TRUE); check = getch(); if (check == -1) return ESCAPE; //     Esc nodelay(stdscr,FALSE); return check; } //else return 0; return 0; } int hot_key(int fd, int alt, int vchar) // { if(alt != 0) { if (alt == 330) // "Alt" + "Delete"  Ctrl + Alt + Delete { vchar = 0; buf[0] = 0x04|0x01; buf[2] = HIDTable[alt]; write(fd, buf, 8); return 0; } if (alt == 114) // "Alt" + "r"  Win + r { vchar = 0; buf[0] = 0x08; buf[2] = HIDTable[alt]; write(fd, buf, 8); return 0; } if (alt == 52) // "Alt" + "4"  Alt + F4 { vchar = 0; buf[0] = 0x04; buf[2] = 0x3d; write(fd, buf, 8); return 0; } if (alt == 116) // "Alt" + "t"  Alt + Tab { vchar = 0; buf[0] = 0x04; buf[2] = 0x2b; write(fd, buf, 8); return 0; } if (alt == 44) // "Alt" + ","  Alt + Shift { vchar = 0; buf[0] = 0x04|0x02; write(fd, buf, 8); return 0; } if (alt == 46) // "Alt" + "."  Ctrl + Shift { vchar = 0; buf[0] = 0x01|0x02; write(fd, buf, 8); return 0; } } else { if (vchar == 17) //   "Ctrl" + "q" { endwin(); exit(0); } //  *nul = '\0'; if (vchar == 28) strcpy(nul, menu); // "Ctrl" + "\" if (vchar == 31) strcpy(nul, zoom); // "Ctrl" + "/" if (vchar == 566) strcpy(nul, kup); // "Ctrl" + "up" if (vchar == 525) strcpy(nul, kdn); // "Ctrl" + "down" if (vchar == 545) strcpy(nul, klf); // "Ctrl" + "left" if (vchar == 560) strcpy(nul, krt); // "Ctrl" + "right" FILE *f = fopen(nul, "w"); //  if (f != '\0') { fwrite("1", 1, 1, f); int wrt = fclose(f); //   usleep(70000); if (wrt == 0) { FILE *f = fopen(nul, "w"); fwrite("0", 1, 1, f); fclose(f); } else printf("error write file: %s", nul); return 0; } return vchar; } } int send_key(int fd, int altkey, int getkey) //  { if (altkey == ESCAPE) { buf[0] = 0x00; buf[2] = 0x29; write(fd, buf, 8); return 1; } if (altkey != 0) { buf[0] = 0x04; buf[2] = HIDTable[altkey]; write(fd, buf, 8); return 1; } else { if (getkey == 0) return 0; //printf("KEY NAME : %s - %d\n", keyname(getkey),getkey); //  buf[0] = modifierTable[getkey]; buf[2] = HIDTable[getkey]; write(fd, buf, 8); return 1; } return(-1); } int release_key(int fd) //    { buf[0] = 0; buf[2] = 0; write(fd, buf, 8); } int main(void) { initscr(); keypad(stdscr,TRUE); //    raw(); //   int fd = open_port(myport); printw("\nHOT KEYS: Alt + Delete = Ctrl + Alt + Delete Alt + r = Win + r Alt + 4 = Alt + F4 Alt + t = Alt + Tab Alt + , = Alt + Shift Alt + . = Ctrl + Shift"); printw("\nGPIO: MENU = Ctrl + \\ ZOOM = Ctrl + / UP = Ctrl + up DOWN = Ctrl + down LEFT = Ctrl + left RIGHT = Ctrl + right"); printw("\n Exit = Ctrl + q"); move(10,1); refresh(); while (fd != -1) { int pkey = getch(); int alt = alt_check(pkey); int hot = hot_key(fd, alt, pkey); send_key(fd, alt, hot); release_key(fd); } endwin(); } 


Save Ctrl + x, y, Enter.

Compile


 g++ LRHIDKeyboard.cpp -o rkeysend -lncurses 

rkeysend is the name of the executable file obtained during the compilation process.
The -lncurses connection when compiling the ncurses library is used to capture the keys in the terminal and send text messages to the same terminal.

If the compilation was successful, you can proceed to the GPIO ports.

Converter control


A “freshly compiled” program can not only transfer keys, but also control the converter. I will explain why. First, you can adjust the image, brightness, contrast, sharpness, etc. Secondly, I already wrote about the resolution of the image obtained from the converter = 720x576. So, the converter has a mode of displaying only a part of the image, while the resolution does not change, in other words, you can see more fine details of the image using this mode.

The converter will be controlled by GPIO. GPIO, as you already know, general-purpose input / output, or if in Russian, I liked the rather accurate definition from Wikipedia “general purpose input / output interface”, which is a microcomputer's way of interacting with the outside world.

Connecting Orangepi PC to the converter


And so we Connect the converter with GPIO. The converter has physical control buttons: left, right, bottom, top, menu, and zoom. They are connected by the following principle as in the picture. The illustration shows only the principle of the buttons.


The converter has a port on which it measures the voltage and, in accordance with the required level, performs the action: opens the menu, enlarges the image, moves the image, etc.

To control the buttons I used bipolar transistors with optical input AOT128A:


The emitter and collector of the transistor are soldered to the ground and the contact of the button. The cathode of the transistor is connected (soldered) to the ground. The anode of the transistor is connected to the desired GPIO port via a 33 Ohm resistor.


If you change something, remember:

The control voltage at the anode of this transistor is not more than 1.6V; when this value is exceeded, the transistor starts to heat up strongly and thermal breakdown can occur. The power source for Orangepi and for the converter is desirable to use the same, otherwise the picture may change due to the potential difference.

We connect the transistor anodes to the following GPIO ports: PA14 - menu, PD14 - zoom, PC4 - top, PC7 - bottom, PG8 - left, PA21 - right.

The serial port for connecting the ATmega16u2 microcircuit is located on Ports 11 (RX) and 13 (TX). We connect as indicated in the image

Well, now everything is connected. At first, I wanted to control the converter on a single field-effect transistor using a single port, but somehow I didn’t ask, the PWM ripple is transmitted to the transistor and as a result, the resistance starts to float on it, there are options for smoothing filters, but this would greatly complicate the design. There is also an option to use a digital potentiometer via SPI or I2C, here everything is in your hands, dare.

Launch


Check whether everything is connected as it should:

  1. Orangepi GPIO to Converter
  2. Converter for VGA to Computer (slave)
  3. AV output converter to AV input video capture card
  4. Video capture card to USB Orangepi
  5. Orangepi to ATmega8U2 / 16U2 / 32U2 microcircuit
  6. ATmega8U2 / 16U2 / 32U2 chip via USB to computer (slave)
  7. Computer (master) on SSH to Orangepi

Run the program


Ha Orangepi we launch the compiled program, there should appear the inscriptions with the indication of the open serial port and key combinations. Something like that.



There are keyboard shortcuts to call the Task Manager or change the layout, for example, to press the Ctrl + Alt + Del computer under your control in the terminal, enter “Alt + Del”, possible combinations are written when the program starts on top of the terminal window.

The video, as in the previous article, transmits motion, available at orangepi:8081 . Well, that's all, all the necessary information for repeating the experience is stated, the mission is completed.

Let's sum up:


Video transfer


The video remains very low quality due to the fact that it is transmitted via the AV input, but now we have remote control of the converter and if you select the desired item in the menu - you can watch the screen in parts in the same resolution.

There are possible solutions to the problem with video quality, only they have one major drawback: the price:

1. Velocap U2m usb 2.0 hdmi
2. UVC USB 3.0 HDMI

I did not try these options, for it is expensive, maybe someone from reading the article will risk.
You can probably save money on the microcomputer board by changing the Orangepi PC to the Orangepi one or Orangepi Zero, its cost is about 500 rubles. But there may be problems with Orangepi Zero, there is a different processor, respectively, another distribution with a different core, in which the necessary drivers and modules may not be available.

Cost price


VGA to AV Converter about 700rub.
The video capture card is about 500 rubles.
Orangepi PC about 1000 rub.
ATmega8U2 / 16U2 / 32U2 approximately 150rub.

Total: 2350 rub.

Well, this article came to an end, thanks to everyone who read it. I hope in practice you will succeed. Although I was not able to implement all of my plans, the result was interesting, especially for such a price.Of course, the resulting device needs some work, but I think it still has a right to exist. I give all my work as it is, without any guarantees, in good hands. Thanks for attention!

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


All Articles