0% found this document useful (0 votes)
67 views11 pages

Lab 1 (Reading Sensors & The Android API) : 1 Objective

This document provides instructions for Lab 1 of the ECE155: Engineering Design with Embedded Systems course. The objectives of Lab 1 are to familiarize students with Android phones and learn how to read sensors on the phones. Students will write an Android application that reads various phone sensors and graphs the values. The lab involves using Eclipse IDE to create an Android app, adding a user interface, creating event handlers for sensors, and including a widget to graph sensor history. Deliverables include displaying current and maximum/minimum sensor values and ensuring the data is readable to users. The document outlines creating infrastructure to display data, creating handlers to read sensors, and testing the application. It also provides background on Android application structure and using JavaDoc documentation.

Uploaded by

ayylmao
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
67 views11 pages

Lab 1 (Reading Sensors & The Android API) : 1 Objective

This document provides instructions for Lab 1 of the ECE155: Engineering Design with Embedded Systems course. The objectives of Lab 1 are to familiarize students with Android phones and learn how to read sensors on the phones. Students will write an Android application that reads various phone sensors and graphs the values. The lab involves using Eclipse IDE to create an Android app, adding a user interface, creating event handlers for sensors, and including a widget to graph sensor history. Deliverables include displaying current and maximum/minimum sensor values and ensuring the data is readable to users. The document outlines creating infrastructure to display data, creating handlers to read sensors, and testing the application. It also provides background on Android application structure and using JavaDoc documentation.

Uploaded by

ayylmao
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

ECE155: Engineering Design with Embedded Systems

Winter 2015

Lab 1 (Reading Sensors & The Android API)


Prepared by Kirill Morozov, Han Xu, Zheng Ma, Devin Binnie

version 1.5

Deadline: You must submit the lab to the SVN repository by the submission deadline (see the syllabus) and be prepared to demonstrate Lab 1 to a TA at the start of your assigned Lab 2 session. The
best way to demo is during a lab session, but any earlier time where you can convince a TA to watch
is OK too.

Objective

The objectives of Lab 1 are for you to:


1. Familiarize yourself with the Android phones that you will be developing for, and
2. Learn how to read the sensors on these phones.
During this lab, you will write a simple Android application that reads the various sensors available
on the phone and graphs them. Your code will initialize an Android Activity; accept the values from
the phones sensors; and display these values on the screen. Consult the lecture notes & slides for
more details on what Android Activities are.
The steps in this lab will be:
1. Use the Eclipse IDE and the Android API to create a basic Android application.
2. Add items to the user interface for your Android application.
3. Create event handlers for a variety of sensors and make them modify the user interface.
4. Include a widget to graph a history of sensor values.

Deliverables.

For this lab, you must:

Create a system that will let you display each sensors current value when the event is received
using an event handler. (See Figure 1, eld Acceleration (linear) (m/s2 ).)
Since the reading from the sensors will change quickly, you must also display the all-time
highest or lowest (depending on which is greater in absolute value) readings from each sensor
so that we can see concrete numbers. (Field Record Acceleration (linear) (m/s2 ) in Figure 1.)
Ensure that the data you display is readable, accessible to the user, and that it does not vanish
off the edge of the screen. How you do this is up to you. For instance, you can enable scrolling,
or simply format the data effectively. Any functional system is acceptable.

Figure 1: An example of a completed Lab 1.

Phases of the lab

The recommended procedure to complete the lab is as follows:


1. Create infrastructure to display raw data to the user.
2. Create handlers to read and record sensor values.
3. Test.
4. Demonstrate.

Create infrastructure to display data to the user

Before we continue, well explain the structure of an Android application and about JavaDoc.

3.1

Digression 1: About the Android application structure

Even the empty Android project (e.g. from Lab 0) contains folders and les. Heres what they do.
The src folder contains all of your .java les for the project. Here you will add the code
youll write. The empty project already contains a Hello World activity, MainActivity.
The gen folder contains automatically generated .java les. Of particular interest is the
R.java le which mirrors the constants and ids you will dene in the projects xml. Do not edit
these les directly. Your changes will be lost when you build your code next.
The bin folder is the output directory for the project. Compiled les appear here.
The libs folder contains your private libraries. (You can ignore this.)
2

The res folder contains application resources, such as drawable les, layout les, and string
values. The res/layout folder is important. Each xml le in that folder describes the layout
of controls in a single activity in your application.

About Activities. The fundamental building block of an Android application is the Activity. Activities represent screens in your application. When a screen gains focus, Android activates the
appropriate activity, which may then interact with the user. When the user switches to a different
screen, Android disables the activity, preserving the program state.
The new Android application wizard will create a blank MainActivity for you. You can work exclusively with that activity, and you wont need to create any new activities for these labs.

Random testing-related tip. If you did not change anything in your code since the last time you
launched your application, Eclipse will not re-upload or restart your application when you click
Run. Instead, it will just make your application active again. If you are trying to reset your applications state, you will either need to build that option in yourself, or force Eclipse to recompile your
application.

3.2

Digression 2: Helping you help yourself: On JavaDoc

For the next step, the rest of the labs, and life in general, you need to learn how to navigate
JavaDocs. JavaDoc is documentation automatically extracted from Java programswhile these programs were being developed, developers and technical writers added JavaDoc documentation in the
form of specially formatted comments in their source code.
Androids JavaDoc documentation is thorough and easy to read. It is at http://developer.android.
com/reference/packages.html. If you installed the documentation when you installed the Android
SDK, you can also reach the documentation from Eclipse. To do this, hover the mouse over something that you want documentation about. A yellow box will pop up; click on it. Finally, click the
right-most button that appears at the bottom of this box. See gure 2 for an example. Keep in mind
that you can only hover over something that is dened by the Android SDK. If you try to hover over
one of your own classes or variables, Eclipse will look for the JavaDoc attached to your code, and
will not nd it (unless you add it yourself.)

Figure 2: Tool-tip youll see when mousing over a class name.

3.3

Back to displaying data to the user

The immediate goal of this exercise is to display information to the user. The best way to do that is
by creating labels and modifying their contents programmatically. Well walk you through changing
the content of the Hello World label from Lab 0.
The Main activity contains the Hello World label. To reference this label from your code, you need
to give it an ID (identier). Or, in other words, we need a way to refer to that label. Heres how.
1. Create a new Android project and in the "Create Activity" window choose "Blank Activity with
fragment".
2. Open the fragment_main.xml le located in [your project] > res > layout.
3. Switch to the xml tab at the bottom of the editor.
4. Look for the xml tag <TextView> and add the attribute android:id="@+id/label1".
In the Android API, all user-visible controls are sub-classes of android.view.View. You can get a
reference to the Hello World label by calling findViewById() in your Activity with the label id
(which you just added) as a parameter. The return value of this function will be the View object that has the ID provided as an argument to the function. The Android compilation system
will add the ids to the R class. For instance, to nd the label you just added above, you might call
findViewById(R.id.label1).
Labels are TextView objects. You can change the text of a label by calling TextView.setText(). You
can just pass any String to TextView.setText(), and Android will automatically redraw the label
with the new value.
In particular, heres how to modify the Hello World label, after youve followed the steps above.
1. Open MainActivity.java in [your project] > src > ca.uwaterloo.[your project].
2. Write the following PlaceholderFragment() class:
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
TextView tv = (TextView) rootView.findViewById(R.id.label1);
tv.setText("Ive replaced the label!");
return rootView;
}
}

Non-deliverable. You should now have an Android application where you can change the label.
We are, however, going to take a step back and remove that label, replacing it with automaticallygenerated labels.

3.4

Adding more labels

