Home of www.RoboHobby.com Java robotics project www.CubesAndCrosses.com
Train your logic skills in geometry
Create and delete one-color crosses
Play for free right in your browser!
Home-made CNC machine
Our new project -
How to make home-made CNC router
PICkit2 - Tutorials, Experiments
PICkit 2 - Small size USB programmer
from Microchip.
How to use it as a demo device for
USB programming in C language

www.RoboHobby.com
Home of www.RoboHobby.com
Java robotics project


Portable Notebook Table
How to make Portable Notebook Table.
Do it yourself!

Control robot on-line (GWT)
Control our robot on-line,
using GWT-based Web interface

Web-based (GWT) remote control for Java robotics.

Control robot on-line
Control our robot on-line,
using simple Web interface
(Old JSP-based version)

Web-based (JSP) remote control for Java robotics.

Sun SPOTs for robotics
Sun SPOT for hobby robotics.
How to use Sun SPOT devices
comunication of group of robots


Sun SPOT Accelerometer + Servo
Sun SPOT Balancing robot
Draft of new article


PICkit2 - Tutorials, Experiments
PICkit 2 - Small size USB programmer
from Microchip.
How to use it as a demo device for
USB programming in C language


Java SE SWING JSR-296 Example
How to run background task in
JSR-296 SWING application
with 'busy animation' in the status bar.
Useful addition to Netbeans template.

Java ME Code Examples
Java ME Source code examples
for robotics projects


Run Java ME Code Examples
How to run our Java ME code examples
for robotics projects


Java - work from home
Draft for article
'Java work from home.
(Java and self-employment)
Where and how to get
remote (telecommuting) job'


ScreenShots
See some screenshots of RoboHobby
Java/SWING application

See some screenshots of www.RoboHobby.com Java SWING application

Where programmers go
after age of 35?

Article in Russian
about job discriminationin
in IT industry:
'Where programmers go
after age of 35'?




Atmel NGW100 for
Java Hobby robotics

Set of articles about
Atmel NGW100 for
Java Hobby Robotics




Canon A570 IS + CHDK for
Kite Aerial Photography

How to use photo camera Canon A570 IS
with CHDK for kite aerial photography

Plastic box for Canon A570 IS
for Kite Aerial Photography (KAP)

How to make plastic box for Canon A570 IS

Kite Aerial Photography
Create your own hand-made kite for KAP
and do snapshots from a kite

Create your own hand-made kite for Kite Aerial Photography (KAP) and do snapshots from a kite, using cell phone or camera.

RoboHobby Kite
How to install and use
J2ME program on your cell phone,
make spy camera from it
and do snapshots from a kite

Picavet Suspension
Hand-made 'Picavet Suspension' for
Kite Aerial Photography (KAP).
How to make it by yourself.

Compact Picavet Suspension
Aluminum Home-made compact
'Picavet Suspension' for
Kite Aerial Photography (KAP).
You can fold it and make it
portable.

How to fly 'Flow form' kite in calm (No Wind) condiction.
Green Island KAP photos
Photo views from kite of
'Green Island'

Green Island
Some views from the ground
of rectreation zone
'Green Island'

KAP Wind Maps
Web-Map-based project
for local win measurement



Simple Spam Protection
Simple Spam Email Protection -
GWT-based code example


Under Linux
Install and Run RoboHobby application under
KNOPPIX 5.0


Under Windows
Install and Run RoboHobby application under
MS Windows XP


Platforms for Java Robotics
Which hardware/os platform to choose
for hobby robotics?



Download
Download RoboHoby Software

SpyGear's 'Spy Robot'
Article about reconstruction RC toy 'Spy Robot'
How to make robot with web camera or
with cell phone on a board from it


Load to your phone
Download RoboHobbyJ2ME application
right to your Siemens S75 cell phone.
Now no need to load it to PC, unzip, etc.


RoboHobby Linux Live CD
RoboHobby Linux Live CD
is ready for download.


