<?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#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Robotics / Electronics / Physical Computing</title>
	<atom:link href="https://trandi.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://trandi.wordpress.com</link>
	<description></description>
	<lastBuildDate>Sun, 29 Jan 2012 12:38:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='trandi.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>https://secure.gravatar.com/blavatar/83658ee95909890c4fe9b0f15874a8be?s=96&#038;d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Fbuttonw-com.png</url>
		<title>Robotics / Electronics / Physical Computing</title>
		<link>https://trandi.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="https://trandi.wordpress.com/osd.xml" title="Robotics / Electronics / Physical Computing" />
	<atom:link rel='hub' href='https://trandi.wordpress.com/?pushpress=hub'/>
		<item>
		<title>SPOKA Night Light controlled from and Android Phone</title>
		<link>https://trandi.wordpress.com/2012/01/13/spoka-night-light-controlled-from-and-android-phone/</link>
		<comments>https://trandi.wordpress.com/2012/01/13/spoka-night-light-controlled-from-and-android-phone/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 23:45:48 +0000</pubDate>
		<dc:creator>trandi</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[attiny2313]]></category>
		<category><![CDATA[bluetooth]]></category>
		<category><![CDATA[ikea]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[night light]]></category>
		<category><![CDATA[pwm]]></category>
		<category><![CDATA[serial]]></category>
		<category><![CDATA[serial port profile]]></category>
		<category><![CDATA[spoka]]></category>
		<category><![CDATA[SPP]]></category>

		<guid isPermaLink="false">http://trandi.wordpress.com/?p=928</guid>
		<description><![CDATA[You people must have been wondering &#8220;what the heck was going on&#8221; and why haven&#8217;t I posted anything for the last 3 months or so&#8230; keep reading and you&#8217;ll find out more ! Some of you must have already seen something like this: It&#8217;s an Ikea Spoka night light and my wife really loves them&#8230; [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=928&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>You people must have been wondering &#8220;what the heck was going on&#8221; and why haven&#8217;t I posted anything for the last 3 months or so&#8230; keep reading and you&#8217;ll find out more !</p>
<span style="text-align:center; display: block;"><a href="https://trandi.wordpress.com/2012/01/13/spoka-night-light-controlled-from-and-android-phone/"><img src="http://img.youtube.com/vi/C9aHQkkmqHI/2.jpg" alt="" /></a></span>
<p><span id="more-928"></span></p>
<p>Some of you must have already seen something like this:</p>
<div id="attachment_946" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/spoka-night-light__0097669_pe238441_s4.jpg"><img class="size-medium wp-image-946" title="spoka-night-light__0097669_PE238441_S4" src="http://trandi.files.wordpress.com/2012/01/spoka-night-light__0097669_pe238441_s4.jpg?w=300&#038;h=300" alt="" width="300" height="300" /></a><p class="wp-caption-text">Ikea Spoka Night Light</p></div>
<p>It&#8217;s an Ikea <a href="http://www.ikea.com/gb/en/catalog/products/40150993/" target="_blank">Spoka night light</a> and my wife really loves them&#8230; to the point that a while back she bought several of them, &#8220;just in case&#8221;&#8230;</p>
<p>We obviously only use one, so I&#8217;ve gotten her permission a few months ago to open another one up and play with it.</p>
<p>This project started actually back at the beginning of October 2011, but after doing the hardest part of it (reverse engineering the simple circuit) I had to abandon it in favour of the Stanford Artificial Intelligence and Machine Learning courses, which took most of my week-ends !</p>
<p>Then my son was born at the end of November, and here I am, more than 3 months later, having decided that I need to do whatever it takes to finish the project and post it.</p>
<p>I&#8217;m trying to do this while waiting for some special &#8220;mega servos&#8221; that I plan to use to automate my baby&#8217;s bouncer (those of you that have babies, know how important it is to rock them while they try to fall asleep, and what is the phonic price to be paid if not careful&#8230; <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).</p>
<p>So here we go&#8230;</p>
<p>Originally, the lamp has 2 modes, that you can select with a switch at the top (which can also turn it off):</p>
<ol>
<li>slowly change between the 3 available colours (blue, red and orange) while dimming the intensity</li>
<li>keep the same colour and intensity</li>
</ol>
<p>The &#8220;obvious&#8221; hack would be to be able to customize the patterns of light that it can display. Another one would be to make it able to synchronize to some random music.</p>
<p>However it occurred to me that both this &#8220;mods&#8221; and plenty of others could be easily achieved by making the lamp controllable remotely, and then &#8220;simply&#8221; sending whatever pattern we want from the controlling device. This way we offload the logic to some more powerful device.</p>
<p>It could also lead to having more than 1 lamp synchronised, but this would be for another project&#8230;</p>
<p>The first idea was to use <a href="http://trandi.wordpress.com/2011/10/24/simple-serial-transceiver/" target="_blank">these</a> 2 simple wireless transceivers and control the Spoka from my PC.</p>
<p>Then it dawned on me that it would be much nicer to control it from my phone, and what better choice than the <a href="http://www.sparkfun.com/products/10748" target="_blank">IOIO</a> to interface Android with the serial transceiver&#8230; ?</p>
<p>And then, I can&#8217;t remember how, I found <a href="http://www.goodluckbuy.com/serial-bluetooth-rf-transceiver-module-rs232.html" target="_blank">these ultra cheap serial bluetooth transceivers</a>&#8230; There are plenty of them on various sites (I got mine from ebay for 5£) and they all seem more or less the same&#8230;</p>
<p>Not only it&#8217;s much cheaper than a IOIO + the RF transceivers, but it&#8217;s also quite small and especially, it doesn&#8217;t  require anything to be wired to the phone (since then the IOIO also supports bluetooth, but then it would mean to integrate one in the Spoka which is not an option&#8230;).</p>
<p>However, as you&#8217;ll see later in this post (and as Ytai told me from the beginning <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ), this advantages come at a price, as the module seems more fiddly and there&#8217;s hardly any documentation out there !</p>
<p>Anyhow, the thought of having this little thing integrated in the Spoka and then being able to remotely control it from my phone, felt worth the effort !</p>
<h2>1. Reverse engineer the light</h2>
<div id="attachment_948" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2011-10-01_spokainitial.jpg"><img class="size-medium wp-image-948" title="2011.10.01_SpokaInitial" src="http://trandi.files.wordpress.com/2012/01/2011-10-01_spokainitial.jpg?w=300&#038;h=296" alt="" width="300" height="296" /></a><p class="wp-caption-text">Original Circuits</p></div>
<p>Thank you Ikea for having easily hackable, through hole boards !</p>
<div id="attachment_947" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2011-09-28_spoka_reverseengineer_schema.jpg"><img class="size-medium wp-image-947" title="2011.09.28_Spoka_ReverseEngineer_Schema" src="http://trandi.files.wordpress.com/2012/01/2011-09-28_spoka_reverseengineer_schema.jpg?w=300&#038;h=234" alt="" width="300" height="234" /></a><p class="wp-caption-text">Spoka Schema</p></div>
<h2>2. Replace the IC with a custom one</h2>
<p>The original IC was a 8 pin one and I would have really liked to be able to just &#8220;drop&#8221; in my own ATtiny45 or 85. This however proved impossible due to a different pin layout.</p>
<div id="attachment_950" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2011-10-01_spoka_originalmcuremoved.jpg"><img class="size-medium wp-image-950" title="2011.10.01_Spoka_OriginalMCURemoved" src="http://trandi.files.wordpress.com/2012/01/2011-10-01_spoka_originalmcuremoved.jpg?w=300&#038;h=184" alt="" width="300" height="184" /></a><p class="wp-caption-text">Original MCU removed, wires soldered</p></div>
<p>There was also the need for serial communication with the bluetooth module and 3 independent PWM for the 3 colours. While I&#8217;m sure an experienced AVR engineer could fit all this on an ATtiny 45, the thought of implementing software serial and struggle with the conflicts with the PWM timers,  didn&#8217;t sound good and hence I opted for a 20pin ATtiny2313 that I had lying around and that provides hardware serial.</p>
<div id="attachment_951" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2011-10-02_spokaconnectedtoattiny2313.jpg"><img class="size-medium wp-image-951" title="2011.10.02_SpokaConnectedToATtiny2313" src="http://trandi.files.wordpress.com/2012/01/2011-10-02_spokaconnectedtoattiny2313.jpg?w=300&#038;h=163" alt="" width="300" height="163" /></a><p class="wp-caption-text">ATtiny2313 in place</p></div>
<div id="attachment_953" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2011-10-02_spokaconnectedtoattiny2313_2.jpg"><img class="size-medium wp-image-953" title="2011.10.02_SpokaConnectedToATtiny2313_2" src="http://trandi.files.wordpress.com/2012/01/2011-10-02_spokaconnectedtoattiny2313_2.jpg?w=300&#038;h=178" alt="" width="300" height="178" /></a><p class="wp-caption-text">ATtiny2313 in place 2</p></div>
<p>The job of the new MCU will be quite simple:</p>
<ul>
<li>wait for incoming serial data containing the intensity of each colour (and a checksum)</li>
<li>provide some acknowledgement on the serial line</li>
<li>update the PWM values accordingly</li>
</ul>
<p>And here&#8217;s the C code.</p>
<p>Notice that I have actually implemented 2 modes:</p>
<ol>
<li>if the first character is a &#8216;#&#8217; then you simply provide the intensity for each colour</li>
<li>if the first character is a &#8216;*&#8217; then you provide a delay only, and the MCU does the transitioning from one colour to the other (similarly to what the original setup was doing, but with the extra feature of being able to change the speed of transition)</li>
</ol>
<p><pre class="brush: cpp; collapse: true; light: false; toolbar: true;">
/*
 * uart.h
 *
 * Created: 09/10/2011 Author: trandi
 */

#ifndef UART_H_
#define UART_H_

//BRR = (F_CPU / 16 / BaudRate ) - 1
#define BAUD_RATE_38400 (F_CPU / 16 / 38400 ) - 1
#define BAUD_RATE_4800 (F_CPU / 16 / 4800 ) - 1
#define BAUD_RATE_2400 (F_CPU / 16 / 2400 ) - 1

void uart_init(unsigned char baudrate);
uint8_t uart_isCharAvailable();
unsigned char uart_getChar();
void uart_putChar(unsigned char data);
void uart_putStr(const char* str);
//void uart_putw_dec(uint16_t w);

#endif /* UART_H_ */

/*
 * uart.c
 *
 * Created: 02/10/2011 Author: trandi
 */

#include &lt;avr/io.h&gt;
#include &lt;util/delay.h&gt;

void uart_init(unsigned char baudrate) {
 UBRRL = baudrate; // Set the baud rate

 UCSRB = _BV(RXEN) | _BV(TXEN); // Enable UART receiver and transmitter
 UCSRC = _BV(UCSZ1) | _BV(UCSZ0); // set to 8 data bits, 1 stop bit

 DDRD |= _BV(PD1); // TZ is output
 DDRD &amp;= ~_BV(PD0); // RX is input
}

uint8_t uart_isCharAvailable() {
 return (UCSRA &amp; _BV(RXC));
}

unsigned char uart_getChar() {
 while(! uart_isCharAvailable()) _delay_ms(10);
 char result = UDR;
 //useful echo
 uart_putChar(result);
 return result;
}

void uart_putChar(unsigned char data){
 /* Wait for empty transmit buffer */
 while (!(UCSRA &amp; _BV(UDRE)));

/* Start transmission */
 UDR = data;
}

void uart_putStr(const char* str) {
 while(*str){
 uart_putChar(*str++);
 }
}

/*
void uart_putw_dec(uint16_t w) {
 uint16_t num = 10000;
 uint8_t started = 0;

while(num &gt; 0){
 uint8_t b = w / num;
 if(b &gt; 0 || started || num == 1){
   uart_putChar('0' + b);
   started = 1;
 }
 w -= b * num;

num /= 10;
 }
}*/

/*
 * SpokaLight.cpp
 *
 * Created: 01/10/2011 Author: trandi
 */

#define F_CPU 8000000UL
#include &lt;avr/io.h&gt;
#include &lt;util/delay.h&gt;
#include &quot;uart.h&quot;

#define PWM1 OCR0A //PB2
#define PWM2 OCR1B //PB3
#define PWM3 OCR1A //PB4
#define BLUE 0
#define RED 1
#define ORANGE 2
#define BUTTON_PORT PORTB // PORTx - register for button output
#define BUTTON_PIN PINB // PINx - register for button input
#define BUTTON_BIT PB1 // bit for button input/output

/*
n = (f / prescaler) * t Where n is the the number of timer ticks (as written in ICR1, OCR1A, OCR1B above).
f is the frequency you run the AVR at.
t is the wanted time.
You can compute this with f in Hz and t in seconds or often better with f in MHz and t in microseconds.
Notice for an 8MHz AVR with /8 prescaler this becomes
n = 8/8*t -&gt; n = t
*/
void init_pwm(){
// OC1A, OC1B, OC0A outputs
 DDRB |= (1&lt;&lt;PB4)|(1&lt;&lt;PB3)|(1&lt;&lt;PB2);
 // TIMER 0
 // Fast PWM mode 3, Clear on compare, clear at TOP
 // TOP set for 255
 TCCR0A = (1&lt;&lt;COM0A0)|(1&lt;&lt;COM0A1)|(1&lt;&lt;WGM01)|(1&lt;&lt;WGM00);
 TCCR0B = (1&lt;&lt;CS00);

// TIMER 1
 // TOP, set for 255Hz
 ICR1 = 255;
 // Fast PWM mode 14, Clear on compare, clear at TOP
 TCCR1A = (1&lt;&lt;COM1A0)|(1&lt;&lt;COM1A1)|(1&lt;&lt;COM1B0)|(1&lt;&lt;COM1B1)|(1&lt;&lt;WGM11);
 TCCR1B = (1&lt;&lt;WGM13)|(1&lt;&lt;WGM12)|(1&lt;&lt;CS10);
}

void set_pwm(uint8_t colour, uint8_t value){
 uint8_t mapped_value = 255 - value;
 if(colour == BLUE) PWM3 = mapped_value;
 else if(colour == RED) PWM1 = mapped_value;
 else if(colour == ORANGE) PWM2 = mapped_value;
}

uint8_t button_is_pressed() {
 // the button is pressed when BUTTON_BIT is clear
 if (bit_is_clear(BUTTON_PIN, BUTTON_BIT)) {
   _delay_ms(25); // debounce time
   if (bit_is_clear(BUTTON_PIN, BUTTON_BIT)) {
   // wait for it to unclear before releasing... !
   while(bit_is_clear(BUTTON_PIN, BUTTON_BIT)) _delay_ms(10);
   return 1;
   }
 }

return 0;
}

// mode 0 - off / 1 - static colours / 2 - dynamic colours
volatile uint8_t _mode = 1;
volatile uint8_t _blue = 50, _red = 50, _orange = 50;
volatile uint8_t _currCol = BLUE, _currVal = 1, _dirUp = 1;
volatile uint16_t _interval = 30, _count = 0;

void update_status(){
 if(_mode == 0 ){
 set_pwm(BLUE, 0);
 set_pwm(RED, 0);
 set_pwm(ORANGE, 0);
 }else if(_mode == 1){
 set_pwm(BLUE, _blue);
 set_pwm(RED, _red);
 set_pwm(ORANGE, _orange);
 }else if(_mode == 2){
 set_pwm(BLUE, 0);
 set_pwm(RED, 0);
 set_pwm(ORANGE, 0);
 }
}

void update_dynamics(){
 // after 100 the intensity of LEDs seems to level off
 if(_currVal == 100) _dirUp = 0;
 else if(_currVal == 0) {
   _dirUp = 1;
   _currCol = (_currCol + 1) % 3;
 }

 _count ++;
 if(_count &gt;= _interval){

_count = 0;
 _currVal = _dirUp ? _currVal + 1 : _currVal - 1;

if(_mode == 2){
 set_pwm(_currCol, _currVal);
 }
 }
}

uint8_t percToByte(uint8_t perc){
 uint16_t temp = perc * 255;
 return temp / 100;
}

int main(void){
 init_pwm();
 uart_init(BAUD_RATE_38400);

while(1){
 // 1. check for instructions over serial line
 if(uart_isCharAvailable()){
 uint8_t temp = uart_getChar();
 if(temp == '#'){
 _mode = 1;
 uart_putStr(&quot;BRO &quot;);
 uint8_t blue = uart_getChar();
 uint8_t red = uart_getChar();
 uint8_t orange = uart_getChar();
 uint8_t checksum = uart_getChar(); //very basic check sum, it simply has to be = to the SUM of prev values, modulo 100

if(checksum == ((uint16_t)blue + (uint16_t)red + (uint16_t)orange) % 100){
 uart_putStr(&quot;OK&quot;);
 _blue = percToByte(blue);
 _red = percToByte(red);
 _orange = percToByte(orange);
 update_status();
 }else{
 uart_putStr(&quot;Nok&quot;);
 }
 }else if(temp == '*'){
 // go in mode &quot;dynamic&quot;
 _mode = 2;
 uart_putStr(&quot;Interval &quot;);
 _interval = ((uint16_t)uart_getChar()) * 50;
 _currCol = BLUE;
 _currVal = 1;
 update_status();
 }
 }

// 2. check for button pressed or not
 if(button_is_pressed()){
 _mode = (_mode + 1) % 3;
 update_status();
 }

// 3. do whatever periodic action is needed
 update_dynamics();

// 4. get some rest
 //_delay_ms(1);
 }
}
</pre></p>
<div id="attachment_954" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2011-10-02_spokaconnectedtopcserial.jpg"><img class="size-medium wp-image-954" title="2011.10.02_SpokaConnectedToPCserial" src="http://trandi.files.wordpress.com/2012/01/2011-10-02_spokaconnectedtopcserial.jpg?w=300&#038;h=210" alt="" width="300" height="210" /></a><p class="wp-caption-text">Works just fine when connected to a PC serial port</p></div>
<h2>3. Connect the bluetooth transceiver</h2>
<div id="attachment_956" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2011-10-15_spoka_serialbluetooth.jpg"><img class="size-medium wp-image-956" title="2011.10.15_Spoka_SerialBluetooth" src="http://trandi.files.wordpress.com/2012/01/2011-10-15_spoka_serialbluetooth.jpg?w=300&#038;h=136" alt="" width="300" height="136" /></a><p class="wp-caption-text">Cheap Serial Bluetooth Transceiver</p></div>
<div id="attachment_957" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2011-10-15_spoka_theserialbluetoothconnected.jpg"><img class="size-medium wp-image-957" title="2011.10.15_Spoka_TheSerialBluetoothConnected" src="http://trandi.files.wordpress.com/2012/01/2011-10-15_spoka_theserialbluetoothconnected.jpg?w=300&#038;h=194" alt="" width="300" height="194" /></a><p class="wp-caption-text">Bluetooth Serial connected, first tests...</p></div>
<h2>4. Program the Android phone</h2>
<p>This was (and still is) quite frustrating&#8230;</p>
<p>I love Android and its ease of programming in Java ! They really make your life much easier by providing everything one needs &#8230; Unless something doesn&#8217;t work as expected that is !</p>
<p>In my case, it was a matter of hours before I put together a simple view, like a joystick with 3 axes. It&#8217;s a simple gray dot that the user can move relative to 3 coloured circles, each corresponding to a set of LEDs on the lamp, which is supposed to update its intensity accordingly.</p>
<p>All the &#8220;back end&#8221; needs to do, is to measure the distance between the gray circle and the other 3 &#8220;reference&#8221; ones, transform this into a percentage and send it across the serial bluetooth line to the MCU.</p>
<p>Everything works nicely, EXCEPT the bluetooth serial port profile connection.</p>
<p>First of all, when I test the connection from the PC, there are no issues what so ever.</p>
<p>On Android however, I get garbled characters most of the time and sometimes the right one. It really feels like a timing issue&#8230;</p>
<p>I&#8217;ve based my code on the example coming with the Android SDK. The sending of bytes is done in the main thread, but the receiving has its own dedicated one.</p>
<p>The really strange thing is that depending on how and when I transform the bytes into a String, the code works or not&#8230;</p>
<p>If I disable the receiving thread and I only send data from the phone to the MCU, then it works 95% of the time, which again makes me think that it&#8217;s a timing issue on the Android side.</p>
<p>That&#8217;s for now the status, I basically send the instructions from the phone, and do NOT wait for the acknowledgement from the ATtiny.</p>
<p>Here&#8217;s the code. Ytai, you must have spend quite a lot of time on this yourself when bluetooth enabling the IOIO, if you have any idea or suggestion, it would be hugely appreciated !</p>
<p><pre class="brush: java; collapse: true; light: false; toolbar: true;">
BTDeviceListActivity.java
-------------------------------------------------------
package trandi.spokalightbluetooth;

import java.util.Set;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

/**
 * This Activity appears as a dialog. It lists any paired devices and
 * devices detected in the area after discovery. When a device is chosen
 * by the user, the MAC address of the device is sent back to the parent
 * Activity in the result Intent.
 */
public class BTDeviceListActivity extends Activity {
 // Debugging
 private static final String TAG = &quot;BTDeviceListActivity&quot;;

 // Return Intent extra
 public static String EXTRA_DEVICE_ADDRESS = &quot;device_address&quot;;

 // Member fields
 private BluetoothAdapter _btAdapter;
 private ArrayAdapter&lt;String&gt; _pairedDevicesArrayAdapter;
 private ArrayAdapter&lt;String&gt; _newDevicesArrayAdapter;

 // The BroadcastReceiver that listens for discovered devices and changes the title when discovery is finished
 private final BroadcastReceiver _receiver = new BroadcastReceiver() {
 @Override
 public void onReceive(Context context, Intent intent) {
 String action = intent.getAction();

// When discovery finds a device
 if (BluetoothDevice.ACTION_FOUND.equals(action)) {
 // Get the BluetoothDevice object from the Intent
 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
 // If it's already paired, skip it, because it's been listed already
 if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
 _newDevicesArrayAdapter.add(device.getName() + &quot;\n&quot; + device.getAddress());
 }
 // When discovery is finished, change the Activity title
 } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
 setProgressBarIndeterminateVisibility(false);
 setTitle(R.string.select_device);
 if (_newDevicesArrayAdapter.getCount() == 0) {
 _newDevicesArrayAdapter.add(getResources().getText(R.string.none_found).toString());
 }
 }
 }
 };

 // The on-click listener for all devices in the ListViews
 private OnItemClickListener _deviceClickListener = new OnItemClickListener() {
 @Override
 public void onItemClick(AdapterView&lt;!--?--&gt; av, View v, int arg2, long arg3) {
 // Cancel discovery because it's costly and we're about to connect
 _btAdapter.cancelDiscovery();

// Get the device MAC address, which is the last 17 chars in the View
 String info = ((TextView) v).getText().toString();
 String address = info.substring(info.length() - 17);

// Create the result Intent and include the MAC address
 Intent intent = new Intent();
 intent.putExtra(EXTRA_DEVICE_ADDRESS, address);

// Set result and finish this Activity
 setResult(Activity.RESULT_OK, intent);
 finish();
 }
 };

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);

