Arduino + Bluetooth + Android + Servo

August 10, 2014 2 comments

Just to have a complete test in terms of communication I would have liked to know more about Arduino and its compatible bluetooth module. The one I found:

Arduino Compatible Bluetooth Serial Port Module

Documentation I used to start:

BT board pins

Having all these details I started soldering the minimum required 4 legs only :) TX/RX/Vcc/GND:

I did not know anything about these type of castellated holes so I just added a bit more solder and prepared the wires:

step 1 prepared

I could solder the wires to the edge of the board with a simple touch (1-2 secs) of soldering iron:

step 2 soldered

and connect to Arduino: Bluetooth board Vcc to Arduino 3.3V, GND to GND, RX to Serial 1 TX and TX to Serial 1 RX.

step 3 connected

This was the hardware part. When it was turned on my PC could discover as a “HC-06” device. This little amount of info went immediately to Google search. HC-06 specification found in few mins. Let me summarize what I really needed to complete the test:

  • This little board starts in 9600 baud rate mode
  • and it is in AT command mode before paired state
  • wait minimum 1 sec after each AT command
  • password for pairing is 1234

Based on it I simply sent two AT commands (using Serial1.print()) to change baud rate from 9600 to 115200:

“AT” to test if the answer is OK and we are really talking :) and

“AT+BAUD8″ to change baud rate.

(Not used commands: change the password with AT+PINxxxx or the device name with AT+NAMExxxx but these are not important now.)

This is a one time action and could be implemented in Arduino setup() function (the loop() can be empty this time):

Serial1.begin(9600);
Serial1.print(“AT”);
delay(2000);
while(Serial1.peek() != -1)
{
Serial.print((char)Serial1.read());
delay(1);
}
Serial.println();
Serial1.print(“AT+BAUD8″);
delay(2000);
while(Serial1.peek() != -1)
{
Serial.print((char)Serial1.read());
delay(1);
}
Serial.println();

In serial monitor I got these answers from the device as it is specified in the docs:

OK
OK115200

When this was completed I could change  Serial1.begin(9600); to  Serial1.begin(115200); and upload the new sketch leaving the same AT command related code :) Now I could pair the device and add real serial communication in Arduino loop().

Let’s check the result!

This could work as an alternative Arduino – Android connection replacing the USB cable and of course I should add a 9V battery too but I am still hesitating. Comparing them on mass level:

USB cable = 43g    vs    9V battery + cable + bluetooth device = 50g

Developing connections – BlueTooth, USB Serial, WiFi

August 7, 2014 Leave a comment

According to our plans an Android mobile could help a lot in our next robot providing tons of sensors and communication channels. Let’s see where we are now with the connections!

1. BlueTooth OK

We have tested successfully the Android – PC connection (actually Blender as target) using BlueTooth. You can see the result in the previous post. This way we could have a much better (visual) feedback.

2. WiFi OK

I also could use WiFi  in order to upload the main robot java application pack from PC to Android. This wireless mode is very useful because the built-in mobile could be programmed remotely. USB cable is required only one time when you initiate this connection. Of course you can see all debug info too from the phone in Eclipse. More info here: http://developer.android.com/tools/help/adb.html Actually you need to type only two lines and you can use it!

Quick summary:

  • plug USB and check if you can see debug info in Eclipse LogCat
  • locate your ADT install dir and go to …\sdk\platform-tools
  • type adb tcpip 5555 and
  • type adb connect your.mobile.ip.address:5555
  • unplug your USB cable and you will still have running debug info in LogCat and you still be able to upload your app via WiFi :) This is very cool! Thanks to Google!

3. USB cable (WT?)

Android Arduino connection. The simplest solution I found was the good old USB cable where simple(?) serial library solves everything on Arduino side and on the top of this it has a perfect 5V power supply! No need to use any additional battery, I think my Sony Xperia SP could provide enough energy for Arduino in this project. I have been testing this for 2 weeks now and it’s absolutely OK. The data communication is still under development because it is not as stable as I expected. Let me try to describe it with more details.

