Showing posts with label Android. Show all posts
Showing posts with label Android. Show all posts

Monday, November 14, 2011

Roaming bandwidth in Spain with the Samsung Galaxy Tab

There seems no end in sight to the roaming ripoff in Europe. While the situation is improving slowly it's still ridiculous.

At the moment I'm on holiday in the Canary Islands (part of Spain). Before travelling I checked with my operator (Vodafone IE) re data roaming packages. The best they could do is €12 per day for 50MB after which €1 is charged per additional MB (down from €5/MB a few years ago!). I need about 100MB per day so that's €12 for the first 50MB and €50 for the next 50MB: a total of €62 per day, or €620 for a 10 day trip! Added to this is the complication that between myself and the wife we have 6 WiFi devices (2 x laptops, 2 x smartphones, a Kindle and an Android tablet). Our hotel WiFi is locked to a single device, is expensive, slow (128kbps?!), and is only accessible in certain areas (not our rooms).

I found a nice solution. I purchased a pay-as-you-go SIM from a local Vodafone shop (a €9 once off charge and you'll need photo ID to make that purchase). I then applied a data top-up to that SIM: €15 for 1GB lasting one week or €20 for 1GB lasting up to a month. I inserted the SIM into my Samsung Galaxy Tab 10.1v and started the portable hotspot mode (under Settings -> Wireless & networking -> Tethering and portable hotspot -> Portable WiFi Hotspot). Bingo: a portable WiFi hotspot good for up to 5 devices.

The Galaxy Tab's battery life is sufficient that I can carry the tablet in my day bag and have enough power to keep all our devices continuously connected no matter where we were. The Galaxy Tab has security disabled by default: I'd strongly recommend enabling security to prevent others nearby gaining unauthorized access to precious bandwidth (the mobile network here is good... it won't take long to download a full 1GB).

There are still a few problems (which I'm sure there are good solutions out there): Android 3.0 (Honeycomb) installed on the Galaxy Tab 10.1v (aka GT-P7100) seems to have no ability to report current or historical bandwidth use. I believe this has been addressed in Android 4.0 which I eagerly look forward to. Also I haven't figured out how to get remaining data credit on my SIM. And finally Windows 7: in the first few minutes after connecting it seems to go through megabytes per minute: presumably software updaters phoning home, Facebook, GMail brower windows fetching updates etc. It seems to settle down to a  reasonable rate after a minute when about 5MB is consumed.

Tuesday, May 24, 2011

Arduino to Android IO on the cheap (aka Poor Man's NFC)

Summary: This article describes how to implement a very low bandwidth one way communication channel between an Arduino (or any other microcontroller) and an Android device using nothing more than about a meter of magnet wire, a resistor and diode. Links to a software sketch for the Arduino and the Android source code is included.

A cheap and simple way of communication between a microcontroller (eg Arduino) and an Android device is surprisingly difficult to achieve. The most practical means of accomplishing this is to use a Bluetooth or WiFi module adding significantly to the cost of a project (in the order of $30 - $60).

This is a little hack that allows very low bandwidth communications in one direction for practically no cost. It's not practical for most applications, but I thought the idea was sufficiently interesting to explore and write up in a blog post.

You'll need the following:
  • An Android phone or device which features a magnetometer (electronic compass). I'm not aware of any device without one.
  • An Arduino or other microcontroller (my examples are for the Arduino)
  • About 1 meter of  enameled copper wire (magnet wire), although any thin insulated wire will do.
  • The Android 'Tricorder' app (available free from the Android app store)
  • A 120 ohm resistor 
  • A diode (optional)
Make a coil by wrapping the 1 meter of magnet wire around something cylindrical  (eg AAA cell) with a diameter about 1cm. You should get about 30 turns from 1 meter. The diameter or number of turns is not important as long as they are in that ball park. Wrap a light thread around the coil to help keep its shape.



Connect the coil as illustrated in the schematic above. The 120 ohm resistor limits current draw to about 40mA which is the maximum allowed [1]. The purpose of the diode is to protect the Arduino from an EMF kick when pin 13 is driven low. This is known as a  flyback diode. With only 30 turns and an air core, you'll probably get away without using it. But it's good practice to include it.

Tricorder app displaying magnetic field. For the
HTC Desire the signal is strongest at the bottom
left of the LCD where the magnetometer is located
This is likely to vary from device to device.
Now to locate the magnetometer. It's location will vary from device to device. This is where the tricorder comes in handy. First load this sketch on the Arduino before you connect the coil.


/**
 * Generate 1Hz square wave on pin 13
 */
void setup() {
  pinMode(13,OUTPUT);
}

void loop() {
    digitalWrite(13,1);
    delay(500);
    digitalWrite(13,0);
    delay(500);
}


When the coil is disconnected you should see the Arduino's LED blink. Now connect the coil. The LED should stop blinking at this point because the coil shorts the LED -- this is expected. Start the Tricorder app and switch to MAG mode and start scanning. Methodically scan the coil across the surface of the Android phone until you start seeing a strong square wave. Where the amplitude of this signal peaks is where the magnetometer is located. You should see a similar square wave if you position the coil at the same location on the bottom surface of the device. Use some tape to keep it positioned there.

Now we have a way of signalling the Android. The temptation at this point is to connect the coil to the Arduino UART and to start firing data at 9600bps. Unfortunately this isn't going to happen for a few reasons:

We are limited by the magnetometer sampling rate available to us by the Android OS. Here is a histogram of time-between-samples from a HTC Desire running Froyo (Anrdoi 2.2) at maximum sampling speed:



We can see here that almost all the samples come in at between 18ms and 25ms. There are a few outliers going all the way up to 45ms but there numbers are so few we can ignore them. This means we are limited to a maximum of a 40Hz sampling rate. If we drive the coil with a digital IO line that immediately caps our maximum bandwidth at 40bps.

But does the magnetometer respond quickly enough?

This Arduino sketch energizes the coil with a square wave of starting at 500Hz and decreases to about 1Hz over a few seconds.

int i;
int d = 1;
void setup() {
  pinMode(13,OUTPUT);
}

void loop() {
  for (i = 1; i < 500; i+=d) {
    
    // Increase increment as frequency decreases
    d = (i>>6) + 1;
   
    digitalWrite(13,1);
    delay(i);
    digitalWrite(13,0);
    delay(i);
  }
}


Here is the magnetometer data:

As expected high frequencies (on the left) are not be detected. It seems that we only get good pickup when the frequency drops to about 6Hz!

For encoding I'm going to use NRZ (non return to zero) similar to that used in RS232 with a bit period of 140ms (about 7 bps). The Arduino's UART lower limit is 300bps, so I can't use it to generate the signal.  So I'm going to 'bit bang' the signal in software. Likewise, on the Android I'm going to have to decode in software also.

#define BIT_DELAY 140

int i;
char *text = "Hello World! ";

void setup() {
  pinMode(13,OUTPUT);
}

void loop() {
 
  char *s;
  s = text;
  while (*s != 0) {
    transmitByte(*s++);
  }
  
  delay (BIT_DELAY*10); 
}
/**
 * Bit bang a byte
 */
void transmitByte (byte c) {
  
  // Start bit
  digitalWrite (13,1);
  delay(BIT_DELAY);
  
  // Data bits
  for (i = 0; i < 8; i++) {
      digitalWrite (13, ( (c&0x80)!=0 ? 1 : 0) );
      delay(BIT_DELAY);
      c <<= 1;
  }
  
  // Stop bit
  digitalWrite (13, 0);
  delay(BIT_DELAY);
}

Here it is in action:


The Android source is available here.

Potential improvements


My simple example uses a digital IO line to drive the coil. The Android magnetometers typically have at least 8 bits of resolution per channel [2]. It may be possible to squeeze another few bits per symbol by driving the coil with a DAC [3]. For example, 4 power levels can be used to encode 2 bits per symbol. The odd bit error  can be corrected using forward error correction.

Also the magnetometer has three channels (X,Y and Z). It may be possible to construct a set of coils that excite the X,Y and Z channels independently … multiplying bandwidth by a further x3. Another thought: I've only discussed digital communication with the Android. Some applications might only require an analog signal.

These ideas are left as an exercise for the reader, but I’d love to hear how you get on if you try it. 

Footnotes


[1] Googleing "Arduino pin 13", one is lead to believe there is a current limiting resistor in series with the MCU pin. However looking at the schematics, the tap for the pin 13 header comes *before* the resistor: so the resistor does not limit current. I only discovered this at the end of the experiment while proofing this post. Omitting the resistor did me no harm, but would advise to include the resistor to be safe. We need as much current as possible (more current means more magnetic flux in the coil). The Arduino Duemilanove datasheet specifies a maximum draw of 40mA on a IO pin, so 120 to 150 ohms should do the trick. If you need more current you'll need to use a transistor.

[2] The HTC Desire uses a AKM Semiconductor AK8973 3-axis magnetometer which uses a combination of a 8 bit ADC and a 8 bit offset DAC to yield up to 12 bits of equivalent resolution spanning +/- 2000µT of magnetic flux.

[3] The Arduino does not have a true DAC, however DAC functionality can be achieved by passing the PWM output through a low pass filter.

Sunday, August 22, 2010

Mapping cell coverage in the Glengarriff Valley

As a follow up to my Froyo on a Stick experiment, I wondered why the signal in the Glengarriff valley was so spotty and where it was coming from.

I found two apps in the Android Market which report and log cell data: "Antennas" and "RF Signal Tracker". I enabled the logging on both apps and cycled around the area. In the immediate vicinity of where I was staying the signal was almost non-existent. But not far away there was acceptable signal levels.

It turns out these apps not only record cell ID, and signal strength, but also (from somewhere?!) downloads the location of the cell towers.

Plotting this data on Google Maps yielded some answers. It turns out the tower was to the north and not the east as I had originally thought. The signal into the valley was being attenuated by a ridge of the Caha Pass a little higher than the tower (despite no line-of-sight, diffraction of radio waves allows some signal through).  On either side of the ridge were peaks exceeding 400m elevation: so it would appear this constrained reception to a beam within the valley.

My data would appear to confirm this. Within the yellow wedge it seemed possible to get a signal (red dots indicate points where I could connect). In the grey wedge a signal was mostly not obtainable.

Data acquisition and visualization

I ran both "Antennas" and "RF Signal Strength" together. The UI in the latter app wasn't very good... it was slow to respond and would frequently hang. Fortunately the logging function worked. The "Antennas" UI on the other hand appeared to work better, but failed to log much data.

The data from "RF Signal Strength" looks like this:

_id,latitude,longitude,rssi,logdate,mcc,mnc,lac,cellid,site_lat,site_lng,tech,ber,callstate,roaming
1,51766086,-9613348,-99,14 Aug 2010 13:56:03,272,1,47,11011,52181474,-1357067,GPRS,-1,IDLE,NO
2,51766086,-9613348,-99,14 Aug 2010 13:56:26,272,1,47,11011,52181474,-1357067,GPRS,-1,IDLE,NO
3,51766086,-9613348,-99,14 Aug 2010 13:56:27,272,1,47,11011,52181474,-1357067,GPRS,-1,IDLE,NO

I wrote a script (Java + Javascript) to plot this on Google Maps Terrain layer. Then copied a screen grab into Google Draw Tool to annotate.

Froyo on a stick

When faced with an impossibly weak cell signal and an Android phone, what can you do?

Recently while on holiday in the Glengarriff valley, west County Cork, I was faced with this problem.

Android 2.2 (aka "Froyo") has a cool feature that allows the phone to become a WiFi access point. This is intended to be a convenient way to allow a laptop to use the phone's internet connection. Normally the phone would be sitting right next to the laptop. But it doesn't have to be so close. A line-of-sight range of more than 20 meters is possible.

At my location I was getting tantalizing brief connections to the cell network (Vodafone IE), and occasionally the odd GPRS IP packet might make it through. But nothing close to usable.

As a rule of thumb you can improve a weak radio signal by raising the height of the antenna.  So I got several planks of wood. Strapped them together with duct tape to form a make shift antenna mast  about 8m in height. I switched the mobile hotspot feature on, taped the phone to the top of the mast and raised it.

And sure enough I was able to get a usable [*] connection where none existed before.


[*] The connection was only GPRS and there was still packet loss... but sufficient to get email in and out. Perhaps another few meters might have made the difference.
  翻译: