assemble the RoverMk1

Finally i got the power plug parts from an electric store.
It’s time to solder the power plug and assemble the RoverMk1 for the first drive test.

Soldering Power Plug
SolderingPowerPlug

RoverMk1:
AbirdsEyeViewOfMK1

I tried to start Rover with a 6V battery pack. The Rover was only able to power a single DC motor. After switched to a 9V battery pack, the Rover finally started.

Upgrade firmware of Roving RN-XV wifi schield

If you are going to use a Roving RN-XV wifi schield for WPA2 Authentication
with your WLAN router, you have to upgrade firmware of the schield first. If not, this schield will probably not work with the WPA2 Authetication.

The Settings of my router is wpa+wpa2 mixed (tkip/AES-ccmp).

The firmware of Roving RN-XV can be upgraded in the following procedure.
First of all the Roving wifi schield should be connected with a putty terminal (which will be described in a another post later).

Type the following commend in putty to execute the upgrade

## Task1: clear settings ##
 > $$$
 > factory RESET
 > reboot
## Task2: After you swithed your Router to WPA1, set Roving schied##
 ## with WPA TKIP for internet access ##
 > set wlan auth 2 (WPA TKIP)
 > get wlan
 ## use get mac to retrieve Roving mac##
 ## if you have a mac filter in your Router ##
 > get mac
## Task3: set channel for auto detection ##
 > set wlan channel 0 (auto)
## Task4: set your SSID for Roving schield ##
 ## Please be aware that '$' should not contained in your SSID and Passphrase ##
 > set wlan ssid
 > xxxxxx
## Task5: set your Passphrase ##
 > set wlan phrase
 > xxxxxxx
 ## Task6: save your conf setting and reboot schield ##
 > save
 > reboot
##Report1: if your schield managed to connect to internet##
 ##you will get the following report after reboot##
 *Reboot*WiFly Ver 2.30, 10-26-2011 on RN-171
 MAC Addr=xxxxxxxx
 Auto-Assoc chan=11 mode=WPA1 SCAN OK
 Joining now..
 *READY*
 Associated!
 DHCP: Start
 DHCP in 1231ms, lease=864000s
 IF=UP
 DHCP=ON
 IP=192.168.xxx.xx:2000
 NM=255.255.255.0
 GW=192.168.xxx.1
 Listen on 2000
##Task6: Ping 10 times the gate way for test##
 > ping 192.168.xxx.xx 10
##Task7: get the ftp setting
 > get ftp
 ##Report2: you will receive the following report of default setting##
 FTP=208.109.78.34.21
 File=wifly-EZX.img
 User=roving
 Pass=Pass123
 Dir=public
 Timeout=40
 FTP_mode=0x0
##Task8: Also the most important Task##
 ##Roving update is moved to www.neelum.com##
 ##New IP of Roving update server is 68.178.254.124##
 ##rn-xv schield need the EZX image##
 > set ftp address 68.178.254.124
 > save
##Task9: execute firmware update##
 > ftp update
 ##Report3##
 FTP connecting to 68.178.254.124
 FTP file=33
 .........................................................
 FTP OK.
 UPDATE OK
##Task10: reinitialize factory RESET (important)##
 > factory RESET
 > reboot
## Notice: use the following appropriate command to suit your needs##
 "ftp update" //This will redirect the module to the new FTP server. You can then upgrade the module via the command below
 "set ftp address" // sets the IP address of your FTP server. Default is Roving FTP server
 "set ftp dir" // sets the directory in the FTP server. Default is public
 "set ftp user" //sets the user name of FTP server
 "set ftp pass" //sets the pass phrase of the FTP server
 ##
##Task9: After the firmware upgrade your can use WPA2 Authentication##
 ##Be aware only to use 2 (WPA1) or 4 (WPA2)##
 ## Authentication 3 (mixed) doesn't work with me##
 > set wlan auth 4
 > save
 > reboot

Now the Roving RN-XV Schield should be able to connect with your router through WPA2 Authentication.

