Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Управление светодиодами и микрозадержки выполнения


Автор: Temdegon 6.5.2009, 13:51
Наткнулся на статью
http://www.hardwareportal.ru/articles/Indikator_zagruzki_protsessora_i_vinchestera_svoimi_rukami/
Из статьи меня заинтересовал индикатор загрузки ЦПУ. По-моему выглядит круто. Захотел себе такой же. Но брать в руки паяльник и паять плату для управления светодиодами через ком порт мне не хочется. Вот и возникла идея возложить функции управления этими светодиодами на программу.
Нужно изменять яркость свечения двух светодиодов в зависимосит от загрузки ЦПУ. Яркость светодиода изменяется не изменением напряжения, а прерыванием напряжения на на доли секунды. Решил вместо ком-порта использовать LPT, т.к. там как раз логическая единица = +5В и ток вполне достаточный для горения светодиода. Достаточно будет просто подключить светодиоды к LPT и выставлять на порте нужные значения, и ничего не нужно паять.
В принципе бета-версию я написал, и она работает у меня нормально. Но есть некоторые проблемы. 
1) Программа всегда должна работать с максимальным преорететом. Со средним преорететом светодиоды горят коряво при высокой загрузке ЦПУ.
Как сделать так, что бы программа запускалась с максимальным преоретеом в Windows?
2) Как реализовать задержки выполнения, типа Sleep(), но не на милисекунды, а на микросекунды? Я для таких задержек написал простую функцию, которая в цикле выполняет арифметические операции и количество итераций цикла подобрал "на глаз". В результате на моем компе работает превосходно, но на других машинах уже выглядит коряво, т.к. производительность процессоров отличается, и мои "задержки" уже совсем другие. В общем, нужно как-то делать задержки в микросекундах более грамотным способом.

В общем, если кому интересно, могу выложить свою прогу и распайку LPT для нее.

Автор: math64 6.5.2009, 15:00
Чтобы горело нормально, нужно писать драйвер.

Добавлено через 6 минут и 45 секунд
Ну или ещё: используй COM, а не LPT. При передаче 0x00 светодиод будет гореть с полной яркостью, при 0xFF - не будет гореть (или наоборот, как схему спаяешь), задержки будут определяться скоростью передачи, а не таймером, нужно только вовремя заполнять буфер передачи. Драйвер не нужен.

Автор: Temdegon 6.5.2009, 15:25
С ком-портом все слишком сложно. Во первых светодиода два, и ими нужно управлять. Если красный горит на 75% то синий на 25%. Что бы это реализовать, нужно паять схему. А моя цель сделать устройство максимально простым, без всяких плат, микросхем, т.к. это сложно.
Через LPT у меня все работает, причем без всяких плат. Просто два светодиода тыкнуты в LPT. Прога проц не грузит вообще, диоды горят красиво, ни чуть не хуже чем на скриншотах. Проблемы всего две: запустить с максимальным преорететом и сделать задержки переносимыми. Драйверы писать не умею и не хочу учиться. А еще мне нравится вариан оформить прогу в виде службы для windows. Но об этом я ничего не знаю..

Автор: cardinal 6.5.2009, 15:36
Цитата(Temdegon @  6.5.2009,  11:51 Найти цитируемый пост)
Нужно изменять яркость свечения двух светодиодов

Попробуй с PWM.
Цитата

By switching voltage to the load with the appropriate duty cycle, the output will approximate a voltage at the desired level.

http://en.wikipedia.org/wiki/Pulse-width_modulation
То есть меняй скважность
http://ru.wikipedia.org/wiki/%D0%A1%D0%BA%D0%B2%D0%B0%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D1%8C
сохраняя одну частоту. Если частота будет оставаться одинаковой, то и переносимость будет... smile 

Автор: Albor 6.5.2009, 15:47
Я бы какой-то буфер на LPT порт всё таки поставил (хотя бы транзисторы). Кто знает, достаточно ли мощные выходные ключи порта. Светодиоды, если взять совдеповские, светят более-менее нормально при 7~10 mA, а те что современные -  15 и более, а это многовато наверняка.

Автор: Temdegon 6.5.2009, 15:53
млин. так я и делаю через изменение сважности. По другому я никак не могу заставить светодиод, висящий на LPT светиться в пол-силы.
Работает так: 
Код

bool sw = false;
while (1){
 if (sw){
    .... // посылаем в LPT единицу, светодиод включается.
    .... // задержка, в зависимости он нужной яркости, от сотен микросекунд до пары милисекунд
 }else{
   .... // посылаем 0, светодиод тухнет
   .... // задержка
 {
 sw = !sw;
}


Тут важно понимать разницу между LPT и COM. Если послать в ком данные, то там сигнал появится короткое время, а в ЛПТ по другому. Если мы записали туда что-то, то напряжение на контактах будет до тех пор, пока мы не пошлем что-то другое. Что бы светодиод постоянно горел, нужно просто повесить его на контакт #2 и 25 и послать в порт 1. и он будет гореть, пока не пошлешь туда 0.
Я дела это без задержек, но тогда проц грузится на 100%. А с задержками вообще не грузится.

Автор: cardinal 6.5.2009, 15:57
Цитата

Детали можно использовать любые подходящие, резисторы мощностью от 0,125 Вт и выше, номиналом 400 ом—620 ом, светодиод любой марки (лучше буржуйские, они ярко светят даже при токах в 2 mA, в то время как отечественным образцам нужен ток в 10 раз больше) и любого цвета, например LG2040; кнопка любая без фиксации, но подойдет и с фиксацией, или вообще любой тумблер. 


Цитата

Обратите свое внимание, что ни LPT, ни COM-порт не содержат выхода источника питания (в противоположность Game-порту, на котором присутствует +5 в), и в большинстве случаев нагрузочная возможность выходных ножек порта не превышает 3—7 mA (милиампер) на каждую ножку. Попытка взять с ножек больший ток в лучшем случае приводит к падению напряжения на ножках, в худшем (при токах более 20 mA) — к возможности выхода порта из строя. Поэтому, если есть возможность — установите в компьютер мультикарту с портами либо переходник USB <–> COM или USB <–> LPT. 


http://mastershome.net.ru/vbfaq/c07.htm

Добавлено через 5 минут и 55 секунд
Цитата(Temdegon @  6.5.2009,  13:53 Найти цитируемый пост)
млин. так я и делаю через изменение сважности.


Цитата(cardinal @  6.5.2009,  13:36 Найти цитируемый пост)
сохраняя одну частоту.

 smile 

Автор: math64 6.5.2009, 16:06
Цитата(Temdegon @  6.5.2009,  15:25 Найти цитируемый пост)
С ком-портом все слишком сложно

Ничего сложного - разъём и светодиод. У меня есть такая заглушка - светодиод светится если идёт передача, никаких плат не нужно. Полезно при отладке программ, работающих с ком портом. Правда паял не сам.

Автор: Temdegon 6.5.2009, 16:16
Так кто-нить подскажет, как запустить ехе - файл с высоким преорететом? Чтоб не нужно было каждый раз через таскманагер искать его и менять преоретет вручную?
И как все-таки делать задерки программы в микросекундах?
У меня уже была мысть как бы калибровать функцию задержки во время первого запуска. Задержка представляет собой простой for, в котором делается чтонить типа z*=i*z*i. Т.е. сначала цикл запускается на 100к итераций, и измеряется время выполнения, а потом в корректируется количество итераций, для получения нужной задержки. Но такая задержка будет грузить проц, а это не есть гуд.

Автор: math64 6.5.2009, 16:31
Если уж делать задержки, то используй команды процессора выдающую число тактов с его влючения. При старте программы нужно вычислить тактовую частоту. Правда, она првилегированная и её можно использовать в Win98 или в драйвере.

Автор: Temdegon 6.5.2009, 16:50
А можно чуть-чуть подробнее. Не совсем понимаю, как зная тактовую частоту делать задержку. Я себе это решение опять же вижу как цикл, в котором проверяется, сколько тактов прошло. Но это опять же цикл, который сожрет все процессорное время.

Автор: xvr 6.5.2009, 16:56
Если ты сделаешь своему процессу RealTime приоритет, а задержки будешь отсчитывать через QueryPerformanceCounter, то светодиоды будут гореть очень хорошо, правда ничего другого на машине уже работать не будет  smile 
Любая задержка меньше ~20ms будет грузить проц, т.к. усыпить и разбудить процесс меньше, чем через тик системного таймера очень проблематично (точнее накладно)
Приоритет процесса и нити в нем можно менять функциями SetPriorityClass и SetThreadPriority (менять надо оба)

Лучше повесь на COM порт, как тут уже советовали. Светодиоды включить встречно - паралельно между TX и GND (не забудь резистор между ними и портом). Выводя в порт разные числа (00, 80, C0, E0, F0, F8, FC, FE, FF) можно менять яркость (надеюсь, 8ми ступеней хватит?). Выводить конечно надо постоянно, но Windows с этим вполне справится сама - сформировать буффер байт на 1000 и вывести блокирующим WriteFile (в цикле)

Автор: Temdegon 6.5.2009, 17:02
я че-то тыкался осциллографом в ком-порт и пробовал слать даные. Нифига не понял. МОжет прохо смотрел? Я так понимаю, кроме данных, которые я буду слать в LPT, там еще будут присутствовать всякие конрольные суммы и прочие служебные биты, которые будут не лучшим образом влиять на светодиоды. А может это и не значительно... 

Автор: xvr 6.5.2009, 19:49
Цитата(Temdegon @ 6.5.2009,  17:02)
я че-то тыкался осциллографом в ком-порт и пробовал слать даные. Нифига не понял. МОжет прохо смотрел? 

Может  smile 
Цитата

Я так понимаю, кроме данных, которые я буду слать в LPT, там еще будут присутствовать всякие конрольные суммы и прочие служебные биты, 
Нет там никаких контрольных сумм. Во первых, там двуполярный выход +/- 12В (приблизительно). Так что можно зажечь сразу 2 светодиода. Когда ничего не передается там стоит -12В. Когда начинается передача байта, там выдается +12В на время одного бита, потом сам байт побитно (0 выдается как -12В, 1 как +12В), в конце делается пауза на 1-2 бита с выдачей -12В. Затем начинается передача следующего байта (если он есть)

Автор: Temdegon 6.5.2009, 20:45
Спасибо. На досуге поэкспериментирую с ком-портом. Должно получиться даже проще чем с LPT, только данные сформировать правильные

Автор: Temdegon 7.5.2009, 01:01
Цитата

Светодиоды включить встречно - паралельно между TX и GND (не забудь резистор между ними и портом).

Диоды трехвольтовые. Для ограничения напряжения я параллельно светодиоду вешал стабилитрон на 3 вольта. Хотел так же сделать и для ком-порта, но что-то у мене возникли сомнения, можно ли так сделать в случае с ком-портом? Получится что параллельно двум диодам будут встречно-параллельно висеть два стабилитрона? как вы считаете? а то дома резисторов нету =(. А если вешать резистор, то какой? 
З.Ы. > Я понимаю, что это не форум для паяльников, не пинайте сильно. Сорри за оффтоп.

Автор: Albor 7.5.2009, 07:08
Цитата(Temdegon @  7.5.2009,  01:01 Найти цитируемый пост)
Для ограничения напряжения я параллельно светодиоду вешал стабилитрон на 3 вольта

Резистор нужен. В таком режиме стабилитрон открываясь делает практически кз, замыкая через себя разницу входного напряжения и напряжения стабилизации.
Цитата(Temdegon @  7.5.2009,  01:01 Найти цитируемый пост)
Получится что параллельно двум диодам будут встречно-параллельно висеть два стабилитрона?

Конечно, стабилитрон используется при обратном включении, а в прямом направлении это тот-же диод, он будет шунтировать светодиод, уменьшая ток через него.
Можешь попробовать включить стабилитрон встречно-последовательно со светодиодом, но при 12 в на входе и светодиоде на 3 вольта нужен стабилитрон на 9 Вольт. Как по мне - проще найти резистор. Посчитать резистор можно по закону Ома. Входное напряжение есть, нужно знать номинальный ток светодиода. Если ток 10 мА, то резистор 1~1.2 Ком.

Автор: xvr 7.5.2009, 08:39
ТОЛЬКО РЕЗИСТОР! Светодиод - прибор с очень нелинейной ВАХ, и для нормальной работы через него нормируется именно ТОК. При изменении напряжения на нем на 0.1В ток может изменится на порядок! Так что никакой стабилитрон не спасет.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)