// Setup the window
 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
 setContentView(R.layout.device_list);

// Set result CANCELED incase the user backs out
 setResult(Activity.RESULT_CANCELED);

// Initialize the button to perform device discovery
 Button scanButton = (Button) findViewById(R.id.button_scan);
 scanButton.setOnClickListener(new OnClickListener() {
 public void onClick(View v) {
 doDiscovery();
 v.setVisibility(View.GONE);
 }
 });

// Initialize array adapters. One for already paired devices and one for newly discovered devices
 _pairedDevicesArrayAdapter = new ArrayAdapter&lt;String&gt;(this, R.layout.device_name);
 _newDevicesArrayAdapter = new ArrayAdapter&lt;String&gt;(this, R.layout.device_name);

// Find and set up the ListView for paired devices
 ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
 pairedListView.setAdapter(_pairedDevicesArrayAdapter);
 pairedListView.setOnItemClickListener(_deviceClickListener);

// Find and set up the ListView for newly discovered devices
 ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
 newDevicesListView.setAdapter(_newDevicesArrayAdapter);
 newDevicesListView.setOnItemClickListener(_deviceClickListener);

// Register for broadcasts when a device is discovered &amp; discovery has finished
 this.registerReceiver(_receiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
 this.registerReceiver(_receiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));

// Get the local Bluetooth adapter
 _btAdapter = BluetoothAdapter.getDefaultAdapter();

// Get a set of currently paired devices
 Set pairedDevices = _btAdapter.getBondedDevices();

// If there are paired devices, add each one to the ArrayAdapter
 if (pairedDevices.size() &gt; 0) {
 findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
 for (BluetoothDevice device : pairedDevices) {
 _pairedDevicesArrayAdapter.add(device.getName() + &quot;\n&quot; + device.getAddress());
 }
 } else {
 _pairedDevicesArrayAdapter.add(getResources().getText(R.string.none_paired).toString());
 }
 }

 @Override
 protected void onDestroy() {
 super.onDestroy();

// Make sure we're not doing discovery anymore
 if (_btAdapter != null) {
 _btAdapter.cancelDiscovery();
 }

// Unregister broadcast listeners
 this.unregisterReceiver(_receiver);
 }

 /**
 * Start device discover with the BluetoothAdapter
 */
 private void doDiscovery() {
 Log.d(TAG, &quot;doDiscovery()&quot;);

// Indicate scanning in the title
 setProgressBarIndeterminateVisibility(true);
 setTitle(R.string.scanning);

// Turn on sub-title for new devices
 findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);

// If we're already discovering, stop it
 if (_btAdapter.isDiscovering()) {
 _btAdapter.cancelDiscovery();
 }

// Request discover from BluetoothAdapter
 _btAdapter.startDiscovery();
 }
}

MainActivity.java
-------------------------------------------------------
package trandi.spokalightbluetooth;

import java.io.IOException;

import trandi.spokalightbluetooth.MainView.ColValues;
import trandi.spokalightbluetooth.MainView.JoystickListener;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Main activity to control the hacked Spoka light.
 *
 * @author trandi
 */
public class MainActivity extends Activity {
 // Debugging
 private static final String TAG = &quot;SpokaLightBluetooth_MainActivity&quot;;

// Intent request codes
 private static final int REQUEST_CONNECT_DEVICE = 1;
 private static final int REQUEST_ENABLE_BT = 2;

 private TextView _title;
 private BluetoothAdapter _bluetoothAdapter;
 private Spoka _spoka;

 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 Log.e(TAG, &quot;+++ ON CREATE +++&quot;);

// Set up the window layout
 requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
 setContentView(R.layout.main);
 getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);
 // register this activity with the View, to listen to Joystick events
 ((MainView)findViewById(R.id.myMainView)).addJoystickListener(new JoystickListener() {
 @Override
 public void onMove(ColValues newColours) {
 if(_spoka != null){
 final String result = _spoka.updateColours(newColours.red, newColours.blue, newColours.orange) ? &quot;OK&quot; : &quot;NOK&quot;;

 Log.d(TAG, &quot;Update Colours &quot; + result + &quot; (&quot; + newColours + &quot;)&quot;);
 }
 }
 });

// Set up the custom title
 _title = (TextView) findViewById(R.id.title_left_text);
 _title.setText(R.string.app_name);
 _title = (TextView) findViewById(R.id.title_right_text);

// Get local Bluetooth adapter
 _bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

// If the adapter is null, then Bluetooth is not supported
 if (_bluetoothAdapter == null) {
 Toast.makeText(this, &quot;Bluetooth is not available&quot;, Toast.LENGTH_LONG).show();
 finish();
 return;
 }
 }

 @Override
 public void onStart() {
 super.onStart();
 Log.d(TAG, &quot;++ ON START ++&quot;);

if (!_bluetoothAdapter.isEnabled()) {
 // If BT is not on, request that it be enabled.
 Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
 // Asynchronous, the onActivityResult will be called back when finished
 startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
 }else {
 // Bluetooth is already enabled
 // Launch the BTDeviceListActivity to see devices and do scan
 Intent serverIntent = new Intent(this, BTDeviceListActivity.class);
 startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
 }
 }

@Override
 public void onDestroy() {
 super.onDestroy();
 Log.d(TAG, &quot;++ ON DESTROY ++&quot;);

 if(_spoka != null) _spoka.disconnect();
 }

public void onActivityResult(int requestCode, int resultCode, Intent data) {
 Log.d(TAG, &quot;onActivityResult &quot; + resultCode);

 switch (requestCode) {
 case REQUEST_CONNECT_DEVICE:
 // When BTDeviceListActivity returns with a device to connect
 if (resultCode == Activity.RESULT_OK) {
 // Get the device MAC address
 String address = data.getExtras().getString(BTDeviceListActivity.EXTRA_DEVICE_ADDRESS);
 // Create a business object which attempts to create to the Spoka !
 //ensureDiscoverable(_bluetoothAdapter);
 try {
 _spoka = new Spoka(_bluetoothAdapter, address);
 } catch (Exception e) {
 Toast.makeText(this, &quot;Can't connect to the SPOKA&quot;, Toast.LENGTH_SHORT).show();
 finish();
 }
 }
 break;
 case REQUEST_ENABLE_BT:
 // When the request to enable Bluetooth returns
 if (resultCode == Activity.RESULT_OK) {
 // Bluetooth is now enabled
 // Launch the BTDeviceListActivity to see devices and do scan
 Intent serverIntent = new Intent(this, BTDeviceListActivity.class);
 startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
 } else {
 // User did not enable Bluetooth or an error occured
 Log.d(TAG, &quot;BT not enabled&quot;);
 Toast.makeText(this, &quot;User did not enable Bluetooth or an error occured&quot;, Toast.LENGTH_SHORT).show();
 finish();
 }
 }
 }

 private void ensureDiscoverable(BluetoothAdapter bluetoothAdapter) {
 if (bluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
 Log.d(TAG, &quot;Force discoverable&quot;);
 Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
 discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
 startActivity(discoverableIntent);
 }
 }
}

MainView.java
-------------------------------------------------------
package trandi.spokalightbluetooth;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class MainView extends View {
 private static final Point _red = new Point(50, 100);
 private static final Point _blue = new Point(250, 100);
 private static final Point _yellow = new Point(150, 300);

 private final List&lt;JoystickListener&gt; _joystickListeners = new ArrayList();

 private Point _joystick = new Point(150, 200);
 private final int _r = 30;
 private boolean _move = false;
 private long _lastMove = 0;

 public MainView(Context context, AttributeSet attrs) {
 super(context, attrs);
 }

 public synchronized void addJoystickListener(JoystickListener listener) {
 _joystickListeners.add(listener);
 }

 @Override
 public boolean onTouchEvent(MotionEvent me) {
 // are we trying to move the &quot;joystick&quot;
 if(Math.abs(me.getX() - _joystick.x) &lt;= _r &amp;&amp; Math.abs(me.getY() - _joystick.y) &lt;= _r){
 if(me.getAction() == MotionEvent.ACTION_DOWN){
 _move = true;
 }else if(me.getAction() == MotionEvent.ACTION_UP){
 _move = false;
 }else if(me.getAction() == MotionEvent.ACTION_MOVE
 &amp;&amp; _move
 &amp;&amp; (System.currentTimeMillis() - _lastMove &gt; 50))
 {
 _lastMove = System.currentTimeMillis();
 // call all the listeners
 new Thread(){
 @Override
 public void run(){
 ColValues updatedColours = new ColValues();
 for(JoystickListener listener : _joystickListeners){
 listener.onMove(updatedColours);
 }
 }
 }.start();
 }
 }

 if(_move){
 _joystick.set(Math.round(me.getX()), Math.round(me.getY()));

 // force to redraw
 this.invalidate();
 }

 return true;
 }

 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);

 // draw the fixed circles
 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
 paint.setColor(Color.RED);
 canvas.drawCircle(_red.x, _red.y, 20, paint);
 paint.setColor(Color.BLUE);
 canvas.drawCircle(_blue.x, _blue.y, 20, paint);
 paint.setColor(Color.YELLOW);
 canvas.drawCircle(_yellow.x, _yellow.y, 20, paint);

 // draw the moving circle (the &quot;joystick&quot;)
 paint.setColor(Color.GRAY);
 canvas.drawCircle(_joystick.x, _joystick.y, _r, paint);
 }

 public static interface JoystickListener {
 void onMove(ColValues newColours);
 }

 public class ColValues {
 public final int red;
 public final int blue;
 public final int orange;

 public ColValues(int red, int blue, int orange){
 this.red = red;
 this.blue = blue;
 this.orange = orange;
 }

 /**
 * Calculates the distances from the position of the joystick and base colour circles
 */
 public ColValues(){
 final double maxDist = getDist(_red, _blue);

this.red = 100 - (int)Math.round(getDist(_joystick, _red) * 100.0 / maxDist);
 this.blue = 100 - (int)Math.round(getDist(_joystick, _blue) * 100.0 / maxDist);
 this.orange = 100 - (int)Math.round(getDist(_joystick, _yellow) * 100.0 / maxDist);
 }

 private int getDist(Point a, Point b) {
 return (int)Math.round(Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2)));
 }

@Override
 public String toString() {
 return &quot;ColValues [red=&quot; + red + &quot;, blue=&quot; + blue + &quot;, orange=&quot; + orange + &quot;]&quot;;
 }
 }
}

Spoka.java
-------------------------------------------------------
package trandi.spokalightbluetooth;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;

public class Spoka {
 // Debugging
 private static final String TAG = &quot;SPOKA&quot;;

 // Unique UUID for this application
 // has to be this precise value for SERIAL port profile (SPP)
 private static final UUID MY_UUID = UUID.fromString(&quot;00001101-0000-1000-8000-00805F9B34FB&quot;);
// private static final UUID MY_UUID_SECURE = UUID.fromString(&quot;fa87c0d0-afac-11de-8a39-0800200c9a66&quot;);
// private static final UUID MY_UUID_INSECURE = UUID.fromString(&quot;8ce255c0-200a-11e0-ac64-0800200c9a66&quot;);

 private BluetoothSocket _btSocket;
 private InputStream _socketIS;
 private OutputStream _socketOS;
 // will need to SYNCHRONISE on this as it's used from multiple threads !
// private Queue&lt;String&gt; _incomingData = new ConcurrentLinkedQueue&lt;String&gt;();
// private String _incomingDataStr = &quot;&quot;;

 public Spoka(BluetoothAdapter bluetoothAdapter, String address) throws IOException{
 Log.d(TAG, &quot;++ CONNECT SPOKA ++&quot;);

// Get the BluetoothDevice object
 BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);

 // Get a BluetoothSocket for a connection with the given BluetoothDevice
 try {
 _btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
 } catch (IOException e) {
 Log.e(TAG, &quot;createRfcommSocketToServiceRecord() failed&quot;, e);
 throw e;
 }

// Attempt to connect to the device
 // Always cancel discovery because it will slow down a connection
 bluetoothAdapter.cancelDiscovery();

 // Make a connection to the BluetoothSocket
 try {
 // This is a blocking call and will only return on a successful connection or an exception
 _btSocket.connect();
 Log.d(TAG, &quot;++ connectED SPOKA ++&quot;);
 } catch (IOException e) {
 disconnect();
 Log.e(TAG, &quot;Can't connect to the Spoka&quot;, e);
 throw e;
 }

 // !!! COMMENTED OUT THE WHOLE INCOMING SERIAL DATA READ, AS THIS SEEMS TO CAUSE THE RECEIVED BYTES TO BE GARBLED !!!
 // start a separate thread that monitors any incoming data, and stores it in a queue
 // this is done so, because we don't seem to have an asynchronous read() on the BluetoothSocket InputStream
// new Thread(){
// @Override
// public void run(){
// byte[] buff = new byte[100];
// while(true){
// try{
// if(_socketIS == null) _socketIS = new BufferedInputStream(_btSocket.getInputStream(), 1024);
//
// if(_socketIS != null){
// // blocking on the read when there's nothing...
// int readCount = _socketIS.read(buff);
// // for some VERY SILLY reason, if we store the bytes here, they come garbled...
// _incomingData.add(new String(buff, 0, readCount));
// }
// } catch (Exception e) {
// Log.e(TAG, &quot;Can't read message from the Spoka&quot;, e);
// }
// }
// }
// }.start();
 }

 public void disconnect() {
 try {
 if(_btSocket != null) _btSocket.close();
 } catch (IOException e) {
 Log.e(TAG, &quot;Unable to close() socket during connection failure&quot;, e);
 }
 }

 public boolean updateColours(int redPerc, int bluePerc, int orangePerc) {
 byte red = checkPerc(redPerc);
 byte blue = checkPerc(bluePerc);
 byte orange = checkPerc(orangePerc);

 // 1. send the special char &quot;#&quot; indicating to the Spoka that we want to manually update the colours
 sendBytes((byte)'#');

 // 2. check that we receive back the &quot;BRO &quot; acknowledgement( Blue, Red, Orange)
 //if(waitForIncomingData(&quot;BRO&quot;, 100)){
 // 3. send the values &amp; the check sum
 sendBytes(blue, red, orange, (byte)(((int)blue + (int)red + (int)orange) % 100));

 // 4. check that we receive back confirmation
 //return waitForIncomingData(&quot;OK&quot;, 100);
 //}

 return false;
 }

 private byte checkPerc(int perc){
 return (byte)(perc &lt; 0 ? 0 : (perc &gt; 100 ? 100 : perc));
 }

 private void sendBytes(byte...bytes) {
 try{
 if(_socketOS == null) _socketOS = new BufferedOutputStream(_btSocket.getOutputStream(), 1024);

 if(_socketOS != null){
 _socketOS.write(bytes);
 _socketOS.flush();
 }
 } catch (IOException e) {
 Log.e(TAG, &quot;Can't send message to the Spoka&quot;, e);
 }
 }

 private boolean waitForIncomingData(String expectedData, int timeoutMillis){
 final long startTime = System.currentTimeMillis();
 byte[] buff = new byte[100];
 String incomingData = &quot;&quot;;
 try{
 if(_socketIS == null) _socketIS = new BufferedInputStream(_btSocket.getInputStream(), 1024);

 if(_socketIS != null){
 while((! incomingData.contains(expectedData))
 &amp;&amp; (System.currentTimeMillis() - startTime &lt; timeoutMillis))
 {
 // blocking on the read when there's nothing...
 int readCount = _socketIS.read(buff);
 // for some VERY SILLY reason, if we store the bytes here, they come garbled...
 incomingData += new String(buff, 0, readCount);
 }
 }
 }catch(IOException e){
 Log.e(TAG, &quot;Can't receive incoming data&quot;, e);
 }

 Log.d(TAG, &quot;RECV: &quot; + incomingData);

 if(incomingData.contains(expectedData)){
 return true;
 }

return false;
 }

// private boolean waitForIncomingData(String expectedData, int timeoutMillis){
// final long startTime = System.currentTimeMillis();
//
// while((! _incomingDataStr.contains(expectedData))
// &amp;&amp; (System.currentTimeMillis() - startTime &lt; timeoutMillis))
// {
// final String head = _incomingData.poll();
// if(head != null) _incomingDataStr += head;
// Thread.yield();
// }
//
// if(_incomingDataStr.contains(expectedData)){
// // REMOVE the expected data (and whatever was before) from the string buffer
// final int pos = _incomingDataStr.indexOf(expectedData) + expectedData.length();
// _incomingDataStr = _incomingDataStr.substring(pos);
//
// return true;
// }
//
// Log.d(TAG, &quot;RECV: &quot; + _incomingDataStr);
// return false;
// }

// /**
// * @return true if the expected incoming data has been received, false if timeout
// */
// private boolean waitForIncomingData(String incomingData, int timeoutMillis){
// final long startTime = System.currentTimeMillis();
// // wait until received expected data or timeout
// while(! peekIncomingData().contains(incomingData) &amp;&amp; (System.currentTimeMillis() - startTime &lt; timeoutMillis)){
// try {
// Thread.sleep(10);
// } catch (InterruptedException e) {
// // nothing to do
// }
// }
//
// final int position = peekIncomingData().indexOf(incomingData);
// if(position &gt; 0){
// // now remove the data from the incoming queue
// for(int i=0; i &lt; position + incomingData.length(); i++){
// _incomingData.poll();
// }
// return true; // found the expected string
// }else{
// Log.e(TAG, peekIncomingData());
// }
//
// return false; // NOT found the expected string and timed out
// }
//
// private String peekIncomingData() {
// Byte[] data = _incomingData.toArray(new Byte[]{});
// byte[] dataChars = new byte[data.length];
// for(int i=0; i
// dataChars[i] = data[i];
// }
// return new String(dataChars);
// }
}
</pre></p>
<p>And here are all the XML configuration files, specific to Android platforms:</p>
<p><pre class="brush: xml; collapse: true; light: false; toolbar: true;">
custom_title.xml
-------------------------------------------------------
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
 android:layout_width=&quot;match_parent&quot;
 android:layout_height=&quot;match_parent&quot;
 android:gravity=&quot;center_vertical&quot;&gt;

 &lt;TextView android:id=&quot;@+id/title_left_text&quot;
 android:layout_alignParentLeft=&quot;true&quot;
 android:ellipsize=&quot;end&quot;
 android:singleLine=&quot;true&quot;
 style=&quot;?android:attr/windowTitleStyle&quot;
 android:layout_width=&quot;wrap_content&quot;
 android:layout_height=&quot;match_parent&quot;
 android:layout_weight=&quot;1&quot;/&gt;

 &lt;TextView android:id=&quot;@+id/title_right_text&quot;
 android:layout_alignParentRight=&quot;true&quot;
 android:ellipsize=&quot;end&quot;
 android:singleLine=&quot;true&quot;
 android:layout_width=&quot;wrap_content&quot;
 android:layout_height=&quot;match_parent&quot;
 android:textColor=&quot;#fff&quot;
 android:layout_weight=&quot;1&quot;/&gt;

&lt;/RelativeLayout&gt;

device_list.xml
-------------------------------------------------------
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
 android:orientation=&quot;vertical&quot;
 android:layout_width=&quot;match_parent&quot;
 android:layout_height=&quot;match_parent&quot;&gt;

 &lt;TextView android:id=&quot;@+id/title_paired_devices&quot;
 android:layout_width=&quot;match_parent&quot;
 android:layout_height=&quot;wrap_content&quot;
 android:text=&quot;@string/title_paired_devices&quot;
 android:visibility=&quot;gone&quot;
 android:background=&quot;#666&quot;
 android:textColor=&quot;#fff&quot;
 android:paddingLeft=&quot;5dp&quot;/&gt;

 &lt;ListView android:id=&quot;@+id/paired_devices&quot;
 android:layout_width=&quot;match_parent&quot;
 android:layout_height=&quot;wrap_content&quot;
 android:stackFromBottom=&quot;true&quot;
 android:layout_weight=&quot;1&quot;/&gt;

 &lt;TextView android:id=&quot;@+id/title_new_devices&quot;
 android:layout_width=&quot;match_parent&quot;
 android:layout_height=&quot;wrap_content&quot;
 android:text=&quot;@string/title_other_devices&quot;
 android:visibility=&quot;gone&quot;
 android:background=&quot;#666&quot;
 android:textColor=&quot;#fff&quot;
 android:paddingLeft=&quot;5dp&quot;/&gt;

 &lt;ListView android:id=&quot;@+id/new_devices&quot;
 android:layout_width=&quot;match_parent&quot;
 android:layout_height=&quot;wrap_content&quot;
 android:stackFromBottom=&quot;true&quot;
 android:layout_weight=&quot;2&quot;/&gt;

 &lt;Button android:id=&quot;@+id/button_scan&quot;
 android:layout_width=&quot;match_parent&quot;
 android:layout_height=&quot;wrap_content&quot;
 android:text=&quot;@string/button_scan&quot;/&gt;

&lt;/LinearLayout&gt;

device_name.xml
-------------------------------------------------------
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;TextView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
 android:layout_width=&quot;match_parent&quot;
 android:layout_height=&quot;wrap_content&quot;
 android:textSize=&quot;18sp&quot;
 android:padding=&quot;5dp&quot;/&gt;

main.xml
-------------------------------------------------------
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
 xmlns:trandi= &quot;http://schemas.android.com/apk/res/trandi.spokalightbluetooth&quot;
 android:orientation=&quot;vertical&quot;
 android:layout_width=&quot;match_parent&quot;
 android:layout_height=&quot;match_parent&quot;&gt;

 &lt;FrameLayout android:id=&quot;@+id/drawingFrame&quot; android:layout_height=&quot;match_parent&quot; android:layout_width=&quot;match_parent&quot;&gt;
 &lt;trandi.spokalightbluetooth.MainView android:id=&quot;@+id/myMainView&quot; android:layout_height=&quot;match_parent&quot; android:layout_width=&quot;match_parent&quot;/&gt;
 &lt;/FrameLayout&gt;
&lt;/LinearLayout&gt;

strings.xml
-------------------------------------------------------
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;resources&gt;
 &lt;string name=&quot;app_name&quot;&gt;Spoka Light Bluetooth&lt;/string&gt;

 &lt;!-- BTDeviceListActivity --&gt;
 &lt;string name=&quot;scanning&quot;&gt;scanning for devices...&lt;/string&gt;
 &lt;string name=&quot;select_device&quot;&gt;select a device to connect&lt;/string&gt;
 &lt;string name=&quot;none_paired&quot;&gt;No devices have been paired&lt;/string&gt;
 &lt;string name=&quot;none_found&quot;&gt;No devices found&lt;/string&gt;
 &lt;string name=&quot;title_paired_devices&quot;&gt;Paired Devices&lt;/string&gt;
 &lt;string name=&quot;title_other_devices&quot;&gt;Other Available Devices&lt;/string&gt;
 &lt;string name=&quot;button_scan&quot;&gt;Scan for devices&lt;/string&gt;
&lt;/resources&gt;
</pre></p>
<h2>5. Final result</h2>
<div id="attachment_959" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2012-01-09_spoka_everythingconnected.jpg"><img class="size-medium wp-image-959" title="2012.01.09_Spoka_EverythingConnected" src="http://trandi.files.wordpress.com/2012/01/2012-01-09_spoka_everythingconnected.jpg?w=300&#038;h=141" alt="" width="300" height="141" /></a><p class="wp-caption-text">Everything connected, ready for final tests</p></div>
<div id="attachment_960" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2012-01-13_spoka_onthestripboard.jpg"><img class="size-medium wp-image-960" title="2012.01.13_Spoka_OnTheStripboard" src="http://trandi.files.wordpress.com/2012/01/2012-01-13_spoka_onthestripboard.jpg?w=300&#038;h=146" alt="" width="300" height="146" /></a><p class="wp-caption-text">On the stripboard</p></div>
<div id="attachment_962" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2012-01-13_spoka_puttingeverythingback.jpg"><img class="size-medium wp-image-962" title="2012.01.13_Spoka_PuttingEverythingBack" src="http://trandi.files.wordpress.com/2012/01/2012-01-13_spoka_puttingeverythingback.jpg?w=300&#038;h=262" alt="" width="300" height="262" /></a><p class="wp-caption-text">Putting everything back</p></div>
<div id="attachment_963" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2012/01/2012-01-13_spoka_withoutthesiliconeskin.jpg"><img class="size-medium wp-image-963" title="2012.01.13_Spoka_WithoutTheSiliconeSkin" src="http://trandi.files.wordpress.com/2012/01/2012-01-13_spoka_withoutthesiliconeskin.jpg?w=300&#038;h=236" alt="" width="300" height="236" /></a><p class="wp-caption-text">Naked, without the silicone skin...</p></div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/trandi.wordpress.com/928/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/trandi.wordpress.com/928/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/trandi.wordpress.com/928/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/trandi.wordpress.com/928/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/trandi.wordpress.com/928/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/trandi.wordpress.com/928/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/trandi.wordpress.com/928/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/trandi.wordpress.com/928/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/trandi.wordpress.com/928/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/trandi.wordpress.com/928/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/trandi.wordpress.com/928/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/trandi.wordpress.com/928/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/trandi.wordpress.com/928/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/trandi.wordpress.com/928/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=928&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>https://trandi.wordpress.com/2012/01/13/spoka-night-light-controlled-from-and-android-phone/feed/</wfw:commentRss>
		<slash:comments>56</slash:comments>
	
		<media:content url="https://secure.gravatar.com/avatar/cf5070dd11dddb4b4fed449609ad09f0?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">trandi</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/spoka-night-light__0097669_pe238441_s4.jpg?w=300" medium="image">
			<media:title type="html">spoka-night-light__0097669_PE238441_S4</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2011-10-01_spokainitial.jpg?w=300" medium="image">
			<media:title type="html">2011.10.01_SpokaInitial</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2011-09-28_spoka_reverseengineer_schema.jpg?w=300" medium="image">
			<media:title type="html">2011.09.28_Spoka_ReverseEngineer_Schema</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2011-10-01_spoka_originalmcuremoved.jpg?w=300" medium="image">
			<media:title type="html">2011.10.01_Spoka_OriginalMCURemoved</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2011-10-02_spokaconnectedtoattiny2313.jpg?w=300" medium="image">
			<media:title type="html">2011.10.02_SpokaConnectedToATtiny2313</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2011-10-02_spokaconnectedtoattiny2313_2.jpg?w=300" medium="image">
			<media:title type="html">2011.10.02_SpokaConnectedToATtiny2313_2</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2011-10-02_spokaconnectedtopcserial.jpg?w=300" medium="image">
			<media:title type="html">2011.10.02_SpokaConnectedToPCserial</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2011-10-15_spoka_serialbluetooth.jpg?w=300" medium="image">
			<media:title type="html">2011.10.15_Spoka_SerialBluetooth</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2011-10-15_spoka_theserialbluetoothconnected.jpg?w=300" medium="image">
			<media:title type="html">2011.10.15_Spoka_TheSerialBluetoothConnected</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2012-01-09_spoka_everythingconnected.jpg?w=300" medium="image">
			<media:title type="html">2012.01.09_Spoka_EverythingConnected</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2012-01-13_spoka_onthestripboard.jpg?w=300" medium="image">
			<media:title type="html">2012.01.13_Spoka_OnTheStripboard</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2012-01-13_spoka_puttingeverythingback.jpg?w=300" medium="image">
			<media:title type="html">2012.01.13_Spoka_PuttingEverythingBack</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2012/01/2012-01-13_spoka_withoutthesiliconeskin.jpg?w=300" medium="image">
			<media:title type="html">2012.01.13_Spoka_WithoutTheSiliconeSkin</media:title>
		</media:content>
	</item>
		<item>
		<title>Simple serial transceiver &#8211; Aurel RTX-MID</title>
		<link>https://trandi.wordpress.com/2011/10/24/simple-serial-transceiver/</link>
		<comments>https://trandi.wordpress.com/2011/10/24/simple-serial-transceiver/#comments</comments>
		<pubDate>Mon, 24 Oct 2011 22:31:45 +0000</pubDate>
		<dc:creator>trandi</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[aurel]]></category>
		<category><![CDATA[IOIO]]></category>
		<category><![CDATA[RTX]]></category>
		<category><![CDATA[RTX-MID]]></category>
		<category><![CDATA[serial]]></category>
		<category><![CDATA[ttl]]></category>

