Understanding PN Junctions with the Pocket Science Lab

The boundary layer between two thin films of a semiconducting material with Positive type and Negative type doping is referred to as a P-N junction, and these are one of the fundamental building blocks of electronics. These junctions exhibit various properties that have given them a rather indispensable status in modern day electronics.

The PSLab’s various measurement tools enable us to understand these devices, and in this blog post we shall explain some uses of PN junctions, and visualize their behaviour with the PSLab.

One might easily be confused and assume that a positive doping implies that the layer has a net positive charge, but this is not the case. A positive doping involves replacing a minute quantity of the semiconductor molecules with atoms from the next column in the periodic table. These atoms such as phosphorus are also charge neutral, but the number of available mobile charge carriers effectively increases.

A diode as a half-wave rectifier

A diode is basically just a PN junction. An ideal diode conducts electricity in one direction offering a path of zero resistance, and it is a perfect insulator in the other direction. In practice, we may observe some additional properties.

Figure : The circuit used for making the half-wave rectifier and studying it. A bipolar sinusoidal signal is input to a diode, and the output voltage is monitored. The 1uF capacitor is used to filter the output signal and make it more or less constant, but it has not been used while obtaining the data shown in the following image

Figure : A diode used as a half-wave rectifier. The input waveform shown in green was passed through a forward biased diode, and monitored by CH2 (red trace ) .

We can observe that only the positive half of the signal passes through the diode. It can also be observed , that since this is not an ideal diode, the conducted portion has lost some amplitude. This loss is a consequence of the forward threshold voltage of the PN junction, and in case of this diode, it is around 0.6 Volts. This threshold voltage depends on the band structure of the diode , and in the next section we shall examine this voltage for various diodes.

Measurement of Current-Voltage Characteristics of diodes

In practice, diodes only start conducting in the forward direction after a certain threshold potential difference is present. This voltage, also known as the barrier potential, depends on the band gap of the diode, and we shall measure it to determine how the electrical properties affect the externally visible physical properties of the diode.

A programmable voltage output of the PSLab (PV1) will be increased in small steps starting from 0 Volts, and a voltmeter input (CH3) will be used to determine the point when the diode starts conducting. The presence of a known resistor between PV1 and CH3 acts as a current limiter, and also enables us to calculate the current flow using some elementary application of the Ohm’s law. I = (PV1-CH3)/1000 .


The following image shows I-V characteristics of various diodes ranging from Schottky to Light Emitting Diodes (LEDs).

It may be interesting to note that the frequency of the light emitted by LEDs is directly proportional to the threshold voltage. In case of the white LED, it is almost similar to the blue LED because white LEDs are composed of blue LEDs, and a phosphor coating that partially converts blue light to yellow. The combination results in white light.

Zener diodes

Zener diodes are a special variant of diodes that also conduct electricity in the the reverse direction once a certain threshold has been crossed. This threshold can be determined during the manufacturing process, and zener diodes with breakdown voltages such as 3.3V , 5.6V , 6.8V etc are commercially available.

In the following image, the I-V characteristics of a 3.3V zener diode have been measured with the PSLab . As can be observed, the diode starts to conduct small amounts of current from around 2V itself, but significant current flow is usually present once the rated voltage is achieved.

In the forward direction, the zener appears to behave as a regular diode.

Resources
Continue ReadingUnderstanding PN Junctions with the Pocket Science Lab

Real time Sensor Data Analysis on PSLab Android

PSLab device has the capacity to connect plug and play sensors through the I2C bus. The sensors are capable of providing data in real time. So, the PSLab Android App and the Desktop app need to have the feature to fetch real time sensor values and display the same in the user interface along with plotting the values on a simple graph.

The UI was made following the guidelines of Google’s Material Design and incorporating some ideas from the Science Journal app. Cards are used for making each section of the UI. There are segregated sections for real time updates and plotting where the real time data can be visualised. A methods for fetching the data are run continuously in the background which receive the data from the sensor and then update the screen.

The following section denotes a small portion of the UI responsible for displaying the data on the screen continuously and are quite simple enough. There are a number of TextViews which are being constantly updated on the screen. Their number depends on the type and volume of data sent by the sensor.

<TextView
       android:layout_width="wrap_content"
       android:layout_height="30dp"
       android:layout_gravity="start"
       android:text="@string/ax"
       android:textAlignment="textStart"
       android:textColor="@color/black"
       android:textSize="@dimen/textsize_edittext"
       android:textStyle="bold" />

