Android and Arduino Yun

The Arduino Yun is a WLAN capable development board featuring an ATMega microcontroller, as well as a separate chip running a small Linux distribution, making it a perfect candidate for
home automation projects
! This basic tutorial will show you how to
communicate wirelessly
between your
Arduino Yun
and an Android device.

Arduino part

To keep things simple, we will begin by using the official Bridge library example sketch from
here
. After this sketch is installed, you can control the Arduino’s pins by entering specific URLs in a web browser. You need to set
REST API access
to
open
in the Arduino Yun configuration webinterface in order for this to work.

For instance (assuming your Arduino’s IP address is 192.168.1.33)

  • http://192.168.1.33/arduino/digital/13/1
    will issue a digitalWrite(13,1). And since pin 13 is connected to the on-board LED, the LED is lit up.
  • http://192.168.1.33/arduino/digital/13/0
    will call digitalWrite(13,0), and thus disable the LED.
  • http://192.168.1.33/arduino/analog/13/128
    results in analogWrite(13,128), which will dim the on-board LED to about 50% intensity. In the following Android application, we will use this URL to dim the LED accordingly.

On the other hand, you can read the state of the Arduino’s pins.

  • http://192.168.1.33/data/get/D13
    will return a JSON string, which can be parsed to get the appropriate value.

Actually, entering the above URL will not directly read pin 13. It will simply try to return a key/value pair in the datastore with key = D13. By studying the Arduino sketch, you can see that there are various occurences of
Bridge.put(key, String(value))
. This is used to update the datastore on the Linux environment.

Using formatted URLs in this way is also known as
Representational state transfer (REST)
.

Android code

The Android part is rather straight forward. We will use the
above URLs to write and read values
on the Arduino. Some care must be taken since this involves networking. Therefore we must use separate threads, but we’ll get to that later. Let’s start a new Android project by adding a SeekBar and a TextView to our main layout.

    

    

The SeekBar slider will be used to
set the brightness of the on-board LED
. The current value is read back from the Arduino and displayed in our TextView. Since calling the URLs will be done in a different thread, we need some form of
inter thread communication
. Synchronized, wait and notify come to mind, but there are – at least in my opinion – easier to grasp mechanisms. For instance an
ArrayBlockingQueue
which is basically a FIFO queue that can safely be filled and emptied from multiple threads. So let’s create an ArrayBlockingQueue and fill it with values whenever the SeekBar slider is moved.

private ArrayBlockingQueue mQueue = new ArrayBlockingQueue(100);

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);

	mSeekBar = (SeekBar) findViewById(R.id.seekBar);
	mSeekBar.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) {
			mQueue.offer(progress);
		}
	});
}

For networking, we will use
two separate threads
, one for sending values to the Arduino and one for reading values from the Arduino. Here is the code for the sending thread. Full source code including both threads is available at the bottom of this post.

