<?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/"
	>

<channel>
	<title>imsolidstate &#187; Electronics</title>
	<atom:link href="http://www.imsolidstate.com/archives/tag/electronics/feed" rel="self" type="application/rss+xml" />
	<link>http://www.imsolidstate.com</link>
	<description>Always improving things...</description>
	<lastBuildDate>Wed, 04 Jan 2012 22:32:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Breathe life into your Xoom</title>
		<link>http://www.imsolidstate.com/archives/995</link>
		<comments>http://www.imsolidstate.com/archives/995#comments</comments>
		<pubDate>Wed, 04 Jan 2012 22:32:56 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=995</guid>
		<description><![CDATA[A few months ago I bought a Xoom and have mostly been disappointed with it. I use it mainly for internet, which is slow on the tablet plus the interface and keyboard are laggy. There are other problems as well, like the &#8220;recent apps&#8221; button that doesn&#8217;t remember certain apps like the browser and I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>A few months ago I bought a Xoom and have mostly been disappointed with it. I use it mainly for internet, which is slow on the tablet plus the interface and keyboard are laggy. There are other problems as well, like the &#8220;recent apps&#8221; button that doesn&#8217;t remember certain apps like the browser and I&#8217;ve found if you leave the device on for more than about a day applications start to behave oddly.</p>
<p>I&#8217;ve been thinking hard about selling it because I didn&#8217;t think that rooting it and installing a tweaked ROM was going to be enough to fix it. I decided to try anyway with the new Android 4 (ICS) release. It only took about five minutes using the Xoom with ICS to realize how wrong I was and how good Android 4 is for the Xoom. Everything is better.</p>
<p><img class="alignnone size-large wp-image-1001" title="Android 4 (ICS)" src="http://www.imsolidstate.com/wp-content/uploads/2012/01/20120104_151635-1024x682.jpg" alt="Android 4 (ICS)" width="645" height="429" /></p>
<p>As usual with hacking all things mobile, you will be heading over to XDA if you want your Xoom to behave like it should. I&#8217;m writing a quick tutorial here since the information is pretty spread out on XDA. I had a couple issues that had me searching through pages of threads, so this is what worked for me.<span id="more-995"></span></p>
<p>Step 1: Unlock your Xoom. You can&#8217;t do anything until this is complete, and in the process it will void your warranty and wipe your device. Back up any important data first. The instructions on unlocking your Xoom are <a href="http://forum.xda-developers.com/showthread.php?t=967065&amp;highlight=fastboot">here</a>. After you install the Android SDK, you will need to install the Android tools and a platform (4.0) from the SDK manager. This will install fastboot, which will be in the platform tools folder you installed. You will run a command window in the folder where fastboot is located in order to send the commands to the device.</p>
<p>Step 2: Install a new recovery console. Use the instructions <a href="http://forum.xda-developers.com/showthread.php?t=1074979">here</a>. Use the non-CWM method. You will be sending it through adb and the command window you used earlier. There is a trick though: you can&#8217;t reboot into recovery with the adb commands unless you are already rooted, and if it&#8217;s your first time you obviously aren&#8217;t. So instead of rebooting via the fastboot command, reboot by pressing the volume up key and the power key until the screen goes black. Then count for 3.5-4 seconds after you see the Motorola logo and press volume down. &#8220;Android recovery&#8221; should appear on the screen. Press volume up to select. If the next screen you get is an Android robot with an exclamation mark, you pressed volume up into recovery too soon. Reboot, reflash the recovery file, reboot, and try again. When you get the timing right you will see the ClockworkMod screen and the recovery console.</p>
<p>Step 3: Root your Xoom. Once you can get into the CWM screen at will, download and install the Universal Xoom Root zip file from <a href="http://forum.xda-developers.com/showthread.php?t=1242241">here</a>. You now have control of your Xoom, it&#8217;s time to load new software on it.</p>
<p>Step 4: Install a new ROM. Download the latest ROM and Google apps package from <a href="http://forum.xda-developers.com/showthread.php?t=1400958">here</a>. This is the team EOS ICS ROM, you can pick from any ROMs available on XDA at this point though. Furthermore this is the wi-fi only Xoom ROM (MZ604). If you have a 3G/4G device you will need to get the appropriate ROM from XDA. Place the two zip files on your SD card and install as before, but make sure you do a factory reset first and clear the caches. After you have installed the two zip files, reboot and enjoy your Xoom.</p>
<p>As usual, do this at your own risk. You can ruin your device if you mess something up. If you aren&#8217;t sure about what you are doing, head over to the<a href="http://forum.xda-developers.com/forumdisplay.php?f=948"> XDA Xoom Android development forum</a> and start reading. This tutorial isn&#8217;t a substitute for any of the information at XDA, just a sequence of events that makes first time rooting a little easier to understand. Much respect to the developers at XDA for making this possible. Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/995/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PIC32 Ethernet Starter Kit and MPLAB X</title>
		<link>http://www.imsolidstate.com/archives/983</link>
		<comments>http://www.imsolidstate.com/archives/983#comments</comments>
		<pubDate>Sun, 09 Oct 2011 01:51:44 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[PIC]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=983</guid>
		<description><![CDATA[I picked up Microchip&#8217;s PIC32 ethernet starter kit in order to check out their 32-bit processors as well as to get started on embedded web servers. The free TCP/IP stack from Microchip was my motivation, since it can be used on any of their chips, including the 8-bit versions. I also was interested in the [...]]]></description>
			<content:encoded><![CDATA[<p>I picked up Microchip&#8217;s PIC32 ethernet starter kit in order to check out their 32-bit processors as well as to get started on embedded web servers. The free TCP/IP stack from Microchip was my motivation, since it can be used on any of their chips, including the 8-bit versions. I also was interested in the C32 compiler, since it is free. I used MPLAB X for the test, along with the downloadable Microchip application libraries. I have been using MPLAB X for PIC18 development, and I really like it. It&#8217;s a nice IDE.</p>
<p>This review will cover getting the SKDE up and running with the TCPIP Demo App from the application libraries in MPLAB X.</p>
<p><img class="alignnone size-full wp-image-984" title="MPweb" src="http://www.imsolidstate.com/wp-content/uploads/2011/10/MPweb.bmp" alt="MPweb" width="609" height="498" /></p>
<p><span id="more-983"></span>Download and install:</p>
<p><a href="http://www.java.com/en/download/index.jsp">Java</a></p>
<p><a href="http://ww1.microchip.com/downloads/mplab/X_Beta/index.html">MPLAB X</a></p>
<p><a href="http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&amp;nodeId=2680&amp;dDocName=en547784">Microchip Application Libraries</a></p>
<p>When you run the CD that comes with the ethernet starter kit, you will have an option to install from CD. This will also install MPLAB 8. I couldn&#8217;t find a way around doing this, as the driver for the board is buried somewhere in that install. It won&#8217;t install the starter kit otherwise.</p>
<p>When the install is completed, start the driver switcher application from the Microchip program directory. Select PIC32 SK, and the radio button to configure for MPLAB X. Apply the setting and wait for it to complete. Then launch MPLAB X. Select Open Project from the file menu. Navigate to the Microchip Solutions directory, then TCPIP, finally select Demo App and MPLAB X. When you open the project it will start loading. It takes a while since the code stack is large. When it loads set the project configuration to the ethernet starter kit (C32-PIC32_ETH_SK). Finally you should be able to build and load the project to the target.</p>
<p>Once complete, plug the ethernet port into a router, where it will get an IP address. Logging on to the router will let you see attached devices and find the assigned IP. You should be able to put the IP in your browser now and see the Microchip demo page.</p>
<p>There are video tutorials on Microchip&#8217;s website that detail the dynamic webpage capabilities of the device. The demo application supports a lot of processors and protocols, so my next task will be to dig in and figure out the smallest code necessary to just run HTTP on the PIC32.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/983/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Netgear WGR614v7</title>
		<link>http://www.imsolidstate.com/archives/981</link>
		<comments>http://www.imsolidstate.com/archives/981#comments</comments>
		<pubDate>Fri, 07 Oct 2011 14:53:39 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=981</guid>
		<description><![CDATA[I&#8217;ve reached the conclusion that this wireless router is pretty much useless. Despite my earlier efforts of heatsinking the processor (which did help), sending email logs when the log was full (unsure if that was useful at all), and updating the firmware to the latest and greatest the thing would still refuse to connect to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve reached the conclusion that this wireless router is pretty much useless. Despite my earlier efforts of heatsinking the processor (which did help), sending email logs when the log was full (unsure if that was useful at all), and updating the firmware to the latest and greatest the thing would still refuse to connect to the WAN randomly.</p>
<p>I did some more digging and figured out that the router doesn&#8217;t really have a WAN port, despite the port on the back being labeled as such. The switch controller is actually a six-port controller, and only five are used. Even though the WAN port on the router is physically separated from the other four ports, the switch controller sees it exactly the same as the rest. All five of the ethernet ports on the back are auto-sensing ports so any one has uplink capability. The polarity of the connection is tested during link or when more than three packets are received with inverted end-of-packet pulses. If any of the ports exhibit this behavior the switch controller reverses the port polarity and stores that status in a register. That port then becomes an uplink.</p>
<p>What I figured out was that if the switch ports are used for other devices, the router will eventually fail to uplink. That is, if you use it as an access point instead of a router, it&#8217;s fine. When you start using the  switch ports it gets confused. I have successfully had the router running for a while by connecting my wired devices through a switch and then uplinking just the switch to port 2, with the router then uplinking to the gateway. Evidently the router&#8217;s processor has an issue with its mapped memory.</p>
<p>I&#8217;ve now bought a Linksys E2500 wireless N router to replace this thing. You can get refurbished wifi routers at <a href="http://homestore.cisco.com/en-us/products/linksys-outlet-refurbished_stcVVcatId543906VVviewcat.htm">Cisco&#8217;s store</a> for about half price.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/981/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Netgear wireless router repair</title>
		<link>http://www.imsolidstate.com/archives/962</link>
		<comments>http://www.imsolidstate.com/archives/962#comments</comments>
		<pubDate>Tue, 28 Jun 2011 20:58:34 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[router]]></category>
		<category><![CDATA[wireless]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=962</guid>
		<description><![CDATA[My wifi internet connection has been slowly deteriorating. I originally thought it was my trusty old IBM T42 going out, but when I got my Alienware M15x it was still bad with that machine. I&#8217;ve had a few problems with this router: it sometimes refuses to allow wireless connections to access the gateway. If you [...]]]></description>
			<content:encoded><![CDATA[<p>My wifi internet connection has been slowly deteriorating. I originally thought it was my trusty old IBM T42 going out, but when I got my Alienware M15x it was still bad with that machine. I&#8217;ve had a few problems with this router: it sometimes refuses to allow wireless connections to access the gateway. If you log in to the router&#8217;s interface over wifi via it&#8217;s IP and clear the log, it will then allow wifi access to the gateway. I set up the router to automatically email the log to an email address when the log is full. That worked for most of the time, but occasionally you still have to log in and do it manually.</p>
<p>Recently though the connection speed over wifi plummeted. I was going to buy a new wireless AP, but I&#8217;m pretty cashed at the moment so I took the router apart to see if I could buy some time.</p>
<p><img class="alignnone size-large wp-image-963" title="Wifi router with heatsinks" src="http://www.imsolidstate.com/wp-content/uploads/2011/06/DSC01054-1024x768.jpg" alt="Wifi router with heatsinks" width="645" height="484" /></p>
<p>You could pretty clearly see that the microprocessor has overheated. The conformal coating is brown on the bottom side of the PCB. I used an infrared thermometer to measure the temperature of the chip, it was running at about 74°C. The ethernet switch controller IC had a similar temperature, but it&#8217;s a larger leaded package whereas the CPU looks like a BGA package. I had some memory heatsinks that I cut to fit the two chips, and with that and some thermal paste I had heatsinks for the two heaters in my router case. They are low profile enough that the case will still go on.</p>
<p>My router works like it should again: speedtest.net reports an average of 18Mbps download speed. The heatsinks keep both ICs at about 49°C now. Guess I won&#8217;t need that new AP for a while.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/962/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Alienware AlienFX repair</title>
		<link>http://www.imsolidstate.com/archives/927</link>
		<comments>http://www.imsolidstate.com/archives/927#comments</comments>
		<pubDate>Sat, 11 Jun 2011 01:42:51 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[AlienFX]]></category>
		<category><![CDATA[Alienware]]></category>
		<category><![CDATA[area 51]]></category>
		<category><![CDATA[m15x]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=927</guid>
		<description><![CDATA[So the other day I was browsing craigslist looking for a way to get rid of one of my Xbox 360s. I found a posting for an Alienware m15x laptop, which said they would be willing to trade for an Xbox. It had an issue where it would shut down if you moved the lid. [...]]]></description>
			<content:encoded><![CDATA[<p>So the other day I was browsing craigslist looking for a way to get rid of one of my Xbox 360s. I found a posting for an Alienware m15x laptop, which said they would be willing to trade for an Xbox. It had an issue where it would shut down if you moved the lid. Since it was otherwise working, had the 1920&#215;1200 LCD, T9500 CPU, 4GB RAM, Blu-ray, etc. I picked it up.<br />
I tore it down and figured out the problem: the wire bundle for the lid&#8217;s AlienFX lights was chafed bad where it goes through the hinge. It was shorting out which is why it would shut down. I carefully seperated out the melted wires and repaired the bundle with a fine-gauge hard drive cable.</p>
<p><img class="alignnone size-large wp-image-928" title="AlienFX wiring bundle repair" src="http://www.imsolidstate.com/wp-content/uploads/2011/06/IMAG0230-1024x612.jpg" alt="AlienFX wiring bundle repair" width="645" height="385" /></p>
<p><span id="more-927"></span>So this got the lights working. Unfortunately, they aren&#8217;t all that simple to work with. The earliest version of Alienware&#8217;s command center works and allows you to set the colors, fades, etc. It won&#8217;t write to the AlienFX EEPROM though, and later versions of CC can&#8217;t communicate with the AlienFX board at all (This is a pre-Dell Alienware machine, the Dell version has different hardware). The lights are controlled by this AlienFX board (which I&#8217;m guessing lives on the motherboard), which enumerates as a USB device. Once you have an OS installed, you can try and write directly to the device. I haven&#8217;t been able to get successful EEPROM writes to the device though, and since I hacked the registry on mine to get the backlit keyboard working, the colors flash somewhat randomly during boot until Windows loads and starts the AlienFX software. Then the lights resume doing whatever you set them to. Evidently it&#8217;s writing stuff to the EEPROM, but it&#8217;s just not the right stuff.  I tried using AlienFX Lite from <a href="http://forum.notebookreview.com/alienware/458528-alienfx-lite-linux-windows-alienfx-tool.html">notebookreview.com</a>, but I only get an error message that the packet was the wrong size.</p>
<p><img class="alignnone size-full wp-image-930" title="Area 51 M15x" src="http://www.imsolidstate.com/wp-content/uploads/2011/06/AWPC.gif" alt="Area 51 M15x" width="640" height="428" /></p>
<p>Since I had to add a couple registry keys and reboot to force the BIOS / AlienFX controller to recognize the keyboard, I&#8217;m guessing there is another key that I&#8217;m missing to get the board to recognize the proper programming sequence. Or maybe I need a different BIOS, but I can&#8217;t find one for this older version of the m15x. I suppose I don&#8217;t really care at this point, since the FX does what I want in Windows anyway.</p>
<p>The only thing I&#8217;d like to fix is that with CC A03 the power light flashes off briefly every time it repeats the color cycle. It gets pretty annoying looking at the screen when the power light just below it is monotonously flashing. The way I get around this is by creating a bunch of themes in A03, and then uninstalling A03 and installing A05. A05 automatically picks up the previous theme, and uses it. If you start the AlienFX editor it crashes, so if you need to edit one of your themes you have to install A03 again. You can also edit the script but it&#8217;s cumbersome.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/927/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Canon A70 CCD replacement</title>
		<link>http://www.imsolidstate.com/archives/915</link>
		<comments>http://www.imsolidstate.com/archives/915#comments</comments>
		<pubDate>Wed, 18 May 2011 16:09:21 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Cameras]]></category>
		<category><![CDATA[ccd]]></category>
		<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=915</guid>
		<description><![CDATA[I just bought a Canon A70 from eBay for about $20. This camera is pretty dated but it has a surprising set of features for a point and shoot camera. It also runs on AA batteries and not some stupid battery pack that will fail about a year after you buy it. The CCD wasn&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>I just bought a Canon A70 from eBay for about $20. This camera is pretty dated but it has a surprising set of features for a point and shoot camera. It also runs on AA batteries and not some stupid battery pack that will fail about a year after you buy it. The CCD wasn&#8217;t working when I got it though. Since I also picked up one of Canon&#8217;s awesome underwater housings for this camera (WP-DC700) I&#8217;m into the whole package for about $45. Really though it&#8217;s the underwater housing&#8217;s coolness that motivated me to fix the camera. Since a bad CCD is a common A70 problem I decided to fix it and found a refurbished CCD on eBay for eight bucks. I made a video of the replacement and embedded it at the end of this post.</p>
<p><img class="alignnone size-large wp-image-916" title="A70 CCD" src="http://www.imsolidstate.com/wp-content/uploads/2011/05/IMAG0150-1024x612.jpg" alt="A70 CCD" width="645" height="385" /></p>
<p>It turns out that the CCD wasn&#8217;t what was wrong with my camera though. Canon repaired a slew of these cameras saying that some of the CCDs they sourced were faulty. On my camera the problem was the connector on the mainboard for the CCD, not the CCD itself. The latch that locks in the CCD&#8217;s flexible circuit board was incredibly frail. <span id="more-915"></span>I figured it out by powering up the camera while I had it apart and lightly pressing on the CCD connector. I ended up fixing it with a small piece of foam. There is just enough of a gap between the flash memory housing and the CCD connector to wedge a bit of foam and keep the CCD circuit board contacts securely connected.</p>
<p><img class="alignnone size-large wp-image-917" title="A70 CCD foam fix" src="http://www.imsolidstate.com/wp-content/uploads/2011/05/IMAG0157-1024x612.jpg" alt="A70 CCD foam fix" width="645" height="385" /></p>
<p>The video embed didn&#8217;t seem to stay so here is the link to the video instead: <a href="http://youtu.be/9Znno5MhP2k">http://youtu.be/9Znno5MhP2k</a></p>
<p>Of course you can always find my videos at YouTube from my channel, imsolidstate.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/915/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Flash a monitor&#8217;s EDID with an mbed and RealTerm</title>
		<link>http://www.imsolidstate.com/archives/879</link>
		<comments>http://www.imsolidstate.com/archives/879#comments</comments>
		<pubDate>Tue, 19 Apr 2011 15:23:14 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[mbed]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=879</guid>
		<description><![CDATA[If you&#8217;ve ever setup ATI&#8217;s Eyefinity with bezel correction or connected your computer to a TV you know what this is about. Bad EDIDs can be missing supported resolutions, or report an incorrect screen size. In my case bad EDIDs prevented me from enabling bezel correction on my Eyefinity three monitor setup. This is because ATI coded [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever setup ATI&#8217;s Eyefinity with bezel correction or connected your computer to a TV you know what this is about. Bad EDIDs can be missing supported resolutions, or report an incorrect screen size. In my case bad EDIDs prevented me from enabling bezel correction on my Eyefinity three monitor setup. This is because ATI coded their Catalyst drivers to read the EDID data directly from the monitors instead of the windows registry, where bad data can be fixed more readily with an EDID_OVERRIDE key.</p>
<p><img class="alignnone size-large wp-image-882" title="DVI and mbed" src="http://www.imsolidstate.com/wp-content/uploads/2011/04/144-1024x768.jpg" alt="DVI and mbed" width="645" height="484" /></p>
<p>EDID is Extended Display Identification Data. It&#8217;s what makes your monitor &#8220;Plug and Play&#8221;. When you plug a monitor into your computer, the monitor communicates data about itself to the computer over the DDC bus, which is an I2C bus. For a DVI connection, the I2C data and clock lines are on pins 6 &amp; 7. Usually you would flash your monitor&#8217;s EDID while it&#8217;s hooked up to your PC with a program like Powerstrip, but you have to buy the registered version of powerstrip to have that functionality. Additionally, revision 3 of the EDID specification requires the EDID to be write-protected. That means to flash the EDID with Powerstrip you need to figure out the manufacturer&#8217;s sequence for temporarily unlocking the EEPROM. Something like turning the brightness and contrast to zero, then power cycling while holding the menu button, etc. I didn&#8217;t feel like messing around with that so I just took the monitor apart.<span id="more-879"></span></p>
<p>The EDID is stored on an I2C EEPROM. With a little bit of intuition you can make out where it is on the driver board. There should be an EEPROM for every input to the monitor, as each input has it&#8217;s own EDID. On mine there was an Atmel 24C02B 2k EEPROM next to the DVI connector. I used a meter to verify the clock and data pins connection to the DVI connector. From the datasheet, pin 7 is the write protect pin of the EEPROM. It is active high, so you need to desolder the pin and use a resistor to pull the pin to ground.</p>
<p><img class="alignnone size-large wp-image-883" title="Write protect disabled" src="http://www.imsolidstate.com/wp-content/uploads/2011/04/141-1024x768.jpg" alt="Write protect disabled" width="645" height="484" /></p>
<p>Now that the write protection is permanently disabled, you can write to the EDID directly over the I2C bus. To interface with the monitor, cut the end off of an old DVI cable. Use a meter to find the I2C clock and data lines. You will also want to find +5V and ground (pin 14 &amp; 15). I then connected those pins to the corresponding pins on my mbed.</p>
<p>The reason I used my mbed was because there is a pre-written mbed program (<a href="http://mbed.org/users/4180_1/notebook/i2c-debug-for-realterm/">I2C debug for RealTerm</a>) that uses the I2C GUI buttons in realterm. I use realterm exclusively as my terminal program, it&#8217;s absolutely excellent for blindly hacking a serial interface. So it was an easy choice.</p>
<p>Import the I2C debug program into the mbed editor, and then compile it and save it to the mbed. Open realterm and set it to 9600,8,N,1 on the virtual COM port your mbed uses (you may have to install the driver for this). Connect the DVI cable to the monitor (double-check your power lines first!) and reset the mbed. The mbed should tell you in realterm that it is ready and found a device at address A0 or something similar. You can now send and receive commands via the interface. Refer to the datasheet for your particular EEPROM, but all I had to do to overwrite values was write the address and the new byte value in the &#8220;write&#8221; box. My monitor needed to be corrected from 1D (290mm vertical) to 1E (300mm vertical). Remember that changing a value will require re-calculation of the checksum. If you are just changing one value, it&#8217;s easy to just add or subtract the checksum with the amount you changed the other value by. In my case I added 1 so I subtracted 1 from the checksum. If you are doing a more significant edit, just import your EDID values into excel. You can then convert the values to decimal, sum the values and perform a modulus by 256. You should get zero as the result. The checksum makes the sum of the 128 byte EDID equal to zero. If you don&#8217;t get zero then modify the checksum until you do. If your checksum is incorrect it won&#8217;t be accepted by windows, which will label it in the registry as &#8220;BAD_EDID&#8221; if I remember right. When you&#8217;re done writing the new values, write an address of 0&#215;00 and the read out 128 bytes. Verify your data. Your done!</p>
<p><img class="alignnone size-full wp-image-884" title="Realterm" src="http://www.imsolidstate.com/wp-content/uploads/2011/04/Realterm.jpg" alt="Realterm" width="619" height="626" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/879/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pressure mapping with DIY foam load cells</title>
		<link>http://www.imsolidstate.com/archives/758</link>
		<comments>http://www.imsolidstate.com/archives/758#comments</comments>
		<pubDate>Mon, 30 Aug 2010 17:54:03 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Horses]]></category>
		<category><![CDATA[ATMega]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[Horse]]></category>
		<category><![CDATA[PCB]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=758</guid>
		<description><![CDATA[I had an idea a while back to make a pressure sensing pad for testing saddle fit on horses. The intent was to create an array of pressure sensing cells, which could then be used to produce a pressure map that would represent any pinch points on a horse&#8217;s back. I found that you can buy this [...]]]></description>
			<content:encoded><![CDATA[<p>I had an idea a while back to make a pressure sensing pad for testing saddle fit on horses. The intent was to create an array of pressure sensing cells, which could then be used to produce a pressure map that would represent any pinch points on a horse&#8217;s back. I found that you can buy this sort of thing, but it&#8217;s way too expensive for the average guy. I decided to try and make my own for cheap. I ended up making one from a handful of copper-clad PCBs and 1/4&#8243; shipping foam.</p>
<p><img class="alignnone size-large wp-image-769" title="Pressure map pad and electronics" src="http://www.imsolidstate.com/wp-content/uploads/2010/08/NewStuff-014-1024x768.jpg" alt="Pressure map pad and electronics" width="645" height="484" /></p>
<p>The active area of the pad is approximately 2&#8242; x 2&#8242;. I think the foam is polyurethane open-cell foam but I&#8217;m not sure. It&#8217;s the stuff you use to pack shipping crates. The load cells are made by sandwiching the foam in between 1&#8243; circle cutouts of copper-clad FR4 PC board. I used single sided board and a hole saw with the pilot bit removed (use a drill press and a clamp). The capacitance varies as the foam compresses, and the amount of capacitance is directly related to the thickness and density of the foam, as well as the area of the copper conductors (plates). So you can create any size or thickness load cell you want really. A bigger plate results in more capacitance, as does placing the plates closer together. I estimated the capacitance I would have in my application with <a href="http://www.daycounter.com/Calculators/Plate-Capacitor-Calculator.phtml">this calculator</a> I found at Daycounter engineering services.</p>
<p>I created an array of 64 cells by making 8 rows and 8 columns, each with 8 copper-clad discs. Wherever the row/column discs align a load cell is created. An AVR typically has eight available ADC inputs along with another eight control outputs, so this way you can scan down through the rows and columns to measure each cell. A square wave is sequentially output on the columns, and after some analog proccessing the AVR&#8217;s ADC scans each row. The analog voltage present represents the amount of pressure (capacitance) at each site.<span id="more-758"></span></p>
<p><img class="size-medium wp-image-771 alignnone" title="Pressure map electronics back" src="http://www.imsolidstate.com/wp-content/uploads/2010/08/NewStuff-006-300x225.jpg" alt="Pressure map electronics back" width="300" height="225" /><img class="size-medium wp-image-772 alignnone" title="Pressure map electronics front" src="http://www.imsolidstate.com/wp-content/uploads/2010/08/NewStuff-008-300x225.jpg" alt="Pressure map electronics front" width="300" height="225" /></p>
<p>The square wave generator is the old two op-amp ramp generator/comparator circuit. This is fed to one side of the cell. The output from the other side is coupled through whatever capacitance is available at the cell, and results in a triangle wave with amplitude proportional to the capacitance thanks to a <a href="http://electronicdesign.com/article/analog-and-mixed-signal/what-s-all-this-transimpedance-amplifier-stuff-any.aspx">transimpedance amplifier</a>. Then it is fed to a peak detector and amplified. The signal is then sent to the ADC. There are more than a few examples out on the web for capacitance sensing, <a href="http://www.discovercircuits.com/DJ-Circuits/low-value-cap-meter.htm">here is a good one</a>.</p>
<p>The AVR outputs the 64 values on a serial port. I used excel&#8217;s surface chart to represent the data. The chart posted here is a map of an english saddle.</p>
<p><img class="alignnone size-full wp-image-765" title="English saddle pressure map" src="http://www.imsolidstate.com/wp-content/uploads/2010/08/EnglishMap.JPG" alt="English saddle pressure map" width="585" height="490" /></p>
<p>It works fairly well, but my analog section needs some improvement. Sensitivity is sufficient for this test, but it&#8217;s relatively poor. Response time also suffers because of noise; my prototype could definitely use improvement in that area and I had to decrease the response time of the amplifier to get consistent output. This is unfortunate because I had planned on trying to make a movie by recording real-time data while riding a horse. I even designed it to run on a 9V battery for this purpose. Maybe if I have enough free time next summer (unlikely) I&#8217;ll try and tune it up a bit.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/758/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>SMS remote control</title>
		<link>http://www.imsolidstate.com/archives/708</link>
		<comments>http://www.imsolidstate.com/archives/708#comments</comments>
		<pubDate>Sat, 17 Jul 2010 02:42:23 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[ATMega]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[PCB]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=708</guid>
		<description><![CDATA[I&#8217;ve been expirimenting with cheap GSM cell phones as remote control devices. I wanted to be able to control stuff at my house just by sending a text from my phone. I also wanted to use an AVR since the options are pretty limitless as to what you can control. I started off simple with relay [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been expirimenting with cheap GSM cell phones as remote control devices. I wanted to be able to control stuff at my house just by sending a text from my phone. I also wanted to use an AVR since the options are pretty limitless as to what you can control. I started off simple with relay outputs for stuff like the garage door, outside lights, etc. It could also be useful for the AVR to send texts based on events, but I haven&#8217;t messed with this yet.</p>
<p><img class="alignnone size-large wp-image-729" title="Cell phone and AVR" src="http://www.imsolidstate.com/wp-content/uploads/2010/07/Stuff-039-1024x768.jpg" alt="Cell phone and AVR" width="645" height="484" /></p>
<p>I planned on just having the AVR recognize a particular text string, like &#8220;open garage&#8221; if I wanted to let someone in my house when I&#8217;m not there without giving them a key for example. It&#8217;s not overly secure, but you could add a number sequence as a prefix to the command that would be like a password. Then you could periodically change your password if you wanted.<span id="more-708"></span></p>
<p>I&#8217;m using cell phones from Siemens. They are older phones with true serial comms. You can score one for $20 or so from ebay. The only thing that sucks about these phones is they use PDU mode for text messages. It&#8217;s a really inconvenient way to send text strings. There&#8217;s a ton of setup to each packet and each character is encoded in seven bits. I haven&#8217;t been able to get my code working with the PDU method yet. It gets stuck trying to decode the received message. I&#8217;m going to post it here to see if anyone has any suggestions.  I&#8217;m all self-taught in C. I&#8217;ve never tried comparing strings before, so that bit is a little cumbersome. I don&#8217;t like using the built-in libraries to do that kind of stuff until I figure out how it works. The only thing I think turned out nice in the code is the unpacking function.</p>
<p>Obviously, you&#8217;d be ahead of the game if you found a serial-interface phone that used the regular text mode instead of PDU. I couldn&#8217;t find any phones that did text mode and didn&#8217;t have a USB interface. (at least not for cheap) Programming a USB host interface is beyond my capabilities on the AVR.</p>
<p>References: <a href="http://www.developershome.com/sms/">Developer&#8217;s Home SMS Tutorial</a></p>
<pre>#include &lt;avr/io.h&gt;
#include &lt;avr/interrupt.h&gt;

#define unpack_state1 0
#define unpack_state2 1
#define unpack_state3 2
#define unpack_state4 3
#define unpack_state5 4
#define unpack_state6 5
#define unpack_state7 6
#define unpack_state8 7
#define F_CPU       8000000
#define BAUD   9600
#define MYUBRR  (F_CPU/(BAUD*(unsigned long)16))-1

void init_USART(void);
void init_timer0(void);
void turnoff_timer0(void);
void init_timer1(void);
void check_sms(void);
void decode_sms(void);
char unpack(unsigned char octet);
void USART_write(unsigned char *buf);

volatile unsigned char rcv_buf[128];
volatile unsigned char rcv_buf_idx;
volatile unsigned char check_message, check_online;

void main(void)
{
 DDRD |= 0x03;
 PORTD &amp;= ~0x03;
 DDRC |= 0x3F;
 PORTC &amp;= ~0x3F;
 DDRB |= 0x3F;
 PORTB &amp;= ~0x3F;
 init_USART();
 init_timer0();
 sei();

 while(check_online&lt;0xF7)
 {
  rcv_buf_idx= 0x00;
  USART_write("at");
  while((rcv_buf_idx&lt;0x08)&amp;(check_online&lt;0x30)) {}
  if( rcv_buf[0x05]==0x4F &amp;
   rcv_buf[0x06]==0x4B)
  {
   PORTB &amp;= ~(1&lt;&lt;PORTB0);   //diagnostic leds
   PORTB &amp;= ~(1&lt;&lt;PORTB5);   //diagnostic leds
   check_online= 0xFA;
  }
  else
  {
   if(rcv_buf_idx&lt;0x01) PORTB |= (1&lt;&lt;PORTB5);
   PORTB |= (1&lt;&lt;PORTB0);
   while(check_online&lt;0xF4){} //8s
   check_online= 0x00;
  }
 }
 turnoff_timer0();
 init_timer1();

while(1)
 {
  if(check_message) check_sms();
 }
}

ISR(USART_RX_vect)
{
 rcv_buf[rcv_buf_idx]= UDR0;
 rcv_buf_idx++;
}

ISR(TIMER0_OVF_vect)
{
 check_online++;
}

ISR(TIMER1_OVF_vect)
{
 check_message= 0x01;
}

void init_USART(void)
{
 UCSR0B |= (1&lt;&lt;RXCIE0)|(1&lt;&lt;RXEN0)|(1&lt;&lt;TXEN0);
 UCSR0C |= (1&lt;&lt;UCSZ00)|(1&lt;&lt;UCSZ01);

 UBRR0L = MYUBRR;
 UBRR0H = (MYUBRR &gt;&gt; 8);
}

void init_timer0(void)
{
 TCCR0B |= (1&lt;&lt;CS00)|(1&lt;&lt;CS02);  //clk/1024
 TIMSK0 |= (1&lt;&lt;TOIE0);
}

void turnoff_timer0(void)
{
 TCCR0B &amp;= ~((1&lt;&lt;CS00)|(1&lt;&lt;CS02));  //clk/1024
 TIMSK0 &amp;= ~(1&lt;&lt;TOIE0);
}

void init_timer1(void)
{
 TCCR1B |= (1&lt;&lt;CS10)|(1&lt;&lt;CS12);  //clk/1024
 TIMSK1 |= (1&lt;&lt;TOIE1);
}

void check_sms(void)
{
 rcv_buf_idx= 0x00;
 USART_write("at+cmgl");
 while(TCNT1&lt;0x90) {}
 if( rcv_buf[0x0A]==0x4F &amp;
  rcv_buf[0x0B]==0x4B) {PORTB &amp;= ~(1&lt;&lt;PORTB1); PORTB &amp;= ~(1&lt;&lt;PORTB5);}
 else if(rcv_buf[0x0A]=='+' &amp;
   rcv_buf[0x0B]=='C' &amp;
   rcv_buf[0x0C]=='M' &amp;
   rcv_buf[0x0D]=='G' &amp;
   rcv_buf[0x0E]=='L' &amp;
   rcv_buf[0x0F]==':') {PORTB &amp;= ~(1&lt;&lt;PORTB1); PORTB &amp;= ~(1&lt;&lt;PORTB5); decode_sms();}
 else
 {
  PORTB |= (1&lt;&lt;PORTB1);
  if(rcv_buf_idx&lt;0x01) PORTB |= (1&lt;&lt;PORTB5);
 }
 check_message= 0x00;
}

void decode_sms(void)
{
 unsigned char offset;
 while(rcv_buf_idx&lt;0x17){}
 unsigned char lenTPDU= (((rcv_buf[0x16] &amp;= ~0x30)*10) + (rcv_buf[0x17] &amp;= ~0x30));
 lenTPDU*= 2;
 while(rcv_buf_idx&lt;0x1B){}
 unsigned char lenSMSC= (((rcv_buf[0x1A] &amp;= ~0x30)*10) + (rcv_buf[0x1B] &amp;= ~0x30));
 lenSMSC*= 2;
 offset= 0x1B;
 while(rcv_buf_idx&lt;(lenSMSC+offset+lenTPDU)){}
 //ignore SMSC part
 //ignore first byte
 offset= 0x1E;
 unsigned char len_sender_number= ((rcv_buf[offset+lenSMSC] &amp;= ~0x30)*10);
 offset= 0x1F;
 if((rcv_buf[offset+lenSMSC]&gt;0x2F) &amp; (rcv_buf[offset+lenSMSC]&lt;0x3A))
  len_sender_number+= (rcv_buf[offset+lenSMSC] &amp;= ~0x30);
 else if(rcv_buf[offset+lenSMSC]=='A') len_sender_number+= 10;
 else if(rcv_buf[offset+lenSMSC]=='B') len_sender_number+= 11;
 else if(rcv_buf[offset+lenSMSC]=='C') len_sender_number+= 12;
 else if(rcv_buf[offset+lenSMSC]=='D') len_sender_number+= 13;
 else if(rcv_buf[offset+lenSMSC]=='E') len_sender_number+= 14;
 else if(rcv_buf[offset+lenSMSC]=='F') len_sender_number+= 15;
 if(len_sender_number%2) len_sender_number++;
 rcv_buf_idx= (0x1B+lenSMSC);
 unsigned char i= len_sender_number;
 while(i)
 {
  unsigned char *sender_number= rcv_buf[++rcv_buf_idx];
  sender_number++;
  *sender_number= rcv_buf[--rcv_buf_idx];
  sender_number++;
  rcv_buf_idx += 0x02;
  i-= 0x02;
 }
 offset= 0x35;
 unsigned char num_septets= ((rcv_buf[offset+lenSMSC+len_sender_number] &amp;= ~0x30)*10);
 offset= 0x36;
 if((rcv_buf[offset+lenSMSC+len_sender_number]&gt;0x2F) &amp; (rcv_buf[offset+lenSMSC+len_sender_number]&lt;0x3A))
  num_septets+= (rcv_buf[offset+lenSMSC+len_sender_number] &amp;= ~0x30);
 else if(rcv_buf[offset+lenSMSC+len_sender_number]=='A') num_septets+= 10;
 else if(rcv_buf[offset+lenSMSC+len_sender_number]=='B') num_septets+= 11;
 else if(rcv_buf[offset+lenSMSC+len_sender_number]=='C') num_septets+= 12;
 else if(rcv_buf[offset+lenSMSC+len_sender_number]=='D') num_septets+= 13;
 else if(rcv_buf[offset+lenSMSC+len_sender_number]=='E') num_septets+= 14;
 else if(rcv_buf[offset+lenSMSC+len_sender_number]=='F') num_septets+= 15;
 offset= 0x37;
 rcv_buf_idx= (offset+lenSMSC+len_sender_number);
 unsigned char loop= 0;
 unsigned char message[16];
 unsigned char message_idx= 0x00;
 offset= 0x1C;
 while(rcv_buf_idx&lt;=(offset+lenTPDU+lenSMSC))
 {
  unsigned char octet= 0;
  if(rcv_buf[rcv_buf_idx]=='A') octet |= 0xA0;
  else if(rcv_buf[rcv_buf_idx]=='B') octet |= 0xB0;
  else if(rcv_buf[rcv_buf_idx]=='C') octet |= 0xC0;
  else if(rcv_buf[rcv_buf_idx]=='D') octet |= 0xD0;
  else if(rcv_buf[rcv_buf_idx]=='E') octet |= 0xE0;
  else if(rcv_buf[rcv_buf_idx]=='F') octet |= 0xF0;
  else octet= ((rcv_buf[rcv_buf_idx] &amp;= ~0x30)*10);
  rcv_buf_idx++;
  if(rcv_buf[rcv_buf_idx]=='A') octet |= 0x0A;
  else if(rcv_buf[rcv_buf_idx]=='B') octet |= 0x0B;
  else if(rcv_buf[rcv_buf_idx]=='C') octet |= 0x0C;
  else if(rcv_buf[rcv_buf_idx]=='D') octet |= 0x0D;
  else if(rcv_buf[rcv_buf_idx]=='E') octet |= 0x0E;
  else if(rcv_buf[rcv_buf_idx]=='F') octet |= 0x0F;
  else octet+= (rcv_buf[rcv_buf_idx] &amp;= ~0x30);
  rcv_buf_idx++;
  message[message_idx]= unpack(octet);
  message_idx++;
  if(++loop==7)
  {
   message[message_idx]= unpack(0x00);
   message_idx++;
   loop=0;
  }
 }
 if( message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='1' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='n') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC |= (1&lt;&lt;PORTC0);}
 else if(message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='1' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='f' &amp;
  message[0x0A]=='f') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC &amp;= ~(1&lt;&lt;PORTC0);}
 else if(message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='2' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='n') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC |= (1&lt;&lt;PORTC1);}
 else if(message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='2' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='f' &amp;
  message[0x0A]=='f') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC &amp;= ~(1&lt;&lt;PORTC1);}
 else if(message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='3' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='n') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC |= (1&lt;&lt;PORTC2);}
 else if(message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='3' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='f' &amp;
  message[0x0A]=='f') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC &amp;= ~(1&lt;&lt;PORTC2);}
 else if(message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='4' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='n') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC |= (1&lt;&lt;PORTC3);}
 else if(message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='4' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='f' &amp;
  message[0x0A]=='f') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC &amp;= ~(1&lt;&lt;PORTC3);}
 else if(message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='5' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='n') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC |= (1&lt;&lt;PORTC4);}
 else if(message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='5' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='f' &amp;
  message[0x0A]=='f') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC &amp;= ~(1&lt;&lt;PORTC4);}
 else if(message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='6' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='n') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC |= (1&lt;&lt;PORTC5);}
 else if(message[0x00]=='r' &amp;
  message[0x01]=='e' &amp;
  message[0x02]=='l' &amp;
  message[0x03]=='a' &amp;
  message[0x04]=='y' &amp;
  message[0x05]==' ' &amp;
  message[0x06]=='6' &amp;
  message[0x07]==' ' &amp;
  message[0x08]=='o' &amp;
  message[0x09]=='f' &amp;
  message[0x0A]=='f') {PORTB &amp;= ~(1&lt;&lt;PORTB2); PORTC &amp;= ~(1&lt;&lt;PORTC5);}
 else PORTB |= (1&lt;&lt;PORTB2);
}

char unpack(unsigned char octet)
{
 static unsigned char unpack_state, remain_val;
 unsigned char septet, masked_val;

 switch(unpack_state)
 {
  case unpack_state1:
   septet= (octet &amp; 0x7F);
   remain_val= (octet &amp; 0x80);
   unpack_state= unpack_state2;
   break;
  case unpack_state2:
   masked_val= (octet &amp; 0x3F);
   septet= (masked_val&lt;&lt;1) | (remain_val&gt;&gt;7);
   remain_val= (octet &amp; 0xC0);
   unpack_state= unpack_state3;
   break;
  case unpack_state3:
   masked_val= (octet &amp; 0x1F);
   septet= (masked_val&lt;&lt;2) | (remain_val&gt;&gt;6);
   remain_val= (octet &amp; 0xE0);
   unpack_state= unpack_state4;
   break;
  case unpack_state4:
   masked_val= (octet &amp; 0x0F);
   septet= (masked_val&lt;&lt;3) | (remain_val&gt;&gt;5);
   remain_val= (octet &amp; 0xF0);
   unpack_state= unpack_state5;
   break;
  case unpack_state5:
   masked_val= (octet &amp; 0x07);
   septet= (masked_val&lt;&lt;4) | (remain_val&gt;&gt;4);
   remain_val= (octet &amp; 0xF8);
   unpack_state= unpack_state6;
   break;
  case unpack_state6:
   masked_val= (octet &amp; 0x03);
   septet= (masked_val&lt;&lt;5) | (remain_val&gt;&gt;3);
   remain_val= (octet &amp; 0xFC);
   unpack_state= unpack_state7;
   break;
  case unpack_state7:
   masked_val= (octet &amp; 0x01);
   septet= (masked_val&lt;&lt;6) | (remain_val&gt;&gt;2);
   remain_val= (octet &amp; 0xFE);
   unpack_state= unpack_state8;
   break;
  case unpack_state8:
   septet= (remain_val&gt;&gt;1);
   unpack_state= unpack_state1;
   break;
 }
 return septet;
}

void USART_write(unsigned char *buf)
{
 while(*buf)
    {
       while ( !( UCSR0A &amp; (1&lt;&lt;UDRE0)) ){}
       UDR0= *buf;
       buf++;
    }
 while ( !( UCSR0A &amp; (1&lt;&lt;UDRE0)) ){}
 UDR0= 0x0D;
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/708/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Flatbed scanner panoramic camera</title>
		<link>http://www.imsolidstate.com/archives/712</link>
		<comments>http://www.imsolidstate.com/archives/712#comments</comments>
		<pubDate>Sat, 17 Jul 2010 02:25:42 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Cameras]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Photography]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=712</guid>
		<description><![CDATA[I&#8217;ve always loved panoramic pictures, especially when they&#8217;re printed up big. I&#8217;m not new to panoramics, as I&#8217;ve done quite a few stitched sequences, as well as true panoramic film photography. A while back I was wondering if I could repurpose the scanning head part of a scanner into a rotating head panoramic camera. After [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve always loved panoramic pictures, especially when they&#8217;re printed up big. I&#8217;m not new to panoramics, as I&#8217;ve done quite a few <a href="http://www.imsolidstate.com/about/my-photography">stitched sequences</a>, as well as <a href="http://www.imsolidstate.com/archives/85">true panoramic film photography</a>. A while back I was wondering if I could repurpose the scanning head part of a scanner into a rotating head panoramic camera. After an initial trial with mediocre results, I did some digging and found out that people have made these before. There&#8217;s quite a few issues though: fitting a new lens, an IR filter, the proper speed rotating part, etc. An added difficulty with flatbed scanners is the scanning head scans over a white strip before every scan to calibrate the sensor, so if you don&#8217;t have something white for the scan head to look at right at the beginning of the scan, you get some really goofy color stripes. Sheet feed scanners aren&#8217;t supposed to do this, so I tried one of those but quickly tired of fooling all of the little switches. It always thinks there&#8217;s a paper jam.</p>
<p><img class="alignnone size-large wp-image-727" title="Line scanner" src="http://www.imsolidstate.com/wp-content/uploads/2010/07/Stuff-037-1024x768.jpg" alt="Line scanner" width="645" height="484" /></p>
<p>The scan head sensor is actually pretty cool, and by definition it&#8217;s a line scan camera. It would still be cool to set it up as a line scan camera to play with.</p>
<p>After seeing <a href="http://hackaday.com/2010/07/14/panoramic-and-spheric-tripod-rig/">this rig </a>at HAD, I&#8217;m convinced I&#8217;m wasting my time. Moving forward I will be designing a stepper-driven tripod mount for my camera and use stitching software instead. If anybody has any suggestions on good software to try let me know. I&#8217;ve been using Panorama Maker or whatever the Nikon bundled program was called. It just doesn&#8217;t always do a very good job, even with the special mount I made that&#8217;s supposed to <a href="http://reallyrightstuff.com/pano/03.html">eliminate parallax</a>. I get a lot of blurring at the upper and lower edge stitches. I would also like to experiment with multi-row so I can use longer lenses.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/712/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

