<?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>Electronics | Hey, ruX is here.</title>
	<atom:link href="https://rux.vc/topics/electronics/feed/" rel="self" type="application/rss+xml" />
	<link>https://rux.vc</link>
	<description>Delivering things - from code to product</description>
	<lastBuildDate>Sun, 27 Dec 2020 10:24:46 +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>Pi-Hole and DNS-over-HTTPS using docker-compose</title>
		<link>https://rux.vc/2020.04/pi-hole-and-dns-over-https-using-docker-compose/</link>
					<comments>https://rux.vc/2020.04/pi-hole-and-dns-over-https-using-docker-compose/#comments</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Sun, 26 Apr 2020 23:46:35 +0000</pubDate>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[docker-compose]]></category>
		<category><![CDATA[docker-machine]]></category>
		<category><![CDATA[raspberry pi]]></category>
		<guid isPermaLink="false">https://rux.vc/?p=3674</guid>

					<description><![CDATA[<p>I'm glad that people started to think about the privacy more than ever In this post I'll share my experience of configuring pi-hole and Cloudflare DNS-over-HTTPS on Raspberry Pi using docker-compose. Before we dig into the configuration a few words what it's all about UPD: Post has been updated with newest version of pi-hole DNS-over-HTTPS(aka ... <a title="Pi-Hole and DNS-over-HTTPS using docker-compose" class="read-more" href="https://rux.vc/2020.04/pi-hole-and-dns-over-https-using-docker-compose/" aria-label="More on Pi-Hole and DNS-over-HTTPS using docker-compose">Read more</a></p>
The post <a href="https://rux.vc/2020.04/pi-hole-and-dns-over-https-using-docker-compose/">Pi-Hole and DNS-over-HTTPS using docker-compose</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p>I'm glad that people started to think about the privacy more than ever</p>
<p>In this post I'll share my experience of configuring <strong>pi-hole</strong> and <strong>Cloudflare DNS-over-HTTPS</strong> on <strong>Raspberry Pi</strong> using <strong>docker-compose</strong>. Before we dig into the configuration a few words what it's all about</p>
<p><strong>UPD: Post has been updated with newest version of pi-hole</strong></p>
<p><span id="more-3674"></span></p>
<h3>DNS-over-HTTPS(aka DoH)</h3>
<p>It's a protocol allowing internet users to retrieve IP information about the internet website(perform DNS resolutions) using a secure connection to the DNS server which supports DoH.</p>
<p><strong>So why is it important?</strong></p>
<p>I hope I won't surprise you that your internet provider really wants to know what you're visiting. For different reasons - for statistics, for advertisement, to collect your data, inject advertisement, etc. In 2020 most of the internet websites are working via HTTPS. That means providers <strong>can't change and see</strong> information sent between your computer and remote server because it's encrypted. Even better - internet provider <strong>can't hijack</strong> into your connection, and for example inject advertisement or install malware.</p>
<p>The problem is, <em>before</em> your computer connects to the server the <strong>domain</strong> needs to be &quot;translated&quot; into the IP address and here we have an <strong>issue</strong>. Classic DNS designed to be really quick and some tradeoffs had been done. For example DNS traffic can be <a href="https://en.wikipedia.org/wiki/DNS_hijacking">hijacked</a>, or <a href="https://en.wikipedia.org/wiki/DNS_spoofing">DNS cache poisoning</a> can be performed. Those attacks which can't guarantee that your computer talks to the genuine server <em>even</em> it's using HTTPS.</p>
<p>Unfortunately, DNS hijacking is not only &quot;hacker&quot; thing, many internet providers and &quot;big brother&quot; type of systems often use those techniques to gain something valuable.  Checkout <a href="/2020.04/grumble-virgin-media-dns-hijacking-and-absence-of-customer-service/">post about Virgin Media UK-based ISP</a> doing those nasty things.</p>
<p><strong>Ok ok, I'm scared. What is the solution?</strong></p>
<p>If you trust, for example cloudflare(you need to trust somebody!) then it's possible to use their DoH service. Read below to learn how to make the whole network use it</p>
<h3>pi-hole - sink for the advertisement</h3>
<p><a href="https://pi-hole.net/">Pi-Hole</a> is a community-led project which basically provides a dns server with a blacklist of the advertisement domains and nice web interface to manage it. No magic there - it simply takes your DNS requests, checks if the domain is blacklisted and if it's not - forwards request to the upstream DNS server of your choice.</p>
<p>I have it enabled only against web crypto miners and popunder-type advertisement</p>
<h3>Cloudflare DNS-over-HTTPS + pi-hole = <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2764.png" alt="❤" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>
<p>What a great friendship! Pi-hole will carefully filter advertisement domains and route all requests into the <a href="https://developers.cloudflare.com/1.1.1.1/dns-over-https/cloudflared-proxy/">cloudflared DoH server</a>. Having docker-compose file makes it work literally in a few clicks.</p>
<p>Prerequisites:</p>
<ul>
<li><strong>Raspberry PI</strong> - I have RPi4. Technically it could be any always-on computer, or ever router but it would require additional configuration</li>
<li><strong>Docker machine</strong> configured for your raspberry - <a href="https://rux.vc/2020.01/installing-docker-machine-on-raspberry-pi/">follow this guide</a></li>
<li><strong>Static IP</strong> for your raspberry must be configured. Normally it's done via web interface of your router.</li>
<li><strong>5 mins</strong> of your time</li>
</ul>
<p>Get this <code>docker-compose.pihole.yml</code> file:</p>
<pre><code>version: &quot;3&quot;

services:
  cloudflared:
    container_name: cloudflared
    image: visibilityspots/cloudflared
    restart: unless-stopped
    networks:
      pihole_net:
        ipv4_address: 10.0.0.2

  pi-hole:
    container_name: pi-hole
    image: pihole/pihole:v5.0
    restart: unless-stopped
    hostname: pihole
    ports:
      - &quot;80:80/tcp&quot;
      - &quot;53:53/tcp&quot;
      - &quot;53:53/udp&quot;
    volumes:
      - &quot;/config/pihole:/etc/pihole&quot;
      - &quot;/config/dnsmasq:/etc/dnsmasq.d&quot;
      - &quot;/dev/null:/var/log/pihole.log:ro&quot;
    environment:
      - DNS1=&#039;10.0.0.2#5054&#039;
      - DNS2=&#039;8.8.8.8#53&#039;
      - IPv6=false
      - TZ=Europe/London
      - DNSMASQ_LISTENING=all
      - WEBPASSWORD=admin
      - PIHOLELOG=/dev/null
    extra_hosts:
      - &quot;printer.mynetwork:192.168.5.33&quot;
      - &quot;router.mynetwork:192.168.5.1&quot;
    networks:
      pihole_net:
        ipv4_address: 10.0.0.3
    dns:
      - 127.0.0.1
      - 1.1.1.1
    cap_add:
      - NET_ADMIN

networks:
  pihole_net:
    driver: bridge
    ipam:
     config:
       - subnet: 10.0.0.0/29

</code></pre>
<p>Params to note:</p>
<ul>
<li><strong>WEBPASSWORD</strong> - envinroment variable allowing you to set password for web admin panel</li>
<li>array <strong>extra_hosts</strong> - here you can set custom hostnames for devices on your local network. For example, <code>printer.mylan:123.123.123.123</code> if your printer has a static ip address assigned. </li>
<li><strong>DNS2</strong> - is a fallback dns server in case your cloudflared daemon dies somehow. I set to google’s 8.8.8.8</li>
</ul>
<p><strong> Fire it up!</strong></p>
<pre><code>➜ eval $(docker-machine env myrpi)  
➜ docker-compose -f docker-compose.pihole.yml  up -d
</code></pre>
<p>That's it.<br />
Soon you'll be able to access <a href="http://your_router_ip">http://your_router_ip</a>./ and see welcome message from the pi-hole</p>
<p>And the last step:</p>
<ul>
<li>set your computer dns to the ip address of your router, make sure everything is working. You'll be able to see requests sent from your computer.</li>
<li>if you happy, go ahead and update DNS settings for the router, it should point to the raspberry pi IP address.</li>
</ul>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f4a5.png" alt="💥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Just a reminder: since your network now depends on the raspberry make sure it's always on otherwise nobody in your household will have Internet access :)</p>
<p><strong>Done.</strong> Sleep well without worying that your internet provider is intercepting or hijacking your DNS internet traffic. From the point of view of ISP you suddenly stopped accessing all Classic DNS, it's because you're using DoH</p>The post <a href="https://rux.vc/2020.04/pi-hole-and-dns-over-https-using-docker-compose/">Pi-Hole and DNS-over-HTTPS using docker-compose</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2020.04/pi-hole-and-dns-over-https-using-docker-compose/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3674</post-id>	</item>
		<item>
		<title>Asus Zenbook UX303UA memory upgrade</title>
		<link>https://rux.vc/2020.02/asus-zenbook-ux303ua-ram-upgrade/</link>
					<comments>https://rux.vc/2020.02/asus-zenbook-ux303ua-ram-upgrade/#comments</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Fri, 07 Feb 2020 16:42:01 +0000</pubDate>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Geek]]></category>
		<category><![CDATA[asus]]></category>
		<category><![CDATA[intel]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[ux303]]></category>
		<guid isPermaLink="false">https://rux.vc/?p=3636</guid>

					<description><![CDATA[<p>I bought UX303UA Zenbook back in June 2016 for £800. It's meant to be be a temporary laptop to be used for 1-2 years max. Although it's quite cheap it had very good spec especially for 2016: i7-6500U @ 2.5Ghz and 12Gb RAM with fair 4-6hours on single charge, just 1.2kg. It was a significant ... <a title="Asus Zenbook UX303UA memory upgrade" class="read-more" href="https://rux.vc/2020.02/asus-zenbook-ux303ua-ram-upgrade/" aria-label="More on Asus Zenbook UX303UA memory upgrade">Read more</a></p>
The post <a href="https://rux.vc/2020.02/asus-zenbook-ux303ua-ram-upgrade/">Asus Zenbook UX303UA memory upgrade</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p>I bought UX303UA Zenbook back in June 2016 for <strong>£800</strong>. It's meant to be be a temporary laptop to be used for 1-2 years max.</p>
<p>Although  it's quite cheap it had very <a href="https://www.asus.com/uk/Laptops/ASUS-ZenBook-UX303UA/">good spec</a> especially for 2016: <strong>i7-6500U @ 2.5Ghz</strong> and <strong>12Gb</strong> RAM with fair <strong>4-6hours</strong> on single charge, just 1.2kg. It was a significant improvement from previous Zenbook with i5 and 8Gb memory. RAM is especially critical for java developers, especially for greedy Android tools.</p>
<p>Even now, in 2020 this spec isn't bad at all. It's still possible to get a similar device bus slightly cheaper. Having said that I was thinking to add more memory so I can continue to use laptop comfortabily. Unfortunatelly, all websites and official sources say <strong>it's impossible</strong> - the max is 8(in the slot)+4(soldered).</p>
<p><span id="more-3636"></span></p>
<blockquote style="color:brown"><p>
Please note: You are using this guide at your own risk. I take no responsibility and will not be held liable for any damages that may occur while using this guide.
</p></blockquote>
<h2>TL;DR</h2>
<p>It's <strong>possible</strong> to replace installed 4 or 8Gb memory module with 16Gb. In total that would give you 20Gb or RAM. Look for the link at the bottom of the post</p>
<h2>Does CPU support more than 16Gb?</h2>
<p>Spec for i7-6500U on the <a href="https://ark.intel.com/content/www/us/en/ark/products/88194/intel-core-i7-6500u-processor-4m-cache-up-to-3-10-ghz.html">Intel website</a> states that max supported memory is 32Gb:</p>
<p><img decoding="async" src="https://rux.vc/wp-content/uploads/2020/02/Screenshot-from-2020-02-07-16-13-23.png" alt="" /></p>
<h2>Official lie</h2>
<p>Here are some official sources:</p>
<p><a href="https://www.crucial.com/usa/en/compatible-upgrade-for/ASUS/zenbook-ux303ua">Crucial compatible upgrades</a>:</p>
<p><img decoding="async" src="https://rux.vc/wp-content/uploads/2020/02/Screenshot-from-2020-02-07-15-04-44.png" alt="" /></p>
<p><a href="https://www.asus.com/Laptops/ASUS-ZenBook-UX303UA/specifications/">Laptop page on Asus website</a></p>
<p><img decoding="async" src="https://rux.vc/wp-content/uploads/2020/02/Screenshot-from-2020-02-07-15-07-47.png" alt="" /></p>
<p>I even asked Asus support, expecting that they know what they're selling:</p>
<p><img decoding="async" src="https://rux.vc/wp-content/uploads/2020/02/Screenshot-from-2020-02-07-15-09-24.png" alt="" /></p>
<p>Once I've got that <em>official</em> response in 2018 I winded down and had decided to buy an another laptop later once my UX303 break. But something went wrong - and it's <em>still</em> working, and working quite well. I'm not mentioning shit quality of the surface - it's all covered with scrateches.</p>
<p>Fast Forward to 2020 and I'm looking for another laptop. Very soon I realised that most hi-end laptops have memory soldered on board. The worst thing is they have 16Gb max. There are only <strong>few</strong> 13-14&quot; laptops with 32Gb memory(!). It's really hard to belive so. That made me think about upgrading memory on UX303 again - if 16Gb module would work it will result in 20Gb total RAM, which is irronically more than hi-end X1 Carbon 7th Gen and UX433.</p>
<p>I gave it a go and replaced memory module. Guess what?</p>
<p><center><br />
<img decoding="async" src="https://rux.vc/wp-content/uploads/2020/02/ux303-20gb-ram-ubuntu.png" alt="" /><br />
<strong>IT WORKS</strong><br />
</center></p>
<h2>How to install 16Gb module on Asus UX303UA?</h2>
<p><a href="https://rux.vc/wp-content/uploads/2020/02/ux303ua-opened-inside.jpg" data-lightboxplus="lightbox[3636]" title="Asus Zenbook UX303UA memory upgrade"><img decoding="async" src="https://rux.vc/wp-content/uploads/2020/02/ux303ua-opened-inside-1024x576.jpg" alt="" /></a></p>
<ol>
<li>You need to understand that memory is used there is **PC12000 DDR3L**, this module can operate at 1.35v (unlike most other - 1.5v). Due to very low demand it's very difficult to find those modules. Even worse - <strong>only</strong> Crutial makes DDR3L 16Gb modules. You'll need <a title="Thanks for buying via my link" href="http://rover.ebay.com/rover/1/710-53481-19255-0/1?ff3=4&amp;pub=5575279825&amp;toolid=10001&amp;campid=5338054517&amp;customid=blogpost-memory-ux303-memory-upgrade&amp;mpre=https%3A%2F%2Fwww.ebay.co.uk%2Fsch%2Fi.html%3F_from%3DR40%26_trksid%3Dm570.l1313%26_nkw%3DCT204864BF160B%26_sacat%3D0">Crutial CT204864BF160B</a> <em>(affiliate link)</em></li>
<li>Unscrew bolts from the bottom panel, carefully remove it</li>
<li><strong>Disconnect</strong> battery by lifting it's socket gently (see on the picture)</li>
<li>Remove anti-static foil from memory, don't tear it - you'll need to put it back. The memory is located in the center of the motherboard, as on the picture above</li>
<li>Unlatch memory, pull it out. Don't put any strength - it should come out easily.</li>
<li>Put memory back, connect battery to motherboard.</li>
<li>Make sure there is no metal bits on the table, flip laptop and try to turn it on. <strong>Fingers crossed</strong></li>
<li>Hopefully it works, you'll see extra memory available.<br />
<img decoding="async" src="https://rux.vc/wp-content/uploads/2020/02/ux303-bios-after-memory-upgrade-1024x576.jpg" alt="" /></li>
<li>Flip it back, <strong>disconnect battery</strong> again, put back antistatic foil, connect battery. In my situation it lost adhesion and I had to put electrical tape on it to keep it in place.<br />
<a href="https://rux.vc/wp-content/uploads/2020/02/ux303-finished.jpg" data-lightboxplus="lightbox[3636]" title="Asus Zenbook UX303UA memory upgrade"><img decoding="async" src="https://rux.vc/wp-content/uploads/2020/02/ux303-finished-1024x576.jpg" alt="" /></a></li>
</ol>
<h2>Conclusion</h2>
<p>After memory upgrade it's possible to open few more tabs in Chrome!</p>
<p>On the serious note I hope this post and experiment could help somebody since Asus support did the terrible job and everything on internet told that it's impossible.  It's very frustrating to think that I could have done that straight after I bought it.</p>
<p>I would not be suprised if other laptops in this family(such as UX303UB, UX303LN, UX303FA, etc) also have slot for memory and it's compatible with 16Gb. Do you research, get memory with good return policy and try if risk worth it. To me it definitely rewarding.</p>The post <a href="https://rux.vc/2020.02/asus-zenbook-ux303ua-ram-upgrade/">Asus Zenbook UX303UA memory upgrade</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2020.02/asus-zenbook-ux303ua-ram-upgrade/feed/</wfw:commentRss>
			<slash:comments>23</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3636</post-id>	</item>
		<item>
		<title>Installing docker-machine on Raspberry PI</title>
		<link>https://rux.vc/2020.01/installing-docker-machine-on-raspberry-pi/</link>
					<comments>https://rux.vc/2020.01/installing-docker-machine-on-raspberry-pi/#comments</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Sun, 12 Jan 2020 17:54:08 +0000</pubDate>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Quick notes]]></category>
		<category><![CDATA[ansible]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[docker-machine]]></category>
		<category><![CDATA[raspberry pi]]></category>
		<guid isPermaLink="false">https://rux.vc/?p=3597</guid>

					<description><![CDATA[<p>One of the nicest things about docker is reproducibility and containerisation. It is possible to run multiple applications which requires different environment on the same computer and make them live happily altogether. Although Raspberry Pi has ARMv7 instructions set, we still can run docker on it - we just need different images. One would be ... <a title="Installing docker-machine on Raspberry PI" class="read-more" href="https://rux.vc/2020.01/installing-docker-machine-on-raspberry-pi/" aria-label="More on Installing docker-machine on Raspberry PI">Read more</a></p>
The post <a href="https://rux.vc/2020.01/installing-docker-machine-on-raspberry-pi/">Installing docker-machine on Raspberry PI</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p>One of the nicest things about docker is reproducibility and containerisation. It is possible to run multiple applications which requires different environment on the same computer and make them live happily altogether. Although Raspberry Pi has <strong>ARMv7</strong> instructions set, we still can run docker on it - we just need different images. One would be surprised there are some official images available on <a href="https://hub.docker.com/u/arm32v7">docker hub</a>.</p>
<p>The configuration can be very simple - literally two commands in terminal, thanks to widely available devops tools such as <strong>docker-machine</strong> and <strong>ansible</strong>. Having this setup there won't be need to login to the RPi and perform any manual configuration per service anymore. Instead, services can be configured and deployed right from your computer.</p>
<p>If you don't have your Rasbperry configured yet refer to <a href="https://rux.vc/2020.01/setting-up-raspberry-pi/">previous article</a> for the initial setup.</p>
<p><span id="more-3597"></span></p>
<h2>Copy ssh key</h2>
<p>To allow login without password using ssh key we need to transfer it to the RPi. This step can be skipped if it was done before.</p>
<p>Assuming that your pi is running with default login <strong>pi</strong> and password <strong>raspberry</strong> run this command and put password:</p>
<pre><code>ssh-copy-id pi@192.168.42.111</code></pre>
<h2>Provisioning</h2>
<p>There are some prerequiests for your local machine:</p>
<ul>
<li><a href="https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html">ansible 2</a></li>
<li><a href="https://docs.docker.com/install/">docker</a> and <a href="https://docs.docker.com/v17.09/machine/install-machine/">docker-machine</a></li>
</ul>
<p>Get the playbook I've created:</p>
<p><script src="https://gist.github.com/ruXlab/fdc8a192b269244301c54c72cbf18484.js"></script></p>
<p>And simply run</p>
<pre><code>ansible-playbook provision-rpi.yml -i 192.168.42.111, --extra-vars &quot;machine_name=myrpi&quot;
</code></pre>
<p>Replacing IP address with your RPi location. Also, note that <strong>comma(,)</strong> at the end of the address is mandatory! Local name of the docker-machine can be configured via <code>machine_name</code> variable, in the example it set to <strong>myrpi</strong></p>
<p>First run can take some time, be patient.</p>
<p>This playbook is updating packages on your RPi, temporary monkey patching name of the OS, installs docker-machine and revert back changes of the name. Since ansible playbook is describing the final state there is no sin of running this playbook again - nothing will break. <em>Be aware that you might want to remove existing docker-machine if it already exists or give it an another name</em></p>
<p>Sample output:</p>
<pre><code class="language-ini">➜  ansible-playbook provision-rpi.yml -i 192.168.42.111, --extra-vars &quot;machine_name=myrpi&quot;

PLAY [RPi initial provisioner] ************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************
ok: [192.168.42.111]

TASK [Remembering target host information] ************************************************************************************************************************
ok: [192.168.42.111]

TASK [Upgrade packages] *******************************************************************************************************************************************
 [WARNING]: Could not find aptitude. Using apt-get instead

ok: [192.168.42.111]

TASK [Check what the new version is] ******************************************************************************************************************************
changed: [192.168.42.111]

TASK [Temporary monkey-patching os-release] ***********************************************************************************************************************
changed: [192.168.42.111]

TASK [Running docker-machine against 192.168.42.111] ***************************************************************************************************************
changed: [192.168.42.111 -&gt; localhost]

TASK [Reverting OS name back in os-release] ***********************************************************************************************************************
changed: [192.168.42.111]

PLAY RECAP ********************************************************************************************************************************************************
192.168.42.111              : ok=7    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
</code></pre>
<h2>Done!</h2>
<p>Let's try to run something against that docker on freshly backed pi</p>
<p>To make our docker client to run against the remote RPi daemon we must setup environment variables. It should be executed only once per session <strong>before</strong> any docker commands</p>
<pre><code class="language-bash">➜ eval $(docker-machine env myrpi)
</code></pre>
<p>Let's see what version of the docker we are running:</p>
<pre><code class="language-bash">➜  docker version
. . . . .
Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea
  Built:            Wed Nov 13 07:34:13 2019
  OS/Arch:          linux/arm

</code></pre>
<p>There are limited number of images available for <a href="https://hub.docker.com/u/arm32v7">arm32v7 on the docker hub</a>. For demostration purposes I can run mediawiki:</p>
<pre><code class="language-bash">➜  docker run  -p 9999:80 -d arm32v7/mediawiki
Unable to find image &#039;arm32v7/mediawiki:latest&#039; locally
latest: Pulling from arm32v7/mediawiki
c4f8e1e649d2: Pull complete 
. . .  . . .
Status: Downloaded newer image for arm32v7/mediawiki:latest
0041a9fbf8d9a3bc85a337eafbbf50e135b77705e4d663c4bfd72771b8935426

➜  docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
22dfef415586        arm32v7/mediawiki   &quot;docker-php-entrypoi…&quot;   26 seconds ago      Up 23 seconds       0.0.0.0:9999-&gt;80/tcp   lucid_ramanujan
</code></pre>
<p>As expected mediawiki is available via network:</p>
<p><img decoding="async" src="https://rux.vc/wp-content/uploads/2020/01/mediawiki-running-on-rpi-via-docker.png" alt="" /></p>
<h2>Conclusion</h2>
<p>Just 2 commands enable us to deploy our applications in the docker in a snap!</p>The post <a href="https://rux.vc/2020.01/installing-docker-machine-on-raspberry-pi/">Installing docker-machine on Raspberry PI</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2020.01/installing-docker-machine-on-raspberry-pi/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3597</post-id>	</item>
		<item>
		<title>Setting up Raspberry Pi without Monitor</title>
		<link>https://rux.vc/2020.01/setting-up-raspberry-pi/</link>
					<comments>https://rux.vc/2020.01/setting-up-raspberry-pi/#comments</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Sat, 11 Jan 2020 23:18:32 +0000</pubDate>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Quick notes]]></category>
		<category><![CDATA[raspberry pi]]></category>
		<category><![CDATA[setup]]></category>
		<category><![CDATA[ssh]]></category>
		<guid isPermaLink="false">https://rux.vc/?p=3583</guid>

					<description><![CDATA[<p>In this post we will setup and configure Rasbian for your RPi to be instantly available via local network and without screen on the linux or mac system. Those steps should be appliable to any Raspberry PI version To start with we need a few things: Raspberry PI itself 8Gb+ SD Card, class 10 at ... <a title="Setting up Raspberry Pi without Monitor" class="read-more" href="https://rux.vc/2020.01/setting-up-raspberry-pi/" aria-label="More on Setting up Raspberry Pi without Monitor">Read more</a></p>
The post <a href="https://rux.vc/2020.01/setting-up-raspberry-pi/">Setting up Raspberry Pi without Monitor</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p>In this post we will setup and configure Rasbian for your RPi to be instantly available via local network and without screen on the linux or mac system. Those steps should be appliable to any Raspberry PI version</p>
<p>To start with we need a few things:</p>
<ul>
<li><strong>Raspberry PI</strong> itself</li>
<li><strong>8Gb+ SD Card</strong>, class 10 at least</li>
<li><strong>Ethernet cable</strong> to connect RPi to the router</li>
<li>Downloaded <a href="https://www.raspberrypi.org/downloads/raspbian/">Raspbian Lite</a> zipped image</li>
</ul>
<p><span id="more-3583"></span></p>
<p><strong>NOTE:</strong> This guide is for Linux users, I'd speculate that different with mac would be minimal but only Apple knows. Give it a go or for instructions for another OS check the <a href="https://www.raspberrypi.org/documentation/installation/installing-images/README.md">official installation guide</a></p>
<h2>Installing OS</h2>
<p>There are few steps:</p>
<ul>
<li>Locate sd card - in this example it's <strong>sdc</strong> </li>
</ul>
<pre><code>➜  dmesg | tail
[308442.076711] usb-storage 2-4:1.0: USB Mass Storage device detected
[308442.076870] scsi host3: usb-storage 2-4:1.0
[308443.089495] scsi 3:0:0:0: Direct-Access     Generic  STORAGE DEVICE   0819 PQ: 0 ANSI: 6
[308443.090009] sd 3:0:0:0: Attached scsi generic sg2 type 0
[308443.571095] sd 3:0:0:0: [sdc] 125042688 512-byte logical blocks: (64.0 GB/59.6 GiB)
[308443.571628] sd 3:0:0:0: [sdc] Write Protect is off
[308443.571641] sd 3:0:0:0: [sdc] Mode Sense: 87 00 00 00
[308443.572295] sd 3:0:0:0: [sdc] Write cache: disabled, read cache: enabled, doesn&#039;t support DPO or FUA
[308443.576743]  sdc: sdc1
[308443.581724] sd 3:0:0:0: [sdc] Attached SCSI removable disk
</code></pre>
<ul>
<li>Write downloaded raspbian image to the flash drive. <br /><strong>Note:</strong> you need to change <strong>sdXXXXX</strong> with your sd card device name(from example above - sdc). <strong>Warning:</strong> providing the wrong device name may <strong>destroy your hard drive</strong>, it's not a joke.</li>
</ul>
<pre><code>➜  unzip -p 2019-09-26-raspbian-buster-lite.zip | sudo dd of=/dev/sdXXXXX bs=4M conv=fsync

0+33279 records in
0+33279 records out
2248146944 bytes (2.2 GB, 2.1 GiB) copied, 36.0719 s, 62.3 MB/s
</code></pre>
<ul>
<li>Sync to flush buffers so memory card can be safetly removed:</li>
</ul>
<pre><code>sudo sync
</code></pre>
<ul>
<li>Remove and insert it back. Your computer should be able to locate a <code>boot</code> partition</li>
<li>Since we want to access RPi remotely even without screen SSH server needs to be enabled. For that create a <code>ssh</code> folder inside the <code>boot</code> directory.</li>
<li>We are done! Unmount the sd card and plug it into the your Raspberry.</li>
</ul>
<h2>Booting up</h2>
<p>Connect your RPi to the network. I plugged it into the router via ethernet cable - that would give me the maximum possible network throughput. Connect power and wait it to boot.</p>
<p>If everything went well soon you'll be able to locate your freshly backed pi on the network, in linux you can use <code>nmap</code> to discover devices on network</p>
<pre><code>root@fake:~# nmap -sP 192.168.42.0/24
Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-11 11:34 GMT
Nmap scan report for internet.router (192.168.42.1)
Host is up (0.0049s latency).
MAC Address: 84:47:11:23:43:ED (Banana Technologies)
. . . . 
Nmap scan report for raspberrypi.router (192.168.42.111)
Host is up (0.0016s latency).
MAC Address: DC:A6:32:XX:XX:XX (Raspberry Pi Trading)
. . . . 
</code></pre>
<p>From the log output above it's clear that my RPi was given <code>192.168.42.111</code> IP address. It's not coincidence - I simply pinned it's mac address in my router's DHCP settings.</p>
<h2>Connect to your RPi</h2>
<pre><code>➜  ssh pi@192.168.42.111 
pi@192.168.1.111&#039;s password: 
Linux raspberrypi 4.19.75-v7l+ #1270 SMP Tue Sep 24 18:51:41 BST 2019 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
. . . . 

pi@raspberrypi:~ $
</code></pre>
<p>Whola!<br />
I've got Raspberry Pi running and available via SSH even without monitor!</p>
<p><img decoding="async" src="https://rux.vc/wp-content/uploads/2020/01/rpi-htop.png" alt="" /></p>
<p><b>This is a prerequisite for next post - setting up docker-machine in RPi</b></p>The post <a href="https://rux.vc/2020.01/setting-up-raspberry-pi/">Setting up Raspberry Pi without Monitor</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2020.01/setting-up-raspberry-pi/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3583</post-id>	</item>
		<item>
		<title>RPI Zero scan button</title>
		<link>https://rux.vc/2017.03/rpi-zero-scan-button/</link>
					<comments>https://rux.vc/2017.03/rpi-zero-scan-button/#respond</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Wed, 29 Mar 2017 21:33:45 +0000</pubDate>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Other]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Quick notes]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[raspberry pi]]></category>
		<guid isPermaLink="false">https://rux.vc/?p=2926</guid>

					<description><![CDATA[<p>While I was finishing wireless scanner and printer server I realised that traditional document scanning approach is not so nice from UX point of view. I really like the way office scanners in multi-functional devices work. Normally if you want to scan you just load stack of paper into and put your email address. Scanner ... <a title="RPI Zero scan button" class="read-more" href="https://rux.vc/2017.03/rpi-zero-scan-button/" aria-label="More on RPI Zero scan button">Read more</a></p>
The post <a href="https://rux.vc/2017.03/rpi-zero-scan-button/">RPI Zero scan button</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p>While I was finishing wireless scanner and printer server I realised that traditional document scanning approach is not so nice from UX point of view.</p>
<p>I really like the way office scanners in multi-functional devices work. Normally if you want to scan you just load stack of paper into and put your email address. Scanner does the rest and in minute you'll get ready-to-use pdf file in your inbox.</p>
<p>I was thinking about having button attached to RPI Zero which initiates scanning and document upload.</p>
<p><span id="more-2926"></span></p>
<p>Alternatively it's possible to program another/one more action, for instance document copy. It's really up to developer - Raspberry PI provides you endless possibilities!</p>
<p>Let's build this scan button:</p>
<ul>
<li>It should indicate scanning process right after user hit the button. The problem is the scanner has to be pre-heated to operate and it can take up to 20-30 seconds. User shouldn't be puzzled by current process. </li>
<li>To display current process we need LED. I found yellow LED 3v</li>
<li>Scanned document should be placed in shared folder accessible from all popular OS. There are not so many options, hence we have to use <strong>Samba</strong>(windows files sharing service)</li>
<li>Documents older than 1h should be removed from that shared folder</li>
<li>Scanned document format - <strong>jpg</strong></li>
</ul>
<h2>Prepare environment</h2>
<p>First things first - we need python libraries and samba server</p>
<pre><code class="bash">sudo apt-get install samba
sudo apt-get install python3-gpiozero python-gpiozero python-pkg-resources
</code></pre>
<h2>Button script</h2>
<p>The script is fairly simple.</p>
<p>It configures LED and Button ports. Then listens to button event. When button is clicked LED blinks to indicate process start and script excecutes <strong>scanimage</strong> utility which convert output from <strong>ppm</strong> to <strong>jpg</strong> format.</p>
<pre><code class="python">&lt;br /&gt;from gpiozero import Button, PWMLED
from signal import pause
from time import sleep, strftime
import os;


OUT_FOLDER=&quot;/smb/scanner&quot;

led = PWMLED(15)
button = Button(23, pull_up=True, hold_repeat=False)

def blink():
  for i in range(20):
    if i % 2 == 0: led.off()
    else: led.value = 0.3
    sleep(0.1)
  led.off()

def toggle():
  blink()
  led.value = 0.3
  ts = strftime(&quot;%d-%b-%Y %H.%M.%S.jpg&quot;)
  cmd = &quot;scanimage --resolution 150 | convert - jpg:- &gt; &#039;{}/{}&#039;&quot;.format(OUT_FOLDER, ts)
  print(&quot;Scanning... {}&quot;.format(cmd))
  os.system(cmd)
  led.off()


button.when_released = toggle

pause()
</code></pre>
<p>PWMLED is used in this script on purpose. Seems like I bought too powerful led without any specs - lady in the shop ensured me that it's low current LED. Unfortunately one of GPIO port has died after I left it on for 10 minutes. To avoid burning another GPIO pin I enabled PWM for LED, if you never heard about it <a href="https://en.wikipedia.org/wiki/Pulse-width_modulation">read wikipedia</a>. From my experiments I found brightness of 30%(0.3) seems minimum acceptable for me. You might need to connect your led via resistor, depending on it's current and voltage.</p>
<p>I couldn't run this script under non-privileged user unfortunately because <strong>scanimage</strong> command doesn't detect scanner. I think there were problems with USB device permission but if you care I'm sure it's possible to fix it.</p>
<h2>Done</h2>
<p>I forgot to copy other configuration files for samba server, crond and systemd and now I don't have access to RPI but trust me it used to work :D I'll put here other configs later on</p>
<p align="right" style="color: gray">This blogpost has been written in airplane over Baltic sea on the way to London</p>The post <a href="https://rux.vc/2017.03/rpi-zero-scan-button/">RPI Zero scan button</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2017.03/rpi-zero-scan-button/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2926</post-id>	</item>
		<item>
		<title>RPI Zero: print &#038; scan servers</title>
		<link>https://rux.vc/2017.03/raspberry-pi-zero-print-scan-server/</link>
					<comments>https://rux.vc/2017.03/raspberry-pi-zero-print-scan-server/#comments</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Sat, 18 Mar 2017 00:38:45 +0000</pubDate>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[printer]]></category>
		<category><![CDATA[raspberry pi]]></category>
		<category><![CDATA[scanner]]></category>
		<guid isPermaLink="false">https://rux.vc/?p=2896</guid>

					<description><![CDATA[<p>I had to make old printer and scanner wirelessly available over local network. It can be done using wireless printer USB adapter but it's not that cheap and still doesn't support scanner Obvious choose is using Raspberry PI with linux installed. Before I heard a lot about RPI Zero but could never believe that it ... <a title="RPI Zero: print &#038; scan servers" class="read-more" href="https://rux.vc/2017.03/raspberry-pi-zero-print-scan-server/" aria-label="More on RPI Zero: print &#038; scan servers">Read more</a></p>
The post <a href="https://rux.vc/2017.03/raspberry-pi-zero-print-scan-server/">RPI Zero: print & scan servers</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p>I had to make old printer and scanner wirelessly available over local network. It can be done using <a href="https://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_id=114&amp;ipn=icep&amp;toolid=20004&amp;campid=5338054517&amp;mpre=http%3A%2F%2Fwww.ebay.co.uk%2Fsch%2Fi.html%3F_from%3DR40%26_sacat%3D0%26_nkw%3Dusb%2Bwifi%2Bprinter%2Badapter%26rt%3Dnc%26LH_BIN%3D1">wireless printer USB adapter</a> but it's not that cheap and still doesn't support scanner</p>
<p>Obvious choose is using Raspberry PI with linux installed. Before I heard a lot about RPI Zero but could never believe that it costs just £5. Actually it is just £5 <em>and +£2.5</em> delivery fee. Surprisingly there are no other options except of first class delivery!</p>
<p>Long story short, I put here main steps how to setup print and scan servers on small Raspberry PI Zero:</p>
<h2>General configuration</h2>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Upgrade RPI software</strong><br />
To access most recent features and freshly created bugs make sure you use <a href="https://www.raspberrypi.org/documentation/raspbian/updating.md" target="_blank">most recent version</a> of RPI firmware. To do so run <strong>sudo apt-get dist-upgrade</strong>.</p>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Static IP</strong><br />
Assign static IP for your raspberry. The easiest way is configure your router DHCP server. Just bind mac address to nice IP in your network, like 192.168.100.100, later in this post I</p>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Reduce graphic memory fraction</strong><br />
If you aren't going to use video <a href="https://www.raspberrypi.org/forums/viewtopic.php?f=29&amp;t=39764">how to</a></p>
<p><span id="more-2896"></span></p>
<h2>Configure cups(print server)</h2>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Install cups</strong></p>
<pre><code class="bash">sudo apt-get install cups
sudo usermod -a -G lpadmin pi
</code></pre>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Configure cups</strong></p>
<p>Make cups listen on all interfaces to make it network available, disable ssl and allow access from network in <strong>/etc/cups/cupsd.conf</strong></p>
<pre><code>Port 631
DefaultEncryption Never
DefaultAuthType None 

 . . . .

&lt;Location /&gt;
  Order allow,deny
  Allow from all
&lt;/Location&gt;
&lt;Location /admin&gt;
  Order allow,deny
  Allow from all
&lt;/Location&gt;
&lt;Location /admin/conf&gt;
  AuthType Default
  Require user @SYSTEM
  Order deny,allow
  Allow from all
&lt;/Location&gt;

</code></pre>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Restart print server</strong></p>
<pre><code>service cups restart
</code></pre>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Install printer</strong></p>
<p>Point your browser to http://192.168.XXX.XXX:631/  and go to Administraton → Printers → [Add Printer]. You might be asked to put your rpi login password. Most likely your printer will be detected, follow the wizard's prompts to finish setup.<br />
You might want to use <a href="http://www.openprinting.org">openprinting</a> where you can download PPD file for your printer</p>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Configure your Linux/MacOS/Windows to use this printer</strong><br />
Using built in tools add network printer.</p>
<p>Fingers crossed it should work :)</p>
<h2>Network scanner</h2>
<p>This is more tricky configuration as clients should support network protocol for sane. Unfortunately there are a lot of moving parts and seems like network scan is not the main priority for the sane developers. It takes a while to finish configuration so keep calm :)</p>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Install sane &amp; xinetd</strong></p>
<pre><code> apt-get install sane sane-utils xinetd
</code></pre>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Find scanner and driver for it</strong></p>
<pre><code> sane-find-scanner
</code></pre>
<p>And hope that you can see connected scanner :) If not google is your friend<br />
At this step you have to make sure that <strong>scanimage > someimage</strong> is working properly</p>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Configure network daemon systemd files</strong><br />
Create file <strong>/etc/systemd/system/saned@.service</strong> with content:</p>
<pre><code>[Unit]                  
Description=Scanner Service
Requires=saned.socket

[Service]
ExecStart=/usr/sbin/saned
User=saned
Group=saned
StandardInput=null
StandardOutput=syslog
StandardError=syslog
</code></pre>
<p>And <strong>/etc/systemd/system/saned.socket</strong> with content:</p>
<pre><code class="ini">[Unit]
Description=saned incoming socket

[Socket]
ListenStream=6566
Accept=yes
MaxConnections=1

[Install]
WantedBy=sockets.target
</code></pre>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Enable daemon</strong><br />
Open /etc/default/saned and replace <strong>RUN=no</strong> with <strong>RUN=yes</strong></p>
<p>In /etc/sane.d/saned.conf<br />
Put your network, eg 192.168.100.0/24</p>
<pre><code>systemctl enable saned.socket
</code></pre>
<p>In theory it should be enough to start using scanner over network.</p>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Configure clients</strong></p>
<ul>
<li>On linux you can configure saned by adding RPI IP address to the file <strong>/etc/sane.d/net.conf</strong>. Running <strong>imagescan -L</strong> should display remote scanner and <strong>xscan</strong> should be able use it. </li>
<li>On windows I found very ugly but working application <a href="http://sanetwain.ozuzo.net/">SaneTwain</a>. </li>
<li>For macos seems there is only one option <a href="http://www.ellert.se/twain-sane/">Sane Twain Interface</a></li>
<li>Full list for sane clients you can find <a href="http://www.sane-project.org/sane-frontends.html">here</a> </li>
</ul>
<p><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Sample output</strong></p>
<p>To make sure you know what to expect here is sample output from the RPI and linux client:</p>
<pre><code>pi@raspberry:~ $ sudo scanimage -L
device `snapscan:libusb:001:004&#039; is a Acer FlatbedScanner23 flatbed scanner

user@client:~ $ scanimage  -L
device `net:192.168.XXX.XXX:snapscan:libusb:001:004&#039; is a Acer FlatbedScanner23 flatbed scanner
</code></pre>
<h2>Costs</h2>
<p>Most of the components you can find on eBay from different vendors:</p>
<table style="min-width:50%; width: auto">
<tr>
<td><a target="_blank" rel="nofollow" href="https://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_id=114&amp;ipn=icep&amp;toolid=20004&amp;campid=5338054517&amp;mpre=http%3A%2F%2Fwww.ebay.co.uk%2Fsch%2Fi.html%3F_from%3DR40%26_sacat%3D0%26_nkw%3Dusb%2Bwifi%2Bprinter%2Badapter%26rt%3Dnc%26LH_BIN%3D1">RPI Zero</a></td>
<td>£5 + £2.5</td>
</tr>
<tr>
<td><a target="_blank" rel="nofollow" href="https://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_id=114&amp;ipn=icep&amp;toolid=20004&amp;campid=5338054517&amp;mpre=http%3A%2F%2Fwww.ebay.co.uk%2Fitm%2F232012513142">WiFi with antenna</a> on <a target="_blank" rel="nofollow" href="https://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_id=114&amp;ipn=icep&amp;toolid=20004&amp;campid=5338054517&amp;mpre=http%3A%2F%2Fwww.ebay.co.uk%2Fsch%2Fi.html%3F_from%3DR40%26_trksid%3Dp2047675.m570.l2632.R2.TR2.TRC1.A0.H0.Xralink%2Brt5370.TRS0%26_nkw%3Dralink%2Brt5370%26_sacat%3D11176">Ralink RT5370</a> chip</td>
<td>£3.34</td>
</tr>
<tr>
<td><a target="_blank" rel="nofollow" href="https://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_id=114&amp;ipn=icep&amp;toolid=20004&amp;campid=5338054517&amp;mpre=http%3A%2F%2Fwww.ebay.co.uk%2Fitm%2F221421517466%3F_trksid%3Dp2057872.m2749.l2649%26ssPageName%3DSTRK%253AMEBIDX%253AIT">micro-USB host adapter</a></td>
<td>£1.00</td>
</tr>
<tr>
<td><a target="_blank" rel="nofollow" href="https://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_id=114&amp;ipn=icep&amp;toolid=20004&amp;campid=5338054517&amp;mpre=http%3A%2F%2Fwww.ebay.co.uk%2Fitm%2F321473485641%3F_trksid%3Dp2057872.m2749.l2649%26ssPageName%3DSTRK%253AMEBIDX%253AIT">4 ports USB 2.0 hub</a></td>
<td>£1.5</td>
</tr>
<tr>
<td><a target="_blank" rel="nofollow" href="https://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_id=114&amp;ipn=icep&amp;toolid=20004&amp;campid=5338054517&amp;mpre=http%3A%2F%2Fwww.ebay.co.uk%2Fitm%2F321473485641%3F_trksid%3Dp2057872.m2749.l2649%26ssPageName%3DSTRK%253AMEBIDX%253AIT">Sandisk microSD 16Gb class 10</a></td>
<td>£7</td>
</tr>
<tr>
<td><a target="_blank" rel="nofollow" href="https://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_id=114&amp;ipn=icep&amp;toolid=20004&amp;campid=5338054517&amp;mpre=http%3A%2F%2Fwww.ebay.co.uk%2Fitm%2F321473485641%3F_trksid%3Dp2057872.m2749.l2649%26ssPageName%3DSTRK%253AMEBIDX%253AIT">HDMI type C to HDMI type A adaptor</a></td>
<td>£1.1</td>
</tr>
<tr>
<td><a target="_blank" rel="nofollow" href="https://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_id=114&amp;ipn=icep&amp;toolid=20004&amp;campid=5338054517&amp;mpre=http%3A%2F%2Fwww.ebay.co.uk%2Fitm%2F351695377267%3F_trksid%3Dp2057872.m2749.l2649%26var%3D620659698750%26ssPageName%3DSTRK%253AMEBIDX%253AIT">RPI Zero Case</a></td>
<td>£1.30</td>
</tr>
<td align="right">Total</a></td>
<td><b>£15.2</b></td>
</tr>
</table>
<p>Wireless computer just for price of two-course meal. Not bad, isn't it?</p>
<h2>Conclusion</h2>
<p>Of course it's possible to extend this computer even more, for example by connecting to external screen for XBMC. You also can connect camera, setup vpn server, host your website and do a lot of fun and useful stuff!</p>The post <a href="https://rux.vc/2017.03/raspberry-pi-zero-print-scan-server/">RPI Zero: print & scan servers</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2017.03/raspberry-pi-zero-print-scan-server/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2896</post-id>	</item>
		<item>
		<title>avr: случайнее random()</title>
		<link>https://rux.vc/2011.11/avr-randomize-random/</link>
					<comments>https://rux.vc/2011.11/avr-randomize-random/#comments</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Thu, 24 Nov 2011 13:09:12 +0000</pubDate>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Quick notes]]></category>
		<category><![CDATA[avr]]></category>
		<category><![CDATA[led]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[seed]]></category>
		<category><![CDATA[xor]]></category>
		<guid isPermaLink="false">http://rux.pp.ru/blog/?p=944</guid>

					<description><![CDATA[<p>В простых встраиваемых устройствах есть большая проблема: очень хочется рандом. Нормальный такой рандом. Но если подумать, то контроллеру совершенно не от чего "рандомизировать" генератор случайных чисел. Ибо каждый старт контроллера "жизнь начинается с 0". Эта проблема всплыла в пресловутом moodlamp (лампа настроения, переливающиеся цвета светодиода). Хочется чтоб "переливы" каждый раз начинались с нового цвета :) ... <a title="avr: случайнее random()" class="read-more" href="https://rux.vc/2011.11/avr-randomize-random/" aria-label="More on avr: случайнее random()">Read more</a></p>
The post <a href="https://rux.vc/2011.11/avr-randomize-random/">avr: случайнее random()</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p>В простых встраиваемых устройствах есть большая проблема: очень хочется рандом. Нормальный такой рандом. Но если подумать, то контроллеру совершенно не от чего "рандомизировать" генератор случайных чисел. Ибо каждый старт контроллера "жизнь начинается с 0". </p>
<p>Эта проблема всплыла в пресловутом moodlamp (лампа настроения, переливающиеся цвета светодиода). Хочется чтоб "переливы" каждый раз начинались с нового цвета :) </p>
<p><span id="more-944"></span></p>
<p>После долгих дум пришёл к следующим идеям</p>
<h3>Использовать шумы</h3>
<p>Вокруг туча замечательных шумов и наводок! Хоть где то их можно использовать. Например читать с ног ADC и использовать для рандомизации эти значения.</p>
<h3>Запоминать значение</h3>
<p>По умолчанию библиотека gcc-avr инициализирует random seed value в 1. Можно заменить на что нить другое. Мы можем запоминать в EEPROM и инкрементировать это каждый запуск контоллера. Разумеется инициализировать генератор этим значением через srandom(val) </p>
<h3>Использовать температуру</h3>
<p>Некоторые контроллеры теперь идут с возможностью измерить температуру кристалла. Или же применение контроллера связанно с измерением каких-либо физических величин. В общем случае это поможет получать хоть сколько-то случайные величины</p>
<h3>Использовать ^ (xor)</h3>
<p>Вместо установки только что полученного значения с ADC/датчиков можно сделать с этим значением xor. Навроде srandom(newvalue ^ oldvalue).</p>
<p>Почему xor? Эта операция гарантированно возвращает новое значение (сущность побитовой операции такая, можно взглянуть в таблицу истинности) </p>
<h3>Читать память</h3>
<p>В процессе работы контроллера меняется значение каких-то переменных, мы может хаотично выбирать их из всего пространства доступной памяти. Это несколько может помочь рандомизировать значения. Причём было бы прикольно читать память при каком-нибудь событии, например по таймеру или по внешнему прерыванию</p>
<p>Пример будет ниже в моём решении</p>
<h3>Сохранять собранные данные в своём EEPROM</h3>
<p>Любые (или часть, или случайная часть) собранных цифр с ADC, датчиков, рандома, памяти сохранять в программируемую память. Это позволит при загрузки использовать больше цифр при начальной инициализации</p>
<h3>Ещё...</h3>
<p>
Можно напридумывать куча способов, рассуждая в этом же направлении :)
</p>
<p>Я очень доверяю народу из форумов avrfreaks, поэтому привожу <a href="http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=254771#254771">их совет</a> :<br />
<code lang="c"><br />
int makeRandom(int upper) {<br />
        return (int)((double)rand() / ((double)RAND_MAX + 1) * upper);<br />
}<br />
</code>
</p>
<h2>Моё решение</h2>
<p>Скомпоновав мысли выше, вывел вот такое:<br />
<code lang="c"></p>
<p>int makeRandom(int upper) {<br />
        return (int)((double)rand() / ((double)RAND_MAX + 1) * upper);<br />
}</p>
<p>void storeRandomToEEPROM() {<br />
        uint8_t i;<br />
        for(i = 0; i &lt; 20; i++)<br />
                eeprom_write_byte((uint8_t *)i, (uint8_t)(makeRandom(1000)%255));<br />
        for(i = 0; i &lt; 20; i++)<br />
                if (makeRandom(1000) % 2)<br />
                        eeprom_write_byte((uint8_t *)i, *((uint8_t*)(makeRandom(1000)%255)));<br />
}</p>
<p>void randomizeFromEEPROM() {<br />
        uint16_t rndVal = (uint16_t)makeRandom(12345), i;<br />
        for(i = 0; i &lt; 10; i++) rndVal ^= eeprom_read_word((uint16_t*)i);<br />
        srandom(rndVal);<br />
}</p>
<p>. . .<br />
void init() {<br />
        . . .<br />
        randomizeFromEEPROM();<br />
        storeRandomToEEPROM();<br />
}</p>
<p>ISR (TIM0_OVF_vect) {<br />
        static uint16_t softcount=0;</p>
<p>        if(++softcount == 0) storeRandomToEEPROM();</p>
<p>        . . . .<br />
}<br />
</code>
</p>
<h2>Что получилось</h2>
<p>До запуска прошивки состояние EEPROM:</p>
<pre>
>>> read eeprom 0 30 
0000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff        |..............  |
</pre>
</p>
<p>
После первого запуска(и последующих картина памяти будет менятся)</p>
<pre>
>>> read eeprom 0 30 
0000  00 35 97 bf 07 00 5d bc  53 4a 00 ea 07 13 06 01  |.5....].SJ......|
0010  00 00 dd 5a ff ff ff ff  ff ff ff ff ff ff        |...Z..........  |
</pre>
</p>
<p>При первом запуске генератор инициализируется значениями из EEPROM (при этом xor-ятся друг с другом), и тут же заполняет это место другими значениями, полученными из обычного рандома, после этого поверх случайным образом из случайного места в памяти записывается значение.</p>The post <a href="https://rux.vc/2011.11/avr-randomize-random/">avr: случайнее random()</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2011.11/avr-randomize-random/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">944</post-id>	</item>
		<item>
		<title>КМУ в СПбГУ ИТМО</title>
		<link>https://rux.vc/2010.04/kmu-v-niu-spbgu-itmo/</link>
					<comments>https://rux.vc/2010.04/kmu-v-niu-spbgu-itmo/#comments</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Wed, 28 Apr 2010 07:14:52 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[events]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Quick notes]]></category>
		<category><![CDATA[freescale]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mc13224]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[open hardware]]></category>
		<category><![CDATA[oseb-13224]]></category>
		<category><![CDATA[ИТМО]]></category>
		<guid isPermaLink="false">http://rux.pp.ru/blog/?p=503</guid>

					<description><![CDATA[<p>20-23 апреля 2010 года в Санкт-Петербургском Государственном Научно-Исследовательском Университете Инфорационных Технологий, Механники и Оптики состоялась седьмая ежегодная Конференция Молодых Учёных, приуроченная к 110летию университета. Была поданна просто уйма заявок(700+ человек), в различные секции, например можно попробовать полистать программу конференции. Секции были не только технические, но и мелькали гуманитарные. В общем на любой вкус и цвет ... <a title="КМУ в СПбГУ ИТМО" class="read-more" href="https://rux.vc/2010.04/kmu-v-niu-spbgu-itmo/" aria-label="More on КМУ в СПбГУ ИТМО">Read more</a></p>
The post <a href="https://rux.vc/2010.04/kmu-v-niu-spbgu-itmo/">КМУ в СПбГУ ИТМО</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p>
<img decoding="async" src="http://rux.pp.ru/blog/wp-content/uploads/2010/04/logo-conference-of-young-scientists.jpg" alt="" title="Логотип Конференции Молодых Учёных" width="200" height="121" class="alignright size-full wp-image-504" style="padding: 7px; background: white" srcset="https://rux.vc/wp-content/uploads/2010/04/logo-conference-of-young-scientists.jpg 200w, https://rux.vc/wp-content/uploads/2010/04/logo-conference-of-young-scientists-150x90.jpg 150w" sizes="(max-width: 200px) 100vw, 200px" /><br />
20-23 апреля 2010 года в Санкт-Петербургском Государственном Научно-Исследовательском Университете Инфорационных Технологий, Механники и Оптики состоялась <u>седьмая</u> ежегодная Конференция Молодых Учёных, приуроченная к 110летию университета.</p>
<p>Была поданна просто уйма заявок(700+ человек), в различные секции, например можно попробовать полистать <a href="http://fppo.ifmo.ru/file/stat/9104.pdf" target="_blank">программу конференции</a>. Секции были не только технические, но и мелькали гуманитарные. В общем на любой вкус и цвет можно было выбирать куда идти.</p>
<p><span id="more-503"></span></p>
<p>Я учавствовал в школе "Информационная безопасность, проектирование, технология элементов и узлов компьютерных систем", секции "Перспективные информационные технологии" с докладом "Применение сенсорных систем для решения задач энергосбережения." в среду, 22го апреля 2010 года. Вот такие длиннные названия :)
</p>
<p>В небольшой аудитории(295, привет <strong>ПКС</strong>!), собрались в одно время докладчики нескольких секций, где по очереди рассказывали о своих работах. Конечно же, присутствовали председатели - главные судьи. Только они задавали вопросы - студенты/аспиранты почти ничего не спрашивали, от аудитории сверстников никакого фидбека не было.
</p>
<p>Управились за пару часов, доклады в среднем минут на 10-15, как и требовал регламент.</p>
<p>Меня вроде как засыпали глобальными вопросами, сводя всю работу на нет. Но потом, уже после, оказалось что они не правы, подтвержденно авторитетными лицами :) Давили на то место, которое я <s>не</s> понимал меньше всего - измерение температуры, и проблемы с ней связанные. Я же рассказывал и хорошо понимал программную часть(написал прошивки для нодов, хаба, а так же демона и веб интерфейс) - всё это чисто средствами open source(и даже open hardware). Жалею что плохо приготовился и понимал физическую часть измерений.
</p>
<p>Вдаваться в подробности <s>комплекса</s> системы не буду. В кратце: ноды собирают информацию о температуре, отправляют хабу по радиоканалу(MAC level IEEE 802.15.4), хаб, подключенный к компьютеру сообщает демону измеренную температуру. Демон(на с++) запихивает это всё в БД(MySQL ессно). А веб интерфейс(php) строит графики температуры, вытаскивая информацию из базы. Отображаются графики с помощью open flash chart.</p>
<p>
Чтоб не быть голословным можно посмотреть презентацию:</p>
<div style="width:425px" id="__ss_3880270"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/ruxer/ss-3880270" title="Сенсорная сеть">Сенсорная сеть</a></strong><object width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=random-100428014631-phpapp01&stripped_title=ss-3880270" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/></object></div>
</p>
<h3>Результат</h3>
<p>В день закрытия конференции, мне позвонила девушка и сказала, чтоб я подошёл в актовый зал на торжественное закрытие. Оказалось у меня лучшая работа в секции. Не ожидал да и не знал что будет какая-то оценка. Дали диплом и стеклянный кулончик, внутри которого здание Университета, а ещё дали возможность написать статью в ВАК - говорят это очень хорошо.</p>
<p>По факту, эту систему я так или иначе стал бы разрабатывать(почему - когда нибудь потом), просто получилось, что подвернулась конференция, которая и промотивировала меня начать этим заниматься. Так что участие в КМУ получилось "по ходу".</p>
<h3>Благодарности</h3>
<ul>
<li><a href="http://www.ifmo.ru/person/265/luk.htm"  target="_blank">Лукьянову Геннадию Николаевичу</a>, декану ИФФ, который и предложил заниматься этим</li>
<li><a href="http://oshw.ru"  target="_blank">Косенкову Павлу Александровичу</a>, аспиранту ПКС, который дал попользовать свою отладочную плату(open hardware), OSEB-13224.</li>
<li><a href="http://www.redwirellc.com/" target="_blank">Mariano Alvira</a> - разработчик библиотеки libmc1322x, который так же помог вычислить ошибку в отладочной плате</li>
<li><a href="http://k0shk.com">k0shk</a> - моральная поддержка :)</li>
</ul>The post <a href="https://rux.vc/2010.04/kmu-v-niu-spbgu-itmo/">КМУ в СПбГУ ИТМО</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2010.04/kmu-v-niu-spbgu-itmo/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">503</post-id>	</item>
		<item>
		<title>Cветодиодная линейка на MAX7219</title>
		<link>https://rux.vc/2010.04/led-line-based-on-max7219/</link>
					<comments>https://rux.vc/2010.04/led-line-based-on-max7219/#comments</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Sat, 03 Apr 2010 21:32:44 +0000</pubDate>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[atmega8]]></category>
		<category><![CDATA[avr]]></category>
		<category><![CDATA[driver]]></category>
		<category><![CDATA[led]]></category>
		<category><![CDATA[max7219]]></category>
		<category><![CDATA[pwm]]></category>
		<category><![CDATA[spi]]></category>
		<guid isPermaLink="false">http://rux.pp.ru/blog/?p=467</guid>

					<description><![CDATA[<p>Попалась мне в руки светодиодная линейка неизвестного происхождения из 52 двухцветных светодиодов - красный и зелёный. Которая управлялась двумя микросхемами maxim max7919(драйвер). У этой платки было 8 пинов для подпайки, один из которых ни к чему не подключался. Цель - разобраться что она из себя представляет, как работает и сделать что-нибудь с ней - погонять ... <a title="Cветодиодная линейка на MAX7219" class="read-more" href="https://rux.vc/2010.04/led-line-based-on-max7219/" aria-label="More on Cветодиодная линейка на MAX7219">Read more</a></p>
The post <a href="https://rux.vc/2010.04/led-line-based-on-max7219/">Cветодиодная линейка на MAX7219</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p><a href="/blog/wp-content/uploads/2010/04/led-line-photo.jpg" target="_blank" data-lightboxplus="lightbox[467]" title="Внешний вид NONAME светодиодной линейки"><img decoding="async" src="/blog/wp-content/uploads/2010/04/led-line-photo-27x150.jpg" alt="" title="Внешний вид NONAME светодиодной линейки" width="27" height="150" class="alignright size-thumbnail wp-image-480" srcset="https://rux.vc/wp-content/uploads/2010/04/led-line-photo-27x150.jpg 27w, https://rux.vc/wp-content/uploads/2010/04/led-line-photo-54x300.jpg 54w, https://rux.vc/wp-content/uploads/2010/04/led-line-photo.jpg 166w" sizes="(max-width: 27px) 100vw, 27px" /></a></p>
<p>Попалась мне в руки светодиодная линейка неизвестного происхождения из 52 двухцветных светодиодов - красный и зелёный. Которая управлялась двумя микросхемами maxim <strong>max7919</strong>(драйвер). У этой платки было 8 пинов для подпайки, один из которых ни к чему не подключался. </p>
<p>Цель - разобраться что она из себя представляет, как работает и сделать что-нибудь с ней - погонять "бегущие огни" будет вполне достаточно.
</p>
<p><span id="more-467"></span></p>
<h2>Предыстория</h2>
<p>Конечно, сама она мне в руки не упала :). Дал мне её преподаватель нового предмета - Основы проектирования. Он очень много знает и <span title="сожалению не все преподы в этом заинтересованны" class="mycomment">желает делится</a> знаниями со студентами, предлагая создать различные проекты. </p>
<h2>Внутри</h2>
<p>Понятия не имею откуда эта линейка и для чего она предназначалась. Поэтому пришлось разбираться. Единственное что было на плате - цифры <strong>8485-01</strong>, видимо какой то серийный номер - ровным счётом ничего не дало. Осмотр схемы + чтение даташита - час ушёл на то, чтоб понять как она примерно работает.</p>
<p>Каждые 4 диода общим анодом к выходам "номерам цифр" драйвера, и к каждому цвету светодиода по ноге из сегментов. В итоге на первый драйвер приходится 8 "номеров цифр", на второй - 5. Под номерами цифр я подразумеваю номера цифр на 7ми сегментных дисплеев
</p>
<p>
Схему в общем виде линейку можно обрисовать так:<br />
<a href="http://rux.pp.ru/blog/wp-content/uploads/2010/04/led-line-two-max7219.jpg" data-lightboxplus="lightbox[467]" title="led-line-two-max7219"><img decoding="async" src="http://rux.pp.ru/blog/wp-content/uploads/2010/04/led-line-two-max7219.jpg" alt="" title="led-line-two-max7219" class="alignright size-full wp-image-469" width="50%" /></a><br />
Ага, рисовал карандашиком. Жутко не хотелось в каде. Посмотрел библиотеки компонентов gEDA, KiCad и даже eagle - там не было драйвера. Пробежался по гуглу - тоже нет. Рисовать - лень, да и не нужно это для одного раза.  Вот карандашиком.. как на начерталке ))
</p>
<p>Разводку платы знать и не нужно - главное,что есть интерфейс. На рисунке - он слева. Пару слов о нём:</p>
<ol>
<li>Пусто.. видимо для отсчёта</li>
<li><strong>GND</strong> - земля. Общая для двух драйверов</li>
<li><strong>DIN</strong> - данные. Также общий для драйверов - разумеется данные предназначаются тому, у которого активен <span style="border-top:1px solid"><strong>CS</strong></span></li>
<li><span style="border-top:1px solid"><strong>CS1</strong></span> - chip select для первой микросхемы. Выставляем в 0, когда хотим что-то сказать ей. На ней 5 сегментов(5 * 4 = 20светодиодов)</li>
<li><span style="border-top:1px solid">CS2</span> - аналочино, для второго драйвера. На этом драйвере висят 8 сегментов(8 * 4 = 32светодиода)</li>
<li><strong>CLK</strong> - clock. Тактируем..</li>
<li><strong>Iset</strong> - установка максимальной яркости led. <u>НЕ ЯРКОСТИ</u>, как многие(судя по форумам) понимают. Яркость задаётся ШИМом и устанавливается значением регистра. Для NONAME светодиодов которые попались - 37кОм слишком много - еле видны, а 31кОм - самое то. Значение устанавливается в зависимости от мощности нагрузки - читаем даташит.</li>
<li><strong>VCC</strong> - питание 5v</li>
</ol>
<p>Поэксперементировав, с зелёным цветом становится быстро понятно - определяется каждым нечётным номером бита. С красным - даже не то что ровно на оборот - они смещенные(но при этом чётные). Вдаваться в подробности не буду, т.к. пока делал - знал какие биты соответствуют какому номеру светодиода - написал прошивку и забыл. Ниже прошивка, в которой не требуется знать какой бит, номер сегмента и микросхемы отвечает за конкретный номер led.</p>
<p>
Для эксперементов подключил atmega8, вот таким способом:<br />
<a href="http://rux.pp.ru/blog/wp-content/uploads/2010/04/led-line-two-max7219-connected-to-atmega8.jpg" data-lightboxplus="lightbox[467]" title="led-line-two-max7219-connected-to-atmega8"><img decoding="async" src="http://rux.pp.ru/blog/wp-content/uploads/2010/04/led-line-two-max7219-connected-to-atmega8.jpg" alt="" title="led-line-two-max7219-connected-to-atmega8" class="aligncenter size-full wp-image-471" width="600"/></a><br />
Разумеется, можно было без кварца, для такой фигни-то. Просто он был на "отладочной плате" - ну и пусть. Также, не отображён коннектор для прошивки. Питалось это всё от USB. <br /><big>Забыл</big> нарисовать резистор 10кОм подключённый между <strong>VCC</strong> и ногой <span style="border-top:1px solid"><strong>RESET</strong></span> - без него мега если и запустится, то будет от каждого чиха перезагружаться
</p>
<h2>Прошивка</h2>
<p>Сначала хотел управлять через usb - но раздумал, не стоит это того, всё равно скоро отдавать, да и практической пользы мало. </p>
<p>Не смотря на то, что как описано в даташите многие значения регистров по дефолту совпадают с тем, что мне нужно, я очень долго бился пока не понял - их все нужно сначала инициализировать. После инициализации вычислил (посылая разные комбинации драйверам) как драйверы подключены к диодам, и уже по из этого вычислил схему подключения :)</p>
<h3>I/O</h3>
<p>Не буду пересказывать даташит. Комманда состоит из 2 байт - в старшем: старшие 4 бита - незначащие, младшие - комманда. Второй байт(младший) - если можно так выразится - аргументы для комманды, ну или значения которые нужно положить в определённый регистр драйвера.</p>
<p> Несколько вспомогательных функций для работы с <span style="border-top: 1px solid"><strong>CS</strong></span>, <strong>DIN</strong> и <strong>CLK</strong> линиями.<br />
<code lang="c" line_numbers="false"><br />
#define LOW 0<br />
#define HIGH 1</p>
<p>void led_cs1(char x) {<br />
    PORTC = x ? PORTC | _BV(4) : PORTC &amp; ~_BV(4);<br />
}<br />
void led_cs2(char x) {<br />
    PORTC = x ? PORTC | _BV(5) : PORTC &amp; ~_BV(5);<br />
}<br />
void led_clk(char x) {<br />
    PORTD = x ? PORTD | _BV(7) : PORTD &amp; ~_BV(7);<br />
}<br />
void led_din(char x) {<br />
    PORTD = x ? PORTD | _BV(6) : PORTD &amp; ~_BV(6);<br />
}<br />
</code><br />
Аргумент у них - должен отвечать на вопрос: установить ли 1 на линии?
</p>
<p>
Когда умеем дёргать линии, можно посылать данные:<br />
<code lang="c++" line_numbers="false"><br />
void outputByte(unsigned char val) {<br />
    for(signed char i = 7; i &gt;= 0; i--) {<br />
        led_din(val &amp; (1 &lt;&lt; i));<br />
        _delay_ms(CLOCK_TIME_MS /2);</p>
<p>        led_clk(HIGH);<br />
        _delay_ms(CLOCK_TIME_MS);</p>
<p>        led_clk(LOW);<br />
        _delay_ms(CLOCK_TIME_MS);<br />
    }<br />
}<br />
void outBytes(char pin, unsigned char reg, unsigned char dat) {<br />
    PORTC &amp;= ~_BV(pin);<br />
    outputByte(reg);<br />
    outputByte(dat);<br />
    PORTC |= _BV(pin);<br />
}<br />
</code><br />
Т.е. отправка комманды комманды(слова) заключается в опускании CS(установки в активное состояние) для нужного драйвера, и последовательной отправки 2 байт.
</p>
<p>
Для отправки какой то одной или сразу двум вынес отдельно:<br />
<code lang="c++" line_numbers="false"><br />
#define outBytesChip1(reg, dat) outBytes(PIN_CS1, reg, dat);<br />
#define outBytesChip2(reg, dat) outBytes(PIN_CS2, reg, dat);</p>
<p>void outBytesChips(unsigned char reg, unsigned char dat) {<br />
    outBytesChip1(reg, dat);<br />
    outBytesChip2(reg, dat);<br />
}<br />
</code><br />
<strong>outBytesChipN()</strong> - через дефайн, т.к. эксперементально определил что прошивка меньше места занимает :)
</p>
<h3>Инициализация</h3>
<p>Как я уже писал выше - промучился, пока жостко не проинициализировал.<br />
<code lang="c" line_numbers="false"><br />
void init() {<br />
    // configure pins to output<br />
    DDRC |= _BV(5) | _BV(4);<br />
    DDRD |= _BV(6) | _BV(7);</p>
<p>    // pre-init drivers line<br />
    led_cs1(HIGH);<br />
    led_cs2(HIGH);<br />
    led_clk(LOW);</p>
<p>    // setup clock interrupt and prescaler<br />
    TCCR0 |= (1&lt;&lt;CS02)|(1&lt;&lt;CS00);<br />
    TIMSK |= (1&lt;&lt;TOIE0);<br />
    TCNT0 = 0;</p>
<p>    // initialize drivers<br />
    outBytesChips(0xc, (1)); // shutdown<br />
    outBytesChips(0xa, (15)); // intensity<br />
    outBytesChips(0x9, 0); // decode mode<br />
    outBytesChips(0xf, 0); // test mode<br />
    outBytesChips(0xb, 7); // scan limit</p>
<p>    // finally, enable interrupts<br />
    sei();<br />
}<br />
</code><br />
Для чего нужны прерывания по таймеру? Ниже.
</p>
<h3>Управление светодиодами</h3>
<p>Весьма сложно вычислять адрес определённого цвета и светодиода. Он складывается из номера драйвера, номера сегмента, номера "цифры" в сегменте в зависимости от цвета. Сделать тупо бегущий огонь - это уже куча перерасчётов.
</p>
<p>
Я сделал нечто "видеопамяти". Некоторый буффер, в котором хранятся значения цветов для каждого светодиода. Элементарное обращение - через несколько функций, которые знают в какую часть массива "видеопамяти" полезть и какие биты прочитать/изменить. </p>
<p>Каждая ячейка состоит из 2х бит - цвета.<br />
<code lang="c++" line_numbers="false"><br />
enum LedStatus{<br />
    lsOff, lsGreen, lsRed, lsOrange<br />
};<br />
</code><br />
Говорящие названия - комментировать не нужно.
</p>
<p>
Выделяем память под массив "видеопамяти" и флажок - признак того, что содержимое памяти изменилось и нужно снова посылать новые значения в драйверы.<br />
<code lang="c++" line_numbers="false"><br />
char buffman_changed = 0;<br />
char buffman_data[13];<br />
</code>
</p>
<p>Функции для манипуляции с массивом таковы:<br />
<code lang="c++" line_numbers="false"><br />
LedStatus buffman_get(unsigned int num) {<br />
    if (num &gt; 52) return lsOff;<br />
    int bitcount = (num * 2);<br />
    int off_bit = bitcount % 8;<br />
    return (LedStatus) ((buffman_data[bitcount/8] &amp; (3 &lt;&lt; off_bit)) &gt;&gt; off_bit);<br />
}<br />
void buffman_setAll(LedStatus stat) {<br />
    unsigned char mask = stat &lt;&lt; 0 | stat &lt;&lt; 2 | stat &lt;&lt; 4 | stat &lt;&lt; 6;<br />
    for(int i = 0; i &lt; 13; i++) buffman_data[i] = mask;<br />
    buffman_changed = 1;<br />
}<br />
void buffman_set(unsigned char num, LedStatus stat) {<br />
    if (num &gt; 51) return;<br />
    int bitcount = (num * 2);<br />
    int off_byte = num &gt;&gt; 2, off_bit = bitcount % 8;<br />
    buffman_data[off_byte] = (buffman_data[off_byte] &amp; ~(3 &lt;&lt; off_bit)) | (((char)stat) &lt;&lt; off_bit);<br />
    buffman_changed = 1;<br />
}<br />
</code><br />
Суть одна - умеют работать с "видеобуфером".
</p>
<p> Самое интересное - то как эта "видеопамять" отображается на массив. По таймеру.<br />
<code lang="c++" line_numbers="false"><br />
ISR(TIMER0_OVF_vect) {<br />
    int mask = 0;<br />
    if (!buffman_changed) return; </p>
<p>    for(int i = 0; i &lt; 15; i++) {<br />
        mask = 0;<br />
        for(int j = 0; j &lt; 4; j++) {<br />
            switch(buffman_get(i*4+j)) {<br />
            case lsOff: continue;<br />
            case lsOrange: mask |= 2 &lt;&lt; redMatrix[j] | 1 &lt;&lt; greenMatrix[j]; break;<br />
            case lsRed: mask |= 2 &lt;&lt; redMatrix[j]; break;<br />
            case lsGreen: mask |= 1 &lt;&lt; greenMatrix[j]; break;<br />
            }<br />
        }</p>
<p>        if (i &lt; 8) {<br />
            outBytesChip2(i+1, mask);<br />
        } else {<br />
            outBytesChip1(i-7, mask);<br />
        }<br />
    }<br />
}<br />
</code><br />
По прерыванию в цикле пробегается по всем сегментам - группам светодиодов(по 4), в зависимости от значения в "видеобуфере" формируется с помощью масок формируется отправляемое значение.
</p>
<p>При том, маска для каждого номера светодиода и цвета в определённой позиции лежит в<br />
<code lang="c" line_numbers="false"><br />
static unsigned char redMatrix[] = {4, 2, 0, 6},<br />
                            greenMatrix[] = {6, 4, 2, 0};<br />
</code>
</p>
<p>А теперь можно в цикле рисовать в массиве через через <strong>buffman_set()</strong> с определённой задержкой - и эти изменения практически моментально отразятся на светодиодной линейке.</p>
<p>
Наример вот такая прошивка:<br />
<code lang="c++" line_numbers="false"><br />
int main(void)<br />
{<br />
    init();</p>
<p>    buffman_setAll(lsOff);</p>
<p>    int dir = 1, i = 1;<br />
    LedStatus ls = lsRed;<br />
    do {<br />
        buffman_set(i-1, lsOrange);<br />
        buffman_set(i, lsRed);<br />
        buffman_set(i+1, lsRed);<br />
        buffman_set(i+2, lsGreen);<br />
        if (i == 0 || i == 49) dir = - dir;<br />
        i+=dir;<br />
        wait(25);<br />
        if (i%2) buffman_set(0, (buffman_get(0) == lsOff ? lsRed : lsOff ));<br />
        if (i%2==0) buffman_set(51, (buffman_get(51) == lsOff ? lsRed : lsOff ));</p>
<p>    } while( 1 );</p>
<p>    return 0;<br />
}<br />
</code><br />
Делает вот такое:<br />
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/UPvac5EV5qY&hl=ru&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param></object>
</p>
<p>
Ещё вот баловался:<br />
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/k6NtYiqG1cA&hl=ru&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param></object>
</p>
<h2>На этом всё</h2>
<p>
На этом всё. Поиграл - и хватит. Делюсь файлами.<br />
Полный текст прошивки:<br />
<code lang="c++"><br />
#include &lt;avr/io.h&gt;<br />
#include &lt;avr/eeprom.h&gt;<br />
#include &lt;avr/interrupt.h&gt;<br />
#include &lt;avr/pgmspace.h&gt;<br />
#include &lt;util/delay.h&gt;</p>
<p>#define PIN_CS1 4<br />
#define PIN_CS2 5</p>
<p>// Clock duration<br />
#define CLOCK_TIME_MS 0.0005</p>
<p>#define LOW 0<br />
#define HIGH 1</p>
<p>static unsigned char redMatrix[] = {4, 2, 0, 6}, greenMatrix[] = {6, 4, 2, 0};</p>
<p>enum LedStatus{<br />
    lsOff, lsGreen, lsRed, lsOrange<br />
};</p>
<p>char buffman_changed = 0;<br />
char buffman_data[13];</p>
<p>LedStatus buffman_get(unsigned int num) {<br />
    if (num &gt; 52) return lsOff;<br />
    int bitcount = (num * 2);<br />
    int off_bit = bitcount % 8;<br />
    return (LedStatus) ((buffman_data[bitcount/8] &amp; (3 &lt;&lt; off_bit)) &gt;&gt; off_bit);<br />
}<br />
void buffman_setAll(LedStatus stat) {<br />
    unsigned char mask = stat &lt;&lt; 0 | stat &lt;&lt; 2 | stat &lt;&lt; 4 | stat &lt;&lt; 6;<br />
    for(int i = 0; i &lt; 13; i++) buffman_data[i] = mask;<br />
    buffman_changed = 1;<br />
}<br />
void buffman_set(unsigned char num, LedStatus stat) {<br />
    if (num &gt; 51) return;<br />
    int bitcount = (num * 2);<br />
    int off_byte = num &gt;&gt; 2, off_bit = bitcount % 8;<br />
    buffman_data[off_byte] = (buffman_data[off_byte] &amp; ~(3 &lt;&lt; off_bit)) | (((char)stat) &lt;&lt; off_bit);<br />
    buffman_changed = 1;<br />
}</p>
<p>void led_cs1(char x) {<br />
    PORTC = x ? PORTC | _BV(4) : PORTC &amp; ~_BV(4);<br />
}<br />
void led_cs2(char x) {<br />
    PORTC = x ? PORTC | _BV(5) : PORTC &amp; ~_BV(5);<br />
}<br />
void led_clk(char x) {<br />
    PORTD = x ? PORTD | _BV(7) : PORTD &amp; ~_BV(7);<br />
}<br />
void led_din(char x) {<br />
    PORTD = x ? PORTD | _BV(6) : PORTD &amp; ~_BV(6);<br />
}<br />
//#define led_din(x) PORTD = x ? PORTD | _BV(6) : PORTD &amp; ~_BV(6);</p>
<p>void outputByte(unsigned char val) {<br />
    for(signed char i = 7; i &gt;= 0; i--) {<br />
        led_din(val &amp; (1 &lt;&lt; i));<br />
        _delay_ms(CLOCK_TIME_MS /2);</p>
<p>        led_clk(HIGH);<br />
        _delay_ms(CLOCK_TIME_MS);</p>
<p>        led_clk(LOW);<br />
        _delay_ms(CLOCK_TIME_MS);<br />
    }<br />
}</p>
<p>void outBytes(char pin, unsigned char reg, unsigned char dat) {<br />
    PORTC &amp;= ~_BV(pin);<br />
    outputByte(reg);<br />
    outputByte(dat);<br />
    PORTC |= _BV(pin);<br />
}</p>
<p>#define outBytesChip1(reg, dat) outBytes(PIN_CS1, reg, dat);<br />
#define outBytesChip2(reg, dat) outBytes(PIN_CS2, reg, dat);</p>
<p>void outBytesChips(unsigned char reg, unsigned char dat) {<br />
    outBytesChip1(reg, dat);<br />
    outBytesChip2(reg, dat);<br />
}</p>
<p>void init() {<br />
    // configure pins to output<br />
    DDRC |= _BV(5) | _BV(4);<br />
    DDRD |= _BV(6) | _BV(7);</p>
<p>    // pre-init drivers line<br />
    led_cs1(HIGH);<br />
    led_cs2(HIGH);<br />
    led_clk(LOW);</p>
<p>    // setup clock interrupt and prescaler<br />
    TCCR0 |= (1&lt;&lt;CS02)|(1&lt;&lt;CS00);<br />
    TIMSK |= (1&lt;&lt;TOIE0);<br />
    TCNT0 = 0;</p>
<p>    // initialize drivers<br />
    outBytesChips(0xc, (1)); // shutdown<br />
    outBytesChips(0xa, (15)); // intensity<br />
    outBytesChips(0x9, 0); // decode mode<br />
    outBytesChips(0xf, 0); // test mode<br />
    outBytesChips(0xb, 7); // scan limit</p>
<p>    // finally, enable interrupts<br />
    sei();<br />
}</p>
<p>ISR(TIMER0_OVF_vect) {<br />
    int mask = 0;<br />
    if (!buffman_changed) return; </p>
<p>    for(int i = 0; i &lt; 15; i++) {<br />
        mask = 0;<br />
        for(int j = 0; j &lt; 4; j++) {<br />
            switch(buffman_get(i*4+j)) {<br />
            case lsOff: continue;<br />
            case lsOrange: mask |= 2 &lt;&lt; redMatrix[j] | 1 &lt;&lt; greenMatrix[j]; break;<br />
            case lsRed: mask |= 2 &lt;&lt; redMatrix[j]; break;<br />
            case lsGreen: mask |= 1 &lt;&lt; greenMatrix[j]; break;<br />
            }<br />
        }</p>
<p>        if (i &lt; 8) {<br />
            outBytesChip2(i+1, mask);<br />
        } else {<br />
            outBytesChip1(i-7, mask);<br />
        }<br />
    }<br />
}</p>
<p>inline void wait(float ms) {<br />
    for(; ms &gt; 0; ms-=1) _delay_ms(1);<br />
}</p>
<p>int main(void)<br />
{<br />
    init();</p>
<p>    buffman_setAll(lsOff);</p>
<p>    int dir = 1, i = 1;<br />
    LedStatus ls = lsRed;<br />
    do {<br />
        buffman_set(i-1, lsOrange);<br />
        buffman_set(i, lsRed);<br />
        buffman_set(i+1, lsRed);<br />
        buffman_set(i+2, lsGreen);<br />
        if (i == 0 || i == 49) dir = - dir;<br />
        i+=dir;<br />
        wait(25);<br />
        if (i%2) buffman_set(0, (buffman_get(0) == lsOff ? lsRed : lsOff ));<br />
        if (i%2==0) buffman_set(51, (buffman_get(51) == lsOff ? lsRed : lsOff ));</p>
<p>    } while( 1 );</p>
<p>    return 0;<br />
}</p>
<p></code><br />
А также запакованный вариант - вместе с мейкфайлом и прошивкой: <a href='/blog/wp-content/uploads/2010/04/led-line-firmware.tar.gz'>led-line-firmware.tar.gz</a>
</p>
</p>
<h2>UPD</h2>
<p>Выкладываю ещё одну демо-прошивку и видео к ней. Есть три функции, выполняющие каждая свой эффект, вызываются циклически по очереди, с плавным переходом(после каждого эффекта уменьшается яркость с помощью встроенного в драйверы ШИМа)</p>
<p>
<code lang="c++" line_numbers="false"><br />
inline void wait(int ms) {<br />
    for(; ms &gt; 0; ms-=1) _delay_ms(1);<br />
}</p>
<p>void e1() {<br />
    int dir = 1, i = 1;<br />
    for(int j = 0; j &lt; 300 ; j++) {<br />
        buffman_set(i-1, lsOrange);<br />
        buffman_set(i, lsRed);<br />
        buffman_set(i+1, lsRed);<br />
        buffman_set(i+2, lsGreen);<br />
        if (i == 0 || i == 49) dir = - dir;<br />
        i+=dir;<br />
        wait(25);<br />
        if (i%2) buffman_set(0, (buffman_get(0) == lsOff ? lsRed : lsOff ));<br />
        if (i%2==0) buffman_set(51, (buffman_get(51) == lsOff ? lsRed : lsOff ));<br />
    }<br />
}<br />
void e2() {<br />
    LedStatus ls = lsRed;<br />
    int i = 1, len=6, end = 52;;<br />
    int delay = 14;<br />
    while(end &gt; 0) {<br />
        for(i = 0; i &lt; end;i++) {<br />
            for(int k = 0; k &lt; len; k++) {<br />
                buffman_set(k+i, ls);<br />
            }<br />
            buffman_set(i-1, lsOff);<br />
            wait(delay);<br />
        }<br />
        delay++;<br />
        end--;end--;<br />
        if (ls == lsRed) ls = lsGreen;<br />
        else if (ls == lsGreen) ls = lsOrange;<br />
        else if (ls == lsOrange) ls = lsRed;<br />
    }<br />
}</p>
<p>void e3() {<br />
    for(int dir = 1, i = 1, j = 0; j &lt; 400; j++) {<br />
        buffman_set(i, lsRed);<br />
        buffman_set(dir&gt;0?i+1:i-1, lsRed);<br />
        buffman_set(i-dir, lsOff);</p>
<p>        buffman_set(52-i, lsGreen);<br />
        buffman_set(52-i-(dir&gt;0?+1:-1), lsGreen);<br />
        buffman_set(52-i+dir, lsOff);</p>
<p>        if(i &gt; 52/2-10) {<br />
            for(int k = 0; k &lt; i-20; k++) {<br />
                buffman_set(k, lsOrange);<br />
                buffman_set(52-k, lsOrange);<br />
            }<br />
        }</p>
<p>        i += dir;<br />
        if (i == 0 || i == 52/2) dir = - dir;<br />
        wait(31);<br />
    }<br />
}</p>
<p>void (*examples[]) (void) = { &amp;e3, &amp;e2, &amp;e1};</p>
<p>int main(void)<br />
{<br />
    init();</p>
<p>    buffman_setAll(lsOff);</p>
<p>    for(int i = 0; ; i = ++i % (sizeof(examples)/sizeof(examples[0]))) {<br />
        examples[i]();<br />
        for(int b = 15; b &gt; 1; b--) {<br />
            outBytesChips(0xa, (b)); // intensity<br />
            wait(150);<br />
        }<br />
        buffman_setAll(lsOff);<br />
        wait(300);<br />
        outBytesChips(0xa, (15)); // intensity</p>
<p>    }</p>
<p>    return 0;<br />
}<br />
</code><br />
Обожаю си за возможность писать такие выверты :)<br />
Всю прошивку можно скачать с исходниками: <a href='http://rux.pp.ru/blog/wp-content/uploads/2010/04/ledline-firmware-3-effects.tar.gz'>ledline-firmware-3-effects.tar</a>
</p>
<p> Ну и видео<br />
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/0zYaztTdUWk&hl=ru&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param></object></p>The post <a href="https://rux.vc/2010.04/led-line-based-on-max7219/">Cветодиодная линейка на MAX7219</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2010.04/led-line-based-on-max7219/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">467</post-id>	</item>
		<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>
		<item>
		<title>avrdude: прошивка в низкоскоростном режиме USB CDC</title>
		<link>https://rux.vc/2010.01/avrdude-proshivka-v-nizkoskorostnom-rezhime-usb-cdc/</link>
					<comments>https://rux.vc/2010.01/avrdude-proshivka-v-nizkoskorostnom-rezhime-usb-cdc/#respond</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Sat, 30 Jan 2010 19:25:14 +0000</pubDate>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[avr]]></category>
		<category><![CDATA[avrdude]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[patch]]></category>
		<category><![CDATA[usb]]></category>
		<category><![CDATA[v-usb]]></category>
		<category><![CDATA[программатор]]></category>
		<guid isPermaLink="false">http://rux.pp.ru/blog/?p=299</guid>

					<description><![CDATA[<p>Мне дали попользоваться в кампусе программатором avr910 с USB интерфейсом. Он мне был просто необходим для сборки своего программатора(USBAsp). Проблемма Простая комманда для чтения флеш памяти: avrdude -P /dev/ttyACM0 -p m8 -c avr910 -U flash:r:flash.hex:i Неожиданно выдала: avrdude: ser_send(): write error: Invalid argument Cудя по lsusb программатор определился: Bus 004 Device 002: ID 16c0:05e1 VOTI. ... <a title="avrdude: прошивка в низкоскоростном режиме USB CDC" class="read-more" href="https://rux.vc/2010.01/avrdude-proshivka-v-nizkoskorostnom-rezhime-usb-cdc/" aria-label="More on avrdude: прошивка в низкоскоростном режиме USB CDC">Read more</a></p>
The post <a href="https://rux.vc/2010.01/avrdude-proshivka-v-nizkoskorostnom-rezhime-usb-cdc/">avrdude: прошивка в низкоскоростном режиме USB CDC</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p>
Мне дали попользоваться в кампусе программатором <strong>avr910</strong> с <b>USB</b> интерфейсом. Он мне был просто необходим для сборки своего программатора(USBAsp).
</p>
<h3>Проблемма</h3>
<p>
Простая комманда для чтения флеш памяти:<br />
<code lang="bash" line_numbers="false"> avrdude -P /dev/ttyACM0 -p m8 -c avr910 -U flash:r:flash.hex:i</code><br />
Неожиданно выдала:<br />
<code line_numbers="false"><br />
avrdude: ser_send(): write error: Invalid argument<br />
</code><br />
Cудя по <strong>lsusb</strong> программатор определился: Bus 004 Device 002: ID 16c0:05e1 VOTI.<br />
Появился соответствующий файл устройства <b>/dev/ttyACM0</b>. Права rw также есть.<br />
Всё казалось бы хорошо..
</p>
<p><span id="more-299"></span></p>
<h3> Причина</h3>
<p>
Гугл подсказал, что из за <strong title="В венде НЕПРАВИЛЬНО реализован стандарт, и она забивает на нессответствие класса устройства и скорости его подключения и поэтому тупо работает.">действительно правильной </strong>реализации(по стандартам) в линуксе ядро и устройство не могут "договориться" между собой, т.к. программатор запрашивает недоступный для низкоскоростных устройств режим CDC. В итоге программатору ставитсья режим INTERRUPT на чём как я понял всё кончается и возникает ошибка выше.
</p>
<h3>Решение</h3>
<p>
Один из вариантом которым я воспользовался я нашёл на форуме сайта <a href="http://electronix.ru/forum/lofiversion/index.php/t18676-800.html" target="_blank">electronix.ru</a> - пропатчить ядро(usb часть), чтоб игнорировало стандарт. Оригиналы патчей лежат<br />
<a href="http://spiffie.org/kits/usb7/driver_linux.shtml"  target="_blank">тут</a>. Разумеется, вам понадобятся исходники ядра.
</p>
<p>
Продублирую их тут:<br />
<code lang="diff"><br />
-- linux-2.6.25/drivers/usb/core/config.c      2008-04-16 22:49:44.000000000 -0400<br />
+++ linux-2.6.25-usbpatch/drivers/usb/core/config.c     2008-06-12 23:56:54.000000000 -0400<br />
@@ -137,12 +137,16 @@<br />
        if (to_usb_device(ddev)-&gt;speed == USB_SPEED_LOW &amp;&amp;<br />
                        usb_endpoint_xfer_bulk(d)) {<br />
                dev_warn(ddev, &quot;config %d interface %d altsetting %d &quot;<br />
-                   &quot;endpoint 0x%X is Bulk; changing to Interrupt\n&quot;,<br />
-                   cfgno, inum, asnum, d-&gt;bEndpointAddress);<br />
-               endpoint-&gt;desc.bmAttributes = USB_ENDPOINT_XFER_INT;<br />
-               endpoint-&gt;desc.bInterval = 1;<br />
-               if (le16_to_cpu(endpoint-&gt;desc.wMaxPacketSize) &gt; 8)<br />
-                       endpoint-&gt;desc.wMaxPacketSize = cpu_to_le16(8);<br />
+               &quot;endpoint 0x%X is Bulk; this violates USB spec for &quot;<br />
+               &quot;low speed devices.\n&quot;,<br />
+               cfgno, inum, asnum, d-&gt;bEndpointAddress);<br />
+//             dev_warn(ddev, &quot;config %d interface %d altsetting %d &quot;<br />
+//                 &quot;endpoint 0x%X is Bulk; changing to Interrupt\n&quot;,<br />
+//                 cfgno, inum, asnum, d-&gt;bEndpointAddress);<br />
+//             endpoint-&gt;desc.bmAttributes = USB_ENDPOINT_XFER_INT;<br />
+//             endpoint-&gt;desc.bInterval = 1;<br />
+//             if (le16_to_cpu(endpoint-&gt;desc.wMaxPacketSize) &gt; 8)<br />
+//                     endpoint-&gt;desc.wMaxPacketSize = cpu_to_le16(8);<br />
        }</p>
<p></code><br />
и второго файла<br />
<code lang="diff"><br />
--- linux-2.6.25/drivers/usb/host/uhci-q.c      2008-04-16 22:49:44.000000000 -0400<br />
+++ linux-2.6.25-usbpatch/drivers/usb/host/uhci-q.c     2008-06-13 17:41:22.000000000 -0400<br />
@@ -1042,8 +1042,8 @@<br />
        int ret;</p>
<p>        /* Can&#039;t have low-speed bulk transfers */<br />
-       if (urb-&gt;dev-&gt;speed == USB_SPEED_LOW)<br />
-               return -EINVAL;<br />
+//     if (urb-&gt;dev-&gt;speed == USB_SPEED_LOW)<br />
+//             return -EINVAL;</p>
<p>        if (qh-&gt;state != QH_STATE_ACTIVE)<br />
                qh-&gt;skel = SKEL_BULK;<br />
</code><br />
Как видно, эти патчи для ядра <big>2.6.25</big>!
</p>
<p>
Соответственно если у вас другое ядро, возможно придётся руками патчить, что я и сделал для своего <strong>2.6.29.2</strong>.<br />
Прикрепляю пропатченные файлы:</p>
<ul>
<li><a href="http://rux.pp.ru/blog/wp-content/uploads/2010/01/config.c">drivers/usb/core/config.c</a></li>
<li><a href="http://rux.pp.ru/blog/wp-content/uploads/2010/01/uhci-q.c">drivers/usb/host/uhci-q.c</a></li>
<li><a href="http://rux.pp.ru/blog/wp-content/uploads/2010/01/drivers.tar.gz">оба</a> - нужно просто распаковать содержимое архива в корне ядра поверх.</li>
</ul>
<p>
Пересобираем ядро:<br />
<code lang="bash"  line_numbers="false">make &amp;&amp; make modules &amp;&amp; make modules_install &amp;&amp; make install<br />
</code>
</p>
<h3>Finish</h3>
<p>
Незабудьте обеспечить себе права доступа к /dev/ttyACM0. В Debian достаточно юзеру войти в группу dialout.<br />
После перезагрузки программатор заработает с avrdude.</p>The post <a href="https://rux.vc/2010.01/avrdude-proshivka-v-nizkoskorostnom-rezhime-usb-cdc/">avrdude: прошивка в низкоскоростном режиме USB CDC</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2010.01/avrdude-proshivka-v-nizkoskorostnom-rezhime-usb-cdc/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">299</post-id>	</item>
		<item>
		<title>Электроника: NONAME HL022 &#8211; сверхяркий светодиод</title>
		<link>https://rux.vc/2009.12/hl022-sverkhyarkijj-svetodiod/</link>
					<comments>https://rux.vc/2009.12/hl022-sverkhyarkijj-svetodiod/#comments</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Tue, 08 Dec 2009 18:56:11 +0000</pubDate>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Quick notes]]></category>
		<category><![CDATA[datasheet]]></category>
		<category><![CDATA[сид]]></category>
		<guid isPermaLink="false">http://rux.pp.ru/blog/?p=254</guid>

					<description><![CDATA[<p>Мне с другом понадобились сверхяркие RGB светодиоды - достали мы их почти без проблемм - на юноне по 200р. Речи о поиске даташита по названию не может быть - производитель NONAME, о чём признались сами продавцы, всё чем они смогли помочь - дать сфотографировать кусок их цветастого каталога. Вот какую таблицу я вынес ARPL-KM-1.5W RGB ... <a title="Электроника: NONAME HL022 &#8211; сверхяркий светодиод" class="read-more" href="https://rux.vc/2009.12/hl022-sverkhyarkijj-svetodiod/" aria-label="More on Электроника: NONAME HL022 &#8211; сверхяркий светодиод">Read more</a></p>
The post <a href="https://rux.vc/2009.12/hl022-sverkhyarkijj-svetodiod/">Электроника: NONAME HL022 – сверхяркий светодиод</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p>
Мне с другом понадобились сверхяркие <b><span style='color:red'>R</span><span style='color:green'>G</span><span style='color:blue'>B</span></b> светодиоды - достали мы их почти без проблемм - на юноне по 200р. Речи о поиске даташита по названию не может быть - производитель NONAME, о чём признались сами продавцы, всё чем они смогли помочь - дать сфотографировать кусок их цветастого каталога.
</p>
<p><span id="more-254"></span><br />
Вот какую таблицу я вынес</p>
<h3>ARPL-KM-1.5W RGB</h3>
<table class="data" width="560">
<tr>
<th rowspan="2">Цвет и яркость</th>
<th colspan="2">Ток, мА</th>
<th colspan="2">Напряжение, B</th>
</tr>
<tr>
<th>I<sub>min</sub></th>
<th>I<sub>max</sub></th>
<th>U<sub>min</sub></th>
<th>U<sub>max</sub></th>
</tr>
<tr>
<td><span style="width:40px; height: 20px; background: red">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;&nbsp;&nbsp;620</td>
<td>18</td>
<td>23</td>
<td>2.2</td>
<td>2.5</td>
</tr>
<tr>
<td><span style="width:40px; height: 20px; background: green">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;&nbsp;&nbsp;520</td>
<td>35</td>
<td>45</td>
<td>3.4</td>
<td>3.6</td>
</tr>
<tr>
<td><span style="width:40px; height: 20px; background: blue">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;&nbsp;&nbsp;470</td>
<td>7</td>
<td>9</td>
<td>3.4</td>
<td>3.6</td>
</tr>
</table>
<h3>ARPL-KM-3W RGB</h3>
<table class="data" width="560">
<tr>
<th rowspan="2">Цвет и яркость</th>
<th colspan="2">Ток, мА</th>
<th colspan="2">Напряжение, B</th>
</tr>
<tr>
<th>I<sub>min</sub></th>
<th>I<sub>max</sub></th>
<th>U<sub>min</sub></th>
<th>U<sub>max</sub></th>
</tr>
<tr>
<td><span style="width:40px; height: 20px; background: red">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;&nbsp;&nbsp;620</td>
<td>10</td>
<td>15</td>
<td>2.0</td>
<td>2.5</td>
</tr>
<tr>
<td><span style="width:40px; height: 20px; background: green">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;&nbsp;&nbsp;520</td>
<td>15</td>
<td>20</td>
<td>3.2</td>
<td>3.5</td>
</tr>
<tr>
<td><span style="width:40px; height: 20px; background: blue">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;&nbsp;&nbsp;470</td>
<td>3</td>
<td>5</td>
<td>3.0</td>
<td>3.5</td>
</tr>
</table>
<p>
Надо отметить,  угол обзора 120<sup>o</sup>
</p>
<p>
По ощущению самые яркий цвет - зелёный, потом идёт красный и "светит, но не освещает" синий. О чём и говорят цифры яркости.
</p>
<p>
Я подобрал(визуально и подсчитал) резисторы для работы трёхватного светодиода в цепи с питанием в 5В.<br />
Для красного(вывод №2) канала -<strong> 120-125 Ом</strong>, зелёного(вывод №1) - <strong>60-64 Ом </strong>и синего(вывод №3) - <strong>170-175 Ом</strong>.</p>The post <a href="https://rux.vc/2009.12/hl022-sverkhyarkijj-svetodiod/">Электроника: NONAME HL022 – сверхяркий светодиод</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2009.12/hl022-sverkhyarkijj-svetodiod/feed/</wfw:commentRss>
			<slash:comments>15</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">254</post-id>	</item>
	</channel>
</rss>