private static Thread sNetworkThreadSend = null;
private final Runnable mNetworkRunnableSend = new Runnable() {
	@Override
	public void run() {
		String urlBase = "http://"+ARDUINO_IP_ADDRESS+"/arduino/analog/13/";
		String url;
		try {
			while(!mStop.get()){
				int val = mQueue.take();
				if(val >= 0){
					HttpClient httpClient = new DefaultHttpClient();
					url = urlBase.concat(String.valueOf(val));
					HttpResponse response = httpClient.execute(new HttpGet(url));
				}
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		sNetworkThreadSend = null;
	}
};

Now we only need to start the threads and we’re golden. A good practice is to start network threads in the Activity’s onStart handler and stop them in the – you guessed right

– onStop handler. After all, one usually doesn’t want to waste resources when the Activity is hidden anyways.

private AtomicBoolean mStop = new AtomicBoolean(false);

@Override
protected void onStart() {
	mStop.set(false);
	if(sNetworkThreadSend == null){
		sNetworkThreadSend = new Thread(mNetworkRunnableSend);
		sNetworkThreadSend.start();
	}
	if(sNetworkThreadReceive == null){
		sNetworkThreadReceive = new Thread(mNetworkRunnableReceive);
		sNetworkThreadReceive.start();
	}
	super.onStart();
}

@Override
protected void onStop() {
	mStop.set(true);
	mQueue.clear();
	if(sNetworkThreadSend != null) sNetworkThreadSend.interrupt();
	if(sNetworkThreadReceive != null) sNetworkThreadReceive.interrupt();
	super.onStop();
}

The full Android and Arduino Yun REST example can be
downloaded from here
.

It get’s better…

The above example should be OK for many applications already, however, you will notice that
it takes quite a while until the LED finally reaches its desired value
. The reason for this is that the SeekBar’s onProgressChanged method is called many times when swiping the slider, and therefore our queue is filled much faster than the thread can handle. One quick fix is to clear to queue before adding a new element, like this:

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
	mQueue.clear();
	mQueue.offer(progress);
}

However, it’s still not very responsive. Instead of issuing a new http request for every value to be transmitted, it would be way better if we had some kind of a
continuous connection
between the Arduino and the Android device. As you can see in the example Bridge sketch, there is a YunServer class. Normally this server listens on port 5555 where URLs in the type of
http://arduino.ip/arduino/some/command
are forwarded for easy REST access. But we can also use the
YunServer to listen on another port
! We may then connect to this port using a socket on the Android side, and we will be able to continuously send new values
without the need to initiate a new http request
. The key is to initiate the YunServer with a different constructor, and also configure it so that it will listen on connections other than localhost, like so:

#include 
#include 
#include 

#define PORT 6666
YunServer server(PORT);

void setup() {
  Serial.begin(115200);
  Bridge.begin();
  server.noListenOnLocalhost();
  server.begin();
}

You can then accept clients in the main loop

void loop() {
  YunClient client = server.accept();

  if(client.connected()){
    String question = "What is your name?n";
    client.write((uint8_t*)&question[0], question.length());
    
    String response;
    while(client.connected()){
      if(client.available()){
        char cmd = client.read();
        if(cmd == 'n'){
          break;
        } else {
          response += String(cmd);
        }
      }
    }
    response = "Bye "+response+"n";
    client.write((uint8_t*)&response[0], response.length());
    
    client.stop();
  }

  delay(1000);
}

Try the above code and then test it from the command line by entering (obviously adjust the IP address)

[email protected]:~$ netcat 192.168.1.47 6666

Pretty neat, right?

For communicating with the Android device we will use a
slightly different sketch
, which you can
download from here
. The basic idea is, that we send the desired brightness value 0..255 in ASCII format from the Android device to the Arduino. Also, the new line symbol ‘n’ is used to detect the end of a brightness value. To send those values, we need to adjust our network thread as follows:

private OutputStream mOutputStream = null;
private Socket mSocket = null;

private static Thread sNetworkThread = null;
private final Runnable mNetworkRunnable = new Runnable() {
	@Override
	public void run() {
		try {
			mSocket = new Socket(ARDUINO_IP_ADDRESS, PORT);
			mOutputStream = mSocket.getOutputStream();
		} catch (UnknownHostException e1) {
			e1.printStackTrace();
			mStop.set(true);
		} catch (IOException e1) {
			e1.printStackTrace();
			mStop.set(true);
		}

		mQueue.clear(); // we only want new values
			
		try {
			while(!mStop.get()){
				int val = mQueue.take();
				if(val >= 0){
					mOutputStream.write((val+"n").getBytes());
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally{
			try {
				mStop.set(true);
				if(mOutputStream != null) mOutputStream.close();
				if(mSocket != null) mSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		sNetworkThread = null;
	}
};

The LED brightness should now adjust as smooth as butter. I have also tried to summarize the most important communication aspects of the whole application in the following diagram:



  1. The Arduino YunServer repeatedly accepts a client to connect
  2. In the network thread on the Android side, a socket is created connecting to the Arduino. Furthermore, an output stream on that socket is opened.
  3. Moving the SeekBar slider adds new values to our queue. This happens on the UI a.k.a main thread
  4. Within a loop in the network thread, values are taken from the queue and written to the acquired output stream.
  5. On the Arduino side, values are received by calling the read method on the client object

We hope this should give you a good starting point for your own Android/Arduino projects

Resources:

Here are again all the files for download.

Android and Arduino simple REST example:

Android and Arduino client/server example:

Using Android in Industrial Automation稿源:Using Android in Industrial Automation (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 移动互联 » Android and Arduino Yun

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录