Making Custom Change Listeners in PSLab Android

In this post we are going to learn how to make custom change listeners. There are many use cases for custom change listeners like if you want to initiate some action when some variable’s value is changed. In PSLab android app, this was required during initialisation of PSLab hardware device, it takes about 3-4 seconds to initialise the device which includes reading calibration data from device and process it. So before starting the initialisation process, app notifies user with the message, “Initialising Wait …” and after initialisation is done, user is notified with the message “Initialisation Completed”.

There might be other ways to accomplish this but I found making a custom change listener for boolean and trigger notifying user action on change of boolean value to be most organised way to do it.

Another way I can think of is to pass the fragment reference to the class  constructor for which the object is to be made. And Views need to be made public for access from that object to change status after some work is done.

Let’s look at an example, we would change status in a fragment after some task in object instantiation is completed.

Implementation

Class with variable on which custom change listener is required:
Create a class and declare a variable for which you want to listen the value change to trigger some action. In this example we have created a InitializationVariable class and defined a boolean variable named initialised.

Define an interface inside the class and that’s where the trick lies. When you set/change the value of the variable through a function setVariable(boolean value) in this case, note that we are triggering the interface method too.

public class InitializationVariable {

   public boolean initialised = false;
   private onValueChangeListener valueChangeListener;

   public boolean isInitialised() {
       return initialised;
   }

   public void setVariable(boolean value) {
       initialised = value;
       if (valueChangeListener != null) valueChangeListener.onChange();
   }

   public onValueChangeListener getValueChangeListener() {
       return valueChangeListener;
   }

   public void setValueChangeListener(onValueChangeListener valueChangeListener) {
       this.valueChangeListener = valueChangeListener;
   }

   public interface onValueChangeListener {
       void onChange();
   }

}

Create an object of above class in activity/fragment:
Create an object to the class we just made and attach onValueChangeListener to it. This example shows how it’s used in PSLab Android, you can use it anywhere but remember to access view elements from a valid context.

public static InitializationVariable booleanVariable;
public class HomeFragment extends Fragment {

   @BindView(R.id.tv_initialisation_status)
   TextView tvInitializationStatus;

   public static InitializationVariable booleanVariable;// object whose value change is noted

   public static HomeFragment newInstance() {
       HomeFragment homeFragment = new HomeFragment();
       return homeFragment;
   }

   @Nullable
   @Override
   public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
       View view = inflater.inflate(R.layout.home_fragment, container, false);
       unbinder = ButterKnife.bind(this, view);
       return view;
   }

   @Override
   public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
       super.onViewCreated(view, savedInstanceState);

       booleanVariable.setValueChangeListener(new InitializationVariable.onValueChangeListener() {
           @Override
           public void onChange() {
               if (booleanVariable.isInitialised())
                   tvInitializationStatus.setText("Initialsation Completed");
               else
                   tvInitializationStatus.setText("Initialising Wait ...");
           }
       });
  }
}

Now whenever booleanVariable.setVariable(value) is called, it triggers the onValueChangeListener where you can manage the action you wanted to do on value change.
This is similar to how other listeners are implemented .You implement an interface and call those interface methods on some value change and classes which implement those interface have overridden methods which handle the action after change.

Hopefully this post gives you an insight about how change listeners are implemented.

Note: This post was specific to PSLab Android App, you can create custom change listener on any variable in any class and perform action on value of the variable getting changed.

Resources

Continue ReadingMaking Custom Change Listeners in PSLab Android

Opening Local HTML Files in PSLab Android App

The PSLab Android App allows users to perform experiments using the PSLab device. The experience to perform an experiment should resemble the generic way to perform the experiment. So we associated an Experiment Doc file which the user can refer to while performing experiment. Just like a regular lab manual, the experiment doc contains the AIM, THEORY & FORMULAS, SCHEMATIC, OUTPUT, etc. In the PSLab Desktop App, since there was already a provision for using HTML docs and so I  avoided reinventing the wheel and used those html files as it is.

    

The problem we faced was how to open a bunch of HTML files with their corresponding CSS, JS files in Android’s webView.

There are two ways it can be done:

  • Host the experiment docs on a server and make a request from the android app for the specific experiment doc like Diode I-V, Zener I-V, etc.
  • Put the folder containing all html, CSS, js files in assets folder and request for the HTML doc files locally.