		<guid isPermaLink="false">http://trandi.wordpress.com/?p=900</guid>
		<description><![CDATA[&#160; I&#8217;ve been looking for a simple and cheap wireless serial data solution for quite a while now&#8230; No specific usage, but things like every time you integrate your Arduino into a project and then 2 days later you want to update the code and you have to dismount everything, or simply remote control a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=900&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<span style="text-align:center; display: block;"><a href="https://trandi.wordpress.com/2011/10/24/simple-serial-transceiver/"><img src="http://img.youtube.com/vi/vky8AL6-NAg/2.jpg" alt="" /></a></span>
<p>&nbsp;</p>
<p>I&#8217;ve been looking for a simple and cheap wireless serial data solution for quite a while now&#8230;</p>
<p>No specific usage, but things like every time you integrate your Arduino into a project and then 2 days later you want to update the code and you have to dismount everything, or simply remote control a project or more generally just getting tired of &#8220;all the wires&#8221;&#8230;</p>
<p><span id="more-900"></span>There are of course plenty of solutions out there, but I wanted something cheap and simple to use !</p>
<p>The WiFly solution that I&#8217;ve already used <a href="http://trandi.wordpress.com/2011/09/26/vfd-clock-connects-to-the-internet/" target="_blank">here</a>, is &#8220;ok&#8221; simplicity wise but far too expensive !</p>
<p>Then you have RF link devices like <a href="http://www.sparkfun.com/products/10532" target="_blank">this one</a>, which are really cheap indeed &#8230; but as simple as they might be to install, they get a fair amount of noise so you get added complexity in the code to filter out some of that noise and do some error checks&#8230;</p>
<p>Anyhow, I&#8217;m sure I could go on forever like this, again one of the reasons I haven&#8217;t gotten anything until now, it&#8217;s that I couldn&#8217;t decide what to go with !</p>
<p>Finally, I got 2 of <a href="http://uk.farnell.com/aurel/rtx-mid-3v/module-transceiver-434mhz-am-3v/dp/1699468#" target="_blank">these</a> TRX-MID <a href="http://uk.farnell.com/aurel/" target="_blank">Aurel boards</a> from <a href="http://www.farnell.com" target="_blank">Farnell</a>  (quite reliable guys, I use them whenever I can, it&#8217;s a shame they seem to be more oriented towards professionals than hobbyists&#8230;) :</p>
<ul>
<li>they are 2-3 times more expensive than the really basic ones (12£ here in the UK, probably ~ 15$ in the US)</li>
<li>they are transceivers, which means you can have bi-directional communication</li>
<li>they seem to be slightly higher specs, so I hope for less noise / more reliable communication</li>
</ul>
<div>
<div id="attachment_905" class="wp-caption aligncenter" style="width: 202px"><a href="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_rectoverso.jpg"><img class="size-medium wp-image-905" title="2011.10.24_Aurel_TRX-MID-3V_RectoVerso" src="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_rectoverso.jpg?w=192&#038;h=300" alt="" width="192" height="300" /></a><p class="wp-caption-text">Aurel TRX-MID-3V Close Up</p></div>
<p>Before I insert them into any project, I need to do some testing / benchmarking to get a feeling for how good / bad they really are.</p>
<p>The simplest setup would have been to connect both of them to the PC through 2 USB to serial adapters, BUT given that I have only 1 3.3Volts cable, I had to use something else&#8230;</p>
<p>The next &#8220;simplest&#8221; solution was for me to use the IOIO board, connected to an Android phone. I know, it doesn&#8217;t sound very simple, but it&#8217;s a 3V3 board and it&#8217;s really quick to write a few lines of Java to make it send some serial data periodically:</p>
<div id="attachment_906" class="wp-caption aligncenter" style="width: 119px"><a href="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_schema.jpg"><img class="size-medium wp-image-906" title="2011.10.24_Aurel_TRX-MID-3V_Schema" src="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_schema.jpg?w=109&#038;h=300" alt="" width="109" height="300" /></a><p class="wp-caption-text">Aurel TRX-MID-3V Test Configuration Schema</p></div>
<ul>
<li><strong>TX</strong></li>
</ul>
<ul>
<li>the Android phone and the IOIO are there simply to periodically send some serial data</li>
<li>GND and VCC come directly from the IOIO board</li>
<li>pin 6 / Enable is connected to VCC through a 10k resitor</li>
<li>pin 5 / TX/RX is connected to VCC, telling the transceiver that it&#8217;s in TX mode</li>
<li>pin 4 / Input Data is connected to pin 5 of the IOIO</li>
</ul>
<ul>
<li><strong>RX</strong></li>
</ul>
<ul>
<li>the FTDI USB &#8211; Serial cable connecting the transceiver directly to the PC, on which I used Tera Term</li>
<li>GND and VCC come directly from the FTDI cable</li>
<li>pin 6 / Enable is connected to VCC through a 10k resistor</li>
<li>pin 5 / TX/RX is not connected, telling the transceiver it&#8217;s in RX mode (same as if I had connected it to GND, I think it has an internal pull down resistor connected to it)</li>
<li>pin 9 / Data Out is connected to the RX pin of the cable</li>
</ul>
<div>
<div id="attachment_907" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_closeup.jpg"><img class="size-medium wp-image-907" title="2011.10.24_Aurel_TRX-MID-3V_CloseUp" src="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_closeup.jpg?w=300&#038;h=204" alt="" width="300" height="204" /></a><p class="wp-caption-text">Aurel TRX-MID-3V</p></div>
<div id="attachment_908" class="wp-caption aligncenter" style="width: 252px"><a href="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_all.jpg"><img class="size-medium wp-image-908" title="2011.10.24_Aurel_TRX-MID-3V_All" src="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_all.jpg?w=242&#038;h=300" alt="" width="242" height="300" /></a><p class="wp-caption-text">Aurel TRX-MID-3V Test Setup Overview</p></div>
<p>&nbsp;</p>
<p>All in all, it&#8217;s a fairly simple connectivity, it literally took me 10minutes to set all this up, and then it worked from the 1st try !</p>
<p>&nbsp;</p>
<p>Now it&#8217;s time for a quick test, which consisted of simply seeing the &#8220;Hello World&#8221; sent by the IOIO board display in the serial terminal on the PC, and then take the board in another room (~5meters and 2 walls apart).</p>
<p>&nbsp;</p>
<p>Everything worked well (at 9600bps), but when I took the transmitter to the other room, I would get some spurious characters at the end of each transmission. I haven&#8217;t fully investigated this, but it seems that without an external antenna, the range is really 5-10 meters, no more. One can obviously add some error checking in the software or lower the bps to extend that.</p>
<p>&nbsp;</p>
<ul>
<li><strong>I like</strong></li>
</ul>
<ul>
<li>the fact that you can start into RX / TX mode by simply pulling a pin down / up (as oposed to the user manual where they describe a fairly complicated sequence (&#8220;<em>From powerdown mode (pin 4-5-6 low), drive high pin 6 (ENABLE), then after 20us drive high pin 5 (RX/TX) 200us, hold on 40us and then drive down 20us pin 6 (ENABLE).</em>&#8220;) which I&#8217;m sure it&#8217;s necessary in some more complex use cases</li>
<li>don&#8217;t have to set the speed</li>
</ul>
<ul>
<li><strong>I dislike</strong></li>
</ul>
<ul>
<li>you need an extra wire to set TX/RX, it&#8217;s not full duplex (can&#8217;t send / receive at the same time) &#8211; that&#8217;s really not problem for connecting remote sensors for example, but it makes it virtually impossible to use these boards to make an Arduino fully wireless</li>
<li>limited at 9600bps, again ok for some sensors, not really enough to replace wires (most of the applications expect at tleast 115200bps)</li>
<li>the range &#8211; this can be mediated by adding an antenna, but that makes things more complex</li>
</ul>
</div>
<div>All in all, it&#8217;s a nice and easy to use product, better than the basic ones as it can do both TX and RX (though not simultaneously), but it&#8217;s uses seem limited to sensors feedback type of use cases, definitely not making your micro-controller fully wireless by replacing the wired connection and debugging remotely.</div>
</div>
<div>As usual, do let me know if you enjoyed the post and if you have any feedback.</div>
<div>P.S. here&#8217;s for the sake of completeness (it really doesn&#8217;t matter who and how was sending the serial data) the code used for the Android/IOIO:</div>
<div><pre class="brush: java; collapse: true; light: false; toolbar: true;">
package org.trandi.helloioio;

import ioio.lib.api.DigitalOutput;
import ioio.lib.api.Uart;
import ioio.lib.api.exception.ConnectionLostException;
import ioio.lib.util.AbstractIOIOActivity;

import java.io.OutputStream;
import java.lang.Thread.UncaughtExceptionHandler;

import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends AbstractIOIOActivity {
	private static final String LOG_TAG = &quot;APT&quot;;
	private static final int RX_PIN = 4;
	private static final int TX_PIN = 5;
	private static final int UART_SPEED = 9600;

	private MyIOIOThread _IOIOthread;

	private TextView _msg;

	/**
	 * Called when the activity is first created. Here we normally initialise our GUI.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
			@Override
			public void uncaughtException(Thread thread, Throwable ex) {
				Log.e(LOG_TAG, &quot;&quot;, ex);
			}
		});

		setContentView(R.layout.main);
		_msg = (TextView) findViewById(R.id.textViewMsg);
	}

	/**
	 * This is the thread on which all the IOIO activity happens. It will be run
	 * every time the application is resumed and aborted when it is paused. The
	 * method setup() will be called right after a connection with the IOIO has
	 * been established (which might happen several times!). Then, loop() will
	 * be called repetitively until the IOIO gets disconnected.
	 */
	class MyIOIOThread extends AbstractIOIOActivity.IOIOThread {
		private DigitalOutput _onboardLED; // The on-board LED
		private Uart _uart;
		private OutputStream _dataOS;
		private long _count = 0;

		/**
		 * Called every time a connection with IOIO has been established.
		 * Typically used to open pins.
		 *
		 * @throws ConnectionLostException When IOIO connection is lost.
		 */
		@Override
		protected void setup() throws ConnectionLostException {
			msg(&quot;IOIO Connected !&quot;, null);

			try {
				_onboardLED  = ioio_.openDigitalOutput(0, true);

				// initialize the UART
				if(_uart != null) _uart.close();
				_uart = ioio_.openUart(RX_PIN, TX_PIN, UART_SPEED, Uart.Parity.NONE, Uart.StopBits.ONE);
				_dataOS = _uart.getOutputStream();
				msg(&quot;Connected to UART&quot;, null);
			} catch (Throwable e) {
				msg(&quot;Can't connect to the UART (&quot; + RX_PIN + &quot;, &quot; + TX_PIN + &quot;, &quot; + UART_SPEED + &quot;)&quot;, e);
			}
		}

		/**
		 * Called repetitively while the IOIO is connected.
		 *
		 * @throws ConnectionLostException When IOIO connection is lost.
		 */
		@Override
		protected void loop() throws ConnectionLostException {
			try {
				onboardLED(true);
				final String msg = &quot;HelloWorld  &quot; + _count++ + &quot;\n&quot;;
				runOnUiThread(new Runnable(){
					@Override
					public void run() {
						_msg.setText(msg);
					}
				});
				_dataOS.write(msg.getBytes());
				onboardLED(false);
				Thread.sleep(1000);
			} catch (Exception e) {
				msg(&quot;Can't write serial data&quot;, e);
			}
		}

		private void onboardLED(boolean on) throws ConnectionLostException{
			_onboardLED.write(!on);
		}

	} // end IOIOThread

	private void msg(final String msg, final Throwable e){
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				_msg.setText(msg + (e != null ? &quot; - &quot; + e.getMessage() : &quot;&quot;));
			}
		});
	}

	/**
	 * A method to create our IOIO thread.
	 */
	@Override
	protected AbstractIOIOActivity.IOIOThread createIOIOThread() {
		_IOIOthread = new MyIOIOThread();
		return _IOIOthread;
	}
}
</pre></p>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/trandi.wordpress.com/900/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/trandi.wordpress.com/900/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/trandi.wordpress.com/900/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/trandi.wordpress.com/900/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/trandi.wordpress.com/900/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/trandi.wordpress.com/900/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/trandi.wordpress.com/900/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/trandi.wordpress.com/900/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/trandi.wordpress.com/900/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/trandi.wordpress.com/900/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/trandi.wordpress.com/900/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/trandi.wordpress.com/900/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/trandi.wordpress.com/900/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/trandi.wordpress.com/900/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=900&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>https://trandi.wordpress.com/2011/10/24/simple-serial-transceiver/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="https://secure.gravatar.com/avatar/cf5070dd11dddb4b4fed449609ad09f0?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">trandi</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_rectoverso.jpg?w=192" medium="image">
			<media:title type="html">2011.10.24_Aurel_TRX-MID-3V_RectoVerso</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_schema.jpg?w=109" medium="image">
			<media:title type="html">2011.10.24_Aurel_TRX-MID-3V_Schema</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_closeup.jpg?w=300" medium="image">
			<media:title type="html">2011.10.24_Aurel_TRX-MID-3V_CloseUp</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/10/2011-10-24_aurel_trx-mid-3v_all.jpg?w=242" medium="image">
			<media:title type="html">2011.10.24_Aurel_TRX-MID-3V_All</media:title>
		</media:content>
	</item>
		<item>
		<title>Electronic Anti-roll system for tractor (or how to connect IOIO to a Basic Atom</title>
		<link>https://trandi.wordpress.com/2011/10/19/electronic-anti-roll-system-for-tractor-or-how-to-connect-ioio-to-a-basic-atom/</link>
		<comments>https://trandi.wordpress.com/2011/10/19/electronic-anti-roll-system-for-tractor-or-how-to-connect-ioio-to-a-basic-atom/#comments</comments>
		<pubDate>Wed, 19 Oct 2011 22:40:48 +0000</pubDate>
		<dc:creator>trandi</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[atom]]></category>
		<category><![CDATA[basic]]></category>
		<category><![CDATA[i2c]]></category>
		<category><![CDATA[IOIO]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[M40]]></category>
		<category><![CDATA[pro]]></category>
		<category><![CDATA[serial]]></category>
		<category><![CDATA[USART]]></category>

		<guid isPermaLink="false">http://trandi.wordpress.com/?p=892</guid>
		<description><![CDATA[&#8220;Tractor&#8221;, what tractor&#8230; ? That&#8217;s what you must be wondering right now, as I don&#8217;t often blog about tractors&#8230; especially full scale agricultural ones&#8230; This is a slightly different post for me, in that it&#8217;s about some help I gave to 2 guys in Germany, working on a hydraulic anti-roll system for a tractor. Wow&#8230; [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=892&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>&#8220;Tractor&#8221;, what tractor&#8230; ? That&#8217;s what you must be wondering right now, as I don&#8217;t often blog about tractors&#8230; especially full scale agricultural ones&#8230;</p>
<p>This is a slightly different post for me, in that it&#8217;s about some help I gave to 2 guys in Germany, working on a hydraulic anti-roll system for a tractor.<br />
Wow&#8230; I never though I would be working on &#8220;revolutionising the agriculture&#8221; as they&#8217;ve put it&#8230; <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div id="attachment_893" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/10/bap40_ioio_iconiaa500.jpg"><img class="size-medium wp-image-893" title="BAP40_IOIO_ICONIAA500" src="http://trandi.files.wordpress.com/2011/10/bap40_ioio_iconiaa500.jpg?w=300&#038;h=224" alt="" width="300" height="224" /></a><p class="wp-caption-text">Basic Atom Pro M40 - IOIO - and the ICONIA A500 Android tablet</p></div>
<p><span id="more-892"></span></p>
<p>It sounds awesome, but my actual contribution is very limited.</p>
<p>The Basic Atom Pro M40 is connected to an inclination sensor and does some funky stuff for the anti-rolling system, but the guys wanted to have some data nicely displayed on an Android tablet.</p>
<p>And that&#8217;s where they needed my help&#8230;</p>
<p>They initially wanted to use I2C to connect the IOIO to the Basic Atom, which I thought was fine, until I realised that the IOIO can NOT be a I2C slave&#8230; I therefore convinced them it would be easier to go down the UART route and after throwing together a simple program, we seem to be in business !</p>
<p>There&#8217;s really not much else to say, the program is really trivial, but it&#8217;s a nice basic example on how to use a USART on the IOIO board !</p>
<p>Without further due, here&#8217;s the main and only class  <span class="Apple-style-span" style="font-family:Consolas, Monaco, monospace;font-size:12px;line-height:18px;white-space:pre;"><em><strong>I2CAtomProTractorActivity</strong></em> :</span></p>
<p><pre class="brush: java; collapse: true; light: false; toolbar: true;">
package com.trandi.i2catompro;

import ioio.lib.api.DigitalOutput;
import ioio.lib.api.Uart;
import ioio.lib.api.exception.ConnectionLostException;
import ioio.lib.util.AbstractIOIOActivity;

import java.io.InputStream;
import java.lang.Thread.UncaughtExceptionHandler;

import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class I2CAtomProTractorActivity extends AbstractIOIOActivity {
	private static final String LOG_TAG = &quot;APT&quot;;
	private static final int RX_PIN = 4;
	private static final int TX_PIN = 5;
	private static final int UART_SPEED = 9600;

	private MyIOIOThread _IOIOthread;

	private TextView _varField;
	private TextView _msg;

	/**
	 * Called when the activity is first created. Here we normally initialise our GUI.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
			@Override
			public void uncaughtException(Thread thread, Throwable ex) {
				Log.e(LOG_TAG, &quot;&quot;, ex);
			}
		});

		setContentView(R.layout.main);
		_varField = (TextView) findViewById(R.id.textViewVarVal);
		_msg = (TextView) findViewById(R.id.textViewMsg);
	}

	/**
	 * This is the thread on which all the IOIO activity happens. It will be run
	 * every time the application is resumed and aborted when it is paused. The
	 * method setup() will be called right after a connection with the IOIO has
	 * been established (which might happen several times!). Then, loop() will
	 * be called repetitively until the IOIO gets disconnected.
	 */
	class MyIOIOThread extends AbstractIOIOActivity.IOIOThread {
		private DigitalOutput _onboardLED; // The on-board LED
		private Uart _uart;
		private InputStream _atomDataIS;
		private final byte[] _data = new byte[2];

		/**
		 * Called every time a connection with IOIO has been established.
		 * Typically used to open pins.
		 *
		 * @throws ConnectionLostException When IOIO connection is lost.
		 */
		@Override
		protected void setup() throws ConnectionLostException {
			msg(&quot;IOIO Connected !&quot;, null);

			try {
				_onboardLED  = ioio_.openDigitalOutput(0, true);

				// initialize the UART
				if(_uart != null) _uart.close();
				_uart = ioio_.openUart(RX_PIN, TX_PIN, UART_SPEED, Uart.Parity.NONE, Uart.StopBits.ONE);
				_atomDataIS = _uart.getInputStream();
				msg(&quot;Connected to UART&quot;, null);
			} catch (Throwable e) {
				msg(&quot;Can't connect to the UART (&quot; + RX_PIN + &quot;, &quot; + TX_PIN + &quot;, &quot; + UART_SPEED + &quot;)&quot;, e);
			}
		}

		/**
		 * Called repetitively while the IOIO is connected.
		 *
		 * @throws ConnectionLostException When IOIO connection is lost.
		 */
		@Override
		protected void loop() throws ConnectionLostException {
			try {
				if(_atomDataIS.available() &gt; 0) {
					onboardLED(true);
					if(_atomDataIS.read() == '#'){
						// this is a message for us, expect 2 more bytes
						_atomDataIS.read(_data, 0, _data.length);
						msg(&quot;Bytes[&quot; + _data[0] + &quot;, &quot; + _data[1] + &quot;]&quot;, null);

						// transform the 2 bytes into an integer
						final int number = _data[0] + _data[1] &lt;&lt; 8;

						// refresh the display (HAS to be on the UI Thread !)
						runOnUiThread(new Runnable() {
							@Override
							public void run() {
								_varField.setText(String.valueOf(number));
							}
						});
					}

					onboardLED(false);
				}

				// don't overheat the CPU
				Thread.sleep(10);
			} catch (Exception e) {
				msg(&quot;Can't read serial data&quot;, e);
			}
		}

		private void onboardLED(boolean on) throws ConnectionLostException{
			_onboardLED.write(!on);
		}

	} // end IOIOThread

	private void msg(final String msg, final Throwable e){
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				_msg.setText(msg + (e != null ? &quot; - &quot; + e.getMessage() : &quot;&quot;));
			}
		});
	}

	/**
	 * A method to create our IOIO thread.
	 */
	@Override
	protected AbstractIOIOActivity.IOIOThread createIOIOThread() {
		_IOIOthread = new MyIOIOThread();
		return _IOIOthread;
	}
</pre></p>
<p>The <em><strong>layout/main.xml</strong></em> :</p>
<p><pre class="brush: xml; collapse: true; light: false; toolbar: true;">
&lt;!--?&lt;span class=&quot;hiddenSpellError&quot; pre=&quot;&quot;--&gt;xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:orientation=&quot;vertical&quot;
    android:layout_width=&quot;fill_parent&quot;
    android:layout_height=&quot;fill_parent&quot;&gt;

&lt;TextView android:text=&quot;Inclination: &quot; android:id=&quot;@+id/textViewVar&quot; android:layout_width=&quot;wrap_content&quot; android:layout_height=&quot;wrap_content&quot;&gt;
id=&quot;@+id/textViewVarVal&quot; android:textAppearance=&quot;?android:attr/textAppearanceLarge&quot; android:layout_width=&quot;wrap_content&quot; android:layout_height=&quot;wrap_content&quot;&gt;
&lt;TextView  android:text=&quot;Message&quot; android:id=&quot;@+id/textViewMsg&quot;  android:layout_height=&quot;wrap_content&quot; android:layout_width=&quot;wrap_content&quot;&gt;&lt;/TextView&gt;

&lt;/LinearLayout&gt;
</pre></p>
<p>And finally the <em><strong>AndroidManifest.xml</strong></em> file :</p>
<p><pre class="brush: xml; collapse: true; light: false; toolbar: true;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
      package=&quot;com.trandi.i2catompro&quot;
      android:versionCode=&quot;1&quot;
      android:versionName=&quot;0.1&quot;&gt;
    &lt;uses-sdk android:minSdkVersion=&quot;3&quot; /&gt;
    &lt;uses-permission android:name=&quot;android.permission.INTERNET&quot;&gt;&lt;/uses-permission&gt;

    &lt;application android:icon=&quot;@drawable/icon&quot; android:label=&quot;@string/app_name&quot;&gt;
        &lt;activity android:name=&quot;.I2CAtomProTractorActivity&quot;
                  android:label=&quot;@string/app_name&quot;&gt;
            &lt;intent-filter&gt;
                &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
                &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;

    &lt;/application&gt;
&lt;/manifest&gt;
</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/trandi.wordpress.com/892/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/trandi.wordpress.com/892/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/trandi.wordpress.com/892/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/trandi.wordpress.com/892/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/trandi.wordpress.com/892/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/trandi.wordpress.com/892/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/trandi.wordpress.com/892/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/trandi.wordpress.com/892/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/trandi.wordpress.com/892/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/trandi.wordpress.com/892/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/trandi.wordpress.com/892/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/trandi.wordpress.com/892/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/trandi.wordpress.com/892/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/trandi.wordpress.com/892/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=892&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>https://trandi.wordpress.com/2011/10/19/electronic-anti-roll-system-for-tractor-or-how-to-connect-ioio-to-a-basic-atom/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="https://secure.gravatar.com/avatar/cf5070dd11dddb4b4fed449609ad09f0?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">trandi</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/10/bap40_ioio_iconiaa500.jpg?w=300" medium="image">
			<media:title type="html">BAP40_IOIO_ICONIAA500</media:title>
		</media:content>
	</item>
		<item>
		<title>VFD Clock Connects to the Internet</title>
		<link>https://trandi.wordpress.com/2011/09/26/vfd-clock-connects-to-the-internet/</link>
		<comments>https://trandi.wordpress.com/2011/09/26/vfd-clock-connects-to-the-internet/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 20:11:35 +0000</pubDate>
		<dc:creator>trandi</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[atmega]]></category>
		<category><![CDATA[fluorescent. display]]></category>
		<category><![CDATA[RN-134]]></category>
		<category><![CDATA[tube]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[vacuum]]></category>
		<category><![CDATA[VFD]]></category>
		<category><![CDATA[weather]]></category>
		<category><![CDATA[wifi]]></category>
		<category><![CDATA[wifly]]></category>
		<category><![CDATA[yahoo]]></category>

		<guid isPermaLink="false">http://trandi.wordpress.com/?p=868</guid>
		<description><![CDATA[Here is, finally, one week later than planned, the sequel to my initial Ice Tube VFD clock . It is able to : get the time from the internet and automatically synchronise itself (why have to set the time and use a battery to keep it running when disconnected, if we have Internet access ?) [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=868&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Here is, finally, one week later than planned, the sequel to my initial <a href="http://trandi.wordpress.com/2011/09/10/vacuum-fluorescent-display-clock-based-on-soviet-iv-18-tube/" target="_blank">Ice Tube VFD clock</a> .</p>
<span style="text-align:center; display: block;"><a href="https://trandi.wordpress.com/2011/09/26/vfd-clock-connects-to-the-internet/"><img src="http://img.youtube.com/vi/ZjUhav5uDgE/2.jpg" alt="" /></a></span>
<p>It is able to :</p>
<ol>
<li>get the <strong>time</strong> from the internet and automatically synchronise itself (why have to set the time and use a battery to keep it running when disconnected, if we have Internet access ?)</li>
<li>periodically fetch some <strong>weather</strong> data and display it</li>
<li>do <strong>searches on Twitter</strong> and display the 1st result</li>
</ol>
<p>So rather than &#8220;simply&#8221; displaying the time, every 15secs it alternates between the time, the weather and a Twitter message.</p>
<p><span id="more-868"></span>Building this clock from Ladyada&#8217;s kit was all nice and fun, but almost too simple to be fully rewarding&#8230;</p>
<p>So I started having a look at the <a href="https://github.com/adafruit/Ice-Tube-Clock" target="_blank">firmware</a> and trying to modify it to make it do more interesting stuff.</p>
<h2>Step 1 &#8211; Add scrolling text</h2>
<p>Adding custom text wasn&#8217;t hard, I just had to insert a new mode in the state machine logic, and then to make it scroll I had to call a custom method from one of the interrupts occurring every millisecond that would move all the display[] array (containing the text currently displayed) one position to the left.</p>
<div id="attachment_871" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_scrollinghelloworld.jpg"><img class="size-medium wp-image-871" title="2011.09.12_VFDClock_ScrollingHelloWorld" src="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_scrollinghelloworld.jpg?w=300&#038;h=197" alt="" width="300" height="197" /></a><p class="wp-caption-text">VFD Clock Scrolling Hello World</p></div>
<p>&nbsp;</p>
<p>The ease with which I was able to insert new logic into the code, and get something working in literally a couple of hours, shows how nicely the code was initially written&#8230; all the logic is in one big file, which might seem hard to follow initially, but it&#8217;s nicely commented and divided into methods&#8230; thank you Ladyada !</p>
<p>&nbsp;</p>
<h2>Step 2 &#8211; Connect to the serial port</h2>
<span style="text-align:center; display: block;"><a href="https://trandi.wordpress.com/2011/09/26/vfd-clock-connects-to-the-internet/"><img src="http://img.youtube.com/vi/iftO821zaWA/2.jpg" alt="" /></a></span>
<p>&nbsp;</p>
<p>There&#8217;s not much point in being able to display some custom text, if it has to be hard-coded into the firmware&#8230; so the obvious next step was to make it easy to send data to the AtMega168 which drives this clock.</p>
<p>I hesitated between the serial and the I2C ports. I&#8217;m a big fan of I2C which I like much more than simple serial, as you can have plenty of different slaves&#8230;</p>
<p>I however went for serial, mainly because there was already code in the firmware that was communicating on that port for debugging purposes. There was also <a href="http://www.ladyada.net/make/icetube/mods.html" target="_blank">already a mod</a> using this port, so overall it would be much quicker / easier to use this instead of I2C.</p>
<p>So let&#8217;s solder the wires to expose this port (pins 2 &amp; 3 of the AtMega 168) :</p>
<p>&nbsp;</p>
<div id="attachment_873" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_solderingserialwires.jpg"><img class="size-medium wp-image-873" title="2011.09.12_VFDClock_SolderingSerialWires" src="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_solderingserialwires.jpg?w=300&#038;h=129" alt="" width="300" height="129" /></a><p class="wp-caption-text">VFDClock Soldering Wires to the Serial Port</p></div>
<p>&nbsp;</p>
<p>I&#8217;ve also added 2 wires to GND and +5V.</p>
<p>Now we can mount the bottom of the case back :</p>
<p>&nbsp;</p>
<div id="attachment_874" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_solderingserialwires2.jpg"><img class="size-medium wp-image-874" title="2011.09.12_VFDClock_SolderingSerialWires2" src="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_solderingserialwires2.jpg?w=300&#038;h=127" alt="" width="300" height="127" /></a><p class="wp-caption-text">VFDClock Soldering Wires to the Serial Port 2</p></div>
<p>&nbsp;</p>
<p>And here is the final result, with the case mostly put back and the wires getting out of it through the battery hole:</p>
<p>&nbsp;</p>
<div id="attachment_875" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_solderingserialwires3.jpg"><img class="size-medium wp-image-875" title="2011.09.12_VFDClock_SolderingSerialWires3" src="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_solderingserialwires3.jpg?w=300&#038;h=216" alt="" width="300" height="216" /></a><p class="wp-caption-text">VFDClock Soldering Wires to the Serial Port 3</p></div>
<h2></h2>
<h2>Step 3 &#8211; Integrate a WiFi board (WiFly / RN-134)</h2>
<p>This is all nice and good, BUT a clock like this is not supposed to stay connected to a PC to keep receiving messages&#8230; it would be nice if it could just sit there by itself, and periodically get data from the Internet and display it&#8230;</p>
<p>The initial idea was to simply make it display some tweets, but then I thought it would be really simple and quite useful for when I leave for work in the morning to see some weather forecast. Also, as I was working on these 2 goals I realised that with an Internet connection it is really easy to get the current exact time, so why bother setting it up or making sure the crystal doesn&#8217;t draft&#8230; just synch it up automatically !</p>
<div>So after some research, it appeared that the easiest way to wirelessly connect a small micro-controller to the Internet would be by using a WiFly board. I didn&#8217;t go for the <a href="http://www.sparkfun.com/products/9954" target="_blank">Sparkfun shield</a>, as the form factor is too big, but for a board using the same RN-131 module.</div>
<div>Here it is, the <a href="http://www.rovingnetworks.com/surf_board.php" target="_blank">RN-134, made directly by rovingnetworks</a> and bought from mouser:</div>
<div>
<div id="attachment_878" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-12_wifly_justreceived.jpg"><img class="size-medium wp-image-878" title="2011.09.12_WiFly_JustReceived" src="http://trandi.files.wordpress.com/2011/09/2011-09-12_wifly_justreceived.jpg?w=300&#038;h=200" alt="" width="300" height="200" /></a><p class="wp-caption-text">WiFly RN-134 just received from Mouser</p></div>
</div>
<div>Here are some preliminary tests of this board:</div>
<div>
<div id="attachment_879" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_wiflyconnectedtopc.jpg"><img class="size-medium wp-image-879" title="2011.09.12_VFDClock_WiFlyConnectedToPC" src="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_wiflyconnectedtopc.jpg?w=300&#038;h=118" alt="" width="300" height="118" /></a><p class="wp-caption-text">WiFly connected to PC to check Internet connectivity</p></div>
<div id="attachment_880" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_wiflyconnectedtoclock_voltageadapter.jpg"><img class="size-medium wp-image-880" title="2011.09.12_VFDClock_WiFlyConnectedToClock_VoltageAdapter" src="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_wiflyconnectedtoclock_voltageadapter.jpg?w=300&#038;h=156" alt="" width="300" height="156" /></a><p class="wp-caption-text">WiFly (RN-134) connected to the VFD clock - voltage converter</p></div>
<p>&nbsp;</p>
<p>Do note the <a href="http://www.sparkfun.com/products/8745" target="_blank">voltage converter</a> between the two, as the clock microcontroller (AtMega 168) is 5V whereas the WiFly runs at 3.3V !</p>
<h3>The Ugly</h3>
<p>Everything looked good at this point, but unfortunately this was the beginning of a very frustrating week&#8230;</p>
<p>Now let’s have a quick look at what took the longest in this project: setting up the WiFly to make the HTTP requests and download the data&#8230;</p>
<p>This board is a great piece of equipment, don’t get me wrong, I love it&#8230; however there were some issues and it got very frustrating for a while.</p>
<p>I’ll also mention straight away that the Roving Networks support is great, I’ve never seen such a quick and knowledgeable reply !</p>
<p>In a nutshell, and without going into the numerous possible config details that this board offers I started by trying the obvious thing: use it in “HTTP mode” (<em>set ip proto 18</em>), which is supposed to allow one to simply specify the name of a server and the desired page and then the board will add the required HTTP headers.</p>
<p>Something doesn’t work quite right with this mode (probably adding some extra spaces / new lines) but believe it or not, I have spent an entire week-end trying to debug it&#8230;</p>
<p>The convoluted thing was that the same query was working when calling it from the PC (TeraTerm connected to the WiFly board) but would not when it was the AtMega microcontroller sending the commands !</p>
<p>Here are 2 threads with more details:</p>
<p><a href="http://groups.google.com/group/nycresistormicrocontrollers/browse_thread/thread/686b328bc10a8b36" target="_blank">http://groups.google.com/group/nycresistormicrocontrollers/browse_thread/thread/686b328bc10a8b36</a></p>
<p><a href="http://groups.google.com/group/london-hack-space/browse_thread/thread/4c40f6abc6dbad74" target="_blank">http://groups.google.com/group/london-hack-space/browse_thread/thread/4c40f6abc6dbad74</a></p>
<p>And by the way, a big THANK YOU to members of both the NYC and London hack spaces for their very valuable help !</p>
<p>Also, from what the roving networks support was saying, the HTTP mode should simply do this:<br />
<strong><em>&lt;remote string&gt;&lt;your data&gt;&lt;SPACE&gt;HTTP/1.0\nHost:&lt;SPACE&gt;&lt;the hostname in config&gt;\n\n</em></strong></p>
<p>which is what the HTTP standard specifies&#8230;</p>
<p>In any case, the solution was to simply go into “TCP mode” (<em>set ip proto 2</em> , the factory default) and manually construct the HTTP request, as you’ll see in the attached code.</p>
<p>And after a little more frustration, due to the fact that  I had reverted the board to factory defaults and had forgotten to remove the “remote string”, which meant that it kept adding “<em>*HELLO*</em>” to whatever I was sending &#8230; lol <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ,  I got it working!</p>
<p>Again, things look frustratingly simple now, but the very confusing thing with this 2<sup>nd</sup> problem was that for some reason the <em>weather.yahooapis.com</em> server would happily work in spite of the extra “<em>*HELLO*</em>” in the request, whereas <em>search.twitter.com</em> would not&#8230;</p>
<h3>The Beautiful</h3>
<p>Code is always beautiful <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Here is what I had to add to the basic firmware.</p>
<p>-         <strong><em>wiFly.h &amp; .c</em></strong> &#8211; deal with controlling the WiFi board, and constructing the HTTP requests</p>
<p>-         <em><strong>textParser.h &amp; .c</strong></em>– deal with parsing the text or XML outputs from the servers and search for data between 2 tags</p>
<p>-         <em><strong>serialMessages.h &amp; .c</strong></em> – deal with putting all this together and keep track of 3 different connections and parsers, one for each service</p>
<p>-         the few methods that I had to add to the main <em><strong>iv.c</strong></em> code which do the scrolling and periodically call the updates from the servers</p>
<p>-         and finally the <em><strong>util.h &amp; .c</strong></em> files, which are not mine, but I put here because I have done several modifications (don’t dare calling them “improvements” ! <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  )</p>
<p>If you’re really interested and want to replicate this mod without having to put together and compile the code yourself, then let me know and I could definitely send you a HEX file.</p>
<p><pre class="brush: cpp; collapse: true; light: false; toolbar: true;">
_________________________ wiFly.h

/*
 * wiFly.h
 *
 * Created: 17/09/2011 Author: trandi
 */

#ifndef WIFLY_H_
#define WIFLY_H_

#include &quot;util.h&quot;

char wf_httpOpen(const char* server, const char* page);

#endif /* WIFLY_H_ */

_________________________ wiFly.c

/*
 * wiFly.c
 *
 * Created: 17/09/2011 Author: trandi
 */

#include &quot;wiFly.h&quot;
#include &quot;util.h&quot;
#include &lt;util/delay.h&gt;
#include &lt;string.h&gt;

uint8_t findInResponse(const char * str){
	if(uart_waitChar(1000)){
		// wait for the first char
		char ch = uart_getchar();
		while(ch != 0 &amp;&amp; ch != str[0]){
			uart_waitChar(300);
			ch = uart_getchar();
		}

		if(ch != 0){
			for(uint8_t offset = 1; offset &lt; strlen(str); offset ++){
				uart_waitChar(300);
				if(uart_getchar() != str[offset]) return 0; // wrong char found
			}

			return 1; // good, found what we were looking for
		}
	}

	// nope, not good....
	return 0;
}

#define CMD(x) uart_emptyReadBuffer();uart_puts_nl(x);

/*
 * Immediately afterwards the response will be available on the serial link !
 * It waits a while for data to come back...
 */
char wf_httpOpen(const char* server, const char* page){
	CMD(&quot;exit&quot;)
	CMD(&quot;close&quot;)
	_delay_ms(250);
	uart_puts(&quot;$$$&quot;); // enter command mode
	_delay_ms(250);

	CMD(&quot;ver&quot;)
	if(! findInResponse(&quot;WiFly Ver&quot;)) return 'v';

	uart_puts(&quot;open &quot;); uart_puts(server); uart_puts_nl(&quot; 80&quot;);
	if(! findInResponse(&quot;*OPEN*&quot;)) return 'o';
	uart_puts(&quot;GET &quot;); uart_puts(page); uart_puts(&quot; HTTP/1.0\r\nHost: &quot;); uart_puts(server); uart_puts_nl(&quot;\r\n&quot;);

	return 'n';
}

_________________________ textParser.h

/*
 * textParser.h
 *
 * Created: 15/09/2011 Author: trandi
 */

#ifndef TEXTPARSER_H_
#define TEXTPARSER_H_

#include &quot;util.h&quot;

#define TEXT_DELIM '&quot;'
#define TEXT_SEP '-'

typedef struct {
	const char* server;
	const char* page;
	const char* tagBegin;
	const char* tagEnd;
	uint8_t	useTextDelimiters;
	uint8_t* usedTextIndices;
	uint8_t usedTextIndicesSize;

	uint8_t tagBeginSize;
	uint8_t tagEndSize;
	uint8_t tagBeginPos;
	uint8_t tagEndPos;
	uint8_t currentTextIsValid;
	uint8_t currentTextIndex;

	char msg[MAX_MSG_SIZE];
	uint8_t msgSize;
	char err;
	uint8_t diffCharsCount;
} text_parser_struc;

void tp_init(text_parser_struc* tp, const char* server, const char* page, const char* tagBegin, const char* tagEnd, uint8_t useTextDelimiters, uint8_t* usedTextIndices, uint8_t usedTextIndicesSize);
void tp_start(text_parser_struc* tp);
uint8_t tp_feedChar(text_parser_struc* tp, char newChar);
uint8_t tp_isMsgReady(text_parser_struc* tp);

#endif /* TEXTPARSER_H_ */

_________________________ textParser.c

/*
 * textParser.c
 *
 * Created: 15/09/2011  Author: trandi
 */

#include &lt;avr/pgmspace.h&gt;
#include &lt;string.h&gt;
#include &lt;ctype.h&gt;
#include &quot;textParser.h&quot;

void tp_init(text_parser_struc* tp, const char* server, const char* page, const char* tagBegin, const char* tagEnd, uint8_t useTextDelimiters, uint8_t* usedTextIndices, uint8_t usedTextIndicesSize){
	tp-&gt;server = server;
	tp-&gt;page = page;
	tp-&gt;tagBegin = tagBegin;
	tp-&gt;tagEnd = tagEnd;
	tp-&gt;useTextDelimiters = useTextDelimiters;
	tp-&gt;tagBeginSize = strlen(tagBegin);
	tp-&gt;tagEndSize = strlen(tagEnd);

	tp-&gt;usedTextIndices = usedTextIndices;
	tp-&gt;usedTextIndicesSize = usedTextIndicesSize;

	// default values
	tp-&gt;err = 'a';

/*
	uart_puts(&quot;Text Parser initialised with: &quot;);
	uart_puts(tagBegin);
	uart_puts(tagEnd);
	uart_puts(&quot;\n\r&quot;);
*/
}

void tp_start(text_parser_struc* tp){
	tp-&gt;tagBeginPos = 0;
	tp-&gt;tagEndPos = 0;
	tp-&gt;msgSize = 0;
	// if we don't use text delimiters then ALL text inside is valid
	tp-&gt;currentTextIsValid = tp-&gt;useTextDelimiters ? 0 : 1;
	tp-&gt;currentTextIndex = 0;
	tp-&gt;diffCharsCount = 0; // assume the message hasn't changed...

	storeChar(tp, TEXT_SEP);storeChar(tp, TEXT_SEP);storeChar(tp, TEXT_SEP);
}

uint8_t tp_isMsgReady(text_parser_struc* tp){
	return ((tp-&gt;tagEndPos &gt;= tp-&gt;tagEndSize) || (tp-&gt;msgSize &gt;= MAX_MSG_SIZE));
}

void storeChar(text_parser_struc* tp, char ch){
	if(ch != tp-&gt;msg[tp-&gt;msgSize]){
		tp-&gt;msg[tp-&gt;msgSize] = ch;
		tp-&gt;diffCharsCount ++;
	}
	tp-&gt;msgSize++;
}

uint8_t tp_feedChar(text_parser_struc* tp, char newChar){
	// can't store anymore chars, no point in continuing !
	if(tp_isMsgReady(tp)) return 1;

	if(tp-&gt;tagBeginPos &lt; tp-&gt;tagBeginSize){
		// still looking for the beginning tag
		if(newChar == tp-&gt;tagBegin[tp-&gt;tagBeginPos]){
			tp-&gt;tagBeginPos ++;
		}else{
			uint8_t prevPos = tp-&gt;tagBeginPos;

			// false hope, wrong tag, start from the beginning
			tp-&gt;tagBeginPos = 0;
			// start from the beginning with the latest chars received, which we know are the same as the beginning of _tagBegin. In case there are repetitions in the tag
			for(uint8_t i=1; i&lt;prevPos; i++) tp_feedChar(tp, tp-&gt;tagBegin[i]);
		}
	}else if(tp-&gt;tagEndPos &lt; tp-&gt;tagEndSize){
		if(tp-&gt;useTextDelimiters){
			if(tp-&gt;currentTextIsValid){
				// in the middle of valid text
				if(TEXT_DELIM == newChar){
					// end of valid text
					tp-&gt;currentTextIsValid = 0;
					tp-&gt;currentTextIndex ++;
				}else if (tp-&gt;usedTextIndices[tp-&gt;currentTextIndex]){
					// normal data, store it
					storeChar(tp, newChar);
				}
			}else{
				if(TEXT_DELIM == newChar){
					// beginning of valid text
					tp-&gt;currentTextIsValid = 1;
					// add a delimitator with the previous text
					if (tp-&gt;usedTextIndices[tp-&gt;currentTextIndex]) {
						storeChar(tp, TEXT_SEP);
					}
				}else {
					if(newChar == tp-&gt;tagEnd[tp-&gt;tagEndPos]){
						// this might be the end
						tp-&gt;tagEndPos ++;
						if(tp-&gt;tagEndPos &gt;= tp-&gt;tagEndSize){
							storeChar(tp, 0); //end of string
						}
					}else{
						uint8_t prevPos = tp-&gt;tagEndPos;

						// false hope, wrong tag, start from the beginning
						tp-&gt;tagEndPos = 0;
						// start from the beginning with the latest chars received, which we know are the same as the beginning of _tagBegin. In case there are repetitions in the tag
						for(uint8_t i=1; i&lt;prevPos; i++) tp_feedChar(tp, tp-&gt;tagEnd[i]);
					}
				}
			}
		}else { //! tp-&gt;useTextDelimiters
			if(newChar == tp-&gt;tagEnd[tp-&gt;tagEndPos]){
				// this might be the end
				tp-&gt;tagEndPos ++;
				if(tp-&gt;tagEndPos &gt;= tp-&gt;tagEndSize){
					storeChar(tp, 0); //end of string
				}
			}else if (tp-&gt;tagEndPos &gt; 0) {
				// we thought we started the end tag and actually not...
				uint8_t prevPos = tp-&gt;tagEndPos;

				// false hope, wrong tag, start from the beginning
				tp-&gt;tagEndPos = 0;
				// start from the beginning with the latest chars received, which we know are the same as the beginning of _tagBegin. In case there are repetitions in the tag
				for(uint8_t i=1; i&lt;prevPos; i++) tp_feedChar(tp, tp-&gt;tagEnd[i]);
			}else {
				// normal data, in the middle of the text store it
				storeChar(tp,  newChar);
			}
		}
	}

	// hasn't yet finish, there's only one way of finishing...
	return tp_isMsgReady(tp);
}

_________________________ serialMessages.h

/*
 * serialMessages.h
 *
 * Created: 17/09/2011  Author: trandi
 */

#ifndef SERIALMESSAGES_H_
#define SERIALMESSAGES_H_

typedef struct {
	uint8_t time_s;
	uint8_t time_m;
	uint8_t time_h;
} time_date_struc;

void sm_init(void (*funcSignalUpdt)(void));
time_date_struc* sm_getTime();
char* sm_getMsg(uint8_t switchMode);
void sm_updateTwitter();
void sm_updateWeather();

#endif /* SERIALMESSAGES_H_ */

_________________________ serialMessages.c

/*
 * serialMessages.c
 *
 * Created: 16/09/2011 Author: trandi
 */

#include &lt;util/delay.h&gt;
#include &quot;serialMessages.h&quot;
#include &quot;util.h&quot;
#include &quot;textParser.h&quot;
#include &quot;wiFly.h&quot;
#include &lt;stdlib.h&gt;

static char ERR[] = {'e', 'r', 'r', ' ', ' ', ' ', ' ', ' ', 0};
#define setErr(x, y) ERR[4] = x; ERR[5] = y

static uint8_t UTI_YAHOO_WEATHER[] = {1, 0, 1, 1, 1, 0};
static uint8_t UTI_TWITTER[] = {1};

text_parser_struc _yahooWeatherParser;
text_parser_struc _twitterParser;
text_parser_struc _timeParser;
time_date_struc _timeDate;

// pointer to the function to call when we receive a new message
void (*funcSignalUpdate)(void);

uint8_t _mode = 0; // 0 - weather, 1 - twitter

void sm_init(void (*funcSignalUpdt)(void)){
	funcSignalUpdate = funcSignalUpdt;

	tp_init(&amp;_yahooWeatherParser,
			&quot;weather.yahooapis.com&quot;,
			&quot;/forecastrss?w=44418&amp;u=c&quot;,  // London, in Celsius
			&quot;&lt;yweather:forecast&quot;,	// tag begin
			&quot;/&gt;&quot;,					// tag end
			1,						// do use the '&quot;' values delimiters, next params are used
			UTI_YAHOO_WEATHER,		// which bits of text to use
			6						// how many bits have we defined
	);

	tp_init(&amp;_twitterParser,
			&quot;search.twitter.com&quot;,
			&quot;/search.json?q=arduino&amp;rpp=1&quot;,
			&quot;\&quot;text\&quot;&quot;,				// tag begin
			&quot;\&quot;to_user_id\&quot;&quot;,		// tag end
			1,						// 0 if we wanted NO '&quot;' text delimiters, next 2 params are ignored !
			UTI_TWITTER,			// which bits of text to use
			1	// how many bits have we defined
	);

	tp_init(&amp;_timeParser,
			&quot;www.timeanddate.com&quot;,
			&quot;/worldclock/city.html?n=136&quot;,
			&quot;=big&gt;&quot;,				// tag begin
			&quot;&lt;/strong&gt;&quot;,			// tag end
			0,						// 0 if we wanted NO '&quot;' text delimiters, next 2 params are ignored !
			0,			// which bits of text to use
			0	// how many bits have we defined
	);
}

void getSerialMsg(text_parser_struc* tp){
	tp-&gt;err = '1';
	if(uart_waitChar(3000)){ // be generous with the initial wait !
		tp_start(tp);

		while(uart_waitChar(1000) &amp;&amp; ! tp_feedChar(tp, uart_getchar()));
		tp-&gt;err = '2';

		if(tp_isMsgReady(tp)) tp-&gt;err = 'n'; // everything ok

		// the message is done, but empty the buffer
		uart_emptyReadBuffer();
	}
}

char* sm_getMsg(uint8_t switchMode){
	if(switchMode){
		_mode = ! _mode;
	}

	if(_mode){
		setErr('y', _yahooWeatherParser.err);
		return _yahooWeatherParser.err == 'n' ? _yahooWeatherParser.msg : ERR;
	}else{
		setErr('w', _twitterParser.err);
		return _twitterParser.err == 'n' ? _twitterParser.msg : ERR;
	}
}

void sm_updateTwitter(){
	_twitterParser.err = wf_httpOpen(_twitterParser.server, _twitterParser.page);
	if(_twitterParser.err == 'n') {
		getSerialMsg(&amp;_twitterParser);

		// call the signal only if there are at least 10 different chars. For some reason there can be small diffs in messages...
		if(_twitterParser.diffCharsCount &gt; 10){
			_twitterParser.diffCharsCount = 0;
			funcSignalUpdate();
		}
	}
}

void sm_updateWeather(){
	_yahooWeatherParser.err = wf_httpOpen(_yahooWeatherParser.server, _yahooWeatherParser.page);
	if(_yahooWeatherParser.err == 'n') {
		getSerialMsg(&amp;_yahooWeatherParser);
	}
}

time_date_struc* sm_getTime(){
	_timeParser.err = wf_httpOpen(_timeParser.server, _timeParser.page);
	if(_timeParser.err == 'n') {
		getSerialMsg(&amp;_timeParser);

		// the msg should be something like Saturday, &quot;24 September 2011, 09:31:40 &quot; extract hours and minutes
		char num[2];
		num[0] = _timeParser.msg[_timeParser.msgSize - 9];
		num[1] = _timeParser.msg[_timeParser.msgSize - 8];
		_timeDate.time_h = atoi(num);
		num[0] = _timeParser.msg[_timeParser.msgSize - 6];
		num[1] = _timeParser.msg[_timeParser.msgSize - 5];
		_timeDate.time_m = atoi(num);
		num[0] = _timeParser.msg[_timeParser.msgSize - 3];
		num[1] = _timeParser.msg[_timeParser.msgSize - 2];
		_timeDate.time_s = atoi(num);
	}else{
		setErr('t', _timeParser.err);
		_timeDate.time_h = 0; _timeDate.time_m = 0; _timeDate.time_s = 0;
	}

	return &amp;_timeDate;
}

_________________________ util.h

#ifndef UTIL_H_
#define UTIL_H_

//BRR = (F_CPU / 16 / BaudRate ) - 1
#if (F_CPU == 16000000)
#define BRRL_2400 416    // for 16MHZ
#define BRRL_9600 103    // for 16MHZ
#define BRRL_19200 52    // for 16MHZ
#define BRRL_115200 8
#elif (F_CPU == 8000000)
#define BRRL_2400 207
#define BRRL_9600 52
#define BRRL_19200 26
#define BRRL_115200 3
#endif

#include &lt;inttypes.h&gt;

// very tricky, uses a lot of space !
// for some reason IF this gets too big and the &quot;Data&quot; part of the program goes beyond 90%,
// the text parser for yahoo weather doesn't work anymore... don't ask WHY !? :)
#define MAX_MSG_SIZE 60

//void delay_ms(unsigned char ms);
void delay_10us(uint8_t us);
void delay_s(uint8_t s);

int uart_putchar(unsigned char c);
void uart_init(uint16_t BRR);

unsigned char uart_getchar(void);
uint8_t uart_isCharAvailable(void);
void uart_emptyReadBuffer(void);
uint8_t uart_waitChar(uint16_t timeoutMs);

void uart_putc_hex(uint8_t b);
void uart_putw_hex(uint16_t w);
void uart_putdw_hex(uint32_t dw);

void uart_putw_dec(uint16_t w);
void uart_putdw_dec(uint32_t dw);
void uart_puts(const char* str);

void RAM_putstring(char *str);
void ROM_putstring(const char *str, uint8_t nl);

#define uart_puts_nl(x) uart_puts(x);uart_puts(&quot;\r\n&quot;)

#define putstring(x) ROM_putstring(PSTR(x), 0)
#define putstring_nl(x) ROM_putstring(PSTR(x), 1)

#define NOP asm(&quot;nop&quot;);
#define nop asm volatile (&quot;nop\n\t&quot;)

#endif /* UTIL_H_ */

_________________________ util.c

/***************************************************************************
 Ice Tube Clock firmware August 13, 2009
 (c) 2009 Limor Fried / Adafruit Industries
  Modified by Tr@ndi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the &quot;Software&quot;), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/

#include &lt;avr/io.h&gt;
#include &lt;avr/interrupt.h&gt;
#include &lt;util/delay.h&gt;
#include &lt;avr/pgmspace.h&gt;
#include &quot;util.h&quot;

void delay_10us(uint8_t ns)
{
  uint8_t i;

  while (ns != 0) {
    ns--;
    for (i=0; i&lt; 30; i++) {
      nop;
    }
  }
}

void delay_s(uint8_t s) {
  while (s--) {
    _delay_ms(1000);
  }
}

// setup the main UART
void uart_init(uint16_t BRR) {
  UBRR0 = BRR;               // set baudrate counter

  UCSR0B = _BV(RXEN0) | _BV(TXEN0);  // Enable receiver and transmitter
  UCSR0C = 3&lt;&lt;UCSZ00;  // Frame format: 8data, No parity, 1stop bit
  DDRD |= _BV(PD1);
  DDRD &amp;= ~_BV(PD0);

}

int uart_putchar(unsigned char c)
{
  loop_until_bit_is_set(UCSR0A, UDRE0);
  UDR0 = c;
  return 0;
}

unsigned char uart_getchar(void) {
	//if (uart_isCharAvailable())
	return UDR0;
	//return 0;
}

uint8_t uart_isCharAvailable(void) {
	return (UCSR0A &amp; _BV(RXC0));
}

void uart_emptyReadBuffer(void){
	char ch;
	while(uart_waitChar(100)) ch = uart_getchar();
}

uint8_t uart_waitChar(uint16_t timeoutMs){
	for(uint16_t i=0; i&lt;timeoutMs &amp;&amp; !uart_isCharAvailable(); i++) _delay_ms(1);
	return uart_isCharAvailable();
}

void ROM_putstring(const char *str, uint8_t nl) {
    for (uint8_t i=0; pgm_read_byte(&amp;str[i]); i++) {
        uart_putchar(pgm_read_byte(&amp;str[i]));
	}
	if (nl) {
		uart_putchar('\n'); uart_putchar('\r');
	}
}

void uart_puts(const char* str)
{
    while(*str){
        uart_putchar(*str++);
	}
}

void uart_putc_hex(uint8_t b)
{
    /* upper nibble */
    if((b &gt;&gt; 4) &lt; 0x0a)
        uart_putchar((b &gt;&gt; 4) + '0');
    else
        uart_putchar((b &gt;&gt; 4) - 0x0a + 'a');

    /* lower nibble */
    if((b &amp; 0x0f) &lt; 0x0a)
        uart_putchar((b &amp; 0x0f) + '0');
    else
        uart_putchar((b &amp; 0x0f) - 0x0a + 'a');
}

void uart_putw_hex(uint16_t w)
{
    uart_putc_hex((uint8_t) (w &gt;&gt; 8));
    uart_putc_hex((uint8_t) (w &amp; 0xff));
}

void uart_putdw_hex(uint32_t dw)
{
    uart_putw_hex((uint16_t) (dw &gt;&gt; 16));
    uart_putw_hex((uint16_t) (dw &amp; 0xffff));
}

void uart_putw_dec(uint16_t w)
{
    uint16_t num = 10000;
    uint8_t started = 0;

    while(num &gt; 0)
    {
        uint8_t b = w / num;
        if(b &gt; 0 || started || num == 1)
        {
            uart_putchar('0' + b);
            started = 1;
        }
        w -= b * num;

        num /= 10;
    }
}

void uart_putdw_dec(uint32_t dw)
{
    uint32_t num = 1000000000;
    uint8_t started = 0;

    while(num &gt; 0)
    {
        uint8_t b = dw / num;
        if(b &gt; 0 || started || num == 1)
        {
            uart_putchar('0' + b);
            started = 1;
        }
        dw -= b * num;

        num /= 10;
    }
}

_________________________ ADDED this bit AT THE END of iv.c

#define SCROLL_SPEED 200				// milliseconds
#define TIME_MSG_MODES_SWITCH_SPEED 15000   // milliseconds
#define TIME_MSG_TIME_UPDATE 3600	// seconds
#define TIME_MSG_WEATHER_UPDATE 3600	// seconds
#define TIME_MSG_TWITTER_UPDATE 60		// seconds

// only beeps if the alarm is on, so that we can control the stuff...
void myBeep() {
	if(alarm_on){
		beep(1500, 1);beep(3500, 1);beep(5000, 1);
	}
}

// Scrolling of the message.
void scrollMsg(){
	// Move the text
	uint8_t firstElem = display[1];
	for(uint8_t i = 1; i &lt; _msgSize; i++) display[i] = display[i+1];
	display[_msgSize] = firstElem;
}

// alternate between SHOW_TIME and SHOW_MSG
void alternateTimeMsgModes(){
	//tick();
	if(displaymode == SHOW_TIME){
		displaymode = SHOW_MSG;
		display_str(sm_getMsg(1));
	}else if(displaymode == SHOW_MSG){
		displaymode = SHOW_TIME;
		_msgSize = 0; //stop scrolling !
	}
}

void updateTime(){
	time_date_struc* timeDate_s = sm_getTime();
	time_h = timeDate_s-&gt;time_h;
	time_m = timeDate_s-&gt;time_m;
	time_s = timeDate_s-&gt;time_s;
}

// called from an interrupt, every millisecond, for short and vital tasks
void customInterruptPeriodicActions(){
	if(_msgSize &gt;= DISPLAYSIZE &amp;&amp; _myMillisCounter %  SCROLL_SPEED == 0) scrollMsg();
	if(_myMillisCounter % TIME_MSG_MODES_SWITCH_SPEED == 0) alternateTimeMsgModes();
}

uint16_t _lastPeriodicActionSecs = 0;
// called from the main loop, for LONGER running tasks
void customPeriodicActions(){
	// don't even do the next calculations if the seconds have not changed
	if(_lastPeriodicActionSecs != _mySecondsCounter){
		if(_mySecondsCounter % TIME_MSG_TIME_UPDATE == 0) updateTime();

		if(_mySecondsCounter % TIME_MSG_TWITTER_UPDATE == 0) sm_updateTwitter();
		if(_mySecondsCounter % TIME_MSG_WEATHER_UPDATE == 0) sm_updateWeather();

		_lastPeriodicActionSecs = _mySecondsCounter;
	}
</pre><br />
In <em><strong>iv.c</strong></em>, the 2 methods that &#8220;inject&#8221; my mod into the rest of the code are</p>
<ul>
<li><strong>customPeriodicActions()</strong>, called at the beginning of the infinite look within the <em>main()</em> method</li>
<li>and <em><strong>customInterruptPeriodicActions()</strong></em>, called in the middle of <em>SIGNAL (SIG_OVERFLOW0) {}</em> which occurs roughly every millisecond</li>
</ul>
<div id="attachment_883" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-25_vfdclock_finished_details.jpg"><img class="size-medium wp-image-883" title="2011.09.25_VFDClock_Finished_Details" src="http://trandi.files.wordpress.com/2011/09/2011-09-25_vfdclock_finished_details.jpg?w=300&#038;h=192" alt="" width="300" height="192" /></a><p class="wp-caption-text">WiFi VFDClock Finished</p></div>
<p>&nbsp;</p>
<p>And here is the final photo, installed in its rightful place, along my collection of miniature single malts <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>&nbsp;</p>
<div id="attachment_884" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-25_vfdclock_finished_finalposition.jpg"><img class="size-medium wp-image-884" title="2011.09.25_VFDClock_Finished_FinalPosition" src="http://trandi.files.wordpress.com/2011/09/2011-09-25_vfdclock_finished_finalposition.jpg?w=300&#038;h=217" alt="" width="300" height="217" /></a><p class="wp-caption-text">WiFi VFDClock Final Position</p></div>
<p>&nbsp;</p>
<p>As usual, if you&#8217;ve made it up to here and had the patience to read all my ramblings, then don&#8217;t hesitate to leave a commend and give some feedback&#8230;</p>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/trandi.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/trandi.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/trandi.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/trandi.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/trandi.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/trandi.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/trandi.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/trandi.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/trandi.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/trandi.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/trandi.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/trandi.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/trandi.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/trandi.wordpress.com/868/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=868&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>https://trandi.wordpress.com/2011/09/26/vfd-clock-connects-to-the-internet/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
	
		<media:content url="https://secure.gravatar.com/avatar/cf5070dd11dddb4b4fed449609ad09f0?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">trandi</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_scrollinghelloworld.jpg?w=300" medium="image">
			<media:title type="html">2011.09.12_VFDClock_ScrollingHelloWorld</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_solderingserialwires.jpg?w=300" medium="image">
			<media:title type="html">2011.09.12_VFDClock_SolderingSerialWires</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_solderingserialwires2.jpg?w=300" medium="image">
			<media:title type="html">2011.09.12_VFDClock_SolderingSerialWires2</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_solderingserialwires3.jpg?w=300" medium="image">
			<media:title type="html">2011.09.12_VFDClock_SolderingSerialWires3</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-12_wifly_justreceived.jpg?w=300" medium="image">
			<media:title type="html">2011.09.12_WiFly_JustReceived</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_wiflyconnectedtopc.jpg?w=300" medium="image">
			<media:title type="html">2011.09.12_VFDClock_WiFlyConnectedToPC</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-12_vfdclock_wiflyconnectedtoclock_voltageadapter.jpg?w=300" medium="image">
			<media:title type="html">2011.09.12_VFDClock_WiFlyConnectedToClock_VoltageAdapter</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-25_vfdclock_finished_details.jpg?w=300" medium="image">
			<media:title type="html">2011.09.25_VFDClock_Finished_Details</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-25_vfdclock_finished_finalposition.jpg?w=300" medium="image">
			<media:title type="html">2011.09.25_VFDClock_Finished_FinalPosition</media:title>
		</media:content>
	</item>
		<item>
		<title>Vacuum Fluorescent Display Clock based on Soviet IV-18 tube</title>
		<link>https://trandi.wordpress.com/2011/09/10/vacuum-fluorescent-display-clock-based-on-soviet-iv-18-tube/</link>
		<comments>https://trandi.wordpress.com/2011/09/10/vacuum-fluorescent-display-clock-based-on-soviet-iv-18-tube/#comments</comments>
		<pubDate>Sat, 10 Sep 2011 09:17:12 +0000</pubDate>
		<dc:creator>trandi</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[atmega168]]></category>
		<category><![CDATA[clock]]></category>
		<category><![CDATA[display]]></category>
		<category><![CDATA[fluorescent]]></category>
		<category><![CDATA[ice tube]]></category>
		<category><![CDATA[IV-18]]></category>
		<category><![CDATA[ladyada]]></category>
		<category><![CDATA[vacuum]]></category>
		<category><![CDATA[VFD]]></category>

		<guid isPermaLink="false">http://trandi.wordpress.com/?p=858</guid>
		<description><![CDATA[This week&#8217;s post is about my first attempt at (yet another ) VFD based clock. Given that I&#8217;m really no expert in vacuum tubes I have simply chosen to go with a kit. I don&#8217;t know if there are many types out there, but ladyada&#8217;s one, seemed really nicely done, reasonably priced and very very [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=858&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div id="attachment_859" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_finished.jpg"><img class="size-medium wp-image-859" title="2011.09.09_VFDClock_Finished" src="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_finished.jpg?w=300&#038;h=179" alt="" width="300" height="179" /></a><p class="wp-caption-text">VFD IV-18 Clock Finished and working</p></div>
<p><span id="more-858"></span></p>
<p>This week&#8217;s post is about my first attempt at (yet another <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ) VFD based clock.</p>
<p>Given that I&#8217;m really no expert in vacuum tubes I have simply chosen to go with a kit. I don&#8217;t know if there are many types out there, but <a href="http://www.ladyada.net/make/icetube/" target="_blank">ladyada&#8217;s one</a>, seemed really nicely done, reasonably priced and very very well documented.</p>
<p>Here&#8217;s the final result, for those that can&#8217;t be bothered with reading through the assembling and testing&#8230;</p>
<span style="text-align:center; display: block;"><a href="https://trandi.wordpress.com/2011/09/10/vacuum-fluorescent-display-clock-based-on-soviet-iv-18-tube/"><img src="http://img.youtube.com/vi/F-KBrI0_Lto/2.jpg" alt="" /></a></span>
<p>&nbsp;</p>
<p>I ordered the kit from the <a href="http://www.watterott.com/en/Ice-Tube-Clock-Kit" target="_blank">German website Watterott</a>, which is far cheaper that the options here in the UK (about 20%) and I&#8217;m quite happy with their speedy delivery and service.</p>
<p>Here are the various parts:</p>
<div id="attachment_861" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_parts.jpg"><img class="size-medium wp-image-861" title="2011.09.09_VFDClock_Parts" src="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_parts.jpg?w=300&#038;h=170" alt="" width="300" height="170" /></a><p class="wp-caption-text">IV-18 VFD Clock electronic parts</p></div>
<div id="attachment_862" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-0_vfdclock_thesoviet_iv-18_tube.jpg"><img class="size-medium wp-image-862" title="2011.09.0_VFDClock_TheSoviet_IV-18_Tube" src="http://trandi.files.wordpress.com/2011/09/2011-09-0_vfdclock_thesoviet_iv-18_tube.jpg?w=300&#038;h=90" alt="" width="300" height="90" /></a><p class="wp-caption-text">VFD Clock - the IV-18 vacuum tube itself</p></div>
<p>&nbsp;</p>
<p>I followed Ladyada&#8217;s tutorial and the soldering was really easy and quick (I really like the fact that she explains the role of almost each component and how they fit together, not simply how to solder !)&#8230;</p>
<div id="attachment_863" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_halfwaythrough.jpg"><img class="size-medium wp-image-863" title="2011.09.09_VFDClock_HalfWayThrough" src="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_halfwaythrough.jpg?w=300&#038;h=225" alt="" width="300" height="225" /></a><p class="wp-caption-text">IV-18 VFD Clock - half way through assembly</p></div>
<p>Also, you get to test each of the 3 parts of the circuit:</p>
<ol>
<li>the 5V power supply on the left</li>
<li>the microcontroller and its watch crystal in the middle</li>
<li>the high voltage boost supply on the right (the VFD tube needs around 50V to light up)</li>
</ol>
<p>Then came the hardest bit of the process, inserting and then soldering the VFD tube itself:</p>
<div id="attachment_864" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_hardestbit.jpg"><img class="size-medium wp-image-864" title="2011.09.09_VFDClock_HardestBit" src="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_hardestbit.jpg?w=300&#038;h=95" alt="" width="300" height="95" /></a><p class="wp-caption-text">IV-18 VFD Clock inserting the tube</p></div>
<div id="attachment_865" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_solderingtube.jpg"><img class="size-medium wp-image-865" title="2011.09.09_VFDClock_SolderingTube" src="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_solderingtube.jpg?w=300&#038;h=295" alt="" width="300" height="295" /></a><p class="wp-caption-text">IV-18 VFD Clock soldering the vacuum tube</p></div>
<p>&nbsp;</p>
<p>Luckily enough everything went smoothly (especially the tube positioning, which can&#8217;t really be fixed if done wrong the first time !) and the final test seems successful :</p>
<div id="attachment_866" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_itworks.jpg"><img class="size-medium wp-image-866" title="2011.09.09_VFDClock_ItWorks" src="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_itworks.jpg?w=300&#038;h=195" alt="" width="300" height="195" /></a><p class="wp-caption-text">VFD Clock - final test</p></div>
<p>&nbsp;</p>
<p>That&#8217;s it ! No code today, as the Atmega168 microcontroller comes pre-programmed, and the kit is really complete, even with the back-up battery !</p>
<p>However, I&#8217;m planning on hacking this clock (even if it required some soldering it felt too easy&#8230; <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ) and make it connect to other &#8220;stuff&#8221; and display some custom messages for example&#8230; so stay tuned !</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/trandi.wordpress.com/858/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/trandi.wordpress.com/858/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/trandi.wordpress.com/858/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/trandi.wordpress.com/858/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/trandi.wordpress.com/858/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/trandi.wordpress.com/858/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/trandi.wordpress.com/858/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/trandi.wordpress.com/858/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/trandi.wordpress.com/858/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/trandi.wordpress.com/858/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/trandi.wordpress.com/858/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/trandi.wordpress.com/858/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/trandi.wordpress.com/858/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/trandi.wordpress.com/858/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=858&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>https://trandi.wordpress.com/2011/09/10/vacuum-fluorescent-display-clock-based-on-soviet-iv-18-tube/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="https://secure.gravatar.com/avatar/cf5070dd11dddb4b4fed449609ad09f0?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">trandi</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_finished.jpg?w=300" medium="image">
			<media:title type="html">2011.09.09_VFDClock_Finished</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_parts.jpg?w=300" medium="image">
			<media:title type="html">2011.09.09_VFDClock_Parts</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-0_vfdclock_thesoviet_iv-18_tube.jpg?w=300" medium="image">
			<media:title type="html">2011.09.0_VFDClock_TheSoviet_IV-18_Tube</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_halfwaythrough.jpg?w=300" medium="image">
			<media:title type="html">2011.09.09_VFDClock_HalfWayThrough</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_hardestbit.jpg?w=300" medium="image">
			<media:title type="html">2011.09.09_VFDClock_HardestBit</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_solderingtube.jpg?w=300" medium="image">
			<media:title type="html">2011.09.09_VFDClock_SolderingTube</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-09_vfdclock_itworks.jpg?w=300" medium="image">
			<media:title type="html">2011.09.09_VFDClock_ItWorks</media:title>
		</media:content>
	</item>
		<item>
		<title>TI eZ430 Watch &#8211; Unboxing and Hello World</title>
		<link>https://trandi.wordpress.com/2011/09/03/ti-ez430-watch-unbox-hworld/</link>
		<comments>https://trandi.wordpress.com/2011/09/03/ti-ez430-watch-unbox-hworld/#comments</comments>
		<pubDate>Sat, 03 Sep 2011 20:31:18 +0000</pubDate>
		<dc:creator>trandi</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[chronos]]></category>
		<category><![CDATA[code composer]]></category>
		<category><![CDATA[ez430]]></category>
		<category><![CDATA[texas instruments]]></category>
		<category><![CDATA[ti]]></category>

		<guid isPermaLink="false">http://trandi.wordpress.com/?p=844</guid>
		<description><![CDATA[It&#8217;s been almost a month since my last post, and this is due among others, to some August holidays in France&#8230; This being the 1st week-end back in London I thought I HAD to hack something and blog about it&#8230; While away I have received the eZ430 Chronos Development Tool / Watch from Texas Instruments (have [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=844&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been almost a month since my last post, and this is due among others, to some August holidays in France&#8230; This being the 1st week-end back in London I thought I HAD to hack something and blog about it&#8230; <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>While away I have received the <a href="http://processors.wiki.ti.com/index.php/EZ430-Chronos?DCMP=Chronos&amp;HQS=Other+OT+chronoswiki" target="_blank">eZ430 Chronos Development Tool / Watch</a> from Texas Instruments (have I ever mentioned how great their service is, how quick and free the delivery, etc. &#8230; !? ) and therefore had to put aside my Android / IOIO related projects, and delve into this new gadget !</p>
<span style="text-align:center; display: block;"><a href="https://trandi.wordpress.com/2011/09/03/ti-ez430-watch-unbox-hworld/"><img src="http://img.youtube.com/vi/mt3Pcsp6kbo/2.jpg" alt="" /></a></span>
<p><span id="more-844"></span></p>
<h2>1. First impressions</h2>
<div id="attachment_845" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-08-30_ez430_unboxing1.jpg"><img class="size-medium wp-image-845" title="2011.08.30_eZ430_UnBoxing1" src="http://trandi.files.wordpress.com/2011/09/2011-08-30_ez430_unboxing1.jpg?w=300&#038;h=225" alt="" width="300" height="225" /></a><p class="wp-caption-text">TI eZ430 Watch Box</p></div>
<p>The packaging looks good, as good or even better than &#8220;real&#8221; watches&#8230; !</p>
<div id="attachment_846" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-08-30_ez430_unboxing2.jpg"><img class="size-medium wp-image-846" title="2011.08.30_eZ430_UnBoxing2" src="http://trandi.files.wordpress.com/2011/09/2011-08-30_ez430_unboxing2.jpg?w=300&#038;h=246" alt="" width="300" height="246" /></a><p class="wp-caption-text">TI eZ430 Watch opened box</p></div>
<div id="attachment_847" class="wp-caption aligncenter" style="width: 229px"><a href="http://trandi.files.wordpress.com/2011/09/2011-08-30_ez430_unboxing3.jpg"><img class="size-medium wp-image-847" title="2011.08.30_eZ430_UnBoxing3" src="http://trandi.files.wordpress.com/2011/09/2011-08-30_ez430_unboxing3.jpg?w=219&#038;h=300" alt="" width="219" height="300" /></a><p class="wp-caption-text">TI eZ430 Watch box contents</p></div>
<p>The contents are quite impressive, and TI seems to be taking these eval kits quite seriously : not only they include the USB programmer / debugger and an USB wireless access point for remote communication, but even a screwdriver and a couple of spare screws&#8230;</p>
<p>Have I mentioned that this kit costed me only 25$ (on sale from the original 50$) including free shipping to the UK !?  I know it&#8217;s all about advertising their products, but still&#8230; THANK YOU TI, this is a lot of stuff for ~ 15£ !</p>
<p>Now let&#8217;s get down to business and try to program this &#8220;beast&#8221;&#8230;</p>
<h2>2. Connect the hardware</h2>
<p>This is quite easy, and here&#8217;s how it looks with the internals exposed:</p>
<div id="attachment_848" class="wp-caption aligncenter" style="width: 303px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-03_ez430_mountback.jpg"><img class="size-medium wp-image-848" title="2011.09.03_eZ430_MountBack" src="http://trandi.files.wordpress.com/2011/09/2011-09-03_ez430_mountback.jpg?w=293&#038;h=300" alt="" width="293" height="300" /></a><p class="wp-caption-text">TI eZ430 Watch Internals</p></div>
<p>And now connected to the USB programmer / debugger :</p>
<div id="attachment_849" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-03_ez430_connectedtousbprogrammer.jpg"><img class="size-medium wp-image-849" title="2011.09.03_eZ430_ConnectedToUSBProgrammer" src="http://trandi.files.wordpress.com/2011/09/2011-09-03_ez430_connectedtousbprogrammer.jpg?w=300&#038;h=169" alt="" width="300" height="169" /></a><p class="wp-caption-text">TI eZ430 Watch Connected to the PC</p></div>
<h2>3. Software environment</h2>
<p>Now the hard stuff commences&#8230;</p>
<p>First look at the &#8220;Sports Watch&#8221; code (basically the firmware that the watch comes with) reminds me why I&#8217;m a Java programmer by trade&#8230;</p>
<p>Then I install the IAR development environment and all of a sudden memories from high school rush back to my mind&#8230; haven&#8217;t these guys notices we&#8217;re in 2011 !</p>
<p>I can&#8217;t even seem to be able to open an existing project&#8230; lol&#8230;</p>
<p>I try Code Composer Studio&#8230; much better, Eclipse based&#8230; Java rocks indeed, at least for the IDE !</p>
<div id="attachment_850" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/09/2011-09-03_ez430_codecomposerstudio.jpg"><img class="size-medium wp-image-850" title="2011.09.03_eZ430_CodeComposerStudio" src="http://trandi.files.wordpress.com/2011/09/2011-09-03_ez430_codecomposerstudio.jpg?w=300&#038;h=237" alt="" width="300" height="237" /></a><p class="wp-caption-text">Code Composer Studio - TI eZ430</p></div>
<p>Ok, I know that I&#8217;m just a newbie when it comes to embedded electronics and that IAR is probably one of the best tools out there, but hey I want to have fun, I&#8217;m not paid to do this ! It&#8217;s enough that I have to program these little marvels in C and that even the slightest string manipulation takes 5 lines of code, I want to enjoy my hobby ! <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>One issue worth nothing is also the general slowness of both the compilation and the download of the firmware to the eZ430. It takes around 1min 20secs even for the slightest change to get re-compiled and transfered over.</p>
<p>&nbsp;</p>
<h2>4. My first program</h2>
<p>All I want to do is create a new mode on the watch that simply displays &#8220;Hello World&#8221;. To make things slightly more complex, and because there are not enough digits, I want the text to <strong>scroll</strong>.</p>
<p>I struggle a couple of hours on a Friday night but finally start to appreciate TI&#8217;s code&#8230; it&#8217;s quite clean and well organised, in some sort of state machine.  All I need to do is replicate the already existing code for the &#8220;acceleration&#8221; mode (the one that periodically reads the accelerometer chip and displays the values on the screen).</p>
<h4>1. the code for the new MODULE</h4>
<p>The HEADER -<em> trandi.h</em></p>
<p><pre class="brush: cpp; collapse: true; light: false; toolbar: true;">
#ifndef TRANDI_H_
#define TRANDI_H_

// ******************************************
// Defines section
#define TRANDI_MODE_OFF		(0u)
#define TRANDI_MODE_ON		(1u)

// ******************************************
// Global Variable section
struct trandi
{
	// TRANDI_MODE_OFF, TRANDI_MODE_ON
	u8			mode;
	// Data to display
	u8  		msg[20];
};
extern struct trandi sTrandi;

// ******************************************
// Extern section
extern void reset_trandi(void);
extern void sx_trandi(u8 line);
extern void display_trandi(u8 line, u8 update);
extern u8 is_trandi_active(void);
extern void do_trandi_random(void);

#endif /*TRANDI_H_*/
</pre></p>
<p>The IMPLEMENTATION &#8211; <em>trandi.c</em></p>
<p><pre class="brush: cpp; collapse: true; light: false; toolbar: true;">
// ******************************************
// Include section

// system
#include &quot;project.h&quot;

// driver
#include &quot;display.h&quot;
#include &quot;vti_as.h&quot;

// logic
#include &quot;trandi.h&quot;
#include &quot;simpliciti.h&quot;
#include &quot;user.h&quot;
#include &quot;string.h&quot;

// ******************************************
// Global Variable section
struct trandi sTrandi;

// ******************************************
// Extern section

// ******************************************
// @fn          reset_trandi
// @brief       Reset / INIT trandi data.
// @param       none
// @return      none
// ******************************************
void reset_trandi(void)
{
	// Reset state is not active
	sTrandi.mode = TRANDI_MODE_OFF;

	strcpy(sTrandi.msg, (u8*)&quot;TRANDI HELLO WORLD  &quot;);
}

// ******************************************
// @fn          sx_trandi
// @brief       Button UP does nothing for now...
// @param       u8 line		LINE2
// @return      none
// ******************************************
void sx_trandi(u8 line)
{

}

// ******************************************
// @fn          display_trandi
// @brief       Display routine.
// @param       u8 line			LINE1
//		u8 update		DISPLAY_LINE_UPDATE_FULL, DISPLAY_LINE_CLEAR
// @return      none
// ******************************************
void display_trandi(u8 line, u8 update)
{
	if (update == DISPLAY_LINE_UPDATE_FULL)
	{
		display_chars(LCD_SEG_L1_3_0, sTrandi.msg, SEG_ON);
		display_symbol(LCD_ICON_HEART, SEG_ON_BLINK_ON);

		// Set mode
		sTrandi.mode = TRANDI_MODE_ON;
	}
	else if (update == DISPLAY_LINE_UPDATE_PARTIAL)
	{
		display_chars(LCD_SEG_L1_3_0, sTrandi.msg, SEG_ON);
	}
	else if (update == DISPLAY_LINE_CLEAR)
	{
		display_symbol(LCD_ICON_HEART, SEG_OFF);

		reset_trandi();
	}
}

// ******************************************
// @fn          is_trandi_active
// @brief       Returns 1 if trandi module is currently active and needs doing random stuff.
// @param       none
// @return      u8		1 = trandi module needs random stuff
// ******************************************
u8 is_trandi_active(void)
{
	return sTrandi.mode == TRANDI_MODE_ON;
}

void do_trandi_random(void)
{
	// Move the text
	u8 firstElem = sTrandi.msg[0];
	u8 len = sizeof(sTrandi.msg) / sizeof(u8);
	u8 i;
	for(i = 0; i &lt; len - 1; i++) sTrandi.msg[i] = sTrandi.msg[i+1];
	sTrandi.msg[len - 1] = firstElem;

	// Set display update flag
	display.flag.update_trandi = 1;
}
</pre></p>
<h4>2. modify the main MENU</h4>
<p>In the <em>menu.c</em> define this new structure</p>
<p><pre class="brush: cpp; collapse: false;">
// Line1 - Trandi secret function
const struct menu menu_L1_Trandi =
{
	FUNCTION(sx_trandi),				// direct function
	FUNCTION(dummy),					// sub menu function
	FUNCTION(display_trandi),			// display function
	FUNCTION(update_trandi),			// new display data
	&amp;menu_L1_Alarm,
};
u8 update_trandi(void)
{
	return (display.flag.update_trandi);
}
</pre></p>
<p>Add it to the chain of L1 menus, after the &#8220;Time&#8221; one, like so:</p>
<p><pre class="brush: cpp; collapse: false;">
const struct menu menu_L1_Time =
{
	FUNCTION(sx_time),			// direct function
	FUNCTION(mx_time),			// sub menu function
	FUNCTION(display_time),		// display function
	FUNCTION(update_time),		// new display data
	&amp;menu_L1_Trandi,
};
</pre></p>
<h4>3. modify the MAIN logic</h4>
<p>In <em>main.c</em> , update <em>init_global_variables()</em> with a pointer to the new menu (if we want it to be displayed by default) and a call to<em> reset_trandi()</em>.</p>
<p><pre class="brush: cpp; collapse: false;">
void init_global_variables(void)
{
	// --------------------------------------------
	// Apply default settings

	// set menu pointers to default menu items
//	ptrMenu_L1 = &amp;menu_L1_Time;
	ptrMenu_L1 = &amp;menu_L1_Trandi;
//	ptrMenu_L1 = &amp;menu_L1_Alarm;
//	ptrMenu_L1 = &amp;menu_L1_Heartrate;
...................
	// Reset acceleration measurement
	reset_acceleration();

	// Reset / init trandi stuff
	reset_trandi();

	// Reset BlueRobin stack
	reset_bluerobin();
}
</pre></p>
<p>Also add<em> if (request.flag.trandi) do_trandi_random();</em> in <em>process_requests()</em>.</p>
<h4>4. update the TIMER calls to enable scrolling</h4>
<p>There&#8217;s plenty of stuff in <em>timer.c</em> and we need to add a trigger on one of the periodic events, so that the trandi module gets &#8220;woken up&#8221; periodically and moves the custom string left.</p>
<p>Initially timer.c is EXCLUDED from the build, simply because I&#8217;m using the Core Edition of CSS which limits the max size of the code compiled (have I told you how much I love Arduino and the Open Source community !? <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ). However I could easily add back this file to be compiled with the others, without going beyond the limit &#8230; hooray&#8230;</p>
<p>In <em>TIMER0_A0_ISR()</em> (this is called every second which is really what we want !):</p>
<p><pre class="brush: cpp; collapse: false;">
	// Send a signal / do some random stuff every second on Trandi, WHEN enabled
	if (is_trandi_active())
	{
		request.flag.trandi = 1;
	}

	// If BlueRobin transmitter is connected, get data from API
	if (is_bluerobin()) get_bluerobin_data();
</pre></p>
<p>And that&#8217;s it ! The text &#8220;TRANDI HELLO WORLD&#8221; scrolls on the L1 display ! (notice that understandably there&#8217;s no easy way to fit a &#8220;W&#8221; in a 7 segments digit, so it&#8217;s not displayed correctly, I get a &#8220;-&#8221; instead&#8230;lol..;) )</p>
<p>At the end of the day, it&#8217;s not terribly complex, it works and it took me only about half a day to get here&#8230;</p>
<p><strong>If you&#8217;re reading this, then thank you for your patience and interest, and please don&#8217;t forget to leave your feedback which would be more than appreciated !</strong></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/trandi.wordpress.com/844/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/trandi.wordpress.com/844/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/trandi.wordpress.com/844/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/trandi.wordpress.com/844/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/trandi.wordpress.com/844/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/trandi.wordpress.com/844/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/trandi.wordpress.com/844/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/trandi.wordpress.com/844/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/trandi.wordpress.com/844/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/trandi.wordpress.com/844/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/trandi.wordpress.com/844/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/trandi.wordpress.com/844/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/trandi.wordpress.com/844/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/trandi.wordpress.com/844/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=844&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>https://trandi.wordpress.com/2011/09/03/ti-ez430-watch-unbox-hworld/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
	
		<media:content url="https://secure.gravatar.com/avatar/cf5070dd11dddb4b4fed449609ad09f0?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">trandi</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-08-30_ez430_unboxing1.jpg?w=300" medium="image">
			<media:title type="html">2011.08.30_eZ430_UnBoxing1</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-08-30_ez430_unboxing2.jpg?w=300" medium="image">
			<media:title type="html">2011.08.30_eZ430_UnBoxing2</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-08-30_ez430_unboxing3.jpg?w=219" medium="image">
			<media:title type="html">2011.08.30_eZ430_UnBoxing3</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-03_ez430_mountback.jpg?w=293" medium="image">
			<media:title type="html">2011.09.03_eZ430_MountBack</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-03_ez430_connectedtousbprogrammer.jpg?w=300" medium="image">
			<media:title type="html">2011.09.03_eZ430_ConnectedToUSBProgrammer</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/09/2011-09-03_ez430_codecomposerstudio.jpg?w=300" medium="image">
			<media:title type="html">2011.09.03_eZ430_CodeComposerStudio</media:title>
		</media:content>
	</item>
		<item>
		<title>Android IOIO Wii Motion Plus &#8211; Gyroscopes</title>
		<link>https://trandi.wordpress.com/2011/08/07/android-ioio-wii-motion-plus-gyros/</link>
		<comments>https://trandi.wordpress.com/2011/08/07/android-ioio-wii-motion-plus-gyros/#comments</comments>
		<pubDate>Sun, 07 Aug 2011 17:46:11 +0000</pubDate>
		<dc:creator>trandi</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[ARM 32bit]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Wii]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[gyro]]></category>
		<category><![CDATA[gyroscope]]></category>
		<category><![CDATA[i2c]]></category>
		<category><![CDATA[imu]]></category>
		<category><![CDATA[IOIO]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[motion]]></category>
		<category><![CDATA[phone]]></category>
		<category><![CDATA[TWI]]></category>
		<category><![CDATA[wii]]></category>

		<guid isPermaLink="false">http://trandi.wordpress.com/?p=835</guid>
		<description><![CDATA[First of all, the more I work with Android, the more I love it &#8230; ! It&#8217;s so cool to have both Linux and Java and everything is so open and hackable &#8230; ! Today I took some time to set up wireless debugging, in order to be able to see the logs at the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=835&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>First of all, the more I work with Android, the more I love it &#8230; ! It&#8217;s so cool to have both Linux and Java and everything is so open and hackable &#8230; !</p>
<div id="attachment_836" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/08/2011-08-07_wiimotionplus2.jpg"><img class="size-medium wp-image-836" title="2011.08.07_WiiMotionPlus2" src="http://trandi.files.wordpress.com/2011/08/2011-08-07_wiimotionplus2.jpg?w=300&#038;h=271" alt="" width="300" height="271" /></a><p class="wp-caption-text">Wii Motion Plus connected to the IOIO board and then to the Android phone</p></div>
<p><span id="more-835"></span></p>
<p>Today I took some time to set up wireless debugging, in order to be able to see the logs at the same time as the phone is connected through USB to the IOIO board. This was not a big issue for very simple programs, but it can quickly become veeery annoying !</p>
<p>As mentioned on this <a href="https://groups.google.com/d/topic/ioio-users/psmXR0E72Wk/discussion" target="_blank">forum topic</a> having a SSHd server running on the Android device and connecting through WiFi to it from the dev PC is a neat solution.</p>
<p>The best part is that I didn&#8217;t have to spend too much time following <a href="http://forum.xda-developers.com/showthread.php?t=442754" target="_blank">this kind</a> of complex tutorial. Here&#8217;s my approach:</p>
<ol>
<li>root the phone (was already like this, and lucky me I had bought it like this on eBay)</li>
<li>BUSYBOX &#8211; can be installed from the Android market for free</li>
<li>Install QuickSSHd (based on dropbear) from Android market for 0.99£ (I know, some people prefer software that is free like in free beer, and I think there are actually some other ads based versions out there, but I couldn&#8217;t be bothered)</li>
<li>and that&#8217;s it: you can uyse Putty or WinSCP to connect to your phone and transfer files</li>
</ol>
<p>Not only this allows me to do &#8220;<em>logcat</em>&#8221; remotely on the phone while it&#8217;s connected to the IOIO board, but I can also <em>SCP</em> the &#8220;<em>.adk</em>&#8221; files and install them manually, allowing me to basically NEVER disconnect it from the IOIO board.</p>
<p>This is AWESOME !</p>
<p>Now back to the main subject of the post&#8230;</p>
<span style="text-align:center; display: block;"><a href="https://trandi.wordpress.com/2011/08/07/android-ioio-wii-motion-plus-gyros/"><img src="http://img.youtube.com/vi/M0xXKD3BHDk/2.jpg" alt="" /></a></span>
<p>I basically want to transform the phone into a proper IMU, but it lacks gyroscopes. It already has accelerometers and compasses, but gyros are vital if we want to have any accuracy&#8230;</p>
<p>So what better solution than try to attach a Wii Motion Plus (containing 3 nice gyros, all conveniently exposed through a I2C interface) &#8230; ? The idea is to do something similar to <a href="http://trandi.wordpress.com/2011/01/16/wii-motion-plus-and-arduino/">this Arduino connection</a>, but with the smart phone, through the IOIO board.</p>
<p>Here are the details of the wiring, basically the same thing as for<a href="http://trandi.wordpress.com/2011/07/24/android-ioio-wii-nunchuck/"> the Wii Nunchuck</a>, the differences are in the code.</p>
<div id="attachment_840" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/08/2011-08-07_wiimotionplus1.jpg"><img class="size-medium wp-image-840" title="2011.08.07_WiiMotionPlus1" src="http://trandi.files.wordpress.com/2011/08/2011-08-07_wiimotionplus1.jpg?w=300&#038;h=265" alt="" width="300" height="265" /></a><p class="wp-caption-text">Wii Motion Plus - details of the wiring to the IOIO board</p></div>
<p>&nbsp;</p>
<p>And finally, the Java / Android code:</p>
<p><pre class="brush: java; collapse: true; light: false; toolbar: true;">

IOIOWiiMotionPlus.java
-------------------------------------------------------
package com.trandi.wii;

import ioio.lib.api.TwiMaster;
import ioio.lib.api.exception.ConnectionLostException;
import android.util.Log;

public class IOIOWiiMotionPlus {

private TwiMaster _twi;
// 7bit addressing
private static final int WII_WMP_ADDR_INIT = 0x53;
private static final int WII_WMP_ADDR = 0x52;
private final byte[] _dataBuffRaw = new byte[6];// array to store nunchuck data
private final int[] _dataBuff = new int[6];
private int _gyroX0, _gyroY0, _gyroZ0; //calibration zeroes
private int _gyroX, _gyroY, _gyroZ;

public boolean init(TwiMaster twi) throws ConnectionLostException, InterruptedException {
_twi = twi;

if(!initGyros()) {
Log.w(Util.LOG_TAG, &quot;Can't INTIALIZE Gyros. This might be normal if they are already initialized and the WMP hasn't been turned off.&quot;);
}
if(! calibrateGyrosZeroes()) {
Log.e(Util.LOG_TAG, &quot;Can't CALIBRATE Gyros&quot;);
return false;
}
return true;
}

private boolean initGyros() throws ConnectionLostException, InterruptedException {
// We don't care about what the WMP returs, but we need to provide a buffer to avoid a
// java.lang.NullPointerException
// E/WII     ( 1164):      at java.lang.System.arraycopy(Native Method)
// E/WII     ( 1164):      at ioio.lib.impl.TwiMasterImpl.dataReceived(TwiMasterImpl.java:141)
boolean res = _twi.writeRead(WII_WMP_ADDR_INIT, false, new byte[]{(byte)0xFE, 0x04}, 2, _dataBuffRaw, 0);
Thread.sleep(10);
return res;
}

public boolean readData() throws ConnectionLostException, InterruptedException {
// Send a request for data and read raw data
if( _twi.writeRead(WII_WMP_ADDR, false, new byte[]{0x00}, 1, _dataBuffRaw, _dataBuffRaw.length)){
for(int i=0; i&lt;_dataBuffRaw.length; i++) _dataBuff[i] = Util.fixJavaByte(_dataBuffRaw[i]);

//see http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus for info on what each byte represents
_gyroZ = ((_dataBuff[3] &gt;&gt; 2) &lt;&lt; 8) + _dataBuff[0] - _gyroZ0;
_gyroX = ((_dataBuff[4] &gt;&gt; 2) &lt;&lt; 8) + _dataBuff[1] - _gyroX0;
_gyroY = ((_dataBuff[5] &gt;&gt; 2) &lt;&lt; 8) + _dataBuff[2] - _gyroY0;

return true;
}

return false;
}


private boolean calibrateGyrosZeroes() throws ConnectionLostException, InterruptedException {
long tempX=0, tempY=0, tempZ=0;
_gyroX0 = 0; _gyroY0 = 0; _gyroZ0 = 0;
for (int i=0; i&lt;10; i++){
if (! readData()) return false;

tempZ += _gyroZ;
tempX += _gyroX;
tempY += _gyroY;

Thread.sleep(10);
}

// average 10 readings
_gyroZ0 = (int)(tempZ / 10);
_gyroX0 = (int)(tempX / 10);
_gyroY0 = (int)(tempY / 10);

return true;
}



public int getGyroX() {
return _gyroX;
}

public int getGyroY() {
return _gyroY;
}

public int getGyroZ() {
return _gyroZ;
}
}





MainActivity.java
-------------------------------------------------------
package com.trandi.wii;

import ioio.lib.api.PwmOutput;
import ioio.lib.api.TwiMaster;
import ioio.lib.api.exception.ConnectionLostException;
import ioio.lib.util.AbstractIOIOActivity;

import java.lang.Thread.UncaughtExceptionHandler;

import android.os.Bundle;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.TextView;


public class MainActivity extends AbstractIOIOActivity {
private TextView _varField;
private TextView _msg;
private FrameLayout _drawingFrame;
private Ball _ball;

/**
* Called when the activity is first created. Here we normally initialize our GUI.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.e(Util.LOG_TAG, &quot;&quot;, ex);
}
});

setContentView(R.layout.main);
_varField = (TextView) findViewById(R.id.textViewVarVal);
_msg = (TextView) findViewById(R.id.textViewMsg);

_drawingFrame = (FrameLayout) findViewById(R.id.drawingFrame);
_ball = new Ball(_drawingFrame.getContext(), 15);
_drawingFrame.addView(_ball);
}


/**
* This is the thread on which all the IOIO activity happens. It will be run
* every time the application is resumed and aborted when it is paused. The
* method setup() will be called right after a connection with the IOIO has
* been established (which might happen several times!). Then, loop() will
* be called repetitively until the IOIO gets disconnected.
*/
class IOIOThread extends AbstractIOIOActivity.IOIOThread {
private final IOIOWiiMotionPlus _wmp = new IOIOWiiMotionPlus();
private PwmOutput _led; // The on-board LED
private boolean _ledOn = false;



/**
* Called every time a connection with IOIO has been established.
* Typically used to open pins.
*
* @throws ConnectionLostException When IOIO connection is lost.
*/
@Override
protected void setup() throws ConnectionLostException {
try {
_led = ioio_.openPwmOutput(0, 300);
_led.setDutyCycle(0);

// initialize the I2C system, join the I2C bus,
TwiMaster twi = ioio_.openTwiMaster(0, TwiMaster.Rate.RATE_100KHz, false);
if(! _wmp.init(twi)) throw new Exception(&quot;Can't initialise WMP&quot;);
} catch (Exception e) {
msg(e);
}
}

/**
* Called repetitively while the IOIO is connected.
*
* @throws ConnectionLostException When IOIO connection is lost.
*/
@Override
protected void loop() throws ConnectionLostException {
try {
if(_wmp.readData()) {
_ball.setPos(mapPos(_wmp.getGyroX()), mapPos(_wmp.getGyroY()));

runOnUiThread(new Runnable() {
@Override
public void run() {
_varField.setText(_wmp.getGyroX() + &quot;  &quot; + _wmp.getGyroY() + &quot;  &quot; + _wmp.getGyroZ());
refreshBall();
}
});

_led.setDutyCycle(_ledOn ? 1 : 0);
_ledOn = ! _ledOn;

Thread.sleep(100);
}
} catch (Exception e) {
msg(e);
}
}
}

private static int mapPos(int value) {
return 150 + value / 30;
}

private void msg(Throwable e){
msg(&quot;ERR: &quot; + e.getMessage());
}

private void refreshBall() {
runOnUiThread(new Runnable() {
@Override
public void run() {
_drawingFrame.removeView(_ball);
_drawingFrame.addView(_ball);
}
});
}

private void msg(final String msg){
runOnUiThread(new Runnable() {
@Override
public void run() {
_msg.setText(&quot;MSG:  &quot; + msg);
}
});
}

/**
* A method to create our IOIO thread.
*
* @see ioio.lib.util.AbstractIOIOActivity#createIOIOThread()
*/
@Override
protected AbstractIOIOActivity.IOIOThread createIOIOThread() {
IOIOThread result = new IOIOThread();
return result;
}
}




Util.java
-------------------------------------------------------
package com.trandi.wii;

public class Util {
static final String LOG_TAG = &quot;WII&quot;;

/**
* Transforms a 0..127 -128 .. 0 range into a 128..0..-128 one
*/
static int fixJavaByte(byte init){
int result = init;
boolean negative = result &lt; 0;
if(negative) result = -result;
result = - result + 128;
if(negative) result = -result;
return result;
}
}




Ball.java
-------------------------------------------------------
package com.trandi.wii;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;

public class Ball extends View {
private float x = 0;
private float y = 0;
private final int r;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

public Ball(Context context, int r) {
super(context);
mPaint.setColor(0xFFFF0000);
this.r = r;
}

public void setPos(float x, float y) {
this.x = x;
this.y = y;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, r, mPaint);
}
}

</pre></p>
<p>&nbsp;</p>
<p>A few things / tricky bits worth mentioning:</p>
<ul>
<li>when calling <strong>TwiMaster.writeRead()</strong> you HAVE to provide an output buffer IF the slave will output something (EVEN IF you don&#8217;t care about it and the output read size is 0)</li>
<li>the <strong>Util.fixJavaByte()</strong> is important because in Java bytes are signed whereas in C they are not</li>
<li>also notice the 2 addresses that the WMP uses: one for the init and the other one for the subsequent requests</li>
</ul>
<p>The problem that I have is that the TWI library on the IOIO doesn&#8217;t time out if there&#8217;s no slave listening at the indicated address. This means that if I call init() and the WMP is already initialised, it will hang forever&#8230;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/trandi.wordpress.com/835/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/trandi.wordpress.com/835/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/trandi.wordpress.com/835/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/trandi.wordpress.com/835/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/trandi.wordpress.com/835/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/trandi.wordpress.com/835/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/trandi.wordpress.com/835/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/trandi.wordpress.com/835/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/trandi.wordpress.com/835/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/trandi.wordpress.com/835/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/trandi.wordpress.com/835/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/trandi.wordpress.com/835/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/trandi.wordpress.com/835/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/trandi.wordpress.com/835/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=835&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>https://trandi.wordpress.com/2011/08/07/android-ioio-wii-motion-plus-gyros/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:content url="https://secure.gravatar.com/avatar/cf5070dd11dddb4b4fed449609ad09f0?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">trandi</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/08/2011-08-07_wiimotionplus2.jpg?w=300" medium="image">
			<media:title type="html">2011.08.07_WiiMotionPlus2</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/08/2011-08-07_wiimotionplus1.jpg?w=300" medium="image">
			<media:title type="html">2011.08.07_WiiMotionPlus1</media:title>
		</media:content>
	</item>
		<item>
		<title>Android IOIO Wii Nunchuck</title>
		<link>https://trandi.wordpress.com/2011/07/24/android-ioio-wii-nunchuck/</link>
		<comments>https://trandi.wordpress.com/2011/07/24/android-ioio-wii-nunchuck/#comments</comments>
		<pubDate>Sun, 24 Jul 2011 17:46:38 +0000</pubDate>
		<dc:creator>trandi</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Wii]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[i2c]]></category>
		<category><![CDATA[IOIO]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[nunchuck]]></category>
		<category><![CDATA[TWI]]></category>
		<category><![CDATA[two wire interface]]></category>
		<category><![CDATA[wii]]></category>

		<guid isPermaLink="false">http://trandi.wordpress.com/?p=820</guid>
		<description><![CDATA[I&#8217;ve already written a post about how to connect the Wii Nunchuck to the Lego NXT using LeJOS, and there is also information on my blog about how to do the same thing with an Arduino (though I can&#8217;t find it right now, so no easy link&#8230;). It&#8217;s only fair that I explore the same [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=820&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve already written <a href="http://trandi.wordpress.com/2010/10/18/nxt-lejos-nunchuck/" target="_blank">a post about how to connect the Wii Nunchuck to the Lego NXT using LeJOS</a>, and there is also information on my blog about how to do the same thing with an Arduino (though I can&#8217;t find it right now, so no easy link&#8230;).</p>
<p>It&#8217;s only fair that I explore the same thing with an Android phone and the IOIO board.</p>
<span style="text-align:center; display: block;"><a href="https://trandi.wordpress.com/2011/07/24/android-ioio-wii-nunchuck/"><img src="http://img.youtube.com/vi/MR-G9-jylAc/2.jpg" alt="" /></a></span>
<p><span id="more-820"></span></p>
<p>The IOIO board is great !</p>
<p>I&#8217;ve already done a quick <a href="http://trandi.wordpress.com/2011/06/18/hello-ioio-android/" target="_blank">Hello World project</a>, and a slightly more <a href="http://trandi.wordpress.com/2011/07/03/android-ioio-rc-servo-or-esc/" target="_blank">advanced one, controlling a RC Servo</a>.</p>
<p>I&#8217;m keen on testing the I2C features&#8230; and what better way than trying to connect a Wii peripheral to the board !?</p>
<p>The Wii Nunchuck I&#8217;m using has had it&#8217;s PULL-UP resistors removed, because they were of quite low value and the Lego NXT couldn&#8217;t cope with it.</p>
<p>So now I&#8217;m using two2 2.2kOhms ones, connected directly from the Data and Clock lines to 3.3V.</p>
<p>The IOIO board works at 3.3V so this is perfect for the nunchuck.</p>
<p>Here&#8217;s an image of the wiring, using the<a href="http://www.solarbotics.com/products/31040/" target="_blank"> Nunchucky</a> 1.0 adapter from Solarbotics :</p>
<div id="attachment_821" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/07/ioionunchuck2.jpg"><img class="size-medium wp-image-821" title="IOIONunchuck2" src="http://trandi.files.wordpress.com/2011/07/ioionunchuck2.jpg?w=300&#038;h=202" alt="" width="300" height="202" /></a><p class="wp-caption-text">Wii Nunchuck connected to the IOIO board - Nunchucky 1.0 adapter from Solarbotics</p></div>
<p>And here is the whole project:</p>
<div id="attachment_822" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/07/ioionunchuck1.jpg"><img class="size-medium wp-image-822" title="IOIONunchuck1" src="http://trandi.files.wordpress.com/2011/07/ioionunchuck1.jpg?w=300&#038;h=254" alt="" width="300" height="254" /></a><p class="wp-caption-text">Android phone + IOIO board + Wii Nunchuck + Battery</p></div>
<p>Once you the data from the nunchuck is retrieved on the Android device, one can obviously do plently of useful things with it, but in my case I&#8217;ve just quickly put together a very basic 2D animation, that simply moved a red ball according to the nunchuck&#8217;s joystick:</p>
<div id="attachment_823" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/07/ioionunchuck3.jpg"><img class="size-medium wp-image-823" title="IOIONunchuck3" src="http://trandi.files.wordpress.com/2011/07/ioionunchuck3.jpg?w=300&#038;h=279" alt="" width="300" height="279" /></a><p class="wp-caption-text">Android IOIO - Wii Nunchuck - 2D animation</p></div>
<h3>And here is the Android Code</h3>
<p>First, the IOIONunchack class, that connects through I2C and does the data decoding:</p>
<p><pre class="brush: java; collapse: true; light: false; toolbar: true;">

package com.trandi.wiinunchuck;

import ioio.lib.api.IOIO;
import ioio.lib.api.TwiMaster;
import ioio.lib.api.exception.ConnectionLostException;

public class IOIONunchuck {
private int joy_x_axis;
private int joy_y_axis;
private int accel_x_axis;
private int accel_y_axis;
private int accel_z_axis;
private boolean z_button = false;
private boolean c_button = false;

private TwiMaster _twi;
private static final int WII_NUN_ADDR = 0x52;  // 7bit addressing.  It would be 0xA4 in 8bit
private static final int WII_NUN_MEM_ADDR = 0x40;
private final byte[] _dataBuff = new byte[6];// array to store nunchuck data

public boolean init(IOIO ioio) throws ConnectionLostException, InterruptedException {
// initialize the I2C system, join the I2C bus,
_twi = ioio.openTwiMaster(0, TwiMaster.Rate.RATE_100KHz, false);

// tell the nunchuck we're talking to it
return _twi.writeRead(WII_NUN_ADDR, false, new byte[]{WII_NUN_MEM_ADDR, 0x00}, 2, new byte[]{}, 0);
}

public boolean readData() throws ConnectionLostException, InterruptedException {
if(readRawData()){
for(int i=0; i&lt;_dataBuff.length; i++) _dataBuff[i] = nunchuckDecodeByte(_dataBuff[i]);

// transform into something meaningful
joy_x_axis = _dataBuff[0];
joy_y_axis = _dataBuff[1];
accel_x_axis = _dataBuff[2];
accel_y_axis = _dataBuff[3];
accel_z_axis = _dataBuff[4];

// byte nunchuck_buf[5] contains bits for z and c buttons
z_button = (_dataBuff[5] &amp; 0x01) == 0;
c_button = (_dataBuff[5] &amp; 0x02) == 0;

// it also contains the least significant bits for the accelerometer data so we have to check each bit of byte outbuf[5]
if ((_dataBuff[5] &amp; 0x03) &gt; 0) accel_x_axis += 2;
if ((_dataBuff[5] &amp; 0x04) &gt; 0) accel_x_axis += 1;

if ((_dataBuff[5] &amp; 0x05) &gt; 0) accel_y_axis += 2;
if ((_dataBuff[5] &amp; 0x06) &gt; 0) accel_y_axis += 1;

if ((_dataBuff[5] &amp; 0x07) &gt; 0) accel_z_axis += 2;
if ((_dataBuff[5] &amp; 0x08) &gt; 0) accel_z_axis += 1;

joy_x_axis = updateRange(joy_x_axis);
joy_y_axis = updateRange(joy_y_axis);
accel_x_axis = updateRange(accel_x_axis);
accel_y_axis = updateRange(accel_y_axis);
accel_z_axis = updateRange(accel_z_axis);

return true;
}

return false;
}

private boolean readRawData() throws ConnectionLostException, InterruptedException {
// 1. Send a request for data to the nunchuck
if(_twi.writeRead(WII_NUN_ADDR, false, new byte[]{0x00}, 1, _dataBuff, 0)) {

Thread.sleep(10);

// 2. read data
return _twi.writeRead(WII_NUN_ADDR, false, new byte[]{}, 0, _dataBuff, _dataBuff.length);
}

return false;
}

/**
* Transforms a 0..127 -128 .. 0 range into a 128..0..-128 one
*/
private static int updateRange(int init){
int result = init;
boolean negative = result &lt; 0;
if(negative) result = -result;
result = - result + 128;
if(negative) result = -result;
return result;
}

private byte nunchuckDecodeByte (byte x){
return (byte)((x ^ 0x17) + 0x17);
}

public int getJoy_x_axis() {
return joy_x_axis;
}

public int getJoy_y_axis() {
return joy_y_axis;
}

public int getAccel_x_axis() {
return accel_x_axis;
}

public int getAccel_y_axis() {
return accel_y_axis;
}

public int getAccel_z_axis() {
return accel_z_axis;
}

public boolean isZ_button() {
return z_button;
}

public boolean isC_button() {
return c_button;
}
}

</pre></p>
<p>Then, the MainActivity and the Ball classes, that do all the Android plubing :</p>
<p><pre class="brush: java; collapse: true; light: false; toolbar: true;">

______________ MainActivity.java

package com.trandi.wiinunchuck;

import ioio.lib.api.PwmOutput;
import ioio.lib.api.exception.ConnectionLostException;
import ioio.lib.util.AbstractIOIOActivity;
import android.os.Bundle;
import android.widget.FrameLayout;
import android.widget.TextView;

public class MainActivity extends AbstractIOIOActivity {
private TextView _varField;
private TextView _msg;
private FrameLayout _drawingFrame;
private Ball _ball;

/**
* Called when the activity is first created. Here we normally initialize our GUI.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//        Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
//            @Override
//            public void uncaughtException(Thread thread, Throwable ex) {
//                Log.e(&quot;&quot;, &quot;&quot;, ex);
//            }
//        });

setContentView(R.layout.main);
_varField = (TextView) findViewById(R.id.textViewVarVal);
_msg = (TextView) findViewById(R.id.textViewMsg);

_drawingFrame = (FrameLayout) findViewById(R.id.drawingFrame);
_ball = new Ball(_drawingFrame.getContext(), 15);
_drawingFrame.addView(_ball);
}

/**
* This is the thread on which all the IOIO activity happens. It will be run
* every time the application is resumed and aborted when it is paused. The
* method setup() will be called right after a connection with the IOIO has
* been established (which might happen several times!). Then, loop() will
* be called repetitively until the IOIO gets disconnected.
*/
class IOIOThread extends AbstractIOIOActivity.IOIOThread {
private final IOIONunchuck _nunchuck = new IOIONunchuck();
private PwmOutput _led; // The on-board LED
private boolean _ledOn = false;

/**
* Called every time a connection with IOIO has been established.
* Typically used to open pins.
*
* @throws ConnectionLostException When IOIO connection is lost.
*/
@Override
protected void setup() throws ConnectionLostException {
try {
_led = ioio_.openPwmOutput(0, 300);
_led.setDutyCycle(0);

_nunchuck.init(ioio_);
} catch (Exception e) {
msg(e);
}
}

/**
* Called repetitively while the IOIO is connected.
*
* @throws ConnectionLostException When IOIO connection is lost.
*/
@Override
protected void loop() throws ConnectionLostException {
try {
if(_nunchuck.readData()) {
_ball.setPos(mapPos(_nunchuck.getJoy_x_axis()), mapPos(_nunchuck.getJoy_y_axis()));

runOnUiThread(new Runnable() {
@Override
public void run() {
_varField.setText(String.valueOf(_nunchuck.getJoy_x_axis()));
refreshBall();
}
});

_led.setDutyCycle(_ledOn ? 1 : 0);
_ledOn = ! _ledOn;

Thread.sleep(100);
}
} catch (Exception e) {
msg(e);
}
}
}

private static int mapPos(int value) {
return 128 + value;
}

private void msg(Throwable e){
msg(&quot;ERR: &quot; + e.getMessage());
}

private void refreshBall() {
runOnUiThread(new Runnable() {
@Override
public void run() {
_drawingFrame.removeView(_ball);
_drawingFrame.addView(_ball);
}
});
}

private void msg(final String msg){
runOnUiThread(new Runnable() {
@Override
public void run() {
_msg.setText(&quot;MSG:  &quot; + msg);
}
});
}

/**
* A method to create our IOIO thread.
*
* @see ioio.lib.util.AbstractIOIOActivity#createIOIOThread()
*/
@Override
protected AbstractIOIOActivity.IOIOThread createIOIOThread() {
IOIOThread result = new IOIOThread();
return result;
}
}



_________ Ball.java

package com.trandi.wiinunchuck;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;

public class Ball extends View {
private float x = 0;
private float y = 0;
private final int r;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

public Ball(Context context, int r) {
super(context);
mPaint.setColor(0xFFFF0000);
this.r = r;
}

public void setPos(float x, float y) {
this.x = x;
this.y = y;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, r, mPaint);
}
}

</pre></p>
<p>And finally, the layout XML, for completeness, even though I doubt is very useful :</p>
<p><pre class="brush: xml; collapse: true; light: false; toolbar: true;">

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout android:id=&quot;@+id/AbsoluteLayout1&quot; xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
android:orientation=&quot;vertical&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
&gt;
&lt;ToggleButton android:text=&quot;ToggleButton&quot; android:layout_width=&quot;wrap_content&quot; android:layout_height=&quot;wrap_content&quot; android:id=&quot;@+id/button&quot;&gt;&lt;/ToggleButton&gt;
&lt;TextView android:text=&quot;Var&quot; android:id=&quot;@+id/textViewVar&quot; android:layout_width=&quot;wrap_content&quot; android:layout_height=&quot;wrap_content&quot;&gt;&lt;/TextView&gt;
&lt;TextView android:text=&quot;Var value&quot; android:id=&quot;@+id/textViewVarVal&quot; android:textAppearance=&quot;?android:attr/textAppearanceLarge&quot; android:layout_width=&quot;wrap_content&quot; android:layout_height=&quot;wrap_content&quot;&gt;&lt;/TextView&gt;
&lt;TextView  android:text=&quot;Message&quot; android:id=&quot;@+id/textViewMsg&quot;  android:layout_height=&quot;wrap_content&quot; android:layout_width=&quot;wrap_content&quot;&gt;&lt;/TextView&gt;
&lt;FrameLayout android:id=&quot;@+id/drawingFrame&quot; android:layout_height=&quot;match_parent&quot; android:layout_width=&quot;match_parent&quot;/&gt;
&lt;/LinearLayout&gt;

</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/trandi.wordpress.com/820/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/trandi.wordpress.com/820/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/trandi.wordpress.com/820/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/trandi.wordpress.com/820/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/trandi.wordpress.com/820/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/trandi.wordpress.com/820/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/trandi.wordpress.com/820/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/trandi.wordpress.com/820/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/trandi.wordpress.com/820/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/trandi.wordpress.com/820/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/trandi.wordpress.com/820/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/trandi.wordpress.com/820/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/trandi.wordpress.com/820/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/trandi.wordpress.com/820/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=820&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>https://trandi.wordpress.com/2011/07/24/android-ioio-wii-nunchuck/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="https://secure.gravatar.com/avatar/cf5070dd11dddb4b4fed449609ad09f0?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">trandi</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/07/ioionunchuck2.jpg?w=300" medium="image">
			<media:title type="html">IOIONunchuck2</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/07/ioionunchuck1.jpg?w=300" medium="image">
			<media:title type="html">IOIONunchuck1</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/07/ioionunchuck3.jpg?w=300" medium="image">
			<media:title type="html">IOIONunchuck3</media:title>
		</media:content>
	</item>
		<item>
		<title>Android &#8211; IOIO &#8211; RC Servo (or ESC)</title>
		<link>https://trandi.wordpress.com/2011/07/03/android-ioio-rc-servo-or-esc/</link>
		<comments>https://trandi.wordpress.com/2011/07/03/android-ioio-rc-servo-or-esc/#comments</comments>
		<pubDate>Sun, 03 Jul 2011 18:28:54 +0000</pubDate>
		<dc:creator>trandi</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[RC]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[ESC]]></category>
		<category><![CDATA[IOIO]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[pwm]]></category>
		<category><![CDATA[servo]]></category>

		<guid isPermaLink="false">http://trandi.wordpress.com/?p=807</guid>
		<description><![CDATA[This is a sequel to my first Hello World example with the IOIO / Android setup&#8230;. It simply adds a RC servo that is controlled by the same seekBar that controls the brightness of the LED. Here&#8217;s a quick and pretty good explanation of how the standard RC protocol (just a specific case of PWM [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=807&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This is a sequel to my first <a href="https://trandi.wordpress.com/2011/06/18/hello-ioio-android/" target="_blank">Hello World example</a> with the IOIO / Android setup&#8230;.</p>
<div id="attachment_808" class="wp-caption aligncenter" style="width: 253px"><a href="http://trandi.files.wordpress.com/2011/07/2011-07-03_withservo.jpg"><img class="size-medium wp-image-808" title="2011.07.03_WithServo" src="http://trandi.files.wordpress.com/2011/07/2011-07-03_withservo.jpg?w=243&#038;h=300" alt="" width="243" height="300" /></a><p class="wp-caption-text">Android + IOIO controlling a RC servo</p></div>
<p><span id="more-807"></span></p>
<p>It simply adds a RC servo that is controlled by the same seekBar that controls the brightness of the LED.</p>
<p>Here&#8217;s a quick and pretty good explanation of how the standard RC protocol (just a specific case of PWM really !) works :<br />
<a href="http://www.google.com/url?sa=D&amp;q=http://www.societyofrobots.com/robotforum/index.php%3Ftopic%3D4299.0" rel="nofollow" target="_blank">http://www.societyofrobots.com/robotforum/index.php?topic=4299.0</a><br />
To sum it up, the RC signal is a 50Hz signal, so 20ms period, out of which it is HIGH between 1 and 2ms. So the duty cycle of the signal has to be between 5 and 10%, with the neutral being around 7.5%.</p>
<p>Here&#8217;s a video showing the theory working:</p>
<span style="text-align:center; display: block;"><a href="https://trandi.wordpress.com/2011/07/03/android-ioio-rc-servo-or-esc/"><img src="http://img.youtube.com/vi/i3UCLBpACAQ/2.jpg" alt="" /></a></span>
<p>And here&#8217;s the Android code.</p>
<p>2 things to notice:</p>
<ol>
<li><strong><em>_servo = ioio_.openPwmOutput(5, 50); </em></strong> that starts a PWM signal on pin 5, with a 20ms period (corresponding to what the standard RC signal expects)</li>
<li><strong><em>_servo.setDutyCycle(0.05f + _varValue * 0.05f);</em></strong> which basically varies the duty cyle between 5 and 10% (depending on the position of the seekBar) so that the HIGH period of the signal will vary between 1 and 2 milliSeconds (again corresponding to that a RC servo/ESC or anything else, expects)</li>
</ol>
<p><pre class="brush: java; collapse: true; light: false; toolbar: true;">

package org.trandi.helloioio;

import ioio.examples.hello.R;
import ioio.lib.api.PwmOutput;
import ioio.lib.api.exception.ConnectionLostException;
import ioio.lib.util.AbstractIOIOActivity;
import android.os.Bundle;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends AbstractIOIOActivity {
private SeekBar _seekBarVar;
private TextView _varField;
private volatile float _varValue;

/**
* Called when the activity is first created. Here we normally initialize our GUI.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
_seekBarVar = (SeekBar) findViewById(R.id.seekBarVar);
_varField = (TextView) findViewById(R.id.textViewVarVal);

_seekBarVar.setMax(100);

_seekBarVar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
_varValue = (float)progress / (float)_seekBarVar.getMax();
_varField.setText(String.valueOf(_varValue));
}
});
}

/**
* This is the thread on which all the IOIO activity happens. It will be run
* every time the application is resumed and aborted when it is paused. The
* method setup() will be called right after a connection with the IOIO has
* been established (which might happen several times!). Then, loop() will
* be called repetitively until the IOIO gets disconnected.
*/
class IOIOThread extends AbstractIOIOActivity.IOIOThread {
// The on-board LED
private PwmOutput _led;
// a attached servo
private PwmOutput _servo;

/**
* Called every time a connection with IOIO has been established.
* Typically used to open pins.
*
* @throws ConnectionLostException When IOIO connection is lost.
*
* @see ioio.lib.util.AbstractIOIOActivity.IOIOThread#setup()
*/
@Override
protected void setup() throws ConnectionLostException {
_led = ioio_.openPwmOutput(0, 300);
_servo = ioio_.openPwmOutput(5, 50); // 20ms periods
}

/**
* Called repetitively while the IOIO is connected.
*
* @throws ConnectionLostException When IOIO connection is lost.
*
* @see ioio.lib.util.AbstractIOIOActivity.IOIOThread#loop()
*/
@Override
protected void loop() throws ConnectionLostException {
_servo.setDutyCycle(0.05f + _varValue * 0.05f);
_led.setDutyCycle(1 - _varValue);
}
}

/**
* A method to create our IOIO thread.
*
* @see ioio.lib.util.AbstractIOIOActivity#createIOIOThread()
*/
@Override
protected AbstractIOIOActivity.IOIOThread createIOIOThread() {
return new IOIOThread();
}
}

</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/trandi.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/trandi.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/trandi.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/trandi.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/trandi.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/trandi.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/trandi.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/trandi.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/trandi.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/trandi.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/trandi.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/trandi.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/trandi.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/trandi.wordpress.com/807/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=807&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>https://trandi.wordpress.com/2011/07/03/android-ioio-rc-servo-or-esc/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
	
		<media:content url="https://secure.gravatar.com/avatar/cf5070dd11dddb4b4fed449609ad09f0?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">trandi</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/07/2011-07-03_withservo.jpg?w=243" medium="image">
			<media:title type="html">2011.07.03_WithServo</media:title>
		</media:content>
	</item>
		<item>
		<title>Random Project Box</title>
		<link>https://trandi.wordpress.com/2011/06/28/random-project-box/</link>
		<comments>https://trandi.wordpress.com/2011/06/28/random-project-box/#comments</comments>
		<pubDate>Tue, 28 Jun 2011 20:01:11 +0000</pubDate>
		<dc:creator>trandi</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[box]]></category>
		<category><![CDATA[buttons]]></category>
		<category><![CDATA[joystick]]></category>
		<category><![CDATA[LCD display]]></category>

		<guid isPermaLink="false">http://trandi.wordpress.com/?p=799</guid>
		<description><![CDATA[&#8230;there&#8217;s not much to say about this one afternoon project&#8230; except that I have no idea what to do with it&#8230; ! I&#8217;m more than open to any interesting suggestion&#8230; One would actually wonder WHY would I build such a thing, if I don&#8217;t have any concrete application for it&#8230; the answer is simple : [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=799&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>&#8230;there&#8217;s not much to say about this one afternoon project&#8230; except that I have no idea what to do with it&#8230; ! <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I&#8217;m more than open to any interesting suggestion&#8230;</p>
<div id="attachment_800" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox5.jpg"><img class="size-medium wp-image-800" title="2011.06.19_ProjectBox5" src="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox5.jpg?w=300&#038;h=257" alt="" width="300" height="257" /></a><p class="wp-caption-text">Project Box Final</p></div>
<p><span id="more-799"></span></p>
<p>One would actually wonder WHY would I build such a thing, if I don&#8217;t have any concrete application for it&#8230; the answer is simple : &#8221; the joystick&#8221; ! I knew I wanted one, since I saw it the first time a year or so ago&#8230; I had been fighting with myself ever since, but finally a couple of weeks ago, I &#8220;had&#8221; to buy it&#8230; and now that I have it, I have to mount it on something&#8230; <img src='https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>&nbsp;</p>
<div id="attachment_801" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox1.jpg"><img class="size-medium wp-image-801" title="2011.06.19_ProjectBox1" src="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox1.jpg?w=300&#038;h=177" alt="" width="300" height="177" /></a><p class="wp-caption-text">Project Box 1</p></div>
<div id="attachment_802" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox2.jpg"><img class="size-medium wp-image-802" title="2011.06.19_ProjectBox2" src="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox2.jpg?w=300&#038;h=237" alt="" width="300" height="237" /></a><p class="wp-caption-text">Project Box 2</p></div>
<div id="attachment_803" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox3.jpg"><img class="size-medium wp-image-803" title="2011.06.19_ProjectBox3" src="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox3.jpg?w=300&#038;h=263" alt="" width="300" height="263" /></a><p class="wp-caption-text">Project Box 3</p></div>
<div id="attachment_804" class="wp-caption aligncenter" style="width: 310px"><a href="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox4.jpg"><img class="size-medium wp-image-804" title="2011.06.19_ProjectBox4" src="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox4.jpg?w=300&#038;h=260" alt="" width="300" height="260" /></a><p class="wp-caption-text">Project Box 4</p></div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/trandi.wordpress.com/799/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/trandi.wordpress.com/799/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/trandi.wordpress.com/799/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/trandi.wordpress.com/799/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/trandi.wordpress.com/799/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/trandi.wordpress.com/799/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/trandi.wordpress.com/799/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/trandi.wordpress.com/799/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/trandi.wordpress.com/799/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/trandi.wordpress.com/799/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/trandi.wordpress.com/799/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/trandi.wordpress.com/799/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/trandi.wordpress.com/799/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/trandi.wordpress.com/799/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=trandi.wordpress.com&amp;blog=5862660&amp;post=799&amp;subd=trandi&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>https://trandi.wordpress.com/2011/06/28/random-project-box/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="https://secure.gravatar.com/avatar/cf5070dd11dddb4b4fed449609ad09f0?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">trandi</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox5.jpg?w=300" medium="image">
			<media:title type="html">2011.06.19_ProjectBox5</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox1.jpg?w=300" medium="image">
			<media:title type="html">2011.06.19_ProjectBox1</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox2.jpg?w=300" medium="image">
			<media:title type="html">2011.06.19_ProjectBox2</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox3.jpg?w=300" medium="image">
			<media:title type="html">2011.06.19_ProjectBox3</media:title>
		</media:content>

		<media:content url="http://trandi.files.wordpress.com/2011/06/2011-06-19_projectbox4.jpg?w=300" medium="image">
			<media:title type="html">2011.06.19_ProjectBox4</media:title>
		</media:content>
	</item>
	</channel>
</rss>
