Схем различных индикаторов, отображающих загруженность ЦП и памяти достаточно много. Но в основном они отображают информацию с помощью LCD дисплея, который или слишком мал, или размеры нормальные, но дорогой. Именно по этой причине я решил собрать индикатор загруженности ЦП на светодиодах.
Эта статья является логическим продолжением для применения кода, описанного в третьем видеоуроке о mikroPascal.
Исходя из того, что у меня нет лазерного принтера (ЛУТ отпадает), двухъядерный процессор и один светодиод стоит примерно 0.8 гривны, было решено делать 3 строки светодиодов по 10 штук в каждой. Две - под индикацию загрузки процессора, и оставшаяся под память или третье ядро (не сталкивался, но слышал).
Основная информация об устройстве:
- Напряжение питания: 5 V
- Потребляемый ток: < 50 mA
- Частота обновления данных: 0,5
Теперь можно перейти к схеме.
Как видите, она достаточно простая. Основа схемы - микроконтроллер ATmega8 (в корпусе DIP-28). Общее количество деталей - 40 шт., из них : светодиодов - 31, транзисторов - 5, остальное микроконтроллер и обвязка генератора.
Не столько для экономии выводов, сколько для удобства обращения к портам я использовал такое включение светодиодов для динамической индикации:
Таким способом мне удалось "уложиться" в два порта МК (PORTB - 6 пин, PORTC - 5 пин). Можно было конечно использовать сдвиговые регистры, но это повлекло бы за собой усложнение программы, а так же занятое место на плате. По-этому решил обойтись без них.
На схеме нет токоограничительных резисторов (применительно к светодиодам), так как они работают в импульсном режиме. Я использовал светодиоды красного, желтого и белого цветов. Красный и желтый - ЦП, белый же для дополнительной строки.
После всех манипуляций со схемой, взялся за разводку печатной платы. Вот тут то и был зарыт кирпич....Если схема была набросана минут за 5 то с платой пришлось возитсья около получаса. В итоге она получилась двухсторонней.
Как видите, разводка платы не самая простая. В этом виновата прежде всего динамическая индикация. Из-за нее пришлось часть проводников перенести на обратную сторону платы, а так же использовать большое количество переходных отверстий (в основном для подключения светодиодов). Но, тем не менее эту плату возможно сделать и без ЛУТа. И последнее относительно платы - я использовал текстолит толщиной 0,5 мм, так как другого с двухсторонним покрытием в наличии не оказалось.
Рассмотрев аппаратную часть можно перейти к программной.
Программу для МК я как всегда писал в среде mikroPascal for AVR (v 6.01). Так как в микропаскале нет библиотеки для микроконтроллера Atmega8, которая позволяет работать с USB, то выбор пал на UART. Но так как последний видеоурок по mikroPascal был про прерывания, то решил и сюда их всунуть. И вот что в итоге получилось:
program iCPU_t; uses AADL; var dat:array [0..2] of byte; rec,i,c,enbl:byte; rcit,rci,ti:integer; const pc: array [0..10] of byte = (31,30,28,24,16,0,30,28,24,16,0); //Объявляем константы const pb0: array [0..10] of byte = (0,254,254,254,254,254,253,253,253,253,253); //Они будут использоваться, как вы уже поняли из const pb1: array [0..10] of byte = (0,251,251,251,251,251,247,247,247,247,247); //из названий, для отправки заданных значений const pb2: array [0..10] of byte = (0,239,239,239,239,239,223,223,223,223,223); //в порт. procedure usart_c(); iv IVT_ADDR_USART__RXC; //Функция, которая вызывается по прерыванию UART begin //(если в буфере приема есть данные). rec:=UART_Read(); // if rec=47 then enbl:=1; //Тут мы ищем нужные нам символы, и сразу их if enbl=1 then inc(enbl) else //переводим. if enbl=2 then begin // case rec of // 48: rec:=0; 49: rec:=1; 50: rec:=2; 51: rec:=3; 52: rec:=4; 53: rec:=5; 54: rec:=6; 55: rec:=7; 56: rec:=8; 57: rec:=9; end; ti:=rec; inc(i); case i of 1: rci:=ti*10; 2: rci:=rci+(ti); end; if i>=2 then begin i:=0; enbl:=0; end; end; end; begin Uart1_init(9600); //Инициализация UART UCSRB.B7:=1; //Прерывание по приему данных UART SREG_I_bit:=1; //Разрешаем прерывания DDRC:=0xFF; DDRB:=0xFF; DDD7_bit:=1; PORTD7_bit:=0; for c:=0 to 2 do dat[c]:=0; While TRUE do begin rcit:=rci; if (rcit>30) and (rcit<40) then dat[2]:=rcit-30; //Присваиваем значение различным if (rcit>20) and (rcit<30) then dat[1]:=rcit-20; //элементам массива dat, в зависимости от того, if (rcit>10) and (rcit<20) then dat[0]:=rcit-10; //какому ядру они соответствуют. for c:=0 to 2 do begin case c of 0: if dat[c]<=5 then begin //Дальше обеспечиваем индикацию. PORTC:=pc[dat[c]]; PORTB:=pb0[dat[c]]; delay_ms(1); end else begin PORTC:=pc[5]; PORTB:=pb0[dat[c]-5]; delay_ms(1); PORTC:=pc[dat[c]]; PORTB:=pb0[dat[c]]; delay_ms(1); end; 1: if dat[c]<=5 then begin PORTC:=pc[dat[c]]; PORTB:=pb1[dat[c]]; delay_ms(1); end else begin PORTC:=pc[5]; PORTB:=pb1[dat[c]-5]; delay_ms(1); PORTC:=pc[dat[c]]; PORTB:=pb1[dat[c]]; delay_ms(1); end; 2: if dat[c]<=5 then begin PORTC:=pc[dat[c]]; PORTB:=pb2[dat[c]]; delay_ms(1); end else begin PORTC:=pc[5]; PORTB:=pb2[dat[c]-5]; delay_ms(1); PORTC:=pc[dat[c]]; PORTB:=pb2[dat[c]]; delay_ms(1); end; end; end; end; end.
В программе тоже ничего сложного нет. Константы в самом начале программы использовались для того, что бы не писать в порт "ручками" каждый раз. В процедуре , вызываемой по прерыванию, используется такой алгоритм:
- Анализируем принятые данные, если они соответствуют "/", то разрешаем в следующий раз программе пройти дальше.
- Расшифровываем из ANCII кодировки.
- Рассчитываем и записываем в переменную
Далее, в основном цикле программы мы сначала сопоставляем, к какому ядру относятся полученные данные, а потом их присваиваем соответствующему элементу массива dat.
Вот и весь алгоритм программы.
Если вас интересует, как данные отображаются, то все так же просто:
- Смотрим, какая строка сейчас должна обновиться.
- Выбираем из массива dat нужный элемент.
- Если нужно зажечь пять или меньше светодиодов в строке, то просто оправляем значение в порт. Если же больше пяти (число n), то сначала зажигаем первые пять, а потом то что осталось (n-5). Все это крутится в цикле.
Из фузов нужно выставить только внешний кварц (8 MHz).
В Khazama AVR Programmer это выглядит следующим образом:
Вот и все! Но если у вас нет каких-то деталей, но есть их аналоги.... Светодиоды можно взять любые, подходящие по току и размерам. Микроконтроллер заменить нельзя. Только взять такой же но с любым другим индексом (например, вместо ATmega8 - ATmega8L и т.д.). Транзисторы так же можно взять любые маломощные структуры p-n-p. Я использовал КТ361Г (работают нормально, хотя еще 1987 г. выпуска :) ). Резисторы - с разбросом от указанного номинала до +/- 20 %.
И напоследок, о программе для Windows, которая управляет индикацией. Она написана в Delphi xe5 и называется iCPU.
\
Рассчитана на 2 ядра. В настройках выбирается порт, к которому подключено устройство. Возможно использовать как встроенный COM порт (через преобразователь уровней на MAX232), так и через виртуальный COM порт, с использованием переходника на базе PL2303 и подобных. У меня в городе можно купить такой кабель для старых моделей NOKIA.
Внутри платка, которая с успехом может использоваться как USB-COM переходник.
Вот несколько фотографий готового устройства.
Обновление от 20.07.2014:
Доработал программу, теперь можно выводить на 3-ю строку загруженность памяти. А так же мелкие исправления.
Обновление от 01.05.2015:
Полностью переписан код как прошивки для МК, так и программы для Windows. Теперь есть отдельная версия для Windows x64.
Для МК прошивка писалась в WinAVR (Cpp).
ВНИМАНИЕ! Старая прошивка + новая версия программы НЕСОВМЕСТИМЫ, как и новая прошивка + старая версия программы.
При прошивке фузы указывать те же, что и для старой версии, за исключением (выставлять как на скрине):
.
Из "нововведений":
- Возможность применять "выравнивание" (по левому краю, по центру и по правому краю).
- Автоматическое отключение индикации через 10с (например, если комп погрузили "в сон").
- Теперь есть "тестовый" режим, в котором включаются все светодиоды (например, при первых включениях уст-ва, для выявления неполадок).
- Если у вас в системе многоядерный процессор, то будут отображаться только первые 2 ядра (на уст-ве, в программе будет видно загрузку всех ядер). В противном случае, на уст-ве будут активными только 1-я и 3-я строки (1 ядро и память соответственно).
Так же хочу заметить, что перед первым запуском программы, впишите номер ком порта, к которому подключено устройство, в файл "settings.ini". Он лежит в папке с exe-шником. Иначе, скорее всего, будете через каждые 0.5с получать окна с ошибками!
В аппаратную часть устройства никакие правки не вносились.
Немного фотографий:
Обновление от 16.05.2015:
Оптимизирован код. Добавлена возможность регулировки яркости (программный ШИМ на таймере T2). Внесены некоторые правки в программу для Windows (теперь, если COM порт выбран неверно (порта с таким номером в системе нет), не будет +100500 окон с ошибками).
Список радиоэлементов
Обозначение | Тип | Номинал | Количество | Примечание | Магазин | Мой блокнот |
---|---|---|---|---|---|---|
U1 | МК AVR 8-бит | ATmega8 | 1 | DIP-28 | Поиск в магазине Отрон | |
D1-D30 | Светодиод | HL-A-3528H308W-S1-13 | 30 | Любые светодиоды 0805, подходящие по току | Поиск в магазине Отрон | |
C1, C2 | Конденсатор | 27 пФ | 2 | 0805 | Поиск в магазине Отрон | |
X1 | Кварцевый резонатор | 8 МГц | 1 | Низкопрофильный | Поиск в магазине Отрон | |
R2-R6 | Резистор | 1 кОм | 5 | 0805 | Поиск в магазине Отрон | |
R1, R7-R10 | Резистор | 30 кОм | 5 | 0805 | Поиск в магазине Отрон | |
Q1-Q4 | Транзистор | 2N3702 | 5 | Или КТ361 | Поиск в магазине Отрон | |
Скачать список элементов (PDF)
Прикрепленные файлы:
- icpu-new.rar (1871 Кб)
- icpu-16_05_2015.rar (1841 Кб)
- comp143_icpu_old.rar (892 Кб)
Комментарии (8) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация
[Автор]
А исходник на Дельфях покажете? И хорошо бы отрабатывать ситуацию отсутствия ком-портов, а то я программу еле прибил через диспетчер задач.
[Автор]
[Автор]
А если 6 ядер, то будет брать только первые два (или три. В программе правку внести).