The PSLab developer team went with the second option as the availability of  Internet  is necessary for the performing experiment if we follow the first option and so to avoid this dependence on the Internet, we went with the second option and stored HTML docs locally in assets folder.

Implementation

  • Put the folder containing all the HTML, CSS, JS files in the assets folder in your android project. In this case the folder is DOC_HTML.

  • Define the WebView in xml and take the webView’s reference in your activity/fragment
    In xml
<WebView
   android:id="@+id/perform_experiment_wv"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />

In activity/fragment

webView = (WebView) view.findViewById(R.id.perform_experiment_wv);
  • Load the url in webView in the format as shown below
webView.loadUrl("file:///android_asset/DOC_HTML/apps/" + htmlFile);

“file:///” acts as resource identifier, so file:///android_asset/ actually points to “pslab-android/app/src/main/assets/”.
From the assets directory, we can a provide route to any HTML file. Here I put all HTML files in apps folder and used the string variable “htmlFile” to point to the specific html file.

Similarly html files stored in the external storage can also be accessed but there are some cases you need to handle. For example,if external storage is mounted, you can’t request the html file from external storage.

To request html files from external storage, make sure that you have the following permission in your AndroidManifest.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();

Relative to baseDir you can specify the path from your html files, like

baseDir + “DOC_HTML/apps” + htmlFile

Conclusion

Putting HTML files in the assets folder and requesting it by webView’s loadURL() method is the best but there are various drawbacks of using this method like the increase in size of the apk. In our case, the normal apk size was 3MB but after adding the html doc folder it increased to 7MB. It increased by almost an additional size of the html folder added in assets. As it’s written, in the android’s project overview guide, the assets folder contains files that should be compiled into an .apk file as-is.

Resources

Continue ReadingOpening Local HTML Files in PSLab Android App

Custom SeekBar in PSLab Android

By default Seekbar in Android only return integer values greater than zero. But there can be some situation where we need the SeekBar to return a float and negative values. To implement trigger functionality in the Oscilloscope activity of PSLab Android app, we require a SeekBar that sets a voltage level that should trigger the capture sequence. Since this voltage value ranges between -16.5 V to 16.5 V, default Seekbar don’t serve the purpose.

The solution is to create a custom SeekBar that returns float values. Let’s understand how to implement it.

Create a FloatSeekBar class which extends AppCompatSeekBar. Create a constructor for the class with Context, AttributeSet and defStyle as parameters. AttributeSet is the set of properties specified in an XML resource file whereas defStyle is default style to apply to this view.

public class FloatSeekBar extends android.support.v7.widget.AppCompatSeekBar {
   private double max = 0.0;
   private double min = 0.0;

   public FloatSeekBar(Context context, AttributeSet attrs, int defStyle) {
       super(context, attrs, defStyle);
       applyAttrs(attrs);
   }

 

Then define setters method which set the max and min values of the SeekBar. This method basically sets the range of the SeekBar.

public void setters(double a, double b)
{
   min = a;
   max = b;
}

 

getValue is a method that manipulates current progress of the SeekBar and returns the value. Here the equation used to determine the value is (max – min) * (getProgress() / getMax()) + min.

public double getValue() {
   DecimalFormat df = new DecimalFormat("#.##");
   Double value = (max - min) * ((float) getProgress() / (float) getMax()) + min;
   value = Double.valueOf(df.format(value));
   return value;
}

 

setValue method takes the double value, and accordingly set the progress of the SeekBar.

public void setValue(double value) {
   setProgress((int) ((value - min) / (max - min) * getMax()));
}

This creates a custom SeekBar, it can be used just like a normal SeekBar.

Now, set the range of custom SeekBar between -16.5 and 16.5.

seekBarTrigger = (FloatSeekBar) v.findViewById(R.id.seekBar_trigger);
seekBarTrigger.setters(-16.5, 16.5);

 

In order to get value of the custom SeekBar call getValue method.

seekBarTrigger.getValue();

In order to follow the entire code for custom SeekBar implementation in PSLab refer FloatSeekBar.java, Attr.xml and TimebaseTrigger.java.

A glimpse of custom SeekBar in PSLab Android.

Resources

 

Continue ReadingCustom SeekBar in PSLab Android

Comparing Different Graph View Libraries and Integrating Them in PSLab Android Application

There is a significant role of graphs in PSLab, they’re used for the following purpose:

For this, we need to implement real time graphs that stimulate real time data from the PSLab device efficiently. It is necessary to analyze each and every Graph View Library, compare them and integrate the best one in PSLab Android app.

Available Graph Libraries

The available Graph View libraries of Android are:

  1. MPAndroidChart
  2. Graph-View
  3. SciChart

Which one is the best with respect to the PSLab project?

MPAndroidChart

Line Graph plotted using MPAndroidChart (image source)

It is an open source graph view library by Philipp Jahoda. The following are the features of MPAndroidChart

  • There are 8 different chart types
  • Scaling on both axes. Scaling can be done using pinch zoom gesture.
  • Dual Axes, we can have 2 Y-axis.
  • Real time support
  • Customizable axis ie we can define different labels to the axis
  • Save chart to SD-Card
  • Predefined color templates
  • Legends which are used to define which line depicts what.
  • Animations
  • Fully customizable, from background color to color of the lines and grids.

On trying MPAndroidChart, I found it to be a slightly difficult to implement.

Graph-View

Line Graph plotted using GraphView Library (image source)

It is also an open source graph view library by Jonas Gehring. The following are features of the Graph-View

  • Supports Line Chart, Bar Chart and Points.
  • Scrolling vertical and horizontal
  • Scaling on both axes.
  • Realtime Graph support
  • Draw multiple series of data. Let the diagram show more that one series in a graph. You can set a color and a description for every series.
  • Legends (as discussed in MPAndroidChart)
  • Custom labels
  • Manual Y axis limits can be set.

SciChart

It is rich APIs for Axis Ranging, Label Formatting, Chart Modifiers (interaction) and Renderable Series. It is packed with features but unfortunately, it is not open sourced.

The Verdict

Both MPAndroidChart and Graph-View are good libraries, packed with a lot of features. GraphView is easier to implement as compared to MPAndroidChat (not that difficult either). Both of them have the features like pinch zoom. MPAndroidChart had the feature of scale adjustment even when the graph is being plotted. The rate of plotting was comparable in both but it was slightly faster in MPAndroidChart. So, finally GraphView is easier to implement but MPAndroidChart has slightly better performance. So, we integrated MPAndroidChart in PSLab Android application.

Integrating MPAndroidChart in PSLab Android App

In order to integrate MPAndroidChart in the Android project add the following code in the build.gradle of your project.

 

compile 'com.github.PhilJay:MPAndroidChart:v3.0.1'

Creating Oscilloscope like graph

If we observe an Oscilloscope, it has a black/blue screen with grid lines. An oscilloscope is a voltage vs time graph hence the x axis represents the time elapsed and y axis the voltage of the signal at the instant of time. There are left and right y axis for different channels.

An Oscilloscope

In order to implement a graph similar to that of Oscilloscope in PSLab Android App using MPAndroidChart library, the graph needed to be customized.

The following step was taken to customized the graph in Oscilloscope Activity.

Background Color

mChart.setBackgroundColor(Color.BLACK);

This sets the background color of the graph as black. mChart is an object of the Line graph.

Legend

Legend l = mChart.getLegend();
l.setForm(Legend.LegendForm.LINE);
l.setTextColor(Color.WHITE);

Here we are setting the Legend form. There are many options available for the same like SQUARE, CIRCLE, and LINE. We are using LINE Legend form.  Also, we set the white color for the legend text.

X Axis Customization

x = mChart.getXAxis();
x.setTextColor(Color.WHITE);

First, we create an object of XAxis and set the textcolor as white.

x.setDrawGridLines(true);

The above method draws the grid lines along the x axis.

x.setAxisMinimum(0f);
x.setAxisMaximum(875f);

Now we will set the range of x axis by setting minimum value as 0 and the maximum value is 875.

Y Axis  Customization

y1 = mChart.getAxisLeft();
y1.setTextColor(Color.WHITE);
y1.setAxisMaximum(16f);
y1.setAxisMinimum(-16f);
y1.setDrawGridLines(true);

This is similar to what we did in x axis formatting.

After performing the above steps we got the following results.

To follow the entire code for graph customization refer chartinit method in Oscilloscope Activity, PSLab Android repository.

Resources

Continue ReadingComparing Different Graph View Libraries and Integrating Them in PSLab Android Application

Plotting Digital Logic Lines In PSLab Android App

The PSLab device offers the Logic Analyzer functionality. A Logic Analyzer is a laboratory instrument that can capture and display digital signals from a digital system or circuit. It is similar to what an oscilloscope is for analog signals and is used to study timing relationship between different logic lines. It plots the logic lines/timing diagram which tells us the information about the state of the Digital System at any instant of time. For example, in the image below we can study the states of digital signals from channels ID1, ID2, ID3 at different times and find parameters like the propagation delay. It’s also used to find errors in Integrated Circuits (ICs) and debug logic circuits.

How I plotted ideal logic lines using MPAndroid Chart library?

Conventional method of adding data points results in the plot as illustrated in the image below. By conventional method I mean basically adding Y-axis (logic state) values corresponding to X-axis values (timestamp).

Result with normal adding and plotting data-points

In the above plot, logic lines follow non-ideal behaviour i.e they take some time in changing their state from high to low. This non-ideal behaviour of these lines increases when the user zooms in graph to analyse timestamps.

Solution to how we can achieve ideal behaviour of logic lines:

A better solution is to make use of timestamps for generating logic lines i.e time instants at which logic made a transition from HIGH -> LOW or LOW -> HIGH. Lets try to figure out with an example:

Timestamps = { 1, 3, 5, 8, 12 } and initial state is HIGH ( i.e at t = 0, it’s HIGH ). This implies that at t = 1, transition from HIGH to LOW took place so at t = 0, it’s HIGH, t = 1 it’s both HIGH and LOW,  at t = 2 it’s LOW.
Now at t = 0 & t = 2, you can simple put y = 1 and 0 respectively. But how do you add data-point for t = 1. Trick is to see how transition is taking place, if it’s HIGH to LOW then add first 1 for t = 1 and then 0 for t = 1.
So the set of points look something like this:

( Y, X ) ( LOGIC , TIME ) -> ( 1, 0 ) ( 1, 1 ) ( 0, 1) ( 0, 2 ) ( 0, 3 ) ( 1, 3 )  ( 1, 4 ) …

Code snippet for adding coordinates in this fashion:

int[] time = timeStamps.get(j);
for (int i = 0; i < time.length; i++) {
   if (initialState) {
       // Transition from HIGH -> LOW
       tempInput.add(new Entry(time[i], 1));
       tempInput.add(new Entry(time[i], 0));
   } else {
       // Transition from LOW -> HIGH
       tempInput.add(new Entry(time[i], 0));
       tempInput.add(new Entry(time[i], 1));
   }

   // changing state variable
   initialState = !initialState;
}

After adding data-points in above mentioned way, we obtained ideal logic lines successfully as illustrated in the image given below

Resources

Continue ReadingPlotting Digital Logic Lines In PSLab Android App

Generating Real-Time Graphs in PSLab Android App

In PSLab Android App, we need to log data from the sensors and correspondingly generate real-time graphs. Real-time graphs mean a data streaming chart that automatically updates itself after every n second. This was different from what we did in Oscilloscope’s graph, here we need to determine the relative time at which the data is recorded from the sensor by the PSLab.

Another thing we need to take care of was the range of x axis. Since the data to be streamed is ever growing, setting a large range of the x axis will only make reading sensor data tedious for the user. For this, the solution was to make real time rolling window graph. It’s like when the graph exceeds the maximum range of x axis, the graph doesn’t show the initial plots. For example, if I set that graph should show the data only for the 10-second window when the 11th-second data would be plot, the 1st-second data won’t be shown by the graph and maintains the difference between the maximum and the minimum range of the graph. The graph library we are going to use is MPAndroidChart. Let’s break-down the implementation step by step.

First, we create a long variable, startTime which records the time at which the entire process starts. This would be the reference time. Flags make sure when to reset this time.

if (flag == 0) {
   startTime = System.currentTimeMillis();
   flag = 1;
}

 

We used Async Tasks approach in which the data is from the sensors is acquired in the background thread and the graph is updated in the UI thread. Here we consider an example of the HMC5883L sensor, which is actually Magnetometer. We are calculating time elapsed by subtracting current time with the sartTime and the result is taken as the x coordinate.

private class SensorDataFetch extends AsyncTask<Void, Void, Void> {
   ArrayList<Double> dataHMC5883L = new ArrayList<Double>();
   long timeElapsed;

