Решение проблемы медленного управления lpt портом под Windows

Предположим вы уже попробовали управлять lpt из под windows inpout32.dll и обнаружили, что скорость и стабильность отклика печальна. Я например управлял шаговым двигателем, и таймауты в миллисекунды данное решение не тянуло.

parallel_port_slow.png
Однако поковырявшись я нашёл обходное решение. Кратко суть: реализацию непосредственного управления портом оставляем на Linux, но запихиваем его в виртуальную машину wmvare, через которую прокидываем lpt порт и мини web-сервер.
Подробно почитать о реализации управления портом в linux.

Обходной путь выбрал следующий. Думаю все знают программу для работы с виртуальными машинами VMware Рlayer. Замечательность её состоит в том, что в ней можно прокинуть внутрь наш lpt порт. Заводим в ней виртуальную машину с Debian XFace. Далее как уже описывал: ставим модуль python-parallel, подключаемся к порту, используем его.
А как же c# спросите вы? А вот как.
В питоне я написал скрипт, задача которого 0 логики - только тупое исполнение комманд, по отправке данных на порт, а также поднятие маленького встроенного web-сервера. То есть скрипт может получать комманды через web, и перенаправлять их на lpt порт. А из c# обратиться к web адресу задача уже тривиальная. Пинги так же не существенны - на одной машине физически находятся и хост и клиент.


Вот упрощённый вариант, в котором поднимается мини веб-сервер на питоне и управляет lpt портом.

import sys
import BaseHTTPServer
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
import parallel
import time
p = parallel.Parallel()

def get_command(path):
command_str = "?command="
command_index = path.find(command_str)
if command_index>-1:
return path.split(command_str)[1]
return "";
def do_command(command):
if command=="on": p.setData(1);
if command=="off": p.setData(0);
time.sleep(0.01);
class HttpProcessor(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("content-type","text/html")
self.end_headers()
command = get_command(self.path);
do_command(command)

ServerClass = BaseHTTPServer.HTTPServer
Protocol = "HTTP/1.0"

if sys.argv[1:]:
port = int(sys.argv[1])
else:
port = 80
server_address = ("192.168.81.131", port)

httpd = ServerClass(server_address, HttpProcessor)

sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
httpd.serve_forever()

Главное сравните ip виртуальной машины с тем, который у меня в скрипте. Скрипт достаточно просто запусить.


Далее нужно настроить сеть с виртуальной машиной. В свойствах виртуальной машины во вкладке сетевого адаптера выбираем режим работы сети Host-only. Так же в вашем скрипте важно указать ваш ip-адрес виртуальной машины. С родительской машины пробуем пинговать. Сохраняете скрипт, как запускать уже рассказывал. Должен подняться http-сервер по 80-му порту.
Набираем в браузере обеих машин адрес: http://192.168.81.129/?command=left
Смотрим как реагирует порт.
Теперь этот адрес нужно дёргать из c#.

Опишем вот такую функцию:
 public const string ServerName = "http://192.168.81.131";
public bool SendCommand(string command)
{
var line = ServerName + "/?command=" + command;
HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(line);
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
StreamReader Reader = new StreamReader(Response.GetResponseStream(), Encoding.GetEncoding(1251));
string temporaryData = Reader.ReadToEnd();
Reader.Close();
Response.Close();
return true;
}
Вызываем: SendCommand("on");

Естественно во время работы функции система будет зависать. Но думаю как выделить её работу в отдельны поток объяснять не нужно (если что, смотрите System.Threading.Thread).


Уведомлять о статьях
  Автор: administrator
Комментариев к статье пока нет
Яндекс.Метрика admin@synxronica.com