When I developed the walking function on Arduino Mega 2560 only using its C/C++ like language I could expect all the functions to work with a given speed and based on the given specifications. And when I write speed I mean microsecond level! The most important timing requirement is take into account the servo control signal’s frequency which is 50Hz. Briefly you have to be able to do all walking related calculations in 20 milliseconds. I felt this was not a big challenge and Little Johnny could move the legs as I expected.

Developing the same on Android a bit more needs to be implemented:

  • walking related calculations where I do not expected any issue with timing
  • communication with Arduino via USB. After two weeks I am still fighting with this!

3.1 Mobile to MCU via serial: first of all you need to have some useful java code to start with. I found few of them but finally I decided to write my own class for this. These libs can do much more than I really need but you could give a try! :)

https://github.com/mik3y/usb-serial-for-android

https://github.com/ksksue/PhysicaloidLibrary (this lib could even upload firmware to Arduino!)

http://android.serverbox.ch/?p=549

I have seen many forums about this type of communication where a simple byte was transferred properly. In our case I want to send 50 bytes with 50Hz and receive few bytes back (result of sensor stuff like Ultrasonic range finders, etc.)

Pack size was calculated based on:

  • the number of servos: 12*2bytes (2 byte is required to send 1500+-500 integer values)
  • +2 control bytes (in position 0 and 1 with values 170 and 204 -> 10101010 and 11001100)
  • +24 bytes for future development (walking mode control, request feedback, etc.)

My idea was to use a simple timer and call my serial transfer function. It was not working :) Any time the previous call could not be completed the new call was blocked for 19 seconds! Arduino’s RX/TX leds were continuously on in these phases. So I simply added a boolean flag which indicated if the previous timer request can be handled or not and the actual request needs to be skipped (similar to frame drop in video games). Later I could use this as a quality indicator. Few drops could mean a better implementation. I played a lot with the timer’s period in order to reduce this but of course I had to speed up the request handling itself.

Secondly I tried to understand how baud rate can have effect on the whole communication. I understand that 1 byte = 10 bits when we talk about data transfer instead of simple data store situation: 1 start bit + 8 data bits + 1 stop bit could be 10. So the transfer speed per sec is about baud rate / 10. For the standard 9600 it is 960 bytes / sec and 19 bytes / frame for 50 Hz. 19 bytes are too few for my planned 50 bytes so I moved to 115200 baud rate on both Arduino and Android side. (with 9600 you would need 52 mS anyway for a 50 byte pack) Arduino can solve this with a very short code line: Serial.begin(115200); :) Let’s calculate again the necessary time to transfer 50 bytes with 115200 baud: 50*10/115200 = 4.34 mS. In the planned 20 mS frame it fits perfectly.

So Android sends the 50 bytes to Arduino using bulkTransfer. How can you receive the stuff? My first attempt was to use the well-known(?) Serial.read() function. My problem was that the given example did not work! :| After many days testing I understood that serial reading has its own ceremony. I would like to share this with you.

3.2 Receiving serial data on Arduino side:

a. Fast read from serial buffer: Here you can use the example code (while available then read in a loop)

b. After this when Serial.available()  of loop1 shows no more data, it does not mean there is no more incoming data! Only the buffer is empty so the second loop has to read bytes following the communication speed. You need to add some delay after every and each read byte. Necessary delay can be calculated easily: for 9600 baud it is  1.042 mS so you could use delay(1) but much better to use delayMicroseconds. For 115200 you should use 86.8uS ( delayMicroseconds(87); exactly) in the loop2.

c. And the most important third loop. When you think you have all the data (using counters, etc,) you still have to continue the reading in order to fully clear the buffer. If you forget this step your next serial action can easily fail…

    So again a small summary:

  • Loop1: Fast read (from buffer)
  • Loop2: Baud rate synchronized read to have all the bytes of your packet
  • Loop3: Baud rate synchronized read blindly to empty the serial buffer.

