• Партнер

  • Идея

    Сидел я как-то вечерком, резался в 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, компилируем, запускаем и
    меряем температуру на здоровье!

    Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии