Идея
Сидел я как-то вечерком, резался в NFS Underground c джойстиком от QuickShot,
дергал "палку удовольствия" вперед - назад, влево - вправо и пришла мне в голову одна идейка...
А что если вместо джойстика подключить термо- или/и фото- сопротивление, тогда
можно смотреть температуру на улице, а так же узнать ночь или день сейчас за окном,
не уходя от компьютера. А раз GAME-порт (порт, к которому подключается
джойстик, находится на звуковушке) есть почти у каждого, то это может сделать любой.
Собираем
Действия себя долго ждать не заставили. В тот же день отправился в Радиолу, купил
пару терморезисторов MMT1 номиналом 120 и 150кОм (номинал GAME-порта 150кОм),
фотосопротивление ФСК-4A и вилку DB-15M с корпусом DP-15C. Все вместе обошлось
всего в 50 рублей. В интернете нашел распайку порта:
Припаял провода в первому (+5V) и третьему (координата AX) контактам вилки с одного
конца, а к другому соответственно термосопротивление. Контакты резистора обязательно
надо заизолировать, например одеть кэмбрики (изоляция от толстого провода) сверху,
а в места соединения залить герметика:
Драйвер
Пока сох герметик, я разбирался (точнее вспоминал) как получать положение джойстика,
то есть значение сопротивления.
Пару лет назад в Windows неNT это делалось так:
i = 0;
_outp( 0x0201, 0 ); // Инициализируем порт
while( _inp(0x0201)&1==1 ) i++; // Пока бит 0 координаты AX не сброшен, инкрементируем счетчик
Но теперь под Windows XP меня ждала засада - любое прямое обращение к порту вызывало
ошибку, нехватку привилегий. Дело в том, что в NT системах приложение не в нулевом
кольце не имеет права напрямую обращаться к портам ввода-вывода. Промелькнула у
меня уже мысль ставить старый добрый 98ой... Но она быстро пролетела.
Выход нашелся в обращении к портам через драйвер PortIO, взятый из
NuMega Driver Studio. Вам для его установки достаточно скачать
архив portio.rar, скопировать из него portio.sys в %WINDIR%\system32\drivers, добавить в реестр
информацию из portio.reg (просто запустить его) и перезагрузить компьютер.
Кодим
Для общения с драйвером, открываем его и получаем дескриптор:
hPortIo = CreateFile( "\\\\.\\PortIo", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
Что бы работать с портом его надо открыть:
OpenPort.open_Address = 0x0201; // Адрес порта 201h (чаще всего)
OpenPort.open_PortSize = 1; // Порт 8-битный, т.е. размер 1 байт
OpenPort.open_PortCount = 1;
status = DeviceIoControl( hPortIo, IOCTL_PORTIO_OPENPORT, &OpenPort, sizeof(OpenPort), &PortHandle, sizeof(PortHandle), &nBytesReturned, NULL );
Когда мы захотели что-то получить из порта, ему надо сказать об этом, записав в
него произвольное значение, что бы он включил "счетчик":
WritePort.wr_Handle = PortHandle;
WritePort.wr_Index = 0;
WritePort.wr_Data = 0;
status = DeviceIoControl( hPortIo, IOCTL_PORTIO_WRITEPORT, &WritePort, sizeof(WritePort), NULL, 0, &nBytesReturned, NULL );
Теперь, пока нужный нам bit не спрошен, инкрементируем счетчик
ReadPort.rd_Handle = PortHandle;
ReadPort.rd_Index = 0;
while( (data&bit)==bit )
{
status = DeviceIoControl( hPortIo, IOCTL_PORTIO_READPORT, &ReadPort, sizeof(ReadPort), &data, sizeof(data), &nBytesReturned, NULL );
i++;
}
После работы с портом, его желательно закрыть:
ClosePort.close_Handle = PortHandle;
DeviceIoControl( hPortIo, IOCTL_PORTIO_CLOSEPORT, &ClosePort, sizeof(ClosePort), NULL, 0, &nBytesReturned, NULL );
Также, как и дескриптор:
CloseHandle(hPortIo);
Всю программу можно скачать здесь termometr.rar. Работа с GAME-портом я реализовал
в виде отдельного модуля gameport.cpp.
Калибруем
Чтобы определять температуру по сопротивлению надо знать зависимость T(R).
Для MMT термисторов эта зависимость логарифмическая: T=B/ln(R/A)+To,
где To=273 - абсолютный ноль, А, B - константы, зависящие от
конкретного сопротивления. Значит для их определения надо определить температуру
и значение сопротивления в двух точках. Я измерил при комнатной 24,50 С получил
значение 51 и при первой реперной точке 0 С значение 100. Вспомнив школьную
математику, посчитал значения A = 0.00897 и B = 2521.35.
Вам, даже если у вас такой же термистор, придется тоже посчитать эти коэффициенты.
Все! Теперь вписываем эти значения в main.cpp из termometr.rar, компилируем, запускаем и
меряем температуру на здоровье!