   @Override
   protected Void doInBackground(Void... params) {
       
     timeElapsed = (System.currentTimeMillis() - startTime) / 1000;

     entriesbx.add(new Entry((float) timeElapsed, dataHMC5883L.get(0).floatValue()));
     entriesby.add(new Entry((float) timeElapsed, dataHMC5883L.get(1).floatValue()));
     entriesbz.add(new Entry((float) timeElapsed, dataHMC5883L.get(2).floatValue()));
       
     return null;
   }

 

As we need to create a rolling window graph we require to add few lines of code with the standard implementation of the graph using MPAndroidChart. This entire code is placed under onPostExecute method of AsyncTasks. The following code sets data set for the Line Chart and tells the Line Chart that a new data is acquired. It’s very important to call notifyDataSetChanged, without this the things won’t work.

mChart.setData(data);
mChart.notifyDataSetChanged();

 

Now, we will set the visible range of x axis. This means that the graph window of the graph won’t change until and unless the range set by this method is not achieved. Here we are setting it to be 10 as we need a 10-second window.

mChart.setVisibleXRangeMaximum(10);

Then we will call moveViewToX method to move the view to the latest entry of the graph. Here, we have passed data.getEntryCount method which returns the no. of data points in the data set.

mChart.moveViewToX(data.getEntryCount());

 

We will get following results

To see the entire code visit this link.

Resources

Continue ReadingGenerating Real-Time Graphs in PSLab Android App

Integrating Stock Sensors with PSLab Android App

A sensor is a digital device (almost all the time an integrated circuit) which can receive data from outer environment and produce an electric signal proportional to that. This signal will be then processed by a microcontroller or a processor to provide useful functionalities. A mobile device running Android operating system usually has a few sensors built into it. The main purpose of these sensors is to provide user with better experience such as rotating the screen as he moves the device or turn off the screen when he is making a call to prevent unwanted screen touch events. PSLab Android application is capable of processing inputs received by different sensors plugged into it using the PSLab device and produce useful results. Developers are currently planning on integrating the stock sensors with the PSLab device so that the application can be used without the PSLab device.

This blog is about how to initiate a stock sensor available in the Android device and get readings from it. Sensor API provided by Google developers is really helpful in achieving this task. The process is consist of several steps. It is also important to note the fact that there are devices that support only a few sensors while some devices will support a lot of sensors. There are few basic sensors that are available in every device such as