3.3 Android timer task: I wanted to have this communication task in another thread separately from the UI because this was proposed on many forums. In my case there is a small difference: the robot can not be blocked, the Android UI is not important and can be blocked. Of course this is against how Android was designed.  I followed all the official instructions and implemented an AsyncTask. This was very comfortable and easy. But two things you have to take into account and it came out only after 2-3 days during my tests:

  • you need to start an AsyncTask using new operator like new DownloadImageTask().execute(http://example.com/image.png”); This meant that every timer event I created a new object/thread etc. This async task was closed after a single sending and receiving cycle. It did not seem to be too elegant… creating tons of objects will result a GC call and GC will kill the party.
  • this AsyncTask creates a  background thread which is not the best choice for a time critical task! I think the UI thread can overrule it anytime running useless redraw operations, etc. This is why I changed the thread handling a bit: I use only one thread where start and stop flags can control the processing in an “endless” loop (you know for(;;)). The result of the test was a much smoother servo movement comparing to the AsyncTask version. Open item: can I change my thread priority to beat UI thread priority level? OR can I change UI thread priority level to a very low value? :)

3.4 Android lagging: on the top of serial buffer related blocks and frame drops I saw many GC activity suddenly blocked my application for 20-40 mS. This “small” GC activity can cause a serious problem for a time critical or real-time application. In my case 2-3 frame drops. Not too funny because this is absolutely visible during even simple slow walking.

You will see something like this in LogCat: 08-06 20:34:56.725: D/dalvikvm(12230): GC_FOR_ALLOC freed 2048K, 44% free 6203K/10932K, paused 20ms, total 20ms

I am still working on this part and try to implement the communication and UI tasks avoiding any new operator in loops and/or try to call the GC from my code more times than system default period to reduce garbage collection run time. We will see in 3.4.1 and 3.4.2

3.4.1 Avoid GC call at all: (working!)

In Eclipse you have a memory allocation tracking tool called DDMS where you can see your process memory map on object level. (to start this tool you need to use Open Perspective from Eclipse) Using this tool I could locate two unnecessary allocations in my code: one was in the timer handler and one in the thread loop. After I moved them to class level GC activity almost totally disappeared! It came in every 30 seconds before and now I can not see anything after 15 mins watching! DDMS shows now only one dynamically allocated object for the System.out.println result where java.lang.AbstractStringBuilder is working to show the simple LogCat debug info… Hopefully this will not occur in production mode.

3.4.2 Totally different approach: Call GC frequently to reduce GC runtime: (bad very bad idea)

I also tested periodic GC calls (System.gc();) but this was not a good idea :) It is running but always with minimum ~16mS and maximum ~270mS independently if this garbage collection has just been done right before the calls… So I choose 3.4.1 solution to reduce lagging.

Other opinions: I have seen and read many comments on Android UI lagging like  http://www.phonearena.com/news/Here-is-why-Android-is-laggy-and-why-its-going-to-remain-like-that-in-the-near-future_id24434 But I can not change my Android phone now… :D

3.5 USB bulk transfer: Another time critical issue is that on Android side I use bulkTransfer. One comment attracted my attention:

” Bulk transfers will use spare un-allocated bandwidth on the bus after all other transactions have been allocated. If the bus is busy with isochronous and/or interrupt then bulk data may slowly trickle over the bus. As a result Bulk transfers should only be used for time insensitive communication as there is no guarantee of latency. ” Would mean to me that Android OS can interrupt/disturb my bulk transfer if it wants to check this USB device…

Let me summarize the situation: I need to complete real-time operations from a low priority thread using low priority transfer method. What a winner position! I did not fight all these stuff on Arduino but I think Android definitely has brutal advantages where I

  • can use a higher level programming language (java instead of C/C++)
  • have a much better IDE. You can compare Eclipse to Arduino IDE any time…
  • have much more resources in one single unit (memory, CPU, SD card, sensors, display, cameras, mic, speaker, lipo battery, etc.)
  • do not need IOIO devices just an USB cable.

The only and real Android disadvantage is the lack of Arduino’s very precise timing which is essential for PWM and servo control. This is why I believe in hybrid solutions and Arduino is still the winner of servo management.

Should I use NDK?