Youll need to create additional labels to display all the needed data. Of course, you could do this by
hand: modify the layout xml for your activity directly, or use the graphical layout tool (double-click
on the layout xml). This lab requires creating a lot of labels, and doing that by hand is tedious. Engineers ruthlessly automate. Conveniently, the Android API lets you create views programmatically.
Heres how to create one label and add it to a view. First, assign an id to the parent:
1. In the layout XML, nd the <RelativeLayout> tag and assign it an id like you did the label.
2. In the onCreateView() method of the PlaceHolderFragment class, declare and initialize a new
TextView object as follows:
TextView tv1 = new TextView(rootView.getContext());
3. Then, set the text as above: tv1.setText("Example Text");
4. In the onCreateView() method of your PlaceholderFragment class, get a reference to the RelativeView
object that we assigned an id to by using findViewByID().
5. Add the TextView to the layout by using the addView() method: layout.addView(tv1)
6. Repeat steps 2 through 5 as necessary to add more labels as needed.
Then, in your PlaceholderFragments onCreateView() method:
1. Get a reference to the top-level layout (which you just assigned an id to) by using findViewByIdwith
the parameter of the ID of the layout (usually starts with R.id.. Cast the result to RelativeLayout.
2. Create a new TextView, e.g. TextView tv1 = new TextView(rootView.getContext())
3. Set the text of tv1, as above.
4. Add tv1 to the layout by calling addView(tv1) on the top-level layout.
You can do this several times. You will nd that you can save some effort if you write a method to
create a new label, add it to the layout and return a reference to the new label.

Common Problems At this stage or very soon afterwards, youll need to create member variables
to contain your TextViews. You can not call getApplicationContext() or findViewById() before the
onCreate() method is executed. For example, the following will cause an null pointer exception:
public class MyActivity extends ActionBarActivity {
TextView globalView = new TextView(getApplicationContext()); // Error
TextView anotherGlobalView = findViewById(R.id.view1); // Another Error
}
Do this instead:
public class MyActivity extends ActionBarActivity {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
LinearLayout lmain = (LinearLayout) rootView.findViewById(R.id.Label1);
TextView tv1 = new TextView(rootView.getContext());
5

tv1.setText(Example);
lmain.addView(tv1);
return rootView;
}
}
RelativeLayout versus LinearLayout. Youll nd that after you follow the above directions and
add a number of labels, your TextViews all run into each other. It is possible to congure the
TextView objects to not step over each other. But its easier to change RelativeLayout for LinearLayout,
which automatically puts its contents in non-overlapping positions.
1. In frament_main.xml, change RelativeLayout to LinearLayout. You have to do that in both the
<RelativeLayout> and </RelativeLayout> tags.
2. In MainActivity.java, change the line
RelativeLayout l = (RelativeLayout)findViewById(R.id.fragment_main);
to
LinearLayout l = (LinearLayout)findViewById(R.id.fragment_main);
3. Add the line
l.setOrientation(LinearLayout.VERTICAL);
which will stack all of the TextView objects vertically rather than horizontally.

Deliverable. Add labels for all of the sensors that well record in the next stage. Your Android app
should now have a number of labels on the screen, which you should have created programmatically. But you might be displaying more labels than will t on the screen.

3.5

Scrolling

It is easy to implement a scrollbar so that the user can look at all of the labels that youve added.
This will not be necessary on a device with a suciently-sized screen, but not all devices are large.
1. Go back to fragment_main.xml, where you should currently have a top-level LinearLayout. Before the LinearLayout, introduce a ScrollView:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroll" android:layout_width="fill_parent"
android:layout_height="wrap_content">
and close the tag after the LinearLayout:
</ScrollView>
2. Change the attribute android:layout_heights value from match_parent to wrap_content.

Deliverable. If you have more content than ts on the screen, make sure that all of the content is
somehow viewable.

Create handlers to read and record sensor values

Tip.

You saw the C# syntax String.Format in ECE150. The corresponding Java syntax is:

String s = String.format("(%f, %f, %f)", x, y, z);


