<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>Topic libgtop | Hey, ruX is here.</title>
	<atom:link href="https://rux.vc/tags/libgtop/feed/" rel="self" type="application/rss+xml" />
	<link>https://rux.vc</link>
	<description>Delivering things - from code to product</description>
	<lastBuildDate>Thu, 11 Mar 2010 09:41:01 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.8</generator>
<site xmlns="com-wordpress:feed-additions:1">162978439</site>	<item>
		<title>CPU load indicator</title>
		<link>https://rux.vc/2010.03/cpu-load-indicator/</link>
					<comments>https://rux.vc/2010.03/cpu-load-indicator/#comments</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Thu, 04 Mar 2010 09:26:39 +0000</pubDate>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[atmega8]]></category>
		<category><![CDATA[avr]]></category>
		<category><![CDATA[circuit]]></category>
		<category><![CDATA[embedded]]></category>
		<category><![CDATA[gadget]]></category>
		<category><![CDATA[led]]></category>
		<category><![CDATA[libgtop]]></category>
		<category><![CDATA[libusb]]></category>
		<category><![CDATA[make]]></category>
		<category><![CDATA[pwm]]></category>
		<category><![CDATA[usb]]></category>
		<category><![CDATA[v-usb]]></category>
		<category><![CDATA[шим]]></category>
		<guid isPermaLink="false">http://rux.pp.ru/blog/?p=378</guid>

					<description><![CDATA[<p>Что это? Этот проект может стать хорошим начальным опытом в разработке устройств на микроконтроллере и программировании его, как прошивки мк так и создании управляющей программы. Собственно это очень простое устройство, плавно показывающее текущую нагрузку процессора меняя яркость светодиода(ну или по желанию можно использовать другую нагрузку). Людям, которые занимаются моддингом особо думаю понравится - нужно только ... <a title="CPU load indicator" class="read-more" href="https://rux.vc/2010.03/cpu-load-indicator/" aria-label="More on CPU load indicator">Read more</a></p>
The post <a href="https://rux.vc/2010.03/cpu-load-indicator/">CPU load indicator</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<h2>Что это?</h2>
<p>
Этот <em title="Ага, именно проект как бы то громко не звучало - вбухал достаточно много времени на контролирующую программу(=драйвер) и описание тут">проект</em> может стать хорошим начальным опытом в разработке устройств на микроконтроллере и программировании его, как прошивки мк так и создании управляющей программы.
</p>
<p>
<img decoding="async" src="http://rux.pp.ru/blog/wp-content/uploads/2010/03/cpuload-indicator-processor-load-average.png" alt="" title="cpuload-indicator-processor-load-average" width="234" height="109" class="alignright size-full wp-image-395" srcset="https://rux.vc/wp-content/uploads/2010/03/cpuload-indicator-processor-load-average.png 234w, https://rux.vc/wp-content/uploads/2010/03/cpuload-indicator-processor-load-average-150x69.png 150w" sizes="(max-width: 234px) 100vw, 234px" />Собственно это очень простое устройство, плавно показывающее текущую нагрузку процессора меняя яркость светодиода(ну или по желанию можно использовать другую нагрузку). Людям, которые занимаются моддингом особо думаю понравится - нужно только приложить фантазию :) Работает через USB, причём программный, реализованный с помощью прооекта <a href="http://www.obdev.at/products/vusb/index.html" target="_blank">V-USB</a>. В качестве мк выбран Atmega8
</p>
<p><span id="more-378"></span></p>
<p>
Предполагается, что уже есть какие то начальные знания в области программирования и электроники. </p>
<h2>Принцип работы</h2>
<p>
Есть 2 стороны - девайса и компьютера. Компьютер периодически с помощью программы посылает через usb информацию о том, на сколько нужно зажечь ярко светодиод. А девайс слушает комманду и плавно приблежает яркость светодиода от текущего значения к новому.</p>
<p>
Хочу отметить, что я посторался сделать как можно более гибкую систему - интервалы опроса текущей загрузки процессора программой на компьютере и интервал с которым приблежается текущая яркость к новой можно задать в коммандной строке программы. Также можно задать верхнюю и нижнюю границу свечения.</p>
<h2>Подробнее</h2>
<h3> Девайс</h3>
<p>
Схема достаточно простая и вполне собирается легко на макетной плате(у кого она есть) или как у меня - на картонке :) Конечно же, при желании можно сделать печатную плату - будет шикарно - я делать не стал, потому, что CPU load indicator оказался промежуточным этапом к большему проекту который я сейчас делаю. Конечно, гик скажет, что это слишком просто, чтоб уделять этому внимание, но кто-то только учиться, вроде меня =:)<br />
<a href="http://rux.pp.ru/blog/wp-content/uploads/2010/03/cpuload-indicator-circuit.png" data-lightboxplus="lightbox[378]" title="CPU load indicator circuit. AVR and V-USB based project - displays current cpu load by change LED's brightness   smoothly"><img decoding="async" src="http://rux.pp.ru/blog/wp-content/uploads/2010/03/cpuload-indicator-circuit-tiny.png" alt="" title="CPU load indicator circuit. AVR and V-USB based project - displays current cpu load by change LED's brightness   smoothly" class="aligncenter size-full wp-image-385" /></a>
</p>
<p>
Комментарии по схеме:</p>
<ul>
<li>J1 - USB порт к компьютеру(D- это вторая нога, D+ это третья), J2 - SPI видимо к программатору :)</li>
<li>X1, C5, C6 - генератор. Кварц можно поставить, например, на 15МГц, главное, чтоб V-USB поддерживал эту частоту, а кондёры тут от 18 до 22пф можно выбирать. У меня 22пф стоят</li>
<li>R1 - подтягивающий резистор, лучше всё-таки 10кОм. Для работы мк ведь требуется reset пассивный, а т.к. он инверсный, нужно подать "1". По идее, там есть внутри 100кОм, но как пишут, нога ловит каждый чих</li>
<li>D2, D3 - стабилитроны для того, чтоб не превысить напряжение на линии USB - так должно быть по стандарту, единица - не должна привышать 3.6в. У меня стеклянные - чёрной полоской к сигнальным линиям(D+ & D-)</li>
<li>R4, R5 - везде стоят по 68 Ом, у меня нормально работает 100 Ом. Если я правильно понимаю, они нужны чтоб не получилось ситуации, когда можно спалить порт мк</li>
<li>R2 - нужно оставить именно таким, это некая индикация USB-хосту что подключённо низкоскоростное устройство. Для эксперемента можно подцепить к usb только этот резюк и ядро будет писать что обнаруженно новое низкоскоростное устройство.</li>
<li>C3 - сглаживает помехи по питанию</li>
</ul>
<h3>ШИМ (PWM) </h3>
<p>Наверное всё это мутно - интервалы, шаги, яркость.. Так вот, "<em>яркость</em>" - это численное значение от <strong>0..255</strong> - значение, которое подаётся на <span class="comment" title=" = PWM">ШИМ(Широтно - Импульсная Модуляция)</span> выход. Про ШИМ можно много где прочитать, мне понравилось <a href="http://www.myrobot.ru/stepbystep/rce_pwm.php" target="_blank">на myRobot</a>. Соответственно максимальной яркости(состоянию, в котором максимальное количество "1") соответствует <strong>255</strong>, минимальной - <strong>0</strong>(максимальное количество "0"), среднему - <strong>127</strong>(примерное равное количесво "1" и "0"). Думаю логика прослеживается.
</p>
<p>
Когда компьютер послал новое значение для ШИМ, которое нужно установить на выходе девайса, то девайс постепенно приблежает текущее значение к новому, с определённой задержкой. Благодаря этому яркость плавно меняется. Так, например, в темноте плавно повышается яркость после еле различимого свечения и место рядом с девайсом около компьютера краснеет - ну разумеется если стоит красный светодиод.
</p>
<p>
Как я уже указал, программа посылает уже конкретное значение ШИМ которое нужно установить. Но перед отправкой, нужно его ещё вычислить. Т.е. при загрузки процессора в 100% яркость индикатора должна быть максимальной, а не (если бы послать просто значение ШИМ <strong>100</strong>) меньше половины от полной. Для этого нужно пересчитать его по простой формуле: (cpu_load * 255/100), где cpu_load - текущая нагрузка процессора.
</p>
<p>
Надеюсь пока ещё понятно, я ж предупредил что минимальная подготовка должна быть =).<br />
А ведь вполне может быть такая ситуация, что светодиод начинает светиться только от значния <strong>80</strong> в ШИМ? Вполне может быть - значит при маленькой нагрузке мы вообще не увидим свечения. А что, если после ШИМ  <strong>200</strong> индикатор так ярко светит, что кажется, вот-вот сгорит? Можно прийти в выводу, что требуется поставить рамки от и до и высчитывать  соответственно величину ШИМ.  Вычисляется по формуле(выжимка из кода):<br />
<code line_numbers="false" lang="c">cpu_load = ((valueMax - valueMin) / 100.0 ) * cpu_load + valueMin ;</code><br />
Названия переменных говорят за себя, пояснения не требуются, как я думаю.
</p>
<h3>Управляющая программа(сторона компьютера) - драйвер</h3>
<p>
Основная программа сосредоточенна в <em>software/cpu_indicator.c</em>.<br />
<b>Внимание!</b> Для сборки приложения нужно воспользоваться коммандой <strong>make clean all</strong>. Для запуска(из папки software) ./cpuload_indicator.<br />
У вас <big>обязательно</big> должен быть установлен пакет <big>libusb-dev</big> и <big>libgtop-dev</big>, иначе ничего не соберётся. Разумеется в зависимости от дистрибутива исходные коды этих библиотек могут отличаться названием.
</p>
<p>
libusb нужен очевидно для работы с USB, а libgtop для получения информации о текущей нагрузке процессора.
</p>
<p>
В начале <em>software/cpu_indicator.c</em> подключаются хедеры и указываются дефолтные значения переменных.<br />
О функциях</p>
<ol>
<li><strong>bool parseOpts(int, char *)</strong> - служит для парсинга коммандной строки и проверки на корректность значений.</li>
<li><strong>bool connectUsb() </strong>- ищет устройство среди всех и открывает его, если нашла. А если не нашла то в зависимости от наличия аргумента коммандной строки <em>-catch</em> будет пытаться искать снова или просто попросит завершить работу программы с информацией о том, что устройство не найдённо. В противном случае, если указан -catch программа будет ждать пока подключат устройство. После открытия успешного устройства посылается комманда устанавливающая шаг времени, с которым значение ШИМ приблежаться к новому. Этот аргумент можно задать в коммандной строке ключом <em>-step N</em>, где N - значение задержки в мсек. </li>
<li> <strong>int main (int, char *)</strong> - собвственнно входная точка программы. Вызывает parseOpts() и connectUsb(), высчитывает нагрузку на процессор за время в процентах, переводит в соответствующее значение ШИМ с учётом верхних и нижних смещений границ(о чём речь шла ранее) и посылает значение в USB. При ошибке, в зависимости от <em>-catch</em>, либо завершается работа программы, либо пытается подсоединиться снова, если аргумент указан.<br />
Особенно сложным оказалось для меня получение информации о нагрузки на процессор. Я воспользовался статьёй <a href="http://colby.id.au/node/39" target="_blank">Calculating CPU Usage from /proc/stat</a>, где нагрузка вычисляется  bash скриптом и берётся информация из /proc/stat.
</li>
<li><strong> void usage(char *) </strong>- выводит информацию об использовании, лучше показать:<br />
<code lang="bash" line_numbers="false"><br />
$ ./cpuload_indicator -help<br />
Control program for CPU Load indicator (c) ruX 2010<br />
Usage ./cpuload_indicator [option=[value]] ..<br />
Options:<br />
   -min NN     - set minimal PWM value [0..255]<br />
   -max NN     - set maxmimum PWM value [0..255]<br />
   -step NN    - set step interval for LED (in msec)<br />
   -update NN  - interval for update load  about current CPU(in seconds)<br />
   -catch      - never quit(always trying to catch device)<br />
   -help       - this help promt<br />