<TextView
       android:id="@+id/tv_sensor_mpu6050_ax"
       android:layout_width="wrap_content"
       android:layout_height="30dp"
       android:layout_gravity="start"
       android:textAlignment="textStart"
       android:textColor="@color/black"
       android:textSize="@dimen/textsize_edittext"
       android:textStyle="bold" />

 

The section here represents the portion of the UI responsible for displaying the graph. Like all other parts of the UI of PSLab Android, MPAndroidChart is being used here for plotting the graph.

<LinearLayout
       android:layout_width="match_parent"
       android:layout_height="160dp"
       android:layout_marginTop="40dp">

       <com.github.mikephil.charting.charts.LineChart
               android:id="@+id/chart_sensor_mpu6050"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:background="#000" />
</LinearLayout>

 

Since the updates needs to continuous, a process should be continuously run for updating the display of the data and the graph. There are a variety of options available in Android in this regard like using a Timer on the UI thread and keep updating the data continuously, using ASyncTask to run a process in the background etc.

The issue with the former is that since all the processes i.e. fetching the data and updating the textviews & graph will run on the UI thread, the UI will become laggy. So, the developer team chose to use ASyncTask and make all the processes run in the background so that the UI thread functions smoothly.

A new class SensorDataFetch which extends AsyncTask is defined and its object is created in a runnable and the use of runnable ensures that the thread is run continuously till the time the fragment is used by the user.

scienceLab = ScienceLabCommon.scienceLab;
i2c = scienceLab.i2c;
try {
    MPU6050 = new MPU6050(i2c);
} catch (IOException e) {
    e.printStackTrace();
}
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        while (true) {
            if (scienceLab.isConnected()) {
                try {
                    sensorDataFetch = new SensorDataFetch();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                sensorDataFetch.execute();
            }
        }
    }
};
new Thread(runnable).start();

 

The following is the code for the ASyncTask created. There are two methods defined here doInBackground and onPostExecute which are responsible for fetching the data and updating the display respectively.

The raw data is fetched using the getRaw method of the MPU6050 object and stored in an ArrayList. The data type responsible for storing the data will depend on the return type of the getRaw method of each sensor class and might be different for other sensors. The data returned by getRaw is semi-processed and the data just needs to be split in sections before presenting it for display.

The PSLab Android app’s sensor files can be viewed here and they can give a better idea about how the sensors are calibrated, how the intrinsic nonlinearity is taken care of, how the communication actually works etc.

After the data is stored, the control moves to the onPostExecute method, here the textviews on the display and the chart are updated. The updation is slowed down a bit so that the user can visualize the data received.

private class SensorDataFetch extends AsyncTask<Void, Void, Void> {
   MPU6050 MPU6050 = new MPU6050(i2c);
   ArrayList<Double> dataMPU6050 = new ArrayList<Double>();

   private SensorDataFetch(MPU6050 MPU6050) throws IOException {
   }

   @Override
   protected Void doInBackground(Void... params) {
       try {
           if (MPU6050 != null) {
               dataMPU6050 = MPU6050.getRaw();
           }
       } catch (IOException e) {
           e.printStackTrace();
       }
           return null;
   }

   protected void onPostExecute(Void aVoid) {
       super.onPostExecute(aVoid);
       tvSensorMPU6050ax.setText(String.valueOf(dataMPU6050.get(0)));
       tvSensorMPU6050ay.setText(String.valueOf(dataMPU6050.get(1)));
       tvSensorMPU6050az.setText(String.valueOf(dataMPU6050.get(2)));
       tvSensorMPU6050gx.setText(String.valueOf(dataMPU6050.get(3)));
       tvSensorMPU6050gy.setText(String.valueOf(dataMPU6050.get(4)));
       tvSensorMPU6050gz.setText(String.valueOf(dataMPU6050.get(5)));
       tvSensorMPU6050temp.setText(String.valueOf(dataMPU6050.get(6)));
   }
}

The detailed implementation of the same can be found here.

Additional Resources

  1. Learn more about how real time sensor data analysis can be used in various fields like IOT http://ieeexplore.ieee.org/document/7248401/
  2. Google Fit guide on how to use native built-in sensors on phones, smart watches etc. https://developers.google.com/fit/android/sensors
  3. A simple starter guide to build an app capable of real time sensor data analysis http://developer.telerik.com/products/building-an-android-app-that-displays-live-accelerometer-data/
  4. Learn more about using AsyncTask https://developer.android.com/reference/android/os/AsyncTask.html