This will allow you to display (x, y, z) coordinate triples, which will be helpful. You may also want
to not display 6 decimal places. Ill leave guring out how to do that up to you. Use the Internet.
Now that you can display data to the user, you need some data to display. For this lab, youll need
to get that data from the phones sensors. A number of Android classes collaborate to allow you to
read this data, including:
The SensorManager. Manages the various sensors of the phone.
Sensors. A software representation of the sensor hardware. You get references to specic
instances of Sensors from the SensorManager.
A SensorEventListener. One of your classes must implement this interface to receive events
from the sensors.
SensorEvents. Represents a single message from a single sensor. The documentation of the
SensorEvent has an excellent explanation of the format that each sensor sends its values in.
Well walk you through how to read the values from the light sensor. You are responsible for reading
the other values and for displaying them on the screen.
1. Implement a SensorEventListener to receive sensor events. You will want to add some way for
the listener to communicate data back to the Fragment. In this example, we give the listener a
reference to a label, but you have the freedom to do this however you like.
class LightSensorEventListener implements SensorEventListener {
TextView output;
public LightSensorEventListener(TextView outputView){
output = outputView;
}
public void onAccuracyChanged(Sensor s, int i) {}
public void onSensorChanged(SensorEvent se) {
if (se.sensor.getType() == Sensor.TYPE_LIGHT) {
// the variable se.values is an array of type int[] or double[].
// the first value (se.values[0]) contains the value
// of the light sensor. store it somewhere useful.
}
}
}
2. In your Fragment request the sensor manager:
SensorManager sensorManager = (SensorManager)
rootView.getContext().getSystemService(SENSOR_SERVICE);
3. In your Fragment request the light sensor:
7

Sensor lightSensor =
sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
4. In your Fragment create an instance of your new SensorEventListener and register it.
SensorEventListener l = new LightSensorEventListener();
sensorManager.registerListener(l, lightSensor,
SensorManager.SENSOR_DELAY_NORMAL);
This should now display the value of the light sensor, if you ll in the TODO line appropriately.
Cleaning up after yourself. For many applications, it is appropriate to unregister sensor event listeners in the onPause() method of the main activity and reregister them in the onResume() method.
Unregistering event listeners helps the phone conserve battery power. Unregistering event listeners is perhaps a good idea for this lab, but will cause havoc for Labs 2 and onward unless you stop
the phone from going to sleep. Were not requiring that you unregister your event listeners.

Deliverables. Your solution must display current sensor information for these sensors, as well as
record values for all sensors but the light sensor.
(TYPE_LIGHT): The readings from the light intensity sensor.
(TYPE_ACCELEROMETER): The three components of linear acceleration from the accelerometer.
(You may also display TYPE_LINEAR_ACCELERATION data as an alternative.)
(TYPE_MAGNETIC_FIELD): The three components of the magnetic eld sensor.
(TYPE_ROTATION_VECTOR): The three components of phones rotation vector.
The record value is the highest absolute value.

Optional Extra (no marks).

4.1

Implement a Clear button which resets the record values.

Digression 3: the accelerometer and gravity

You will notice that when the phone is at rest, the accelerometer reports an z-acceleration of approximately 9.81 m/s2 . Surprisingly, this is not the acceleration due to gravity, but rather the acceleration due to the normal force. To understand why this is, we need to look at what exactly an
accelerometer measures.
A simple one-axis accelerometer consists of a test mass on a spring. When a force is applied to the
case of the accelerometer, the mass moves until the force of the spring matches the force applied
to the case. The degree to which the spring is stretched or compressed tells us how much force the
case is experiencing.
Now, if we imagine this device in free-fall (dont drop your phones!), we can see that the spring will
be at its rest position, while if the device was resting on the ground, the spring would be compressed
under the weight of the test mass. Thus, an accelerometer measures acceleration relative to freefall. In relativity theory, this acceleration is called proper acceleration.
In Lab 2, youll process the data from the accelerometer to measure footsteps. To get the absolute
acceleration experienced by your phone, you will need to apply a low-pass lter to the acceleration
data. Stay tuned for more information!
8

Figure 3: An accelerometer designed by the Archimedes Automated Assembly Planning Project at


Sandia National Laboratory.

Graphing

