Enclosure for Bug’s uc + Environment Sensing

This entry is part 10 of 10 in the series Android Robot

Printed out an enclosure for Bug’s circuit boards.

Enclosure for circuit boards

Enclosure for circuit boards

Also connected the 2 IR sensors on the bumper to the IOIO board for environment sensing. I’ve got the phone’s display to change colour based on whether or not something is detected in front of either of the two sensors.
Here’s the video:

However, the motors have stopped turning. I mistakenly connected the positive terminals from the sensors to Vin on the board instead of the 3.3V terminal and that seems to have damaged something. Oh well! I’ve just ordered a replacement IOIO board and a motor driver board.

Printing Bug’s Bumper

This entry is part 8 of 10 in the series Android Robot
The MakerBot Replicator 2 printing the robot bumper

The MakerBot Replicator 2 printing the robot bumper

The bumper was designed in Google Sketchup (see my previous post on this topic).
Google Sketchup saves files in .skp format. So the .skp file needed to be converted into .stl format using this su2stl plugin.
The .stl file was then imported using the MakerWare software that you can download from here.
MakerWare outputs a file (in .x3g format) that was transferred into the SD card of the printer. This file slices the model into layers that the printer uses to build the final 3D object.

A video of the build process:

And finally, the bumper on Bug, with two IR sensors for obstacle avoidance:

The bumper with two IR sensors on the robot

The bumper with two IR sensors on the robot

Phone Holder for Android Robot

This entry is part 6 of 10 in the series Android Robot

Phone Holder for Android Robot


Fashioned a phone holder out of an old phone holder for my car. Note that the phone front camera (which will be used for robot navigation and localization) has a clear view of the scene in front of the robot. The rear camera looks back and up and will be used to interact with people.

Obstacle Avoidance Using an Infrared Proximity Sensor

This entry is part 5 of 10 in the series Android Robot

The Sharp GP2Y0A21YK is an infrared (IR) proximity sensor available from Little Bird Electronics for about $15 and this was the 2nd sensor I attempted in getting the Android robot (shall we christen him Bug?) to avoid obstacles.
The sensor outputs an analog signal between 0.4V and 3.1V to indicate distances to obstacles from 80 cm away to 10 cm away.

Watch a video of Bug avoiding obstacles using a single IR sensor by clicking on the pic above.

The first sensor I used was an ultrasonic sensor, the Parallax Ping available for $35. This sensor has a much longer range (2cm – 3m). It has a digital input and the input (trigger) signal is followed by the return (pulse width indicates distance to target) output on the same pin. I was not able to get input and output signals on the same pin working with the IOIO board, and from the forums, this seems to be a problem other people have had too.

The Sharp IR sensor has 3 leads: +ve, GND and signal. Connect the +ve and GND leads from the sensor to the 3.3V and GND pins of the IOIO board. Connect the analog signal lead to pin 34 on the IOIO (peripheral input output pin).

Once you’ve connected the sensor to the IOIO, you have to write and download an app to your phone that does the sensing and obstacle avoidance.

The following is a code snippet that does this:

/**
 * Modified from code from the book Getting Started with IOIO (2011 Simon Monk)
 * and code from http://mitchtech.net/android-ioio-range-finder/
 * by Jay Chakravarty 2013
 *
 * Simple program for Obstacle Avoidance using one Infrared Sensor
 */

package com.ioiobook.rover;

import ioio.lib.api.AnalogInput;
import ioio.lib.api.DigitalOutput;
import ioio.lib.api.PwmOutput;
import ioio.lib.api.exception.ConnectionLostException;
//import ioio.lib.util.AbstractIOIOActivity;

import ioio.lib.util.BaseIOIOLooper;
import ioio.lib.util.IOIOLooper;

import ioio.lib.util.android.IOIOActivity;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.Window;

import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;


public class MainActivity extends IOIOActivity {

    private static final int AIN1_PIN = 41;
    private static final int AIN2_PIN = 40;
    private static final int PWMA_PIN = 39;
    private static final int PWMB_PIN = 45;
    private static final int BIN2_PIN = 44;
    private static final int BIN1_PIN = 43;
    private static final int STBY_PIN = 42;
    private static final int LED_PIN = 0;
    
    private static final int INFRARED_PIN = 34;//infrared analog input


    private static final int PWM_FREQ = 100;

    private float left_ = 0;
    private float right_ = 0;
    
    TextView mXTextView, mYTextView;

	SeekBar mXSeekBar, mYSeekBar;
	
    private float infraredOutputVolts = 0;



    /**
     * 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);
		mXTextView = (TextView) findViewById(R.id.tvX);
		mXSeekBar = (SeekBar) findViewById(R.id.sbX);
	    


	    

    }

    /**
     * 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 Looper extends BaseIOIOLooper {
        private DigitalOutput ain1_;
        private DigitalOutput ain2_;
        private PwmOutput pwma_;
        private PwmOutput pwmb_;
        private PwmOutput led_;
        private DigitalOutput bin2_;
        private DigitalOutput bin1_;
        private DigitalOutput stby_;
        
        private AnalogInput mXInput;

        /**
         * 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 {
        	
        	try{
	            ain1_ = ioio_.openDigitalOutput(AIN1_PIN);
	            ain2_ = ioio_.openDigitalOutput(AIN2_PIN);
	            pwma_ = ioio_.openPwmOutput(PWMA_PIN, PWM_FREQ);
	            pwmb_ = ioio_.openPwmOutput(PWMB_PIN, PWM_FREQ);
	            //pwma_ = ioio.openPwmOutput(new DigitalOutput.Spec(PWMA_PIN, OPEN_DRAIN), PWM_FREQ);
	            
	            
	            bin2_ = ioio_.openDigitalOutput(BIN2_PIN);
	            bin1_ = ioio_.openDigitalOutput(BIN1_PIN);
	            stby_ = ioio_.openDigitalOutput(STBY_PIN);
	            stby_.write(true); // On
	            led_  = ioio_.openPwmOutput(LED_PIN,PWM_FREQ);
	            
	            mXInput = ioio_.openAnalogInput(INFRARED_PIN);
        	} catch (ConnectionLostException e) {
				throw e;
			}
        }

        /**
         * Called repetitively while the IOIO is connected.
         * 
         * @throws ConnectionLostException
         *             When IOIO connection is lost.
         * @throws InterruptedException
         * 
         * @see ioio.lib.util.AbstractIOIOActivity.IOIOThread#loop()
         */
        
        public void loop() throws ConnectionLostException {
        		led_.setDutyCycle((float)0.9);
        		
        		
        		if( infraredOutputVolts*100 > 40 )
        		{
        			//Obstacle very close, turn tracks in opposite directions (turns left on the spot)
        			pwma_.setDutyCycle((float)0.8);
            		ain1_.write(true);
            		ain2_.write(false);
            	
            		pwmb_.setDutyCycle((float)0.8);
            		bin1_.write(false);
            		bin2_.write(true);
        		}
        		else if( infraredOutputVolts*100 > 25 )
        		{
        			//Obstacle a little further away, still turn
        			pwma_.setDutyCycle((float)0.0);
            		ain1_.write(false);
            		ain2_.write(true);
            		
            		pwmb_.setDutyCycle((float)0.8);
            		bin1_.write(false);
            		bin2_.write(true);
        		}
        		else
        		{
        			//No obstacles in immediate vicinity, move straight
        			pwma_.setDutyCycle((float)0.8);
            		ain1_.write(false);
            		ain2_.write(true);
            		
            		
            		pwmb_.setDutyCycle((float)0.8);
            		bin1_.write(false);
            		bin2_.write(true);
        		}
        		
        		   

            try {
            	infraredOutputVolts = mXInput.read();         
            	setSeekBars((int) (infraredOutputVolts * 100));

				setText(Float.toString((infraredOutputVolts * 100)));
            	Thread.sleep(10);
        	} catch (InterruptedException e) {
			}
        }

    }

    /**
     * A method to create our IOIO thread.
     * 
     * @see ioio.lib.util.AbstractIOIOActivity#createIOIOThread()
     */
    @Override
    protected IOIOLooper createIOIOLooper() {
        return new Looper();
    }
    
    private void setSeekBars(final int xValue) {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				mXSeekBar.setProgress(xValue);
			}
		});
	}

	private void setText(final String xText) {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				mXTextView.setText(xText);
			}
		});
	}

}

Connecting DC motors to the IOIO through the TB6612FNG, a motor driver break out board

This entry is part 3 of 10 in the series Android Robot

The IOIO has the capability to output Pulse Width Modulated (PWM) signals on its pins. You can vary the duty cycle of PWM signals to control the speed of DC motors. It’s recommended that you don’t connect the IOIO directly to motors, but use a motor driver breakout board in between.

The board I’m using to power the DC motors on my Android robot is the TB6612FNG.

And this is the circuit diagram for connecting the IOIO to the TB6612FNG, modified from the book Getting Started With IOIO, by Simon Monk.

IOIO to TB6612FNG motor driver board circuit diagram, modified from the book Getting Started with IOIO (2011 Simon Monk)

The only modifications I’ve made to Simon’s original circuit diagram are:

1. I’m using a 9V power supply instead of his 6V.
2. Consequently, I’ve connected Vm, the motor’s power supply to the 5V
output on the IOIO board instead of directly to the batteries as the
motors I’m using are 6V DC motors.

So, the following are the steps to do this:

1. Solder a header onto the side of the TB6612FNG board with pins Vm to GND.

Solder header onto motor driver board

2. Solder 7 pins onto IOIO board from outputs 39 to 45. Do this so that the pins stick out off the top of the IOIO board and the TB6612FNG can later be threaded onto these pins.

Solder 7 pins on IOIO outputs 39-45.

3. Solder the TB6612FNG to the IOIO using the pins from step 2, so that the outputs 39 to 45 on the IOIO are connected to inputs PWMA to GND on the TB6612FNG.

Solder the TB6612FNG to the IOIO pins

4. Finally, wire all connections as shown in the circuit diagram shown earlier.

IOIO connected to DC motors on robot through the TB6612FNG

Note that I’ve not soldered on a switch as yet in the image above.

Also, the PowerTech power supply I was using in my previous post turned out to be woefully inadequate in powering the motors as it was pumping out a mere 500 mA. So I used a 9V alkaline battery instead.

Watch the video of the robot motors being driven from the phone here:

If your motors turn in the wrong direction, just reverse the motor output polarities on the pins A1/A2 and B1/B2 of the TB6612FNG.

And here’s the Java code to run the motors from an Android app.

/**
 * Modified from code from the book Getting Started with IOIO (2011 Simon Monk)
 * by Jay Chakravarty 2012
 *
 * Simple program to connect to two motors and drive them forward 
 * using Pulse Width Modulation (PWM)
 */

package com.ioiobook.rover;

import ioio.lib.api.DigitalOutput;
import ioio.lib.api.PwmOutput;
import ioio.lib.api.exception.ConnectionLostException;
//import ioio.lib.util.AbstractIOIOActivity;

import ioio.lib.util.BaseIOIOLooper;
import ioio.lib.util.IOIOLooper;

import ioio.lib.util.android.IOIOActivity;

import android.os.Bundle;

public class MainActivity extends IOIOActivity {

    private static final int AIN1_PIN = 41;
    private static final int AIN2_PIN = 40;
    private static final int PWMA_PIN = 39;
    private static final int PWMB_PIN = 45;
    private static final int BIN2_PIN = 44;
    private static final int BIN1_PIN = 43;
    private static final int STBY_PIN = 42;
    private static final int LED_PIN = 0;

    private static final int PWM_FREQ = 100;

    private float left_ = 0;
    private float right_ = 0;

    //private RoverControlView roverControlView_;

    /**
     * Called when the activity is first created. Here we normally initialize
     * our GUI.
     */
   @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //roverControlView_ = new RoverControlView(this);
        //roverControlView_.setBackgroundColor(Color.WHITE);
        //setContentView(roverControlView_);
    }

    /**
     * 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 Looper extends BaseIOIOLooper {
        private DigitalOutput ain1_;
        private DigitalOutput ain2_;
        private PwmOutput pwma_;
        private PwmOutput pwmb_;
        private PwmOutput led_;
        private DigitalOutput bin2_;
        private DigitalOutput bin1_;
        private DigitalOutput stby_;

        /**
         * 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 {
            ain1_ = ioio_.openDigitalOutput(AIN1_PIN);
            ain2_ = ioio_.openDigitalOutput(AIN2_PIN);
            pwma_ = ioio_.openPwmOutput(PWMA_PIN, PWM_FREQ);
            pwmb_ = ioio_.openPwmOutput(PWMB_PIN, PWM_FREQ);
            //pwma_ = ioio.openPwmOutput(new DigitalOutput.Spec(PWMA_PIN, OPEN_DRAIN), PWM_FREQ);
            
            
            bin2_ = ioio_.openDigitalOutput(BIN2_PIN);
            bin1_ = ioio_.openDigitalOutput(BIN1_PIN);
            stby_ = ioio_.openDigitalOutput(STBY_PIN);
            stby_.write(true); // On
            led_  = ioio_.openPwmOutput(LED_PIN,PWM_FREQ);
        }

        /**
         * Called repetitively while the IOIO is connected.
         * 
         * @throws ConnectionLostException
         *             When IOIO connection is lost.
         * @throws InterruptedException
         * 
         * @see ioio.lib.util.AbstractIOIOActivity.IOIOThread#loop()
         */
        
        public void loop() throws ConnectionLostException {
        		led_.setDutyCycle((float)0.9);
        		
        		//Setting PWM Duty Cycle for 1st motor
        		//Note: This should not exceed 1.0
        		//Vary between 0 and 1 to achieve different speeds
        		pwma_.setDutyCycle((float)1.0);
        		ain1_.write(false);
        		ain2_.write(true);
        		
        		
        		//Setting PWM Duty Cycle for 2nd motor
        		//Note: This should not exceed 1.0
        		//Vary between 0 and 1 to achieve different speeds
        		pwmb_.setDutyCycle((float)1.0);
        		bin1_.write(false);
        		bin2_.write(true);
            

            try {
            	Thread.sleep(10);
        	} catch (InterruptedException e) {
			}
        }

    }

    /**
     * A method to create our IOIO thread.
     * 
     * @see ioio.lib.util.AbstractIOIOActivity#createIOIOThread()
     */
    @Override
    protected IOIOLooper createIOIOLooper() {
        return new Looper();
    }

}