Roving RN-XV WiFi shield connected to Arduino

Devices:

  • Arduino Uno
  • Roving RN-XV WiFi shield with RN-171 WiFly Mode
  • Power Regulator TS2940 (3.3V)
  • 2 breadboards
  • 7 LEDs
  • Resistors: 1×220 Ohm, 1x1K Ohm, 1x2K Ohm
  • FTDI USB to serial cable

Arduino Libraries:

  • WiFlySerial
  • SoftwareSerial
  • Streaming

Serial I/O to WLAN module

Requires 3.3V power supply

Pin 1: 3.3V power supply (use 3.3V (voltage regulator))
Pin 2: TX (connect to Pin 2 of Arduino, direct)
Pin 3: RX (connect to Pin 3 of Arduino, via voltage divider!)
Pin GND: connect to common ground

Arduino board normally has 5V output, but we need 3.3V for RX Pin

• Pin 3 of RN-XV (RX): connect to Pin 3 of Arduino
– via voltage divider!
– TX of Arduino uses +5V
– RX of RN-XV expects +3.3V

• Example: R1 = 3000 Ω, R2 = 1500 Ω
– U1 = 5V * R1 / (R1 + R2) = 3.33V

ArduinoWifiShield

The outcome of our experiment

Code for the Arduino Server


#include <Arduino.h>
#include <WiFlySerial.h>
#include <SoftwareSerial.h>
#include <Streaming.h>

#define BUFFSIZE 128

int ledPin = 6;
int data = 0;

// Wifi parameters
char ssid[] = "YOUR_SSID";
char passphrase[] = "YOUR_PASSPHRASE";

char *ip = (char *)malloc(BUFFSIZE);
char *ssidTest = (char *) malloc(BUFFSIZE);
char *mac = (char *) malloc(BUFFSIZE);

boolean success = false;

// Connect the WiFly TX pin to the Arduino RX pin  (Transmit from WiFly-> Receive into Arduino)
// Connect the WiFly RX pin to the Arduino TX pin  (Transmit from Arduino-> Receive into WiFly)
// 
// Connect the WiFly GND pin to an Arduino GND pin
// Finally, connect the WiFly BATT pin to the 3.3V pin (NOT the 5v pin)

#define ARDUINO_RX_PIN  2
#define ARDUINO_TX_PIN  3

WiFlySerial wifi(ARDUINO_RX_PIN ,ARDUINO_TX_PIN);

void reconnect(){

  Serial.println("Start to connect to WIFI...");

  char *macTest = wifi.getMAC(mac,BUFFSIZE);
  Serial.println("MAC-Adrress:");
  Serial.println(macTest);

  success = wifi.setAuthMode( WIFLY_AUTH_WPA2_PSK);
  if(success) Serial.println("--> Auth Mode set!");
  else Serial.println("--> FAILED to set Auth Mode!");

  success = wifi.setJoinMode(  WIFLY_JOIN_AUTO );
  if(success) Serial.println("--> Join Mode set!");
  else Serial.println("--> FAILED to set Join Mode!");

  success = wifi.setChannel("0");
  if(success) Serial.println("--> Channel set!");
  else Serial.println("--> FAILED to set Channel!");

  success = wifi.setPassphrase(passphrase);
  if(success) Serial.println("--> Passphrase set!");
  else Serial.println("--> FAILED to set Passphrase!");

  success = wifi.setSSID(ssid);
  if(success) Serial.println("--> SSID set!");
  else Serial.println("--> FAILED to set SSID!");

 //static IP because DHCP was not working
  success = wifi.setIP("192.168.2.64");
  if(success) Serial.println("--> IP set!");
  else Serial.println("--> FAILED to set IP!");

  success = wifi.setDHCPMode( WIFLY_DHCP_OFF );
  if(success) Serial.println("--> DHCP Mode set!");
  else Serial.println("--> FAILED to set DHCP Mode!");

  success = wifi.setLocalPort(3456);
  if(success) Serial.println("--> Port set!");
  else Serial.println("--> FAILED to set Port!");

  success = wifi.join();
  if(success) Serial.println("--> WIFI JOINED!");
  else Serial.println("--> FAILED to join WIFI!");

}

void setup(){

  pinMode(ledPin, OUTPUT);   // sets the pin as output

  Serial.begin(9600);

   reconnect();

  //Print SSID
  char *rv_ssidTest = wifi.getSSID(ssidTest,BUFFSIZE);
  Serial.println(rv_ssidTest);

  //Print IP
  char *rv_ip = wifi.getIP(ip,BUFFSIZE);
  Serial.println(rv_ip);

  free(ip);
  free(ssidTest);
  free(mac);

  Serial.println("Waiting for Clients to connect...");
  boolean connection = wifi.serveConnection();

  if(connection) Serial.println("Client connected!");
  else Serial.println("Internal error!");

}

void loop(){

  if(wifi.available() > 0){
     data = wifi.read();
     Serial.println(data); 
     analogWrite(ledPin,data);
  }

}

Client Code for Android Phone

package com.example.arduinoledapp;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

	private TextView txt;
	private int value = 0;
	private SeekBar bar;

	private OutputStream out; 
	private Socket client;

	private InetAddress address;
	private int port = 3456;

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

        try {
			address = InetAddress.getByName("192.168.2.64");
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        try {
			connectSocket();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        txt = (TextView) findViewById(R.id.textView1);

        bar = (SeekBar) findViewById(R.id.seekBar1);   
        bar.setMax(255); //Max value for Arduino PWM signal

        bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

			public void onStopTrackingTouch(SeekBar seekBar) {

			}

			public void onStartTrackingTouch(SeekBar seekBar) {
				// TODO Auto-generated method stub

			}

			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {

				value = seekBar.getProgress();
				txt.setText("Value: "+value);

				try {
					writeSocket(value);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		});

    }

    void connectSocket() throws IOException{

    	client = new Socket(address,port);
    	out = client.getOutputStream();

    	if((client != null) && (out != null) && client.isConnected()) Log.v("Connection","Connected to Server!");
    	else Log.v("Connection","Could not connect to Server!");

    }

    void writeSocket(int value) throws IOException{

    	Log.v("Value",""+value);

    	if(out != null){
	    	out.write(value);
	    	out.flush();
    	}
    }

    void closeSocket() throws IOException{
    	if(out != null && client != null){
	    	out.close();
	    	client.close();
    	}
    }

    @Override
    protected void onResume(){
        super.onResume();
    	try {
    		connectSocket();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	Log.v("onResume","onResume");
    }
    
    @Override
    protected void onPause(){
    	try {
			closeSocket();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	Log.v("onPause","onPause");
        super.onPause();
    } 
    
    // die Activities onRestart and onStop not used anymore, you can just delete it for clarity
    @Override
    protected void onRestart(){
        super.onRestart();
    	try {
    		connectSocket();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	//super.onResume(); A Typo
    	Log.v("onRestart","onRestart");
    }

    
    @Override
    protected void onStop(){
    	try {
			closeSocket();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	super.onStop();
    	Log.v("onStop","onStop");
    }

}

manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.arduinoledapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="15" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerHorizontal="true"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="135dp"
        android:paddingLeft="30dp"
        android:paddingRight="30dp" />

</LinearLayout>

Test Server

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

	public static void main(String[] args) throws IOException{

		ServerSocket server = new ServerSocket(3456);

		while (true) {

			Socket socket = server.accept();

			System.out.println("Client accepted!");

			Thread t = new ClientThread(socket);
			t.start();

		}
	}
}

class ClientThread extends Thread{

	private Socket socket;
	private InputStream in;
	private int c;

	public ClientThread(Socket socket) throws IOException{
		this.socket = socket;
		in = socket.getInputStream();
	}

	public void run(){
		try {
			while ((c = in.read())!=-1){
				System.out.println("Received: "+c);

			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

References:

Image from Wifly Datasheet:

http://www.rovingnetworks.com/products/RN_XV