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