Projects
List of old and current RoboHobby projects.

Hardware
List of what we use as a hardware

Software
List of software, we use in our projects

Computer vision
Vision is the main sense of our robots.
See some Java algorithms we use

Tips-n-Tricks
Some advices about hardware and software tricks

PIC Programming
(firmware)

Assembler program for PIC16F628A
Communication program for sending
commands from cell phone to motors.
Driver for motor controller.


RoboHobbyPlugin
Open Source project on
SourceForge, Java brain
for the robot

How to update Java
on KNOPPIX 5.0

Set of articles about how to remove
old version of Java (JRE or JDK)
on KNOPPIX and install new one
on remastered CD
Part 1 (Just test new Java)

Part 2
(Place new Java on Linux Live CD)



Java to EXE
Article about how to compile Java
programs to native binary code
(EXE for Windows)


Range of Bluetooth, Wi-Fi, ZigBee
What is the a real connection distance
of typical Bluetooth and Wi-Fi,
ZigBee or other RF devices?



What is inside?

What is inside web camera
'Genius Look 312P'?
How to re-construct it,
improve and use in robotics.

What is inside web camera
'Genius VideoCAM GE111'?
How to re-construct it,
improve and use in robotics.

What is inside web/photo camera
'Genius G-Shot D612'?
How to use it for
Kite Aerial Photography (KAP).


Sun SPOTs (in Russian)
Sun SPOT for hobby robotics.
Introduction lecture in Russian.




About
Some info about this site

About EATJ Java hosting
Some info about EATJ Java server-side
JSP/Servlet hosting



Short description of www.RoboHobby.com in German In German
Short description of www.RoboHobby.com
in German


Short description of www.RoboHobby.com in French In French
Short description of www.RoboHobby.com
in French


Short description of www.RoboHobby.com in Spanish In Spanish
Short description of www.RoboHobby.com
in Spanish


Short description of www.RoboHobby.com in Italian In Italian
Short description of www.RoboHobby.com
in Italian


Short description of www.RoboHobby.com in Russian In Russian
Short description of www.RoboHobby.com
in Russian







www.RoboHobby.com

Is it possible to create balancing robot, using Sun SPOT and small servomotor?

Servomotors

We did some experiments with Sun SPOT and servomotors.
We had 3 servo in our hands - two micro servomotors 'E-Sky'
and one micro servo 'GWS PICO'.

After some first tests we found some good things and some bad things.



NOTE: Wires color scheme of GWS servo is differ from standard (typical) color scheme of servomotors.

Usually wires marked:
Black is Ground
Red is +5
White is Signal wire

But for GWS the colors of wires a little bit differ:
Dark Brown is Ground
Red is +5
Orange is Signal wire




Good things:
It was very easy to connect servo to Sun SPOT.
And it was easy to use them with Sun SPOT.

Bad things:
We found that our servomotors with Sun SPOT can rotate their shafts only about 90-100 degrees instead of 180 degrees.

Another disappointed thing - the servomotors work too slow.

Using our code example, you can check - how fast your servos.
Our servos are not so fast.
May be these servos are too cheap to be fast enough ( he-he-he).


Here you can see servomotor movement from minimal position to maximum position.
The test algorithm is very easy:

goto min position
wait 1 second
goto max position
wait 1 second
etc...

As you see 1 sec is enough for full rotation from min position to max position.
The angle is about 100-110 degrees.



This photo illustrates time collision.

The idea of test algorithm is the same and very easy:
goto min position
wait 200 milliseconds
goto max position
wait 200 milliseconds
etc...

As you see wait 200 milliseconds is NOT enough for full rotation from min position to max position.
The angle is limited - it is not so wide as angle with 1000 milliseconds.
With 200 milliseconds delay the angle is about 45-60 degrees.


If you continue to decrease the delay, you can get less and less angle.
Practically up to zero movement.






For demo we created simple aluminum construction.
It is rotation platform with Sun SPOT on it.
Platform has two servos and can do pan and tilt movements.



