<?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; Automation</title>
	<atom:link href="http://www.imsolidstate.com/archives/category/automation/feed" rel="self" type="application/rss+xml" />
	<link>http://www.imsolidstate.com</link>
	<description>Always improving things...</description>
	<lastBuildDate>Mon, 30 Aug 2010 17:54:03 +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>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[Automation]]></category>
		<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>5</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[Automation]]></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>
		<item>
		<title>DIY Router table</title>
		<link>http://www.imsolidstate.com/archives/716</link>
		<comments>http://www.imsolidstate.com/archives/716#comments</comments>
		<pubDate>Sat, 17 Jul 2010 02:24:42 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[DIY]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=716</guid>
		<description><![CDATA[I made my own router table because, as usual, what is affordable and available in stores is lame and insufficient for my needs. I don&#8217;t really want to spend something like $500 just for a good router table so I made one. I also made my own adapter instead of buying one by re-purposing the [...]]]></description>
			<content:encoded><![CDATA[<p>I made my own router table because, as usual, what is affordable and available in stores is lame and insufficient for my needs. I don&#8217;t really want to spend something like $500 just for a good router table so I made one. I also made my own adapter instead of buying one by re-purposing the fixed base I already had.</p>
<p><img class="alignnone size-large wp-image-721" title="Router Table" src="http://www.imsolidstate.com/wp-content/uploads/2010/07/Horses-013-1024x768.jpg" alt="Router Table" width="645" height="484" /><span id="more-716"></span></p>
<p>I made the base out of 2&#215;4s and Simpson strong-ties. The <a href="http://www.lowes.com/pd_96060-72913-RTC24_4294929087_?productId=3047954&amp;Ntt=strong+ties&amp;Ntk=i_products&amp;pl=1&amp;currentURL=/pl_Angles%2BClips%2Band%2BStraps_4294929087__s?Ntk=i_products$rpp=15$No=30$Ntt=strong ties">corner ties</a> are about $5 a piece or you can use two cheaper &#8221;<a href="http://www.lowes.com/pd_96037-72913-RTA2Z_4294929087_?productId=3047951&amp;Ntt=strong+ties&amp;Ntk=i_products&amp;pl=1&amp;currentURL=/pl_Angles%2BClips%2Band%2BStraps_4294929087__s?Ntk=i_products$rpp=15$No=15$Ntt=strong ties">Z-MAX</a>&#8221; connectors. The top is 3/4 MDF. You can buy adapter plates for various router brands, or just make one like I did from 1/4&#8243; acrylic that replaced the acrylic bottom piece of my fixed-base router. Use your router to cut a hole in the MDF and then use a rabbeting bit to create the countersunk part the acrylic base fits in.  Remember to seal the MDF top with a clear sealer or something similar so the MDF doesn&#8217;t expand.</p>
<p><img class="alignnone size-large wp-image-722" title="Router base replacement" src="http://www.imsolidstate.com/wp-content/uploads/2010/07/Horses-014-1024x768.jpg" alt="Router Mount" width="645" height="484" /></p>
<p>It works great, it&#8217;s way better than the $99 hardware store special, and I can use it for workspace in my shop instead of taking it up like a bench-top router table would. When I&#8217;m not using it I just lower the router and I have another table to work on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/716/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Electronic choke</title>
		<link>http://www.imsolidstate.com/archives/222</link>
		<comments>http://www.imsolidstate.com/archives/222#comments</comments>
		<pubDate>Tue, 25 Aug 2009 23:57:17 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Choke]]></category>
		<category><![CDATA[Servo]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=222</guid>
		<description><![CDATA[When I had carbureted vehicles, I always hated the choke spring. They never worked right, no matter how much you twiddled with them. They either never pulled all the way off or never closed enough to start on that really cold day when it&#8217;s so much fun to adjust chokes.
I thought the design could use [...]]]></description>
			<content:encoded><![CDATA[<p>When I had carbureted vehicles, I always hated the choke spring. They never worked right, no matter how much you twiddled with them. They either never pulled all the way off or never closed enough to start on that really cold day when it&#8217;s so much fun to adjust chokes.<br />
I thought the design could use some modernization, so I designed a true electric choke. Or maybe electronic choke is more accurate, because &#8220;electric choke&#8221; just means a heater mounted to the bi-metallic spring.</p>
<p><img class="alignnone size-large wp-image-223" title="Electronic choke prototype, a rusted-up old DualJet" src="http://www.imsolidstate.com/wp-content/uploads/2009/08/Default-003-1024x682.jpg" alt="Default 003" width="645" height="429" /></p>
<p>I used a servo to command a certain choke position, and I designed a simple spring mechanism so that the servo wouldn&#8217;t burn itself up trying to get to a position when the throttle was closed and the position of the fast idle cam can&#8217;t be adjusted. I didn&#8217;t have my CNC machine running at the time or I would have made a housing and ordered a smaller servo so that it all had about the same appearance of an electric choke, except for an extra wire. That extra wire would go to a temperature sensor in the coolant circuit.</p>
<p>I would have also added a dip switch for making adjustments to choke pull off points based on engine temperature. If I ever have another carbureted vehicle I might finish it.</p>
<p><img class="alignnone size-large wp-image-224" title="Servo and spring mechanism" src="http://www.imsolidstate.com/wp-content/uploads/2009/08/Default-006-1024x682.jpg" alt="Default 006" width="645" height="429" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/222/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Piezo pump</title>
		<link>http://www.imsolidstate.com/archives/30</link>
		<comments>http://www.imsolidstate.com/archives/30#comments</comments>
		<pubDate>Tue, 25 Aug 2009 17:16:55 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[AdaptivEnergy]]></category>
		<category><![CDATA[Piezo]]></category>
		<category><![CDATA[Pump]]></category>
		<category><![CDATA[Solidworks]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=30</guid>
		<description><![CDATA[Some time ago I designed a piezo pump to demonstrate a concept for an extremely low flow liquid slurry pumping application. The pump was based around AdaptivEnergy&#8217;s Ruggedized Laminated Piezo actuator, or RLP-125. AdaptivEnergy also manufactures the Joule-Thief, which is also based on piezo technology. The actuator was driven by the company&#8217;s proprietary electronics that [...]]]></description>
			<content:encoded><![CDATA[<p>Some time ago I designed a piezo pump to demonstrate a concept for an extremely low flow liquid slurry pumping application. The pump was based around <a href="http://www.adaptivenergy.com/">AdaptivEnergy&#8217;s</a> Ruggedized Laminated Piezo actuator, or RLP-125. AdaptivEnergy also manufactures the <a href="http://www.adaptivenergy.com/docs/DataSheet_Random_20090408_Rev4_pp1.pdf">Joule-Thief</a>, which is also based on piezo technology. The actuator was driven by the company&#8217;s proprietary electronics that they call the Energy Key. I used umbrella valves from <a href="http://www.vernay.com/">Vernay</a> that allow the pump to build pressure and move fluid.</p>
<p>The pump works very well for extremely low flow liquid and slurry applications. The wetted parts of the actuator are 300 series stainless steel, and the valves  and housing can be made of a number of materials for resistance to many fluids. This pump design is a great selection particularly if you are moving an abrasive slurry, as there are less contact wear surfaces like in a more conventional pump.</p>
<p>Perhaps the most interesting thing about this pump is that both the frequency and displacement of the element can be varied. This allows the pump to operate at different resonant frequencies for different fluids, and still accurately control flow. </p>
<p>Here is a 3D section view of the model that I made in Solidworks.</p>
<p><img class="alignnone size-large wp-image-31" title="piezo pump assembly" src="http://www.imsolidstate.com/wp-content/uploads/2009/08/piezo-pump-assembly-1024x655.jpg" alt="piezo pump assembly" width="614" height="393" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/30/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Textile needle loom</title>
		<link>http://www.imsolidstate.com/archives/93</link>
		<comments>http://www.imsolidstate.com/archives/93#comments</comments>
		<pubDate>Mon, 24 Aug 2009 18:06:40 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Automation]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=93</guid>
		<description><![CDATA[Probably the most complicated piece of equipment I&#8217;ve designed and built to date would have to be a textile needle loom for Goodrich. This machine is fully instrumented with position sensors, accelerometers, load cells, etc. for characterization of a textile needling process. Every parameter from speed and feed to force and distance is adjustable real time. This [...]]]></description>
			<content:encoded><![CDATA[<p>Probably the most complicated piece of equipment I&#8217;ve designed and built to date would have to be a textile needle loom for Goodrich. This machine is fully instrumented with position sensors, accelerometers, load cells, etc. for characterization of a textile needling process. Every parameter from speed and feed to force and distance is adjustable real time. This was definitely the most challenging mechanical design I have completed. I modeled the entire project in Solidworks to verify the design, and had over one hundred custom parts machined.</p>
<p><img class="alignnone size-large wp-image-128" title="IMAG0126" src="http://www.imsolidstate.com/wp-content/uploads/2009/08/IMAG0126-1024x768.jpg" alt="IMAG0126" width="645" height="484" /></p>
<p><img class="alignnone size-large wp-image-129" title="IMAG0160" src="http://www.imsolidstate.com/wp-content/uploads/2009/08/IMAG0160-1024x768.jpg" alt="IMAG0160" width="645" height="484" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/93/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cascade process heater</title>
		<link>http://www.imsolidstate.com/archives/81</link>
		<comments>http://www.imsolidstate.com/archives/81#comments</comments>
		<pubDate>Mon, 24 Aug 2009 18:03:17 +0000</pubDate>
		<dc:creator>imsolidstate</dc:creator>
				<category><![CDATA[Automation]]></category>

		<guid isPermaLink="false">http://www.imsolidstate.com/?p=81</guid>
		<description><![CDATA[One of the first big projects I completed was a machine that supplied a variable heated flow of gas to a process. The temperature and flow of the process gas was controlled to a setpoint with PID loops, and the machine could switch between one of two different gases required by the process both manually [...]]]></description>
			<content:encoded><![CDATA[<p>One of the first big projects I completed was a machine that supplied a variable heated flow of gas to a process. The temperature and flow of the process gas was controlled to a setpoint with PID loops, and the machine could switch between one of two different gases required by the process both manually or automatically. The process required the flow of gas to be switched automatically at a certain temperature, and had to recognize the change in temperature at any one of twelve thermocouples.</p>
<p>An immersion heater placed inside of a tube was used to heat the flow of gas. A frame was constructed around the heater to support it, and an electrical enclosure was mounted to the frame. The frame was mounted on wheels so that it could be removed when not needed, and full-flow quick disconnects were used for the gas lines.</p>
<p><img class="alignnone size-large wp-image-126" title="IMG00062" src="http://www.imsolidstate.com/wp-content/uploads/2009/08/IMG00062-1024x819.jpg" alt="IMG00062" width="645" height="516" /></p>
<p>This project was also my introduction to AutoCAD. I designed the whole thing in AutoCAD, including assembly prints and prints for the machine shop. Since then I&#8217;ve been using Solidworks, and I&#8217;ve never looked back. Solidworks makes designing and maintaining a design so much easier.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imsolidstate.com/archives/81/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