I also saw a proposal I have never tested (native coding and use C/C++ instead of Java):  https://developer.android.com/tools/sdk/ndk/index.html

Interesting part: ” Typical good candidates for the NDK are CPU-intensive workloads such as game engines, signal processing, physics simulation, and so on. “

Conclusion:

Now I can transfer data with 30Hz (from 20mS I changed the timer period to 33mS) and there are not too many frame drops and this still could result continuous leg movement. Plus as a bonus performance I would expect a bit better speed still using normal Java SDK when I change from debug mode to release build. Last time when I measured the speed of a Flash application it was 15 times! faster in release version so I hope Java could do something similar…  Worst case scenario is that 30Hz will not be enough and I start a totally new Android NDK project…

Android Blender Connector

July 29, 2014 Leave a comment

In our next robot we would like to add a mobile (Sony Xperia SP) as a sensor pack. This small post was dedicated to understand:

- Android Java coding

- Sensor handling (mainly accelerometer and compass)

- Possible communication between Android and PC and Arduino (Bluetooth and USB cable and WiFi)

- Possible feedback from the robot about leg positions and body orientation

- The necessity of buying IOIO OTG devices (here you can find more about this item)

All this was tested with a very funny task: rotate a Blender object with Android phone. I know that this was implemented many times before but all these need to be application specific for the robot and need to be customized in terms of energy consumption, speed, cost, etc.

If you plan to connect your phone with Blender as an external/wireless controller you could easily add few useful functions like coloring, movement on top of rotation, change different modes (edit mode, wire frame, etc.) My only problem was with using mouse and mobile at a time that my brain was not able to handle this two-handed coordination so I should practice more :) The other direction I can imagine: use two Android phones and implement a gesture based interface where you can reach all Blender functions! That would be cool!

One comment on (re)implementing the same which has been done before: any time I reread even one of our posts I can see that new devices are available, new programming libraries can be used, new versions coming, etc. Sometimes it is much much easier using newer stuff but you always need to start from scratch :)

Categories: Experiments Tags: , ,

Better servo positioning

July 27, 2014 Leave a comment

In the “Little Johnny careful steps” post I have mentioned a better way of servo positioning. So let’s try this writeMicroseconds() stuff!

Arduino code for the test using two modes (write and writeMicroseconds  for the same movement range and speed):

#include <Servo.h>

// R = 18.5 cm
// 1 degree step = R*Pi/180 = 0.323 cm = 3.23 mm!

Servo myservo;

void setup()
{
myservo.attach(9);
myservo.write(90); // set servo to mid-point
}

int spos = 90;
int mode = 1;
int upos = 1500;
void loop()
{
if(mode==0)
{
for(spos=70;spos<110;spos++)
{
myservo.write(spos);
delay(1000);
}
for(spos=110;spos>70;spos–)
{
myservo.write(spos);
delay(1000);
}
}

if(mode==1)
{
for(upos=1400;upos<1600;upos++)
{
myservo.writeMicroseconds(upos);
delay(200);
}
for(upos=1600;upos>1400;upos–)
{
myservo.writeMicroseconds(upos);
delay(200);
}
}

}

Testing with analog and digital servos: simple straw is used to have big enough end point movement.

servo_write_vs_writemicro

In the case of analog servo I saw 2 sometimes 3 movements / sec and in the case of digital it was 3 almost in all the cases. After viewing the  writeMicroseconds based positioning I experienced

- a much smoother positioning

- quieter servo

- less trembling

- only 3 times better than write function (originally I expected 5 times) but this could be caused by inertial mass…

All these could lead us to a better and smoother walking with less oscillation.

If you would like to know more about the implementation see some code used behind the scenes (located in your Arduino IDE install /libraries/Servo/Servo.cpp). Based on it you can use write in any code and it is able to detect if you want to use degrees or microsecs for controlling. A simple if is used: if the position you specify is less than 544 (0-180 normally) you got degree based control and finally all calls ends in writeMicroseconds lib function. When you send degrees it converts using Arduino map command: usec_value = map(degree_value, 0, 180, 544, 2400); You can check if 90 degrees lead you to 1500 usec  as a middle position. I got 1472 as result… It seems the library is prepared to handle all the extreme minimum and maximum positioning values BUT it has cost. Let’s see what we got if we have a very normal servo which is prepared to handle 1000 uS to 2000 uS (1500 middle => 1 degree = 5,555 uSec ):

