[C++, Разработка под Windows, Разработка под Arduino] Управляем Windows пультом от телевизора или как передать сигналы через последовательный порт
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Решил я , что хочу переключать громкость звука и аудио треки на ноутбуке под Windows с инфракрасного пульта. Под руку тут же попали: ардуино уно, кучка проводов с макетной платой, инфракрасный датчик, ноутбук и, собственно, инфракрасный пульт.Идея есть, железо есть, а вот теория хромает. Как заставить компьютер понимать инфракрасные сигналы пульта и выполнять требуемые действия? Я надумал использовать ардуино для приема сигналов пульта через инфракрасный датчик на макетной плате и посылать сообщения в ноутбук через USB. Для этого требовались хоть какие то познания, как все это работает.Было решено разобраться.Знакомим ардуино с пультомДля приема сигнала от инфракрасного пульта необходим приёмник, который мы подключим к ардуино через макетную плату по следующей схеме:
кодировка сигнала по протоколу NECДля того, чтобы ардуино понимала, по какому протоколу и с какой командой передается сигнал, существует библиотека IRremote, которую в новых версиях Arduino IDE можно добавить из стандартных библиотек. Сама библиотекаМоим желанием было научиться менять громкость звука компьютера и управлять медиа (пауза/ переключение треков). Для этого необходимо 5 кнопок пульта.Для того, чтобы понять, какую информацию нам передает пульт, необходимо воспользоваться командой IrReceiver.decodedIRData.decodedRawData. На мониторе порта мы увидим подробную информацию о том, что содержит сигнал. Здесь нас интересует значение команд. Каждая кнопка пульта содержит свою команду, их мы и будем использовать для управления медиа. Прощёлкав все интересующие нас кнопки и записав коды команд, мы можем написать следующее:
#include <IRremote.h>
int IR_RECEIVE_PIN = 2; // Получаем сигнал на 2-ой пин
long command;
void setup()
{
Serial.begin(9600);
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
}
void loop() {
if (IrReceiver.decode()) // Расшифровываем последовательность сигналов пульта
{
command = IrReceiver.decodedIRData.decodedRawData; /* Проверяем какие комманды пульта
соответствуют нужным нам кнопкамм*/
switch(command) //Задаем действия в соответствии с полученным провеяремым сигналом
{
case 0xEA15FF00:
Serial.write("D"); delay(120);
break;
case 0xB946FF00:
Serial.write("U"); delay(120);
break;
case 0xBF40FF00:
Serial.write("P"); delay(120);
break;
case 0xBC43FF00:
Serial.write("N"); delay(120);
break;
case 0xBB44FF00:
Serial.write("R"); delay(120);
break;
}
IrReceiver.resume(); // Продолжаем получать сигналы
}
}
Данный код сравнивает команды в принимаемом сигнале пульта с командами нужных нам кнопок, и если нужная кнопка была нам нажата, отправляет сообщение по USB.Управление воспроизведением и громкостью WindowsКак управлять громкостью и медиа Windows, я нашел в этом посте.Управление можно осуществлять с помощью виртуальных кодов - имитации действий клавиатурой и мышью. Я использовал С++ и Visual Studio так как там есть удобная для этой задачи библиотека Windows.hДля того, чтобы программа имитировала нажатие клавиш, необходимо использовать функцию SendInput и написать следующее:
INPUT Input = { 0 };
Input.type = INPUT_KEYBOARD;
Input.ki.wVk = VK_VOLUME_UP; /* Пишем здесь нужный нам виртуальный код,
который мы хотим имитировать*/
SendInput(1, &Input, sizeof(Input));
ZeroMemory(&Input, sizeof(Input));
Нас интересуют следующие коды: увеличение и уменьшение громкости (VK_VOLUME_UP, VK_VOLUME_DOWN); проигрывание и пауза медиа (VK_MEDIA_PLAY_PAUSE); "перелистывание" медиа (VK_MEDIA_NEXT_TRACK, VK_MEDIA_PREV_TRACK)Полный набор виртуальных кодов доступен здесь. Что такое Serial port и как с этим бороться?Ардуино уно передает сигналы компьютеру через USB, эмулируя последовательный порт (Serial port), который в Windows называется COM порт, как дань памяти старым последовательным портам IBM PC. Для того, чтобы получить сообщение от ардуино и выполнить какое то действие в зависимости от сообщения, необходима программа. Функции работы с последовательным портом также есть в библиотеке Windows.h
#include <Windows.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
HANDLE Port;
BOOL Status;
DCB dcbSerialParams = { 0 };
COMMTIMEOUTS timeouts = { 0 };
DWORD dwEventMask;
char ReadData;
DWORD NoBytesRead;
bool Esc = FALSE;
Port = CreateFile(L"\\\\.\\COM3", GENERIC_READ, 0, NULL, // Открываем последовательный порт
OPEN_EXISTING, 0, NULL);
if (Port == INVALID_HANDLE_VALUE)
{
printf("\nError to Get the COM state\n");
CloseHandle(Port);
}
else
{
printf("\nopening serial port is succesful\n");
}
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Status = GetCommState(Port, &dcbSerialParams); // Принимаем существующие настройки порта
if (Status == FALSE)
{
printf("\n Error to Get the COM state \n");
CloseHandle(Port);
}
dcbSerialParams.BaudRate = CBR_9600; // Задаем настройки порта
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
Status = SetCommState(Port, &dcbSerialParams);
if (Status == FALSE)
{
printf("\n Error to Setting DCB Structure \n ");
CloseHandle(Port);
}
timeouts.ReadIntervalTimeout = 10; /* Задаем временные интервалы приема сигналов
с порта (я их от балды поставил) */
timeouts.ReadTotalTimeoutConstant = 200;
timeouts.ReadTotalTimeoutMultiplier = 2;
if (SetCommTimeouts(Port, &timeouts) == FALSE)
{
printf("\n Error to Setting Timeouts");
CloseHandle(Port);
}
while (Esc == FALSE)
{
Status = SetCommMask(Port, EV_RXCHAR);
if (Status == FALSE)
{
printf("\nError to in Setting CommMask\n");
CloseHandle(Port);
}
Status = WaitCommEvent(Port, &dwEventMask, NULL); /* Задаем ожидание события
(поступления сообщения в порт) */
if (Status == FALSE)
{
printf("\nError! in Setting WaitCommEvent () \n");
CloseHandle(Port);
}
Status = ReadFile(Port, &ReadData, 3, &NoBytesRead, NULL); // Считываем сообщение
printf("\nNumber of bytes received = % d\n\n", sizeof(ReadData) - 1);
switch (ReadData) /* В зависимости от сообщения
симулируем нажатие медиа клавиш */
{
case 'U':
{
INPUT Input = { 0 };
Input.type = INPUT_KEYBOARD;
Input.ki.wVk = VK_VOLUME_UP;
SendInput(1, &Input, sizeof(Input));
ZeroMemory(&Input, sizeof(Input));
}
break;
case 'D':
{
INPUT Input = { 0 };
Input.type = INPUT_KEYBOARD;
Input.ki.wVk = VK_VOLUME_DOWN;
SendInput(1, &Input, sizeof(Input));
ZeroMemory(&Input, sizeof(Input));
}
break;
case 'P':
{
INPUT Input = { 0 };
Input.type = INPUT_KEYBOARD;
Input.ki.wVk = VK_MEDIA_PLAY_PAUSE;
SendInput(1, &Input, sizeof(Input));
ZeroMemory(&Input, sizeof(Input));
}
break;
case 'N':
{
INPUT Input = { 0 };
Input.type = INPUT_KEYBOARD;
Input.ki.wVk = VK_MEDIA_NEXT_TRACK;
SendInput(1, &Input, sizeof(Input));
ZeroMemory(&Input, sizeof(Input));
}
break;
case 'R':
{
INPUT Input = { 0 };
Input.type = INPUT_KEYBOARD;
Input.ki.wVk = VK_MEDIA_PREV_TRACK;
SendInput(1, &Input, sizeof(Input));
ZeroMemory(&Input, sizeof(Input));
}
break;
default:
printf("\n Error\n");
break;
}
PurgeComm(Port, PURGE_RXCLEAR); // Очищаем порт от всякого мусора
}
CloseHandle(Port); /* Закрываем порт при завершении работы программы,
чтобы дргуие программы могли получить к нему доступ */
}
Информацию по работе с последовательными порта я нашел здесь.https://www.xanthium.in/Serial-Port-Programming-using-Win32-APIhttp://citforum.ru/hardware/articles/comports/ИтогТеперь моей лени нет предела, мне не нужно дотягиваться до ноутбука, чтобы переключить трек или ролик на ютубе. Не зря говорят: Лень - двигатель прогресса.Извините, данный ресурс не поддреживается. :( У подобной комбинации (пульт + виртуальные коды) есть потенциал в управлении разными частями ОС. Например, можно назначить на кнопки запуск программ или сделать из пульта что-то вроде контроллера. Но самое удобное, на мой взгляд, это управление медиа.
===========
Источник:
habr.com
===========
Похожие новости:
- [Совершенный код, C++, Компиляторы, IT-стандарты, Законодательство в IT] Чему равно выражение -3/3u*3 на С++? Не угадаете. Ответ: -4. Приглашаю на небольшое расследование
- [Adobe Flash, Разработка под Windows] Microsoft удалит Flash Player из Windows 10 в июле
- [Программирование, C++, Qt, Геоинформационные сервисы] Создаём плагин Qt GeoServices на примере ОС Аврора, OpenStreetMap и Sight Safari
- [Разработка под Arduino] Дисплей 1602 подключение к arduino
- [C++] Понимаем красно-черное дерево. Часть 1. Введение
- [Игры и игровые приставки, IT-компании] Microsoft урезает комиссию для разработчиков в Windows Store с 30 до 12 процентов
- [Информационная безопасность, Читальный зал, Лайфхаки для гиков] Как крупное кредитное бюро Experian 5 лет зарабатывает на уязвимости в своей системе (перевод)
- [C++, Программирование микроконтроллеров, Схемотехника, Разработка под Arduino, DIY или Сделай сам] Ненормативная схемотехника: ATmega8 – кто сказал, что выше головы не прыгнешь?
- [Ненормальное программирование, NoSQL, Компиляторы, Разработка под Windows] Clarion — Язык программирования, про который все забыли. А мне пришлось вспомнить
- [Программирование, C++, IT-стандарты] Стандарт C++20: обзор новых возможностей C++. Часть 1 «Модули и краткая история C++»
Теги для поиска: #_c++, #_razrabotka_pod_windows (Разработка под Windows), #_razrabotka_pod_arduino (Разработка под Arduino), #_arduino_uno, #_windows, #_c++, #_razrabotka_pod_windows (
Разработка под Windows
), #_razrabotka_pod_arduino (
Разработка под Arduino
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 07:59
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Решил я , что хочу переключать громкость звука и аудио треки на ноутбуке под Windows с инфракрасного пульта. Под руку тут же попали: ардуино уно, кучка проводов с макетной платой, инфракрасный датчик, ноутбук и, собственно, инфракрасный пульт.Идея есть, железо есть, а вот теория хромает. Как заставить компьютер понимать инфракрасные сигналы пульта и выполнять требуемые действия? Я надумал использовать ардуино для приема сигналов пульта через инфракрасный датчик на макетной плате и посылать сообщения в ноутбук через USB. Для этого требовались хоть какие то познания, как все это работает.Было решено разобраться.Знакомим ардуино с пультомДля приема сигнала от инфракрасного пульта необходим приёмник, который мы подключим к ардуино через макетную плату по следующей схеме: кодировка сигнала по протоколу NECДля того, чтобы ардуино понимала, по какому протоколу и с какой командой передается сигнал, существует библиотека IRremote, которую в новых версиях Arduino IDE можно добавить из стандартных библиотек. Сама библиотекаМоим желанием было научиться менять громкость звука компьютера и управлять медиа (пауза/ переключение треков). Для этого необходимо 5 кнопок пульта.Для того, чтобы понять, какую информацию нам передает пульт, необходимо воспользоваться командой IrReceiver.decodedIRData.decodedRawData. На мониторе порта мы увидим подробную информацию о том, что содержит сигнал. Здесь нас интересует значение команд. Каждая кнопка пульта содержит свою команду, их мы и будем использовать для управления медиа. Прощёлкав все интересующие нас кнопки и записав коды команд, мы можем написать следующее: #include <IRremote.h>
int IR_RECEIVE_PIN = 2; // Получаем сигнал на 2-ой пин long command; void setup() { Serial.begin(9600); IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); } void loop() { if (IrReceiver.decode()) // Расшифровываем последовательность сигналов пульта { command = IrReceiver.decodedIRData.decodedRawData; /* Проверяем какие комманды пульта соответствуют нужным нам кнопкамм*/ switch(command) //Задаем действия в соответствии с полученным провеяремым сигналом { case 0xEA15FF00: Serial.write("D"); delay(120); break; case 0xB946FF00: Serial.write("U"); delay(120); break; case 0xBF40FF00: Serial.write("P"); delay(120); break; case 0xBC43FF00: Serial.write("N"); delay(120); break; case 0xBB44FF00: Serial.write("R"); delay(120); break; } IrReceiver.resume(); // Продолжаем получать сигналы } } INPUT Input = { 0 };
Input.type = INPUT_KEYBOARD; Input.ki.wVk = VK_VOLUME_UP; /* Пишем здесь нужный нам виртуальный код, который мы хотим имитировать*/ SendInput(1, &Input, sizeof(Input)); ZeroMemory(&Input, sizeof(Input)); #include <Windows.h>
#include <stdio.h> #include <string.h> int main(void) { HANDLE Port; BOOL Status; DCB dcbSerialParams = { 0 }; COMMTIMEOUTS timeouts = { 0 }; DWORD dwEventMask; char ReadData; DWORD NoBytesRead; bool Esc = FALSE; Port = CreateFile(L"\\\\.\\COM3", GENERIC_READ, 0, NULL, // Открываем последовательный порт OPEN_EXISTING, 0, NULL); if (Port == INVALID_HANDLE_VALUE) { printf("\nError to Get the COM state\n"); CloseHandle(Port); } else { printf("\nopening serial port is succesful\n"); } dcbSerialParams.DCBlength = sizeof(dcbSerialParams); Status = GetCommState(Port, &dcbSerialParams); // Принимаем существующие настройки порта if (Status == FALSE) { printf("\n Error to Get the COM state \n"); CloseHandle(Port); } dcbSerialParams.BaudRate = CBR_9600; // Задаем настройки порта dcbSerialParams.ByteSize = 8; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; Status = SetCommState(Port, &dcbSerialParams); if (Status == FALSE) { printf("\n Error to Setting DCB Structure \n "); CloseHandle(Port); } timeouts.ReadIntervalTimeout = 10; /* Задаем временные интервалы приема сигналов с порта (я их от балды поставил) */ timeouts.ReadTotalTimeoutConstant = 200; timeouts.ReadTotalTimeoutMultiplier = 2; if (SetCommTimeouts(Port, &timeouts) == FALSE) { printf("\n Error to Setting Timeouts"); CloseHandle(Port); } while (Esc == FALSE) { Status = SetCommMask(Port, EV_RXCHAR); if (Status == FALSE) { printf("\nError to in Setting CommMask\n"); CloseHandle(Port); } Status = WaitCommEvent(Port, &dwEventMask, NULL); /* Задаем ожидание события (поступления сообщения в порт) */ if (Status == FALSE) { printf("\nError! in Setting WaitCommEvent () \n"); CloseHandle(Port); } Status = ReadFile(Port, &ReadData, 3, &NoBytesRead, NULL); // Считываем сообщение printf("\nNumber of bytes received = % d\n\n", sizeof(ReadData) - 1); switch (ReadData) /* В зависимости от сообщения симулируем нажатие медиа клавиш */ { case 'U': { INPUT Input = { 0 }; Input.type = INPUT_KEYBOARD; Input.ki.wVk = VK_VOLUME_UP; SendInput(1, &Input, sizeof(Input)); ZeroMemory(&Input, sizeof(Input)); } break; case 'D': { INPUT Input = { 0 }; Input.type = INPUT_KEYBOARD; Input.ki.wVk = VK_VOLUME_DOWN; SendInput(1, &Input, sizeof(Input)); ZeroMemory(&Input, sizeof(Input)); } break; case 'P': { INPUT Input = { 0 }; Input.type = INPUT_KEYBOARD; Input.ki.wVk = VK_MEDIA_PLAY_PAUSE; SendInput(1, &Input, sizeof(Input)); ZeroMemory(&Input, sizeof(Input)); } break; case 'N': { INPUT Input = { 0 }; Input.type = INPUT_KEYBOARD; Input.ki.wVk = VK_MEDIA_NEXT_TRACK; SendInput(1, &Input, sizeof(Input)); ZeroMemory(&Input, sizeof(Input)); } break; case 'R': { INPUT Input = { 0 }; Input.type = INPUT_KEYBOARD; Input.ki.wVk = VK_MEDIA_PREV_TRACK; SendInput(1, &Input, sizeof(Input)); ZeroMemory(&Input, sizeof(Input)); } break; default: printf("\n Error\n"); break; } PurgeComm(Port, PURGE_RXCLEAR); // Очищаем порт от всякого мусора } CloseHandle(Port); /* Закрываем порт при завершении работы программы, чтобы дргуие программы могли получить к нему доступ */ } =========== Источник: habr.com =========== Похожие новости:
Разработка под Windows ), #_razrabotka_pod_arduino ( Разработка под Arduino ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 07:59
Часовой пояс: UTC + 5