For the next labs, it is enormously useful to be able to see how the accelerometer reacts when you
manipulate the phone in various ways. We have provided an implementation of a line graph view
that will display sets of data points. You will nd LineGraphView.java in the materials directory
of the course repository. Figure 1 shows what the graph view looks like. There is a bit of tearing in
the screenshot of the graph because the process of taking a screenshot takes longer than one graph
update.

Using the LineGraphView The following sample code shows how to set up the LineGraphView
that weve provided. You are under no obligation to use this code; you can provide your own, if you
want, or modify the code as you feel best, but chances are you will just want to stick with the code
we provided.
Note that youll have to include an import statement for this class, since it belongs to the ca.uwaterloo.sensortoy
package. Imports are like using statements in C#1 . Hitting Ctrl-Shift-O in Eclipse often xes your imports.
class MainActivity {
LineGraphView graph;
public void onCreate(Bundle savedInstanceState) {
// ... code was already here ...
LinearLayout layout = ((LinearLayout)findViewById(R.id.layout));
graph = new LineGraphView(getApplicationContext(),
100,
Arrays.asList("x", "y", "z"));
layout.addView(graph);
graph.setVisibility(View.VISIBLE);
1 http://www.harding.edu/fmccown/java_csharp_comparison.html

// ... other code ...


}
}
Relevant parameters in the constructor call are 100 and Arrays.asList("a", "b", "c"). The 100
represents the number of samples to keep on the t-axis. The syntax Arrays.asList("x", "y", "z")
is Java shorthand for providing a list of labels for the graph.
The LineGraphViews constructor takes three parameters. The rst is the application context. It is a
special object that the view needs to know how to interact with the global state of the Android OS.
The second parameter is an integer telling the LineGraphView how many samples its X axis should
be. The last parameter is an Object that implements Javas List interface. This object should contain
a list of strings that will be used as the labels of the different lines in the graph. Here is some sample
code initialising a three-variable graph. It should go into the onCreate() method of your Activity.
Once youve created your view, you can start adding data to it. Use methods addPoint() and purge().
purge() will clear the graph. addPoint() takes either an array or List of data points. The data must
be in the same order as the labels that were passed into the constructor. Well include an example
of how to populate the graph below.

Integrating the LineGraphView.


the LineGraphView as follows.

Now you have code to handle sensor changes. You can hook up

public void onSensorChanged(SensorEvent event) {


// ... other code ...
graph.addPoint(event.values);
// ... other code ...
}

Deliverable. Plot the accelerometer data in graphical format.

Test

Your application should now display the current values of the sensors. You must display sensor
values showing the three components of each sensor along with the lifetime maximum reading for
these components. Also, you must display a graph of the accelerometer sensor readings over time.
Your application should not crash or throw exceptions.

Demonstration

Once you are satised that your design and implementation are working correctly, arrange a demonstration with a teaching assistant. You will need to have the TA complete an assessment form. All
of the members of your laboratory group must sign the completed assessment form. Your grade
will be based on the results of the project demonstration at the end of the laboratory session and
an evaluation of how well your code follows engineering design principles. (We will run plagiarism detection software on the source code, which may subsequently lower your grade and trigger
a Policy 71 case. Dont plagiarize!)

10

Writing Good Code. Your application must follow good engineering design principles. You should
therefore avoid: unnecessary code duplication; excessive use of variables the state of which you
keep synchronized manually; forgetting to deallocate (free up) resources like les you have requested from the Android OS; and any other such design failures that make your application difcult to maintain or that step on the toes of other applications you share the device with.

Submission of project les

Commit the Lab1_SSS_XX les to your Subversion repository. The TAs will not mark labs that have
not been submitted to SVN. The address is
https://ecesvn.uwaterloo.ca/courses/ece155/w15/groups/group-NNN-MM
Email Sanjay Singh if you cant commit to that address.

Too Long; Did Not Read

If you just want to cut to the chase and get an exact listing of what to do, check the lab 1 assessment
form and you will see exactly what we are looking for in the deliverables for this lab.

11

You might also like