Degrees / result micro seconds to control (comment about real position):

0 : 544 (under 1000 nothing happens or the servo goes to zero)
10 : 647 (same but you lost 10 degrees!)
20 : 750 (lost 20)
30 : 853 (lost 30)
40 : 956 (almost but still lost 40 degrees!)
50 : 1059 (finally got acceptable value which will position the servo to 10 degree position instead of 50!)
60 : 1162 (29 instead of 60)
70 : 1265 (47.7…)
80 : 1368 (66.24)
90 : 1472 (85 almost 90)
100 : 1575 (103.5)
110 : 1678 (122!)
120 : 1781 (140.6)
130 : 1884 (159)
140 : 1987 (177)
150 : 2090 (nothing happens or your servo goes to end position)
160 : 2193 (same and you lost another 10 degrees)
170 : 2296 (lost 20)
180 : 2400 (lost 30)

Testing code:

void setup() {
Serial.begin(9600);
}

int comp=0;
void loop()
{
if(comp==1)return;
int val = 0;
int deg = 0;
for(deg=0;deg<190;deg+=10)
{
Serial.print(deg);
Serial.print(” : “);
val = map(deg, 0, 180, 544, 2400);
Serial.println(val);
}
comp=1;
}

It seems to be a bit shocking. If we use 544-2400 instead of the servo specific values (1000-2000uSec) we can easily loose about 70 degrees out of 180 and have absolutely invalid physical position plus a much bigger servo step length! My servo step should be 5.555 uSec/degree but using write function I have 10.311! Almost two times bigger than I want to have…

Conclusion: If you know your servo parameters you definitely have to use writeMicroseconds function and a simple map like

usec_value = map(degree_value, 0, 180, your_servo_min, your_servo_max);

(Or you just overwrite 544 and 2400 in Servo.h after reading the license and change conditions)

I must have been blinded by my very limited brain capacity to realize this conclusion only after 3 years testing… Luckily I can eliminate this small frustration with 3 beers :D

Categories: Experiments Tags: , , ,

Walking with battery pack – milestone

July 2, 2014 Leave a comment

So here is the test result of walking with battery pack!

On one hand it means totally independent movement and for us this is a milestone. On the other hand this can cause additional load and kill all the servos (this would not mean a real milestone :) ). Our expectation was to see this small robot to walk and walk alone without any external support (no external power, no external control, nothing just Little Johnny).

Vote before you watch the video! Agony or walking?

Add battery and use internal power supply!

June 29, 2014 Leave a comment

This was a critical part of the development. With external power source everything was easy and simple: 5V was just coming flawlessly. Adding the batteries suddenly caused unlimited number of problems:

Problem 1: where on Earth can we place 6 AA batteries in a small robot body? This is solved because my brother designed a battery holder right under the Arduino Mega almost a year ago as you can see below. Sorry :)

battery pack holder

Problem 2: how can you connect AA batteries without soldering and use as less energy and time as possible. I found a proposal to use “snail” formed wires and simple tape.

AA battery connector wire

This was really simple and quick: in 10 minutes I could connect 6 batteries and have a 2200mA 9V pack built-in to the pack holder!

half connected

Problem 3: additional load! Normal weight was 305g before this step and now it is 455g! Will the servos accept this additional load?

Problem 4: can this battery pack provide enough power for the servos – to hold the extra mass caused by the battery pack :) ?

This definitely has to be tested…

Walking on lego – round 2

June 24, 2014 Leave a comment

Last time a simple 4-5cm thick lego obstacle could stop LJ why I simply changed step height to maximum :) Let’s see the result!

Categories: Robot HW and SW Tags: , ,
Follow

Get every new post delivered to your Inbox.