How it works. Description of small test program


This video is just a first test of Accelerometer-Servo connection on Sun SPOT device. It's kind of 'Compensation moving test'.
See source code on my server.



Accelerometer reading when Sun SPOT moving from horizontal to vertical position.
Accelerometer reading when Sun SPOT moving from horizontal to vertical position.
Accelerometer reading when Sun SPOT moving from horizontal to vertical position.
Accelerometer reading when Sun SPOT moving from horizontal to vertical position.
Accelerometer reading when Sun SPOT moving from horizontal to vertical position.
Accelerometer reading when Sun SPOT moving from horizontal to vertical position.
Accelerometer Telemetry reading when Sun SPOT slowly moving from horizontal to vertical position. Accelerometer Telemetry reading when Sun SPOT slow and fast moving from horizontal to vertical position.
Accelerometer Telemetry reading when Sun SPOT slow and fast moving from horizontal to vertical position.
Accelerometer Telemetry reading when Sun SPOT fast moving from horizontal to vertical position.
Accelerometer Telemetry reading when Sun SPOT fast moving from horizontal to vertical position.
Accelerometer Telemetry reading: Peaks when Sun SPOT fast moving from horizontal to vertical position.
Accelerometer Telemetry reading: Peaks when Sun SPOT fast moving from horizontal to vertical position.
----------------------
We created small program in Java (Sun SPOT J2ME) for testing accelerometer.
You can download the source code of the program from this location:

SunSpot_BalancingRobot.zip - NetBeans project with source code.


Right after the start of the program, you see that left LED is green.
That means: "Ready to start, press left button on Sun SPOT".

Press left switch (SW1) on the Sun SPOT and right LED (LED 7) starts to shine.

When you press SW1, the program reads and save initial values of accelerometer
(rawX, rawY, rawZ).
Then these values will be used as 'base' value.
And the Sun SPOT will try to use servomotors to return to these initial positions.

To simplify the things we will use only one axis - axis Z.
And we will use tilts and see - is it possible for Sun SPOT
to return from random position to original position
(position, where you press SW1).

In main circle the program all the time reads new value of rawZ from the accelerometer.
1)Program measure the value of rawZ
2)We see that we should go to the position in N points (N degrees)
3)We send command to the servo - 'Go to the position N'
4)The motor starts to work and the device is rotating
5)This rotation is going in background. The device is moving and the program is working.
6)The program is going back to the beginning of the
circle - to the Step 1 'Program measure the value of rawZ' (see above).
And the program see again that we should send new command to the servo - usually it is command to go in the same direction, as it was in previous circle.
But (!) the servo is not finished it's moving!

Usually servo works much more slow then program works and execution mechanism
is not suite for the brain.

Also note that we don't have back signals from the servo.
We have only 'one way' connection: The program can send commands to the servo,
but can not read the servo position.
The only way to know servo position is the reading from accelerometer.

But - one more interesting question: Can we trust the value, read from accelerometer?

This is the them of next article - how to interpret data from accelerometer?

There is collision: When you read data from accelerometer,
you should understand that there are two values in this reading:

1)Position indication
2)Value of 'g'. (Where 'g' is the value of acceleration) - How fast was the moving in that moment of reading the data.

And there is a question - how to separate these two values:
- position in the 3D space and acceleration.


Source code of main class:
  1 /*
  2  * Copyright (c) 2009, Oleg Lyubchenko (Oleg [at] RoboHobby [dot] com)
  3  *
  4  * www.RoboHobby.com
  5  *
  6  * This is first test example of the J2ME code.
  7  * The idea is to test - is it possible to create balancing robot,
  8  * using SunSPOT's accelerometer as source of information about
  9  * robot position ('tilt') and servomotor as an execution machine for
 10  * compensation tilt rotationg.
 11  *
 12  * See details on :
 13  * http://www.robohobby.com/sun_spot_balancing_robot.jsp
 14  * http://www.RoboHobby.com/sun_spot_hobby_robotics.jsp
 15  *
 16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 23  * SOFTWARE.
 24  */
 25
 26 package com.robohobby.sunspot.BalancingRobot;
 27
 28 import com.sun.spot.peripheral.Spot;
 29 import com.sun.spot.sensorboard.EDemoBoard;
 30 import com.sun.spot.sensorboard.peripheral.ISwitch;
 31 import com.sun.spot.sensorboard.peripheral.ITriColorLED;
 32 import com.sun.spot.peripheral.radio.IRadioPolicyManager;
 33 import com.sun.spot.io.j2me.radiostream.*;
 34 import com.sun.spot.io.j2me.radiogram.*;
 35 import com.sun.spot.sensorboard.peripheral.ILightSensor;
 36 import com.sun.spot.sensorboard.peripheral.LIS3L02AQAccelerometer;
 37 import com.sun.spot.sensorboard.peripheral.Servo;
 38 import com.sun.spot.util.*;
 39
 40 import java.io.*;
 41 import javax.microedition.io.*;
 42 import javax.microedition.midlet.MIDlet;
 43 import javax.microedition.midlet.MIDletStateChangeException;
 44
 45 /**
 46  * The startApp method of this class is called by the VM to start the
 47  * application.
 48  *
 49  * The manifest specifies this class as MIDlet-1, which means it will
 50  * be selected for execution.
 51  */
 52 public class SunSpotBalancingRobotApp extends MIDlet {
 53
 54     private static final int CENTER_VALUE = 1500;
 55     private static final int MIN_VALUE = 1000;
 56     private static final int MAX_VALUE = 2000;
 57
 58     EDemoBoard eDemoBoard = EDemoBoard.getInstance();
 59
 60     Servo panServo = new Servo(eDemoBoard.getOutputPins()[EDemoBoard.H0]);
 61     Servo tiltServo = new Servo(eDemoBoard.getOutputPins()[EDemoBoard.H1]);
 62
 63     private ITriColorLED [] leds = EDemoBoard.getInstance().getLEDs();
 64
 65     public LIS3L02AQAccelerometer accelerometer;
 66
 67
 68     protected void startApp() throws MIDletStateChangeException {
 69
 70         accelerometer = (LIS3L02AQAccelerometer)EDemoBoard.getInstance().getAccelerometer();
 71         accelerometer.setScale(LIS3L02AQAccelerometer.SCALE_2G);        // start using 2G scale
 72
 73
 74         ISwitch sw1 = EDemoBoard.getInstance().getSwitches()[EDemoBoard.SW1];
 75         ISwitch sw2 = EDemoBoard.getInstance().getSwitches()[EDemoBoard.SW2];
 76
 77         leds[0].setRGB(0,100,0);                // set color to green
 78         leds[7].setRGB(0,100,0);                // set color to green
 79
 80         boolean stop = false;
 81         boolean isReady = false;
 82
 83
 84         int initValueX = 470;
 85         int initValueY = 470;
 86         int initValueZ = 470;
 87
 88         int stepZ = 1;
 89         int servoCorrectionZ = 0;
 90         int deltaZ = 0;
 91
 92         int minDeltaZ = 800;
 93         int maxDeltaZ = -800;
 94
 95         int minServoCorrectionZ = MAX_VALUE;
 96         int maxServoCorrectionZ = 0; //MIN_VALUE;
 97
 98 //            testServoRotation( 1000 );
 99 //            testServoRotation( 200 );
100
101         while ( !stop )
102         {
103
104             if (sw2.isClosed()) //Go out from the application
105             {
106                 stop = true;
107             } else {
108
109                 if (sw1.isClosed()) {
110                     if (isReady) {
111                         isReady = false;
112                     } else {
113                         isReady = true;
114
115                         try {
116                             initValueZ = accelerometer.getRawZ();
117                         } catch (IOException ex) {
118                             ex.printStackTrace();
119                         }
120                     }
121                 }
122
123                 if ( !isReady )
124                 {
125                     //show that we are ready to do the job:
126                     leds[7].setOff();
127                     leds[0].setOn();
128                 }
129                 else
130                 {
131                     //do the job:
132                     leds[0].setOff();
133                     leds[7].setOn();
134
135                     int rawX = 0;
136                     int rawY = 0;
137                     int rawZ = 0;
138
139                     try {
140
141                         rawX = accelerometer.getRawX();
142                         rawY = accelerometer.getRawY();
143                         rawZ = accelerometer.getRawZ();
144
145                         System.out.println(
146                                 "initValueZ=" + initValueZ +
147                                 " servoCorrectionZ=" + servoCorrectionZ +
148                                 " rawX=" + rawX +
149                                 " rawY=" + rawY +
150                                 " rawZ=" + rawZ
151                                 );
152
153
154                         if ( rawZ < initValueZ )
155                         {
156                             System.out.println( "Moving Plus" );
157                             if( CENTER_VALUE + servoCorrectionZ < MAX_VALUE )
158                                 servoCorrectionZ += stepZ;
159                         }
160                         else
161                         {
162                             System.out.println( "Moving Minus" );
163                             if( CENTER_VALUE + servoCorrectionZ > MIN_VALUE )
164                             servoCorrectionZ -= stepZ;
165                         }
166
167                         System.out.println( "servoCorrectionZ(1)=" + servoCorrectionZ );
168
169                         deltaZ = initValueZ - rawZ;
170
171
172                         if ( deltaZ < minDeltaZ )
173                             minDeltaZ = deltaZ;
174
175                         if ( deltaZ > maxDeltaZ )
176                             maxDeltaZ = deltaZ;
177
178                         System.out.println( "deltaZ=" + deltaZ +
179                                 " minDeltaZ=" + minDeltaZ +
180                                 " maxDeltaZ=" + maxDeltaZ );
181
182                         if ( servoCorrectionZ <  minServoCorrectionZ )
183                              minServoCorrectionZ = servoCorrectionZ;
184
185                         if ( servoCorrectionZ > maxServoCorrectionZ )
186                             maxServoCorrectionZ = servoCorrectionZ;
187
188
189                         int servoPositionZ = CENTER_VALUE + servoCorrectionZ;
190                         System.out.println( "servoPositionZ=" + servoPositionZ +
191                                 " minServoCorrectionZ=" + minServoCorrectionZ +
192                                 " maxServoCorrectionZ=" + maxServoCorrectionZ);
193                         tiltServo.setValue( servoPositionZ );
194
195                     }
196                     catch (IOException io_e)
197                     {
198                         System.out.println( "Error in getting rawX io_e=" + io_e );
199                     }
200                 }
201
202             }
203
204         }
205        notifyDestroyed();                      // cause the MIDlet to exit
206     }
207
208     private void testServoRotation( int delay )
209     {
210         tiltServo.setValue( MIN_VALUE );
211         Utils.sleep( delay );                  // wait
212         tiltServo.setValue( MAX_VALUE );
213         Utils.sleep( delay );                  // wait
214     }
215
216     protected void pauseApp() {
217         // This is not currently called by the Squawk VM
218     }
219
220     /**
221      * Called if the MIDlet is terminated by the system.
222      * I.e. if startApp throws any exception other than MIDletStateChangeException,
223      * if the isolate running the MIDlet is killed with Isolate.exit(), or
224      * if VM.stopVM() is called.
225      * 
226      * It is not called if MIDlet.notifyDestroyed() was called.
227      *
228      * @param unconditional If true when this method is called, the MIDlet must
229      *    cleanup and release all resources. If false the MIDlet may throw
230      *    MIDletStateChangeException  to indicate it does not want to be destroyed
231      *    at this time.
232      */
233     protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
234         for (int i = 0; i < 8; i++) {
235             leds[i].setOff();
236         }
237     }
238 }
239
240

----------------------
TO BE CONTINUED...