Copyright by ruX, 2010, http://ruX.pp.ru/<br />
</code>
</ol>
</p>
<p>
Думаю на столько краткого описания достаточно. За подробностями - в исходник. Есть ещё файл obdev_usb.c - там лежат довольно стандартные функции для открытия устройства(по его VID:PID, имени, имени разработчика) - они качуют из различных проектов, иногда немного правясь. Так и я взял за из проекта <a href="http://johannes.krude.de/projects/usb-Relay/" target="_blank">usb-relay</a>.
</p>
<h3>Программа прошивки</h2>
<p>Разумеется, всё что относится к прошивке девайса лежит в <em>firmware</em>, как ни странно :)
</p>
<p>
Код программы для мк можно разделить условно на 2 части: работа с USB, реализованная с помощью библиотеки V-USB и основной логики.
</p>
<p>
Важный этап - настройка V-USB, которая находится в файле <em>firmware/usbdrv.h</em>. То, что там определенно будет решать каким будет устройство. Файл шаблонный, от obdev. Но добавил 2 строчки, которые определяют константы комманд, которые посылает компьютер - для установки нового значения ШИМ и установки интервала шага приближения к новому значению:<br />
<code lang="c">#define REQUEST_SET_TARGET      1<br />
#define REQUEST_SET_STEP        2</code>
</p>
<p>
В основном файле логики <em>firmware/cpuload_indicator.c</em> сначала устанавливается конфигурация перефирии: направление вывода и настройка ШИМ.<br />
<code lang="c">    // Configure port B pin 1 as output<br />
    DDRB = (_BV(1));</p>