  • “Accelerometer” – Measures acceleration along X, Y and Z axis
  • “Gyroscope” – Measures device rotation along X, Y and Z axis
  • “Light Sensor” – Measures illumination in Lux
  • “Proximity Sensor” – Measures distance to an obstacle from sensor

The implementing steps are as follows;

  1. Check availability of sensors

First step is to invoke the SensorManager from Android system services. This class has a method to list all the available sensors in the device.

SensorManager sensorManager;
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);

Once the list is populated, we can iterate through this to find out if the required sensors are available and obstruct displaying activities related to sensors that are not supported by the device.

for (Sensor sensor : sensors) {
   switch (sensor.getType()) {
       case Sensor.TYPE_ACCELEROMETER:
           break;
       case Sensor.TYPE_GYROSCOPE:
           break;
       ...
   }
}

  1. Read data from sensors

To read data sent from the sensor, one should implement the SensorEventListener interface. Under this interface, there are two method needs to be overridden.

public class StockSensors extends AppCompatActivity implements SensorEventListener {

    @Override
    public void onSensorChanged(SensorEvent sensorEvent) {

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {

    }
}

Out of these two methods, onSensorChanged() method should be addressed. This method provides a parameter SensorEvent which supports a method call getType() which returns an integer value representing the type of sensor produced the event.

@Override
public void onSensorChanged(SensorEvent sensorEvent) {
   switch (sensorEvent.sensor.getType()) {
       case Sensor.TYPE_ACCELEROMETER:
           break;
       case Sensor.TYPE_GYROSCOPE:
           break;
       ...
   }
}

Each available sensor should be registered under the SensorEventListener to make them available in onSensorChanged() method. The following code block illustrates how to modify the previous code to register each sensor easily with the listener.

for (Sensor sensor : sensors) {
   switch (sensor.getType()) {
       case Sensor.TYPE_ACCELEROMETER:
           sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
           break;
       case Sensor.TYPE_GYROSCOPE:
           sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_UI);
           break;
   }
}

Depending on the readings we can provide user with numerical data or graphical data using graphs plotted using MPAndroidChart in PSLab Android application.

The following images illustrate how a similar implementation is available in Science Journal application developed by Google.

Resources

Continue ReadingIntegrating Stock Sensors with PSLab Android App

Expandable ListView In PSLab Android App

In the PSLab Android App, we show a list of experiments for the user to perform or refer to while performing an experiment, using PSLab hardware device. A long list of experiments need to be subdivided into topics like Electronics, Electrical, School Level, Physics, etc. In turn, each category like Electronics, Electrical, etc can have a sub-list of experiments like:

  • Electronics
    • Diode I-V characteristics
    • Zener I-V characteristics
    • Transistor related experiments
  • Electrical
    • Transients RLC
    • Bode Plots
    • Ohm’s Law

This list can continue in similar fashion for other categories as well. We had to  display  this experiment list to the users with a good UX, and ExpandableListView seemed the most appropriate option.

ExpandableListView is a two-level listView. In the Group view an individual item can be expanded to show it’s children. The Items associated with ExpandableListView come from ExpandableListAdapter.

 

 

 

 

 

 

 

 

Implementation of Experiments List Using ExpandableListView

First, the ExpandableListView was declared in the xml layout file inside some container like LinearLayout/RelativeLayout.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical">
   <ExpandableListView
       android:id="@+id/saved_experiments_elv"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:divider="@color/colorPrimaryDark"
       android:dividerHeight="2dp" />
</LinearLayout>

Then we populated the data onto the ExpandableListView, by making an adapter for ExpandableListView by extending BaseExpandableListAdapter and implementing its methods. We then passed a Context, List<String> and Map<String,List<String>> to the Adapter constructor.

Context: for inflating the layout

List<String>: contains titles of unexpanded list

Map<String,List<String>>: contains sub-list mapped with title string

public SavedExperimentAdapter(Context context,
                                 List<String> experimentGroupHeader,
                                 HashMap<String, List<String>> experimentList) {
       this.context = context;
       this.experimentHeader = experimentGroupHeader;
       this.experimentList = experimentList;
   }

In getGroupView() method, we inflate, set title and return group view i.e the main list that we see on clicking and the  sub-list is expanded. You can define your own layout in xml and inflate it. For PSLab Android, we used the default one provided by Android

 android.R.layout.simple_expandable_list_item_2
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
   String headerTitle = (String) getGroup(groupPosition);
   if (convertView == null) {
       LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
       convertView = inflater.inflate(android.R.layout.simple_expandable_list_item_2, null);
   }
   TextView tvExperimentListHeader = (TextView) convertView.findViewById(android.R.id.text1);
   tvExperimentListHeader.setTypeface(null, Typeface.BOLD);
   tvExperimentListHeader.setText(headerTitle);
   TextView tvTemp = (TextView) convertView.findViewById(android.R.id.text2);
   tvTemp.setText(experimentDescription.get(groupPosition));
   return convertView;
}

Similarly, in getChildView() method, we inflate, set data and return child view. We wanted simple TextView as sub-list item thus inflated the layout containing only TextView and setText by taking reference of textView from the inflated view.

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
   String experimentName = (String) getChild(groupPosition, childPosition);
   if (convertView == null) {
       LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
       convertView = inflater.inflate(R.layout.experiment_list_item, null);
   }
   TextView tvExperimentTitle = (TextView) convertView.findViewById(R.id.exp_list_item);
   tvExperimentTitle.setText(experimentName);
   return convertView;
}

The complete code for the Adapter can be seen here.

After creating the adapter we proceeded similarly to the normal ListView. Take the reference for ExpandableListView by findViewById() or BindView if you are using ButterKnife and set the adapter as an instance of adapter created above.

@BindView(R.id.saved_experiments_elv)
ExpandableListView experimentExpandableList;
experimentAdapter = new SavedExperimentAdapter(context, headerList, map);
experimentExpandableList.setAdapter(experimentAdapter);
Source: PSLab Android

Roadmap