Power to the IOIO

This entry is part 2 of 10 in the series Android Robot

The IOIO board (unlike the Arduino) does not come with headers attached on it, so you’ve got to solder them on yourself. Use the Arduino headers (again available from Little Bird Electronics) and solder them on to the board. I’ve used an 8 pin header on the VIN side of the board and a 6 pin header for the GND side of the board, which are by the way the two pins across which you can apply 5-15V DC (with a minimum of 500 mA current). I’m using a PowerTech battery eliminator with a variable (3-12V) output voltage power supply. In my experience, these often don’t supply the correct voltage and make sure you check the voltage across the output. In this particular case, I found that the 3V output actually gives a 5.75-6V output, which is what I’m using.

3 V DC Powertech power supply actually 5.75 - 6 V


Use the 3rd hand tool to solder the headers onto the IOIO board. First, thread the header pins onto the top of the IOIO board and tape it to it (so you can hold it up-side down without the header falling off). Then, hold the IOIO board upside-down using the 3rd hand and solder the underside of the board around the pins with a minimum amount of solder on each pin.

Use the 3rd hand to hold the IOIO in place while soldering the headers to it


Do this for both the headers. Finally, check that there is no solder-bridge across successive pins (using the continuity tester on your multimeter). Now make the connection from the positive terminal of the power supply (6V DC) to the VIN socket on the header and from the negative terminal of the power supply to any one of the three GND sockets on the header on the other side of the board. If all is well, your power light on the IOIO should glow red.
Note that I used Arduino Jumper cables which slot directly into the headers. You don’t have to solder them on, they are pretty tight in the headers (won’t come out unless you pull on them) and are perfect for testing. After you’ve finished soldering the headers onto the IOIO board, you can cut off the remainder of the pins protruding from the underside of the board just below the solder joints using a pair of scissors.

Power LED on IOIO glows red if your connections are right

Now, if you attach your phone through the USB cable to the IOIO, it should start charging from it.

Setting Up Your First IOIO Project In Eclipse

This entry is part 1 of 10 in the series Android Robot

If you’ve already been programming Android apps with Eclipse, as I have, you would’ve thought that the downloading and running of the HelloIOIO app would’ve been a synch. As with everything software, you would’ve been wrong. It is just impossible to get new apps involving new libs up and running without some fiddling around!

IOIO, if you don’t already know what it is, is a tiny PCB board invented by Ytai Ben-Tsvi that enables you to use your Android device (tablet/phone) to control sensors and actuators, so you can make it actually do something useful. Like using your cutting board to control the display of your Android device while looking up recipes so you don’t have to touch the screen using your messy hands!

Watch the video of the MIT Media Lab guys building this contraption here: http://player.vimeo.com/video/36862291

The board is sold in Australia by Little Bird Electronics for $55.

You can download the IOIO library and example code from here:
https://github.com/ytai/ioio/wiki/IOIO-Over-Bluetooth

Once you’ve unzipped the folder and imported all the projects into Eclipse, you will get the error “Project has no default.properties file! Edit the project properties to set one.”
This is because at some point, the Android Development Toolkit (ADT) for Eclipse had its properties files renamed from project.properties to default.properties.
So, I renamed the project.properties file to default.properties in all the imported projects (including the libraries IOIOLib, IOIOLibAccessory and the IOIOLibBT).
After this, the library projects IOIOLib, IOIOLibAccessory and IOIOLibBT compiled fine, but my HelloIOIO project still would not compile. I found that the problem was with the IOIOLibAccessory_src and the IOIOLibBT_src libraries in the HelloIOIO folder. I deleted these folders from the HelloIOIO folder as the project did not seem to be using these particular libraries and that solved the problem (for now) and the HelloIOIO project compiled successfully.

If you run the project, you should get the following image on your emulator screen.

Those of you un-familiar with the emulator need to know that you will need to give it 2-3 minutes to boot into the Android home screen and then when you unlock the screen (by swiping at the bottom), only then does the app show up.

If you now connect your phone to your computer through USB, you should get the same screen you got on your emulator on your phone.