<p>    // Setup PWM<br />
    TCCR1A=0xA1;<br />
    TCCR1B=0x09;<br />
    TCNT1H=0x00;<br />
</code><br />
Дальше вызывается process() в котором и происходит основная работа - один раз инициализируется USB и начинается бесконечный цикл, в котором происходит опрос usb - usbPoll() и приближение значения ШИМ, выполняется маленькая задержка:<br />
<code lang="c"><br />
void process(void)<br />
{<br />
    unsigned int dsec = 0;</p>
<p>    for(startUsb(); ;dsec++){<br />
        usbPoll();</p>
<p>        if (dsec % (delay * 10) == 0 &amp;&amp; OCR1A != target) {<br />
            if (OCR1A &gt; target) OCR1A--; else OCR1A++;<br />
        }</p>
<p>        _delay_ms(0.1);</p>
<p>        if (dsec == 10000) dsec = 0;<br />
    }<br />
}<br />
</code><br />
У меня в качестве выхода ШИМ используется <strong>T/C1</strong> - PORTB, бит 1, нога 15 в PDIP корпусе, соответственно имеем дело с <strong>OCR1A</strong>. Ещё нюанс: компьютер посылает интервал шага приближения в мсек, а внутри цикла задержка 0.1мсек, поэтому приходиться делать (delay * 10), чтоб привести к одному порядку - к примеру у нас компьютер передал,что шаг - 50мсек(=5 * 10<sup>-2</sup>, значит нужно сделать 50 * 10 = 500 циклов перед тем, как будет приблежение значения ШИМ к новому.
</p>
<p>
Если кто то не понял код выше - в цикле сначала происходит опрос, а дальше проверяется, если наступило время, когда нужно сделать шаг(т.е. интервал задержки прошёл) и при этом текущее значение ШИМ это не то, что компьютер "попросил" выставить, то приблежаемся к требуемому значению. Дальше задержка на 10<sup>-4</sup>сек и попытка избежать переполнения если число в счётчике циклов dsec достаточно большое.
</p>
<p>
Ещё определенна uchar usbFunctionSetup(uchar data[8]), которая вызывается, когда компьютер послал данные - в нашем случае это либо новое значение ШИМ, либо установка интервала шага приблежения.<br />
<code lang="c"><br />
uchar usbFunctionSetup(uchar data[8])<br />
{<br />
    usbRequest_t *request = (usbRequest_t*) data;<br />
    switch (request-&gt;bRequest) {<br />
    case REQUEST_SET_TARGET:<br />
        target = request-&gt;wValue.bytes[0];<br />
        break;</p>
<p>    case REQUEST_SET_STEP:<br />
        delay = (short int)(request-&gt;wValue.bytes);<br />
        break;<br />
    }</p>
<p>    return 0;<br />
}<br />
</code><br />
Структура usbRequest_t *request содержит информацию о том, что нам пришло, подробнее можно узнать в доках. request->bRequest определяет номер комманды, а request->wValue.bytes переданные от компьютера данные.<br />
<strong>target</strong> - значение ШИМ, которое нужно установить, фактически используется только 1 байт, поэтому и выбираем только первый байт из того, что пришло. А <strong>delay</strong> - задержка в милисекундах, поэтому тут одним байтом не обойтись, берём 2 сразу, делая тайпкастинг к short int.
</p>
<h3>Прошивка прошивки :)</h3>
<p>
В <em>firmware/</em> определён мэйкфайл, который можно настроить под себя - в моём случае я использовал мк atmega8, программатор usbasp и частота цварца - 12MГц. По желанию можно изменить:<br />
<code lang="bash" line_numbers="false"><br />
. . . .<br />
DEVICE = atmega8<br />
PROGRAMMER = usbasp<br />
FREQ = 12000000<br />
. . . .<br />
</code>
</p>
<p> Чтоб полностью откомпилировать, прошить программу и фьюзы, достаточно выполнить <strong>make clean all flash fuse</strong> :) Из фьюзов нужно отметить, что установленно тактирование от кварца, свыше 12МГц, кому интересно найдут интерпретацию фьюзов. Кстати о них(<b title="лучше ещё раз выделить..">для atmega8</b>) : старший байт -<strong> 0xC9</strong>, младший - <strong>0xEF</strong></p>
<h2>Фото</h2>
<p>
Повторюсь, это сделанно на картонке, из за отсутствия макетной платы, причём буквально на коленке и для другого проекта, поэтому, уведенное может показаться совсем не то, что на схеме было. Но так оно и есть, поверьте :) Итак, <a href="#showme_all_photo_please" onClick="document.getElementById('showme_all_photo_please').style.display = 'block';">показать фото</a></p>
<div id="showme_all_photo_please" style="display:none; text-align:center"><center><br />
<a href="http://rux.pp.ru/blog/wp-content/uploads/2010/03/cpuload-indicator-photo2.jpg" data-lightboxplus="lightbox[378]" title="cpuload-indicator-photo2"><img decoding="async" src="http://rux.pp.ru/blog/wp-content/uploads/2010/03/cpuload-indicator-photo2-150x122.jpg" alt="" title="cpuload-indicator-photo2" width="150" height="122" class="aligncenter size-thumbnail wp-image-388" srcset="https://rux.vc/wp-content/uploads/2010/03/cpuload-indicator-photo2-150x122.jpg 150w, https://rux.vc/wp-content/uploads/2010/03/cpuload-indicator-photo2-300x245.jpg 300w, https://rux.vc/wp-content/uploads/2010/03/cpuload-indicator-photo2.jpg 417w" sizes="(max-width: 150px) 100vw, 150px" /></a> <a href="http://rux.pp.ru/blog/wp-content/uploads/2010/03/cpuload-indicator-photo1.jpg" data-lightboxplus="lightbox[378]" title="cpuload-indicator-photo1"><img decoding="async" src="http://rux.pp.ru/blog/wp-content/uploads/2010/03/cpuload-indicator-photo1-150x92.jpg" alt="" title="cpuload-indicator-photo1" width="150" height="92" class="aligncenter size-thumbnail wp-image-387" srcset="https://rux.vc/wp-content/uploads/2010/03/cpuload-indicator-photo1-150x92.jpg 150w, https://rux.vc/wp-content/uploads/2010/03/cpuload-indicator-photo1-300x184.jpg 300w, https://rux.vc/wp-content/uploads/2010/03/cpuload-indicator-photo1.jpg 416w" sizes="(max-width: 150px) 100vw, 150px" /></a></center>
</div>
</p>
<h2>Финал</h2>
<p>На этом всё, буду рад если кому то это помогло. Хотя это уже помогло мне самому :)<br />
Такие простые штуки позволяют сразу много всего пощюпать, хоть и не глубоко. А это помогает разложить по полочкам тонны информации. </p>
<p>Это - всё таки посложнее просто миганием светодиодов. И даже посложнее чем мигание светодиодов через USB(кстати, огромное спасибо проекту <a href="http://johannes.krude.de/projects/usb-Relay/" target="_blank">usb-Relay</a>, который помог мне разобраться во многом).</p>
<p>Стоимость сборки такого устройства порядка 100-120р(по крайней мере с ценами, которые в мегаэлектронике в СПБ)</p>
<p>У линуксодидов проблемм быть не должно. У *bsd и solaris как я понимаю тоже нет(разве что поправить пути к инклюдам в мейкфайле). С виндой всё хуже. То, что нужно libusb это очевидно, кто чистал описание проекта V-USB сразу это поняли. По идее, как я понимаю, ничего не изменится, кроме места получения текущей нагрузки процессора - тут придётся разбираться самостоятельно. Или, если получится, воспользоваться cygwin(не из за libusb, а из за<strong> libgtop!</strong>), если умеете, я если честно практически не предствляю что он умеет и как :) Ну и разумеется нужно иметь make & gcc & winAvr</p>
<p>Скачать прошивку, программу и схему(в формате KiCad) в одном файле: <a href='http://rux.pp.ru/blog/wp-content/uploads/2010/03/cpuload_indicator_v0.1.tar.gz'>cpuload_indicator_v0.1.tar.gz</a></p>The post <a href="https://rux.vc/2010.03/cpu-load-indicator/">CPU load indicator</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2010.03/cpu-load-indicator/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">378</post-id>	</item>
	</channel>
</rss>