We are planning to divide the experiment sub-list into categories like

  • Electronics
    • Diode
      • Diode I-V
      • Zener I-V
      • Diode Clamping
      • Diode Clipping
    • BJT and FET
      • Transistor CB (Common Base)
      • Transistor CE (Common Emitter)
      • Transistor Amplifier
      • N-FET output characteristic
    • Op-Amps
  • Electrical

This is a bit more complex than it looks, I tried using an ExpandableListView as a child for a group item but ran into some errors. I will write a post as soon as this view hierarchy has been achieved.

Resources

Continue ReadingExpandable ListView In PSLab Android App

The Pocket Science Lab: Who Needs it, and Why

Science and technology share a symbiotic relationship. The degree of success of experimentation is largely dependent on the accuracy and flexibility of instrumentation tools at the disposal of the scientist, and the subsequent findings in fundamental sciences drive innovation in technology itself. In addition to this, knowledge must be free as in freedom. That is, all information towards constructing such tools and using them must be freely accessible for the next generation of citizen scientists. A common platform towards sharing results can also be considered in the path to building a better open knowledge network.

But before we get to scientists, we need to consider the talent pool in the student community that gave rise to successful scientists, and the potential talent pool that lost out on the opportunity to better contribute to society because of an inadequate support system. And this brings us to the Pocket Science Lab

How can PSLab help electronics engineers & students?

This device packs a variety of fundamental instruments into one handy package, with a Bill-of-materials that’s several orders of magnitude less than a distributed set of traditional instruments.

It does not claim to be as good as a Giga Samples Per second oscilloscope, or a 22-bit multimeter, but has the potential to offer a greater learning experience. Here’s how:

  • A fresh perspective to characterize the real world. The visualization tools that can be coded on an Android device/Desktop (3D surface plots, waterfall charts, thermal distributions etc ), are far more advanced than what one can expect from a reasonably priced oscilloscope. If the same needs to be achieved with an ordinary scope, a certain level of technical expertise is expected from the user who must interface the oscilloscope with a computer, and write their own acquisition & visualization app.
  • Reduce the entry barrier for advanced experiments.: All the tools are tightly integrated in a cost-effective package, and even the average undergrad student that has been instructed to walk on eggshells around a conventional scope, can now perform elaborate data acquisition tasks such as plotting the resonant frequency of a tuning fork as a function of the relative humidity/temperature. The companion app is being designed to offer varying levels of flexibility as demanded by the target audience.

  • Is there a doctor in the house? With the feature set available in the PSlab , most common electronic components can be easily studied , and will save hours while prototyping new designs.  Components such as resistors, capacitors, diodes, transistors, Op-amps, LEDs, buffers etc can be tested.

How can PSLab help science enthusiasts ?

Physicists, Chemists and biologists in the applied fields are mostly dependent on instrument vendors for their measurement gear. Lack of an electronic/technical background hinders their ability to improve the gear at their disposal, and this is why a gauss meter which is basically a magnetometer coupled with a crude display in an oversized box with an unnecessarily huge transformer can easily cost upwards of $150 . The PSLab does not ask the user to be an electronics/robotics expert , but helps them to get straight to the acquisition part. It takes care of the communication protocols, calibration requirements, and also handles visualization via attractive plots.

A physicist might not know what I2C is , but is more than qualified to interpret the data acquired from a physical sensor, and characterize its accuracy.

  • The magnetometer (HMC5883L) can be used to demonstrate the dependence of the axial magnetic field on distance from the center of a solenoid
  • The pressure,temperature sensor (BMP280) can be used to verify the gas laws, and verify thermodynamic phenomena against prevalent theories.

Similarly, a chemist can use an RGB sensor (TCS3200) to put the colour of a solution into numbers, and develop a colorimeter in the process. Colorimeters are quite handy for determining molality of coloured solutions., and commercial ones are rather expensive. What it also needs is a set of LEDs with known wavelengths, and most manufacturers offer proper characterisation information.

What does it mean for the hobbyist?

It is capable of greatly speeding up the troubleshooting process . It can also instantly characterize the expected data from various sensors so that the hobbyist can code accordingly. For example, ‘beyond what tilt threshold & velocity should my humanoid robot swing its arms forward in order to prevent a broken nose?’ . That’s not a question that can be easily answered by said hobbyist who is currently in the process of developing his/her own acquisition system.