Continue ReadingReal time Sensor Data Analysis on PSLab Android

Creating a Four Quadrant Graph for PSLab Android App

While working on Oscilloscope in PSLab Android, we had to implement XY mode. XY plotting is part of regular Oscilloscope and in XY plotting the 2 signals are plotted against each other. For XY plotting we require a graph with all 4 quadrants but none of the Graph-View libraries in Android support a 4 quadrants graph. We need to find a solution for this. So, we used canvas class to draw a 4 quadrants graph.  The Canvas class defines methods for drawing text, lines, bitmaps, and many other graphics primitives. Let’s discuss how a 4 quadrants graph is implemented using Canvas.

Initially, a class Plot2D extending View is created along with a constructor in which context, values for X-Axis, Y-Axis.

public class Plot2D extends View {
public Plot2D(Context context, float[] xValues, float[] yValues, int axis) {
   super(context);
   this.xValues = xValues;
   this.yValues = yValues;
   this.axis = axis;
   vectorLength = xValues.length;
   paint = new Paint();
   getAxis(xValues, yValues);
}

 

So, now we need to convert a particular float value in a pixel. This is the most important part and for this, we create a function where we send the value of the pixels, the minimum and the maximum value of the axis and array of float values. We get an array of converted pixel values in return. p[i] = .1 * pixels + ((value[i] – min) / (max – min)) * .8 * pixels; is the way to transform an int value to a respective pixel value.

private int[] toPixel(float pixels, float min, float max, float[] value) {
   double[] p = new double[value.length];
   int[] pInt = new int[value.length];

   for (int i = 0; i < value.length; i++) {
       p[i] = .1 * pixels + ((value[i] - min) / (max - min)) * .8 * pixels;
       pInt[i] = (int) p[i];
   }
   return (pInt);
}

 

For constructing a graph we require to create the axis, add markings/labels and plot data in the graph. To achieve this we will override onDraw method. The parameter to onDraw() is a Canvas object that the view can use to draw itself. First, we need to get various parameters like data to plot, canvas height and width, the location of the x axis and y axis etc.

@Override
protected void onDraw(Canvas canvas) {

   float canvasHeight = getHeight();
   float canvasWidth = getWidth();
   int[] xValuesInPixels = toPixel(canvasWidth, minX, maxX, xValues);
   int[] yValuesInPixels = toPixel(canvasHeight, minY, maxY, yValues);
   int locxAxisInPixels = toPixelInt(canvasHeight, minY, maxY, locxAxis);
   int locyAxisInPixels = toPixelInt(canvasWidth, minX, maxX, locyAxis);

 

Drawing the axis

First, we will draw the axis and for this, we will use the white color. To draw the white color axis line we will the following code.

paint.setColor(Color.WHITE);
paint.setStrokeWidth(5f);
canvas.drawLine(0, canvasHeight - locxAxisInPixels, canvasWidth,
       canvasHeight - locxAxisInPixels, paint);
canvas.drawLine(locyAxisInPixels, 0, locyAxisInPixels, canvasHeight,
       paint);

 

Adding the labels

After drawing the axis lines, now we need to mark labels for both x and y axis. For this, we use the following code in onDraw method. By this, the axis labels are automatically marked after a fixed distance. The no. of labels depends on the value of n. The code ensures that the markings are apt for each of the quadrant, for example in the first quadrant the markings of the x axis is below the axis, whereas markings of the y axis are to the left.

float temp = 0.0f;
int n = 8;
for (int i = 1; i <= n; i++) {
    if (i <= n / 2) {
           temp = Math.round(10 * (minX + (i - 1) * (maxX - minX) / n)) / 10;
           canvas.drawText("" + temp,
                   (float) toPixelInt(canvasWidth, minX, maxX, temp),
                   canvasHeight - locxAxisInPixels - 10, paint);
           temp = Math.round(10 * (minY + (i - 1) * (maxY - minY) / n)) / 10;
           canvas.drawText("" + temp, locyAxisInPixels + 10, canvasHeight
                           - (float) toPixelInt(canvasHeight, minY, maxY, temp),
                   paint);
       } else {
           temp = Math.round(10 * (minX + (i - 1) * (maxX - minX) / n)) / 10;
           canvas.drawText("" + temp,
                   (float) toPixelInt(canvasWidth, minX, maxX, temp),
                   canvasHeight - locxAxisInPixels + 30, paint);
           temp = Math.round(10 * (minY + (i - 1) * (maxY - minY) / n)) / 10;
           canvas.drawText("" + temp, locyAxisInPixels - 65, canvasHeight
                           - (float) toPixelInt(canvasHeight, minY, maxY, temp),
                   paint);

By using this code we get the following results

Plotting the data

The last step is to plot the data, to achieve this we first convert float values of x axis and y axis data point to pixels using toPixel method and simply draw it on the graph. In addition to this, we set a red color to the line.

paint.setStrokeWidth(2);
canvas.drawARGB(255, 0, 0, 0);
for (int i = 0; i < vectorLength - 1; i++) {
   paint.setColor(Color.RED);
   canvas.drawLine(xValuesInPixels[i], canvasHeight
           - yValuesInPixels[i], xValuesInPixels[i + 1], canvasHeight
           - yValuesInPixels[i + 1], paint);
}

 

This implements a 4 quadrants graph in PSLab Android app for XY plotting in Oscilloscope Activity. The entire code for the same is available in here.

Resources

  1. A simple 2D Plot class for Android
  2. Android.com reference of Custom Drawing
Continue ReadingCreating a Four Quadrant Graph for PSLab Android App

Designing A Virtual Laboratory With PSLab

What is a virtual laboratory

A virtual lab interface gives students remote access to equipment in laboratories via the Internet without having to be physically present near the equipment. The idea is that lab experiments can be made accessible to a larger audience which may not have the resources to set up the experiment at their place. Another use-case scenario is that the experiment setup must be placed at a specific location which may not be habitable.

The PSLab’s capabilities can be increased significantly by setting up a framework that allows remote data acquisition and control. It can then be deployed in various test and measurement scenarios such as an interactive environment monitoring station.

What resources will be needed for such a setup

The proposed virtual lab will be platform independent, and should be able to run in web-browsers. This necessitates the presence of a lightweight web-server software running on the hardware to which the PSLab is connected. The web-server must have a framework that must handle multiple connections, and allow control access to only authenticated users.

Proposed design for the backend

The backend framework must be able to handle the following tasks:

  • Communicate with the PSLab hardware attached to the server
  • Host lightweight web-pages with various visual aids
  • Support an authentication framework via a database that contains user credentials
  • Reply with JSON data after executing single commands on the PSLab
  • Execute remotely received python scripts, and relay the HTML formatted output. This should include plots

Proposed design for the frontend

  • Responsive, aesthetic layouts and widget styles.
  • Essential utilities such as Sign-up and Sign-in pages.
  • Embedded plots with basic zooming and panning facilities.
  • Embedded code-editor with syntax highlighting
  • WIdgets to submit the code to the server for execution, and subsequent display of received response.

A selection of tools that can assist with this project, and the purpose they will serve:

Backend

  • The Python communication library for the PSLab
  • FLASK: ‘Flask is a BSD Licensed microframework for Python based on Werkzeug, Jinja 2 and good intentions.’   . It can handle concurrent requests, and will be well suited to serve as our web server
  • MySQL: This is a database management utility that can be used to store user credentials, user scripts, queues etc
  • WerkZeug: The utilities to create and check password hashes are essential for exchanging passwords via the database
  • Json: For relaying measurement results to the client
  • Gunicorn + Nginx: Will be used when more scalable deployment is needed, and the built-in webserver of Flask is unable to handle the load.

Frontend

  • Bootstrap-css: For neatly formatted, responsive UIs
  • Jqplot: A versatile and expandable js based plotting library
  • Ace code editor: A browser based code editor with syntax highlighting, automatic indentation and other user-friendly features. Written in JS
  • Display documentation:  These can be generated server side from Markdown files using Jekyll. Several documentation files are already available from the pslab-desktop-apps, and can be reused after replacing the screenshot images only.

Flow Diagram

Recommended Reading

[1]: Tutorial series  for creating a web-app using python-flask and mysql. This tutorial will be extensively followed for creating the virtual-lab setup.

[2]: Introduction to the Virtual Labs initiative by the Govt of India

[3]: Virtual labs at IIT Kanpur

Continue ReadingDesigning A Virtual Laboratory With PSLab

Handling graph plots using MPAndroid chart in PSLab Android App

In PSLab Android App, we expose the Oscilloscope and Logic Analyzer functionality of PSLab hardware device. After reading data-points to plot, we need to show plot data on graphs for better understanding and visualisation. Sometimes we need to save graphs to show output/findings of the experiment. Hence we will be using MPAndroidChart library to plot and save graphs as it provides a nice and clean methods to do so.

First add MPAndroid Chart as dependency in your app build.gradle to include the library

dependencies {
 compile 'com.github.PhilJay:MPAndroidChart:v3.0.2'
}

For chart view in your layout file, there are many available options like Line Chart, Bar Chart, Pie Chart, etc. For this post I am going to use Line Chart.

Add LineChart in your layout file

<com.github.mikephil.charting.charts.LineChart
        android:id="@+id/lineChart"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

Take a reference to LineChart of layout file in your Activity/Fragment

LineChart lineChart = (LineChart) findViewById(R.id.chart);// Activity
LineChart lineChart = (LineChart) view.findViewById(R.id.chart);// Fragment

Now we add dataset to LineChart of layout file, I am going to add data for two curves sine and cosine function to plot sine and cosine wave on LineChart. We create two different LineDataSet one for the sine curve entries and other for the cosine curve entries.

List <Entry> sinEntries = new ArrayList<>(); // List to store data-points of sine curve 
List <Entry> cosEntries = new ArrayList<>(); // List to store data-points of cosine curve

// Obtaining data points by using Math.sin and Math.cos functions
for( float i = 0; i < 7f; i += 0.02f ){
sinEntries.add(new Entry(i,(float)Math.sin(i)));
cosEntries.add(new Entry(i,(float)Math.cos(i)));
}

List<ILineDataSet> dataSets = new ArrayList<>(); // for adding multiple plots

LineDataSet sinSet = new LineDataSet(sinEntries,"sin curve");
LineDataSet cosSet = new LineDataSet(cosEntries,"cos curve");

// Adding colors to different plots 
cosSet.setColor(Color.GREEN);
cosSet.setCircleColor(Color.GREEN);
sinSet.setColor(Color.BLUE);
sinSet.setCircleColor(Color.BLUE);

// Adding each plot data to a List
dataSets.add(sinSet);
dataSets.add(cosSet);

// Setting datapoints and invalidating chart to update with data points
lineChart.setData(new LineData(dataSets));
lineChart.invalidate();

After adding datasets to chart and invalidating it, chart is refreshed with the data points which were added in dataset.

After plotting graph output would look like the image below:

You can change the dataset and invalidate chart to update it with latest dataset.

To save graph plot, make sure you have permission to write to external storage, if not add it into your manifest file

<manifest ...>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
</manifest>

To save the photo of chart into Gallery:

lineChart.saveToGallery("title");

To save a some specific location:

lineChart.saveToPath("title", "Location on SD Card");

If you want to do some resizing in chart or save two three charts in a single image, you can do so by taking out the Bitmaps and processing them to meet your requirements:

lineChart.getChartBitmap();

Resources

Continue ReadingHandling graph plots using MPAndroid chart in PSLab Android App

Packing and Unpacking Data in PSLab Android App

In PSLab we communicate with PSLab Hardware device, to exchange data, i.e we give a command or instruction and it responses accordingly. So this giving and receiving is in terms of packed byte string. Thus, we need some solid knowledge to pack and unpack data. In python communication library, there is struct module available. In JAVA we can use NIO’s ByteBuffer or implement our own functions. In this blog post I discuss both methods.  

In Python we have struct module for packing data in byte strings. As different languages interpret data types differently like Java takes 4 bytes for int and C++ takes 2 bytes for int. To send and receive data properly, we pack data in a byte string and unpack on other side with it’s data type properties. In PSLab, we have to communicate with device for various applications like getting calibration data during power up time as raw data doesn’t make much sense until calibration is applied on it.

You also need to take care of order of sequence of bytes like there are generally two types of order in which a sequence of bytes are stored in memory location:

  • Big – Endian: In which MSB is stored first.

    Source: Wikipedia
  • Little – Endian: In which LSB is stored first.

    Source: Wikipedia

In Python

The standard sizes and format characters of particular data type can be seen in the image below.

Format C Type Python Type Standard
x Pad byte No value
c char string of length 1 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1
h short integer 2
H unsigned short integer 2
i int integer 4
I unsigned int integer 4
l long integer 4
L unsigned long integer 4
q long long integer 8
Q unsigned long long integer 8
f float float 4
d double float 8
s char[] string
p char[] string
P void* integer

Source: Python Docs

For Packing data

import struct
struct.Struct(“B”).pack(254)   # Output ->  b’\xfe’
a = struct.Struct(“I”).pack(2544)   # Output -> b’\xf0\t\x00\x00′

Now a is the byte string that has packed value as 2544, this can be send to some device byte by byte and reconstructed on receiving side by knowing how many bytes does the data type received contains.

For Unpacking data

import struct
struct.unpack(“I”,a)  # Output -> (2544,)

In JAVA

For Packing data

Suppose you have to pack an integer, in java int takes 32 bits (4 bytes)

Using JAVA’s NIO’s ByteBuffer

byte[] bytes = ByteBuffer.allocate(4).putInt(2544).array();

If you want hardcore method to see what exactly is happening, use

byte[] intToByteArray(int value){
 return new byte[]{
     (byte)value >>> 24,
     (byte)value >>> 16,
     (byte)value >>> 8,
     (byte)value
  };
}

“>>>” is used for unsigned shifting, you can use according to your requirements.

After you have your byte array, you can easily create a string out of it and transmit.

For Unpacking data

Using JAVA’s NIO’s ByteBuffer

int fromByteArray(byte[] bytes){
int a = ByteBuffer.wrap(bytes).getInt();
return a;
}

It assumes that byte array is stored as Big Endian, if bytes in byte array is stored as Little Endian, add order() after wrap()

int fromByteArray(byte[] bytes){
int a = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt();
return a;
}

Note: Make sure the bytes array that you provide has same number of bytes as that of the data type that you are trying to unpack. For example: if you want int, bytes array should have 4 bytes as int type in JAVA has 4 bytes. If you want short, bytes array should have 2 bytes as short type in JAVA has 2 bytes.

To visualise underlying implementation, see

int from byteArray(byte[] bytes){
return bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3];
}

In all above implementation big-endian order was assumed, you can modify function if you are using little-endian or some other sequence.

References

Continue ReadingPacking and Unpacking Data in PSLab Android App

Reducing UI lags with AsyncTask in PSLab Android

In the Oscilloscope Activity, communication with the PSLab device goes in parallel with updations of the graph which result in inoperable UI if both these functions are performed in the main thread. This would severely degrade the user experience. In order to avoid this, we simply used AsyncTask. AsyncTasks are used to perform communications with the device in the background thread and update UI when the task in background thread completes. AsyncTask thus solves the problem of making UI super laggy while performing certain time-consuming functions. The UI remains responsive throughout.

More about AsyncTask

AsyncTask is an abstract Android class which helps the Android applications to handle the Main UI thread in a more efficient way. AsyncTask class allows to perform long lasting background operations and update the results in UI thread without affecting the main thread.

Implementing AsyncTask in Android applications

  • Create a new class inside Activity class and extend AsyncTask:

private class Task extends AsyncTask<Void, Void, Void> {
  	protected Long doInBackground(aVoid) {
     	}
 	protected void onProgressUpdate(aVoid) {
     	}
 	protected void onPostExecute(aVoid) {
     	}
}
  • Execute the task:

new Task().execute();

How they are used in Oscilloscope Activity?

The following diagram explains how AsyncTasks are used in Oscilloscope Activity. 

AsyncTask in PSLab Android App

A public class extending AsyncTask is defined, this task is executed from another thread.

public class Task extends AsyncTask<String, Void, Void> {
   ArrayList<Entry> entries;
   String analogInput;

 

doInBackgroundMethod performs the part related to communication with the PSLab device.

Here we are capturing the data from the hardware using captureTraces and fetchTraces method.

 @Override
   protected Void doInBackground(String... params) {
       try {
           analogInput = params[0];
           //no. of samples and timegap still need to be determined
           scienceLab.captureTraces(1, 800, 10, analogInput, false, null);
           Log.v("Sleep Time", "" + (800 * 10 * 1e-3));
           Thread.sleep((long) (800 * 10 * 1e-3));
           HashMap<String, double[]> data = scienceLab.fetchTrace(1); //fetching data
           double[] xData = data.get("x");
           double[] yData = data.get("y");
           entries = new ArrayList<Entry>();
           for (int i = 0; i < xData.length; i++) {
               entries.add(new Entry((float) xData[i], (float) yData[i]));
           }
       }
       catch (NullPointerException e){
           cancel(true);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       return null;
   }

 

After the thread, completely executed onPostExecute is called to update the UI/graph. This method runs on the main thread.

 @Override
   protected void onPostExecute(Void aVoid) {
       super.onPostExecute(aVoid);
       LineDataSet dataset = new LineDataSet(entries, analogInput);
       LineData lineData = new LineData(dataset);
       dataset.setDrawCircles(false);
       mChart.setData(lineData);
       mChart.invalidate();    //refresh the chart
       synchronized (lock){
           lock.notify();
       }
   }
}

 

This simply solves the problem of lags and the Oscilloscope works like a charm.

Resources

Continue ReadingReducing UI lags with AsyncTask in PSLab Android

Using Hierarchical Blocks in KiCAD to Collaborate in PSLab Hardware Development

The PSLab hardware project designed in KiCAD, an ECAD tool; doesn’t support collaborative features like Git providing for software projects. As explained in a previous blog post on techniques to help up with project collaboration, this blog post will demonstrate how two developers can work together on the same hardware project.

The difficulties arise as the whole project is in one big schematic file. Editing made by one developer will affect to the editing done by the other developers causing merge conflicts. KiCAD doesn’t compile nicely if the changes were fixed manually most of the cases.

The solution practiced in the pslab-hardware project is using hierarchical blocks. This blog post will use a KiCAD project with an oscillator implementation and a voltage regulator implementation just like the ones in pslab-hardware schematics. To avoid complications in understanding changes in a huge circuit, only these two modules will be implemented separately in the blog.

Initially the project will look like the following figure;

Sheet1 Sheet2

These two hierarchical blocks will be created as different .sch files in the project directory as follows;

Assume two different developers are working on these two different blocks. That is the key concept in collaborating hardware projects in KiCAD. As long as the outer connections (pins) don’t get changed, edits made to one block will have no effect on the other blocks.

Developer 1 decided that the existing power circuit is not efficient for the PSLab device. So he decided to change the circuit in Sheet 1. The circuit before and after modification is shown in the table below.

Sheet 1 (Before) Sheet 1 (After)

If we take a look at the git status now, it will be as follows;

From this it is noticeable that neither the main schematic file nor Developer2.sch hasn’t been touched by the edits made to Developer1.sch file. This avoids merge conflicts happening when all the developers are working on the same schematic file.

Resources :

Continue ReadingUsing Hierarchical Blocks in KiCAD to Collaborate in PSLab Hardware Development

Adding Tablet support for PSLab Android App

Making layouts compatible with tablet definitely, helps in increasing the target audience. Tablets are different than smartphones, they available in size as big as 7’’ and 10’’. This gives developers/designers a lot of screen space to work on which in turn can be utilized in a way different than smartphones. In the PSLab Oscilloscope Activity and in fact the entire application needs to have tablet support. To achieve these two approaches are used. They are as follow:

  1. Creating layouts compatible with the tablet
  2. Programmatically differentiate between phone and tablet

Creating layouts compatible with the Tablet

A series of following steps help to create layouts for the tablet with much ease

  1. Right click on layouts. Then move the cursor to new and select Layout resource file.

  1. A new resource file dialog box will appear. Under filename type the same name of the file for which you want to create tablet layout. Under directory name type layout-sw600dp for the layout of 7’’ tablet and layout-sw720dp for layout of 10’’ tablet.

  1. The Android Studio will automatically create a folder with two layouts, one for phone and another for tablet inside layouts folder. Now you can work on tablet layout and make the app compatible with the tablet.

Programmatically differentiate between Phone and Table

In Oscilloscope Activity of PSLab Android App, the dimensions of the layout are programmatically set. These dimensions are different from that should be used for the tablet. So, it is important for the app to know whether it’s operating on a phone or a tablet.

This can be achieved using the following steps.

  1. Right click on resources, move the cursor on new and select Android resource file.

  1. A new resource file dialog will appear, under file name type isTablet and press OK. Here we are creating a resource for a phone.

  1. In the XML file isTablet write the following code.

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <bool name="isTablet">false</bool>
</resources>

This resource returns false when accessed.

  1. Repeat 1, 2 step and under new resource file dialog box type values-600dp. Then write the following code.

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <bool name="isTablet">true</bool>
</resources>

This resource returns true when accessed.

  1. Now you can access this resource in Activity simply writing the following code.

boolean tabletSize = getResources().getBoolean(R.bool.isTablet);

tabletSize will be true if accessed in a tablet otherwise it will be false. Hence code can written accordingly.

By this way, we can find whether the application is running on tablet or phone programmatically.

Resources

 

Continue ReadingAdding Tablet support for PSLab Android App

Developing Oscilloscope UI in PSLab Android App

User Interface (UI) is one of the most important part of any software development. In PSLab while developing the UI of the Oscilloscope the following points are very critical.

  1. The UI should expose all the functionalities of Oscilloscope that can be performed using PSLab.
  2. The UI should be very convenient to use. It should allow the user to access functionalities of the PSLab with ease.
  3. The UI should be attractive.

Since Android smartphones come with relatively small size, it was a challenge to develop a UI for Oscilloscope. In this blog, I am going to mention the steps involved in developing the Oscilloscope UI.

Step 1: Creating a mockup

Initially, a mock-up for Oscilloscope UI is created using moqups tool. Later, the mock-up was discussed in public channel where fellow developers and mentors approved it. Let’s discuss some benefits of adopting this layout for Oscilloscope Activity.

  • The graph is ensured maximum screen space as it is the most important component/section of the Oscilloscope. This is also the reason why we kept the screen orientation to landscape.
  • The widgets don’t populate the screen, make the UI look clean.
  • The UI is comparable to basic app’s people use in their daily lives hence very convenient to use.

Mockup of Oscilloscope UI developed using moqups tool

Step 2: Deciding the API to be used

In Oscilloscope Activity, the main component is the graph. The captured data from the PSLab device is plotted on the graph. We decided to use MPAndroidCharts for the same.

Step 3: Deciding the space given to different sections of the UI

The next step was to decide how much screen space each section of Oscilloscope should acquire. There are 3 sections of the Oscilloscope UI.

  1. Graph
  2. Side panel consisting of buttons, each button loads a different set Oscilloscope controls and features in 3.
  3. A lower panel which is basically a fragment displaying controls and features corresponding to the button selected in 2.

By trying different dimensions and arrangements the following configuration fits the best.

To achieve this, the dimensions of different sections is set programmatically. This makes the UI compatible with different screen sizes.

public void onWindowFocusChanged() {

       RelativeLayout.LayoutParams lineChartParams = (RelativeLayout.LayoutParams) mChartLayout.getLayoutParams();
       lineChartParams.height = height * 2 / 3;
       lineChartParams.width = width * 5 / 6;
       mChartLayout.setLayoutParams(lineChartParams);
       RelativeLayout.LayoutParams frameLayoutParams = (RelativeLayout.LayoutParams) frameLayout.getLayoutParams();
       frameLayoutParams.height = height / 3;
       frameLayoutParams.width = width * 5 / 6;
       frameLayout.setLayoutParams(frameLayoutParams);
   
}

onWindowFocusChanged method is called in onCreate method. Here we are first receiving current layout parameters and then setting new layout parameters.

Step 4: Developing each section

  1. Graph

The graph needs to be customized concerning following requirements

  • Dual y axis, one dedicated to CH2 and another to analog input selected.
  • Black background
  • Grid lines
  • Scaling
  • Initial scale for x and y axis.

To achieve this a chartInit method is created which initializes the graph as per required. It is called in onCreate method.

2. Side Panel

It is a simple layout consisting of image buttons and text views. It is used to replace fragments in Lower Panel. To achieve this, image buttons and textviews were added to the layout and image buttons weight is set to 2. Later onClick listeners were added to both image buttons and textviews.

3. Lower Panel

The lower panel is frame layout which accommodates different fragments (one at a time). To achieve these different fragments are created that are ChannelsParametersFragment, TimebaseTriggerFragment, DataAnalysisFragment and XYPlotFragment. In ChannelsParametersFragment, TimebaseTriggerFragment and XYPlotFragment fragments, constraint views are used whereas in TimebaseTriggerFragment table layout is used. Each fragment allows the user to access different controls and features.

The Final Layout

The above is the GIF of the Oscilloscope UI.

This covers various steps for developing Oscilloscope UI in PSLab Android App.

Resources

Continue ReadingDeveloping Oscilloscope UI in PSLab Android App