How can we involve the community?

The PSLab features an experiment designer that speeds acquisition by providing spreadsheets, analytical tools, and visualisation options all in one place. An option for users to upload their new experiments/utilities to the cloud, and subject those to a peer-review process has been planned. Following which , these new experiments can be pumped back into the ecosystem which will find more uses for it, improve it, and so on.

For example , a user can combine the waveform generator with an analog multiplier IC, and develop a spectrum analyzer.

The case for self-reliance

The average undergraduate laboratory currently employs dedicated instruments for each experiment as prescribed by the curriculum. These instruments often only include the measurement tools essential to the experiment, and students merely repeat the procedure verbatim. That’s not experimentation, it’s rather just verification. PSLab offers a wide array of additional instruments that can be employed by the student to enhance the experiment with their own inputs.

For example, a commonly used diode IV curve-tracer kit usually has a couple of power supplies, a voltmeter, and an ammeter. But, if a student wishes to study the impact of temperature on the band gap, he will hard pressed for the additional tools, and software to combine the acquisition process. With the PSLab, however , he/she can pick from a variety of temperature sensors (LM35, BMP180, Si7021 .. ) depending on the requirement, and explore beyond the book. They are thus better prepared to enter research labs .

And in conclusion , this project has immense potential to help create the next generation of scientists, engineers and creators.

Resources

 

Continue ReadingThe Pocket Science Lab: Who Needs it, and Why

Exporting Functions in PSLab Firmware

Computer programs consist of several hundreds line of code. Smaller programs contain around few hundreds while larger programs like PSLab firmware contains lines of code expanding over 2000 lines. The major drawback with a code with lots of lines is the difficulty to debug and hardship for a new developer to understand the code. As a solution modularization techniques can be used to have the long code broken down to small set of codes. In C programming this can be achieved using different .c files and relevant .h(header) files.

The task is tricky as the main code contains a lot of interrelated functions and variables. Lots of errors were encountered when the large code in pslab-firmware being modularized into application specific files. In a scenario like this, global variables or static variables were a much of a help.

Global Variables in C

A global variable in C is a variable whose scope spans wide across the entire program. Updation to the variable will be reflected everywhere it is used.

extern TYPE VARIABLE = VALUE;

Static Variables in C

This type of variables preserve their content regardless of the scope they are in.

static TYPE VARIABLE = VALUE;

Both the variables preserve their values but the memory usage is different depending on the implementation. This can be explained using a simple example.

Suppose a variable is required in different C files and it is defined in one of the header files as a local variable. The header file is then added to several other c files. When the program is compiled the compiler will create several copies of the same variable which will throw a compilation error as variable is already declared. In PSLab firmware, a variable or a method from one library has a higher probability of it being used in another one or many libraries.

This issue can be addressed in two different ways. They are by using static variables or global variables. Depending on the selection, the implementation is different.

The first implementation is using static variables. This type of variables at the time of compilation, create different copies of himself in different c files. Due to the fact that C language treats every C file as a separate program, if we include a header file with static variables in two c files, it will create two copies of the same variable. This will avoid the error messages with variables redeclared. Even though this fixes the issue in firmware, the memory allocation will be of a wastage. This is the first implementation used in PSLab firmware. The memory usage was very high due to duplicate variables taking much memory than they should take. This lead to the second implementation.

first_header.h

#ifndef FIRST_HEADER_H 
#define FIRST_HEADER_H 

static int var_1;

#endif 

/* FIRST_HEADER_H */

second_header.h

#ifndef SECOND_HEADER_H
#define SECOND_HEADER_H

static int var_1;

#endif    

/* SECOND_HEADER_H */

first_header.c

#include <stdio.h>
#include "first_header.h"
#include "second_header.h"

int main() {
    var_1 = 10;
    printf("%d", var_1);
}

The next implementation uses global variables. This type of variables need to be declared only in one header file and can be reused by declaring the header file in other c files. The global variables must be declared in a header file with the keyword extern and defined in the relevant c file once. Then it will be available throughout the application and no errors of variable redeclaration will occur while compiling. This became the final implementation for the PSLab-firmware to fix the compilation issues modularizing application specific C and header files.

Resources:

Continue ReadingExporting Functions in PSLab Firmware