Filling Audio Buffer to Generate Waves in the PSLab Android App

The PSLab Android App works as an oscilloscope and a wave generator using the audio jack of the Android device. The implementation of the oscilloscope in the Android device using the in-built mic has been discussed in the blog post “Using the Audio Jack to make an Oscilloscope in the PSLab Android App” and the same has been discussed in the context of wave generator in the blog post “Implement Wave Generation Functionality in the PSLab Android App”. This post is a continuation of the post related to the implementation of wave generation functionality in the PSLab Android App. In this post, the subject matter of discussion is the way to fill the audio buffer so that the resulting wave generated is either a Sine Wave, a Square Wave or a Sawtooth Wave. The resultant audio buffer would be played using the AudioTrack API of Android to generate the corresponding wave. The waves we are trying to generate are periodic waves.

Periodic Wave: A wave whose displacement has a periodic variation with respect to time or distance, or both.

Thus, the problem reduces to generating a pulse which will constitute a single time period of the wave. Suppose we want to generate a sine wave; if we generate a continuous stream of pulses as illustrated in the image below, we would get a continuous sine wave. This is the main concept that we shall try to implement using code.

Initialise AudioTrack Object

AudioTrack object is initialised using the following parameters:

  • STREAM TYPE: Type of stream like STREAM_SYSTEM, STREAM_MUSIC, STREAM_RING, etc. For wave generation purposes we are using stream music. Every stream has its own maximum and minimum volume level.  
  • SAMPLING RATE: It is the rate at which the source samples the audio signal.
  • BUFFER SIZE IN BYTES: Total size of the internal buffer in bytes from where the audio data is read for playback.
  • MODES: There are two modes-
    • MODE_STATIC: Audio data is transferred from Java to the native layer only once before the audio starts playing.
    • MODE_STREAM: Audio data is streamed from Java to the native layer as audio is being played.

getMinBufferSize() returns the estimated minimum buffer size required for an AudioTrack object to be created in the MODE_STREAM mode.

minTrackBufferSize = AudioTrack.getMinBufferSize(SAMPLING_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
audioTrack = new AudioTrack(
       AudioManager.STREAM_MUSIC,
       SAMPLING_RATE,
       AudioFormat.CHANNEL_OUT_MONO,
       AudioFormat.ENCODING_PCM_16BIT,
       minTrackBufferSize,
       AudioTrack.MODE_STREAM);

Fill Audio Buffer to Generate Sine Wave

Depending on the values in the audio buffer, the wave is generated by the AudioTrack object. Therefore, to generate a specific kind of wave, we need to fill the audio buffer with some specific values. The values are governed by the wave equation of the signal that we want to generate.

public short[] createBuffer(int frequency) {
   short[] buffer = new short[minTrackBufferSize];
   double f = frequency;
   double q = 0;
   double level = 16384;
   final double K = 2.0 * Math.PI / SAMPLING_RATE;

   for (int i = 0; i < minTrackBufferSize; i++) {
         f += (frequency - f) / 4096.0;
         q += (q < Math.PI) ? f * K : (f * K) - (2.0 * Math.PI);
         buffer[i] = (short) Math.round(Math.sin(q));
   }
   return buffer;
}

Fill Audio Buffer to Generate Square Wave

To generate a square wave, let’s assume the time period to be t units. So, we need the amplitude to be equal to A for t/2 units and -A for the next t/2 units. Repeating this pulse continuously, we will get a square wave.

buffer[i] = (short) ((q > 0.0) ? 1 : -1);

Fill Audio Buffer to Generate Sawtooth Wave

Ramp signals increases linearly with time. A Ramp pulse has been illustrated in the image below:

We need repeated ramp pulses to generate a continuous sawtooth wave.

buffer[i] = (short) Math.round((q / Math.PI));

Finally, when the audio buffer is generated, write it to the audio sink for playback using write() method exposed by the AudioTrack object.

audioTrack.write(buffer, 0, buffer.length);

Resources

Continue ReadingFilling Audio Buffer to Generate Waves in the PSLab Android App

Performing Oscillator Experiments with PSLab

Using PSLab we can read the waveform generated by different Oscillators. First, let’s discuss what’s an Oscillator? An Oscillator is an electronic circuit that converts unidirectional current flow from a DC source into an alternating waveform. Oscillators can produce a sine wave, triangular wave or square wave. Oscillators are used in computers, clocks, watches, radios, and metal detectors. In this post, we are going to discuss 3 different types of Oscillators.

  • Colpitts Oscillator
  • Phase Shift Oscillator
  • Wien Bridge Oscillator

Colpitts Oscillator

The Colpitts oscillator produces sinusoidal oscillations. The Colpitts oscillator has a tank circuit which consists of two capacitors in series and an inductor connected in parallel to the serial combination. The two capacitors in series produce a 180o phase shift which is inverted by another 180o to produce the required positive feedback. The frequency of the oscillations is determined by the value of the capacitors and inductor in the tank circuit.

Image source

Image source

Phase Shift Oscillator

A phase-shift oscillator produces a sine wave output using regenerative feedback obtained from the combination of resistor and capacitor. This regenerative feedback from the RC network is due to the ability of the capacitor to store an electric charge.

Image source

Wien bridge oscillator

A Wien bridge oscillator generates sine waves. It can generate a large range of frequencies and is based on a bridge circuit. It employs two transistors, each producing a phase shift of 180°, and thus producing a total phase-shift of 360° or 0°. It is simple in design, compact in size, and stable in its frequency output.

 

Image source

Mapping output waves from the Oscillator Circuits in PSLab Android app

To make PSLab Android app to support experiments related to read the waveforms received from the Oscillator we reused Oscilloscope Activity. In order to analyze the frequencies of the waves captured, we used sine fitting. Sine fitting function simply takes the data points and returns the amplitude, frequency, offset and phase shift of the wave.

The following is a glimpse of output signals from the Oscillators being captured by PSLab Android.

Resources

Read more on Oscillator from the following links

Continue ReadingPerforming Oscillator Experiments with PSLab

Performing Custom Experiments with PSLab

PSLab has the capability to perform a variety of experiments. The PSLab Android App and the PSLab Desktop App have built-in support for about 70 experiments. The experiments range from variety of trivial ones which are for school level to complicated ones which are meant for college students. However, it is nearly impossible to support a vast variety of experiments that can be performed using simple electronic circuits.

So, the blog intends to show how PSLab can be efficiently used for performing experiments which are otherwise not a part of the built-in experiments of PSLab. PSLab might have some limitations on its hardware, however in almost all types of experiments, it proves to be good enough.

  • Identifying the requirements for experiments

    • The user needs to identify the tools which are necessary for analysing the circuit in a given experiment. Oscilloscope would be essential for most experiments. The voltage & current sources might be useful if the circuit requires DC sources and similarly, the waveform generator would be essential if AC sources are needed. If the circuit involves the use and analysis of data of sensor, the sensor analysis tools might prove to be essential.
    • The circuit diagram of any given experiment gives a good idea of the requirements. In case, if the requirements are not satisfied due to the limitations of PSLab, then the user can try out alternate external features.
  • Using the features of PSLab

  • Using the oscilloscope
    • Oscilloscope can be used to visualise the voltage. The PSLab board has 3 channels marked CH1, CH2 and CH3. When connected to any point in the circuit, the voltages are displayed in the oscilloscope with respect to the corresponding channels.
    • The MIC channel can be if the input is taken from a microphone. It is necessary to connect the GND of the channels to the common ground of the circuit otherwise some unnecessary voltage might be added to the channels.

  • Using the voltage/current source
    • The voltage and current sources on board can be used for requirements within the range of +5V. The sources are named PV1, PV2, PV3 and PCS with V1, V2 and V3 standing for voltage sources and CS for current source. Each of the sources have their own dedicated ranges.
    • While using the sources, keep in mind that the power drawn from the PSLab board should be quite less than the power drawn by the board from the USB bus.
      • USB 3.0 – 4.5W roughly
      • USB 2.0 – 2.5W roughly
      • Micro USB (in phones) – 2W roughly
    • PSLab board draws a current of 140 mA when no other components are connected. So, it is advisable to limit the current drawn to less than 200 mA to ensure the safety of the device.
    • It is better to do a rough calculation of the power requirements in mind before utilising the sources otherwise attempting to draw excess power will damage the device.

  • Using the Waveform Generator
    • The waveform generator in PSLab is limited to 5 – 5000 Hz. This range is usually sufficient for most experiments. If the requirements are beyond this range, it is better to use an external function generator.
    • Both sine and square waves can be produced using the device. In addition, there is a feature to set the duty cycle in case of square waves.
  • Sensor Quick View and Sensor Data Logger
    • PSLab comes with the built in support for several plug and play sensors. The support for more sensors will be added in the future. If an experiment requires real time visualisation of sensor data, the Sensor Quick View option can be used whereas for recording the data for sensors for a period of time, the Sensor Data Logger can be used.
  • Analysing the Experiment

    • The oscilloscope is the most common tool for circuit analysis. The oscilloscope can sample data at very high frequencies (~250 kHz). The waveform at any point can be observed by connecting the channels of the oscilloscope in the manner mentioned above.
    • The oscilloscope has some features which will be essential like Trigger to stabilise the waveforms, XY Plot to plot characteristics graph of some devices, Fourier Transform of the Waveforms etc. The tools mentioned here are simple but highly useful.
    • For analysing the sensor data, the Sensor Quick View can be paused at any instant to get the data at any instant. Also, the logged data in Sensor Data Logger can be exported as a TXT/CSV file to keep a record of the data.
  • Additional Insight

    • The PSLab desktop app comes with the built-in support for the ipython console.
    • The desired quantities like voltages, currents, resistance, capacitance etc. can also be measured by using simple python commands through the ipython console.
    • A simple python script can be written to satisfy all the data requirements for the experiment. An example for the same is shown below.

This is script to produce two sine waves of 1 kHz and capturing & plotting the data.

from pylab import *
from PSL import sciencelab
I=sciencelab.connect()
I.set_gain('CH1', 2) # set input CH1 to +/-4V range
I.set_gain('CH2', 3) # set input CH2 to +/-4V range
I.set_sine1(1000) # generate 1kHz sine wave on output W1
I.set_sine2(1000) # generate 1kHz sine wave on output W2
#Connect W1 to CH1, and W2 to CH2. W1 can be attenuated using the manual amplitude knob on the PSlab
x,y1,y2 = I.capture2(1600,1.75,'CH1') 
plot(x,y1) #Plot of analog input CH1
plot(x,y2) #plot of analog input CH2
show()

 

References

Continue ReadingPerforming Custom Experiments with PSLab

Electrical Experiments with PSLab

PSLab has the capability to perform a variety of experiments. The PSLab Android App and the PSLab Desktop App have built-in support for over 70 experiments which are commonly performed by students. In addition to that, it can be used in other experiments conveniently. This blog post is in continuation with the previous two posts regarding performing experiments (links in the reference) and this blog deals with another category of experiments that can be performed using PSLab.

The blog lists experiments which mainly involve the basic circuit elements like resistors, capacitors and inductors. These experiments involve the study of R-C, L-R, L-C and L-C-R circuits. These circuits have properties which make them important in real life applications and this blog attempts to give a rough picture of their importance.

Ohm’s Law, Capacitive Reactance and Inductive Reactance

These experiments involve the study of each of the basic circuit element individually. The current and voltage characteristics of each of the elements is studied.

The definitions of the above are:

Ohm’s Law – This is a law familiar to most. It relates the voltage and current of a purely resistive circuit stating that the voltage and current are proportional to each other and their ratio is a constant called the resistance. In this case, the current and voltage are in the same phase.

Capacitive Reactance – Across a capacitor in an AC circuit, the current and voltage are not in the same phase and the current leads the voltage. For a purely capacitive circuit, this difference is 90o.

Inductive Reactance –  Across an inductor in an AC circuit, the current and voltage are not in the same phase and the current lags behind the voltage. For a purely inductive circuit, this difference is 90o.

The reactance is given for capacitor and inductor is given by 1/wC and wL respectively, where C & L are the values of capacitance and inductance respectively and w is the frequency of the AC signal.

The circuit for the setup is shown below. We need to observe the plot of the input waveform and the plot of the voltage across individual elements to observe the phase shift.

  1. Connect CH1 & GND across the input terminals and CH2 & GND across the terminals of any of the elements.
  2. An external signal can be used or can be generated using the PSLab. Use the PSLab to generate a sinusoidal signal of frequency 1000 Hz. by connecting the ends of PV1 in the circuit.
  3. Observe the waveforms. In case of the resistor, there should be no observable phase lag between the two. In case of the capacitor and inductor, there will be an observable phase difference of 90o.
  4. For the capacitive and inductive circuits, just replace the resistor in the above circuit with capacitor/inductor.

RC Circuits

Drawing their names from their respective calculus functions, the integrator produces a voltage output proportional to the product (multiplication) of the input voltage and time; and the differentiator (not to be confused with differential) produces a voltage output proportional to the input voltage’s rate of change.

RC Integrator circuit

For constructing the RC integrator circuit, connect the circuit as shown in the diagram.

  • Construction of the integrator circuit is fairly simple once the differentiator circuit is done.
  • Interchange the positions of the capacitor and resistor in the above circuit and the circuit for the integrator is complete.
  • Observe the output waveform. Plot both the CH1 and CH2 data simultaneously to compare the waveforms.

RC Differentiator circuit

For constructing the RC differentiator circuit, connect the circuit as shown in the diagram.

  • The values of resistance and capacitance used here are 10k ohm and 0.01uF.
  • Connect the CH1 and GND pins of the board with the input side marked as Vi. Ensure that GND is connected to the GND of the circuit.
  • Similarly, connect CH2 and GND with the corresponding ends of the output side marked as Vo.
  • PSLab can also be used for supplying the input to the circuit. Connect the ends of W1 and GND across Vi. W1 can be used to generate a square wave of 10V peak to peak voltage with a frequency of 500 Hz.
  • Observe the output waveform. Plot both the CH1 and CH2 data simultaneously to compare the waveforms.

RL Circuits

RL Integrator Circuit.

For constructing the RL integrator circuit, connect the circuit as shown in the diagram.

  • Construction of the integrator circuit is fairly simple once the differentiator circuit is done.
  • Interchange the positions of the inductor and resistor in the above circuit and the circuit for the integrator is complete.
  • Observe the output waveform. Plot both the CH1 and CH2 data simultaneously to compare the waveforms.

RL Differentiator Circuit

For constructing the RL differentiator circuit, connect the circuit as shown in the diagram.

  • The values of resistance and inductance used here are 470 ohm and 10mH.
  • Connect the CH1 and GND pins of the board with the input side marked as Vi. Ensure that GND is connected to the GND of the circuit.
  • Similarly, connect CH2 and GND with the corresponding ends of the output side marked as Vo.
  • PSLab can also be used for supplying the input to the circuit. Connect the ends of W1 and GND across Vi. W1 can be used to generate a square wave of 2V peak to peak voltage with a frequency of 5000 Hz.
  • Observe the output waveform. Plot both the CH1 and CH2 data simultaneously to compare the waveforms.

Frequency Response

Frequency Response of an electric or electronics circuit allows us to see exactly how the output gain (known as the magnitude response) and the phase (known as the phase response) changes at a particular single frequency, or over a whole range of different frequencies from 0Hz, (d.c.) to many thousands of megahertz, (MHz) depending upon the design characteristics of the circuit.

Frequency response of a circuit can be studied using different tools like Bode plots, phase plots etc. However, this blog would limit to using simple RC and RL circuits as they can be easily visualised using an oscilloscope.

RC Circuits

  • For observing the frequency response of RC circuits, the circuit can be constructed as shown below.
  • The values of resistance and capacitance used here are 10k ohm and 0.01uF.
  • Connect the CH1 and GND pins of the board with the input side marked as Vi. Ensure that GND is connected to the GND of the circuit.
  • Similarly, connect CH2 and GND with the corresponding ends of the output side marked as Vo.
  • PSLab can also be used for supplying the input to the circuit. Connect the ends of W1 and GND across Vi. W1 can be used to generate a square wave of 10V peak to peak voltage with a frequencies ranging from 100 Hz to 5000 Hz.
  • Switch to the X-Y mode of the oscilloscope and observe the waveform formed.

RL Circuits

  • For observing the frequency response of RL circuits, the circuit can be constructed as shown below.
  • The values of resistance and inductance used here are 470 ohm and 10mH.
  • Connect the CH1 and GND pins of the board with the input side marked as Vi. Ensure that GND is connected to the GND of the circuit.
  • Similarly, connect CH2 and GND with the corresponding ends of the output side marked as Vo.
  • Note: PSLab in this case cannot be used as an AC source as the maximum frequency of waveforms produced by PSLab is limited to 5kHz. However, this experiment would also need frequencies much higher than 5 Hz i.e upto 50 kHz. So, a dedicated function generator is needed. However, the oscilloscope would work just fine.
  • Switch to the X-Y mode of the oscilloscope and observe the waveform formed.

References:

  1. The previous blog on experiments using PSLab focusing in electronics https://blog.fossasia.org/electronics-experiments-with-pslab/
  2. The previous blog on experiments using PSLab involving some general experiments https://blog.fossasia.org/fascinating-experiments-with-pslab/
  3. Read more about differentiators and integrators and their uses https://www.allaboutcircuits.com/textbook/semiconductors/chpt-8/differentiator-integrator-circuits/

Continue ReadingElectrical Experiments with PSLab

Enabling Google App Signing for Android Project

Signing key management of Android Apps is a hectic procedure and can grow out of hand rather quickly for large organizations with several independent projects. We, at FOSSASIA also had to face similar difficulties in management of individual keys by project maintainers and wanted to gather all these Android Projects under singular key management platform:

To handle the complexities and security aspect of the process, this year Google announced App Signing optional program where Google takes your existing key’s encrypted file and stores it on their servers and asks you to create a new upload key which will be used to sign further updates of the app. It takes the certificates of your new upload key and maps it to the managed private key. Now, whenever there is a new upload of the app, it’s signing certificate is matched with the upload key certificate and after verification, the app is signed by the original private key on the server itself and delivered to the user. The advantage comes where you lose your key, its password or it is compromised. Before App Signing program, if your key got lost, you had to launch your app under a new package name, losing your existing user base. With Google managing your key, if you lose your upload key, then the account owner can request Google to reassign a new upload key as the private key is secure on their servers.

There is no difference in the delivered app from the previous one as it is still finally signed by the original private key as it was before, except that Google also optimizes the app by splitting it into multiple APKs according to hardware, demographic and other factors, resulting in a much smaller app! This blog will take you through the steps in how to enable the program for existing and new apps. A bit of a warning though, for security reasons, opting in the program is permanent and once you do it, it is not possible to back out, so think it through before committing.

For existing apps:

First you need to go to the particular app’s detail section and then into Release Management > App Releases. There you would see the Get Started button for App Signing.

The account owner must first agree to its terms and conditions and once it’s done, a page like this will be presented with information about app signing infrastructure at top.

So, as per the instructions, download the PEPK jar file to encrypt your private key. For this process, you need to have your existing private key and its alias and password. It is fine if you don’t know the key password but store password is needed to generate the encrypted file. Then execute this command in the terminal as written in Step 2 of your Play console:

java -jar pepk.jar –keystore={{keystore_path}} –alias={{alias}} –output={{encrypted_file_output_path}} –encryptionkey=eb10fe8f7c7c9df715022017b00c6471f8ba8170b13049a11e6c09ffe3056a104a3bbe4ac5a955f4ba4fe93fc8cef27558a3eb9d2a529a2092761fb833b656cd48b9de6a

You will have to change the bold text inside curly braces to the correct keystore path, alias and the output file path you want respectively.

Note: The encryption key has been same for me for 3 different Play Store accounts, but might be different for you. So please confirm in Play console first

When you execute the command, it will ask you for the keystore password, and once you enter it, the encrypted file will be generated on the path you specified. You can upload it using the button on console.

After this, you’ll need to generate a new upload key. You can do this using several methods listed here, but for demonstration we’ll be using command line to do so:

keytool -genkey -v -keystore {{keystore_path}} -alias {{alias_name}} -keyalg RSA -keysize 2048 -validity 10000

The command will ask you a couple of questions related to the passwords and signing information and then the key will be generated. This will be your public key and be used for further signing of your apps. So keep it and the password secure and handy (even if it is expendable now).

After this step, you need to create a PEM upload certificate for this key, and in order to do so, execute this command:

keytool -export -rfc -keystore {{keystore_path}} -alias {{alias_name}} -file {{upload_certificate.pem}}

After this is executed, it’ll ask you the keystore password, and once you enter it, the PEM file will be generated and you will have to upload it to the Play console.

If everything goes right, your Play console will look something like this:

 

Click enrol and you’re done! Now you can go to App Signing section of the Release Management console and see your app signing and new upload key certificates

 

You can use the SHA1 hash to confirm the keys as to which one corresponds to private and upload if ever in confusion.

For new apps:

For new apps, the process is like a walk in park. You just need to enable the App Signing, and you’ll get an option to continue, opt-out or re-use existing key.

 

If you re-use existing key, the process is finished then and there and an existing key is deployed as the upload key for this app. But if you choose to Continue, then App Signing will be enabled and Google will use an arbitrary key as private key for the app and the first app you upload will get its key registered as the upload key

 

This is the screenshot of the App Signing console when there is no first app uploaded and you can see that it still has an app signing certificate of a key which you did not upload or have access to.

If you want to know more about app signing program, check out these links:

Continue ReadingEnabling Google App Signing for Android Project

Creating an Elementary Oscilloscope in PSLab’s Remote Framework

The last couple of blog posts explained how we could put together the versatility of ember components, the visual appeal of jqplot, the flexibility of Python Flask, and the simplicity of Python itself in order to make simple scripts for PSLab that would could be run on a server by a remote client anywhere on the web. We have also seen how callbacks could be assigned to widgets created in these scripts in order to make object oriented applications. In this blog post, we shall see how to assign a capture method to a button, and update a plot with the received data. It will also demonstrate how to use ember-lodash to perform array manipulations.

Specifying the return data type in the callback success routine

For a more instructive write-up on assigning callbacks, please refer to these posts .

Whenever the callback assigned to a button is a function that returns an array of elements, and the target for the resultant data is a plot, the stacking order of the returned array must be specified in order to change its shape to suit the plotting library. The default return data from a capture routine (oscilloscope) is made up of separate arrays for X coordinate and Y coordinate values. Since JQplot requires [X,Y] pairs , we must specify a stacking order of ‘xy’ so that the application knows that it must convert them to pairs (using lodash/zip)  before passing the result to the plot widget. Similarly, different stacking orders for capture2, and capture4 must also be defined.

Creating an action that performs necessary array manipulations and plots the received data

It can be seen from the excerpt below, that if the onSuccess target for a callback is specified to be a plot in the actionDefinition object, then the stacking order is checked, and the returned data is modified accordingly

Relevant excerpt from controllers/user-home.js/runButtonAction

if (actionDefinition.success.type === 'update-plot') {
  if (actionDefinition.success.stacking === 'xy') {
    $.jqplot(actionDefinition.success.target, [zip(...resultValue)]).replot();
  } else if (actionDefinition.success.stacking === 'xyy') {
    $.jqplot(actionDefinition.success.target, [zip(...[resultValue[0], resultValue[1]]), zip(...[resultValue[0], resultValue[2]])]).replot();
  } else if (actionDefinition.success.stacking === 'xyyyy') {
    $.jqplot(actionDefinition.success.target, [zip(...[resultValue[0], resultValue[1]]), zip(...[resultValue[0], resultValue[2]]), zip(...[resultValue[0], resultValue[3]]), zip(...[resultValue[0], resultValue[4]])]).replot();
  } else {
    $.jqplot(actionDefinition.success.target, resultValue).replot();
  }
}

 

With the above framework in place, we can add a plot with the line plt = plot(x, np.sin(x)) , and associate a button with a capture routine that will update its contents with a single line of code: button(‘capture1’,”capture1(‘CH1’,100,10)”,”update-plot”,target=plt)

Final Result

The following script created on the pslab-remote platform makes three buttons and plots, and sets the buttons to invoke capture1, capture2, and capture4 respectively when clicked.

import numpy as np
x=np.linspace(0,2*np.pi,30)
plt = plot(x, np.sin(x))
button('capture 1',"capture1('CH1',100,10)","update-plot",target=plt)

plt2 = plot(x, np.sin(x))
button('capture 2',"capture2(50,10)","update-plot",target=plt2,stacking='xyy')

plt3 = plot(x, np.sin(x))
button('capture 4',"capture4(50,10)","update-plot",target=plt3,stacking='xyyyy')

 

 

 

 

 

 

 

 

 

 

 

 

Resources

 

Continue ReadingCreating an Elementary Oscilloscope in PSLab’s Remote Framework

Export Sensor Data from the PSLab Android App

The PSLab Android App allows users to log data from the sensors connected to the PSLab hardware device. Sensor Data is stored locally but can be exported in various formats. Currently the app supports exporting data in .txt and .csv (comma-separated values) format. Exported data can be used by other users or scientists to study or analyze the data. Data can also be used by other softwares like Python, GNU octave, Matlab to further process it or visualise it in 3D. In this post, we will discuss how to export the locally stored realm data in .txt or .csv format. We will take the data of MPU6050 sensor as an example for understanding how locally logged data is exported.

Query Local Realm Data

We have attached a long click listener to sensor list view that detects which list item is selected. Clicking any sensor from sensor list for slightly longer than usual would result in a dialog popping up with the option to

  • Export Data: Results in exporting data in a format which is selected in App settings
  • Share Data: Shares sensor data with other users or on social media (yet to be implemented)
Source: PSLab Android App

As soon as the Export Data option is selected from the dialog, sensor data of the corresponding sensor is queried. The data model of the sensor and how it’s saved in the local realm database is discussed in the post Sensor Data Logging in the PSLab Android App.

RealmResults<DataMPU6050> results = realm.where(DataMPU6050.class).findAll();

Once we get the required data, we need to write it in .txt or .csv format depending on what the user has selected as a preference in App Settings.

Getting User Preference from App Settings

The format in which the sensor data should be exported is presented to the user as a preference in App Settings. Currently the app supports two formats .txt and .csv.

Source: PSLab Android App
private String format;
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String formatValue = preferences.getString("export_data_format_list", "0");
if ("0".equals(formatValue))
   format = "txt";
else
   format = "csv";

Export Data in .txt Format

To export the sensor data in .txt format, we need to create a .txt file in the external storage. folder variable is a path to PSLab Android folder in the external storage. If the folder doesn’t exist, it will be created.

File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "PSLab Android");

After getting reference of the app folder in the external storage, we would create a text file in the PSLab Android folder. As soon as the text file is created, we initialize the FileOutputStream object to write data into the text file. The sensor data that was queried in the previous section is written into the text file just created. Finally after the complete sensor data is written, the stream is closed by stream.close() method.

FileOutputStream stream = null;
File file = new File(folder, "sensorData.txt");
try {
   stream = new FileOutputStream(file);
   for (DataMPU6050 temp : results) {
       stream.write((String.valueOf(temp.getAx()) + " " + temp.getAy() + " " + temp.getAz() + " " +
               temp.getGx() + " " + temp.getGy() + " " + temp.getGz() + " " + temp.getTemperature() + "\n").getBytes());
   }
} catch (IOException e) {
   e.printStackTrace();
} finally {
   try {
       if (stream != null) {
           stream.close();
       }
   } catch (IOException e) {
       e.printStackTrace();
   }
}

Export Data in .csv Format

Writing data in .csv format is similar to that in .txt format. As CSV stands for Comma Separated Values, which means each data value is separated by “,” (comma). It is similar to an excel sheet. The first row consists of labels that denote the type of value in that particular column. The other rows consist of the sensor data, with each row corresponding to a sample of the sensor data.

File file = new File(folder, "sensorData.csv");
PrintWriter writer;
try {
   writer = new PrintWriter(file);
   StringBuilder stringBuilder = new StringBuilder();
   stringBuilder.append("Ax,Ay,Ax,Gx,Gy,Gz,Temperature\n");
   for (DataMPU6050 temp : results) {
       stringBuilder.append(String.valueOf(temp.getAx()));
       stringBuilder.append(',');
       stringBuilder.append(String.valueOf(temp.getAy()));
       stringBuilder.append(',');
       stringBuilder.append(String.valueOf(temp.getAz()));
       stringBuilder.append(',');
       stringBuilder.append(String.valueOf(temp.getGx()));
       stringBuilder.append(',');
       stringBuilder.append(String.valueOf(temp.getGy()));
       stringBuilder.append(',');
       stringBuilder.append(String.valueOf(temp.getGz()));
       stringBuilder.append(',');
       stringBuilder.append(String.valueOf(temp.getTemperature()));
       stringBuilder.append('\n');
   }
   writer.write(stringBuilder.toString());
   writer.close();
} catch (FileNotFoundException e) {
   e.printStackTrace();
}

Resources

Continue ReadingExport Sensor Data from the PSLab Android App

How Switch Case improve performance in PSLab Saved Experiments

PSLab android application contains nearly 70 experiments one can experiment on using the PSLab device and the other necessary circuit components and devices. These experiments span over areas such as Electronics, Electrical, Physical and High school level. All these experiments are accessible via an android adapter in the repository named “PerformExperimentAdapter”. This adapter houses a tab view with two different tabs; one for the experiment details and the other for actual experiment and resultant graphs.

The adapter extends an inbuilt class FragmentPagerAdapter;

public class PerformExperimentAdapter extends FragmentPagerAdapter

This class displays every page attached to its viewpager as a fragment. The good thing about using fragments is that they have a recyclable life cycle. Rather than creating new views for every instance of an experiment, the similar views can be recycled to use once again saving resources and improving performance. FragmentPagerAdapter needs to override a method to display the correct view on the tab select by user.

@Override
public Fragment getItem(int position) {

}

Depending on the value of position, relevant experiment documentation and the experiment implementation fragments are displayed determined using the experiment title. Performance can be critical in this place as if it takes too long to process and render a fragment, user will feel a lag.

The previous implementation was using consecutive if statements.

@Override
public Fragment getItem(int position) {
   switch (position) {
       case 0:
           if (experimentTitle.equals(context.getString(R.string.diode_iv)))
               return ExperimentDocFragment.newInstance("D_diodeIV.html");
           if (experimentTitle.equals(context.getString(R.string.zener_iv)))
               return ExperimentDocFragment.newInstance("D_ZenerIV.html");
           ...
       case 1:
           if (experimentTitle.equals(context.getString(R.string.diode_iv)))
               return ZenerSetupFragment.newInstance();
           if (experimentTitle.equals(context.getString(R.string.zener_iv)))
               return DiodeExperiment.newInstance(context.getString(R.string.half_wave_rectifier));
           ...
       default:
           return ExperimentDocFragment.newInstance("astable-multivibrator.html");
   }
}

This setup was suitable for applications where there is less than around 5 choices to chose between. As the list grows, the elements in the end of the if layers will take more time to load as each of the previous if statements need to be evaluated false in order to reach the bottom statements.

This is when this implementation was replaced using switch case statements instead of consecutive if statements. The theory behind the performance improvement involves algorithm structures; Hash Tables

Hash Tables

Hash tables use a hash function to calculate the index of the destination cell. This operation on average has a complexity of O(1) which means it will take the same time to access any two elements which are randomly positioned.

This is possible because java uses the hash code of the string to determine the index where the target is situated at. This way it is much faster than consecutive if statement calls where in the worst case it will take O(n) time to reach the statement causing a lag in the application.

Current application uses switch cases in the PerformExperimentAdapter;

@Override
public Fragment getItem(int position) {
   switch (position) {
       case 0:
           switch (experimentTitle) {
               case "Diode IV Characteristics":
                   return ExperimentDocFragment.newInstance("D_diodeIV.html");
               case "Zener IV Characteristics":
                   return ExperimentDocFragment.newInstance("D_ZenerIV.html");
               case "Half Wave Rectifier":
                   return ExperimentDocFragment.newInstance("L_halfWave.html");
           }
       case 1:
           switch (experimentTitle) {
               case "Diode IV Characteristics":
                   return ZenerSetupFragment.newInstance();
               case "Zener IV Characteristics":
                   return ZenerSetupFragment.newInstance();
               case "Half Wave Rectifier":
                   return DiodeExperiment.newInstance(context.getString(R.string.half_wave_rectifier));
           }
       default:
           return ExperimentDocFragment.newInstance("astable-multivibrator.html");
   }
}

There is one downfall in using switch case in the context. That is the inability to use string resources directly as Java requires a constant literals in the evaluation statement of a case.

Resources:

Continue ReadingHow Switch Case improve performance in PSLab Saved Experiments

Coloring Waveforms in PSLab Charts

Charts are used to display set of data in an analytical manner such that an observer can easily come to a conclusion by just looking at it without having to go through all the numerical data sets. Legends are used to differentiate a set of data set from another set. Generally, different colors and different names are used to form a legend in a chart.

MPAndroidChart is an amazing library with the capability of generating different types of graphs in an Android device. In PSLab several user interfaces are implemented using LineCharts to display different waveforms such as readings from channels attached to PSLab device, logic levels etc.

When several data sets are being plotted on the same graph area, legends are used. In PSLab Android application, Oscilloscope supports four different type of waveforms to be plotted on the same graph. Logic Analyzer implements one to four different types of logic level waveforms on the same plot. To identify which is which, legends with different colors can be used rather than just the names. For the legends to have different colors, it should be explicitly set which color should be held by which data set. Otherwise it will use the default color to all the legends making it hard to differentiate data lines when there are more than one data set is plotted.

Assume a data set is generated from a reading taken from a probe attached to PSLab device. The set will be added as an Entry to an array list as follows;

ArrayList<Entry> dataSet = new ArrayList<Entry>();

The next step will be to create a Line Data Set

LineDataSet lineData = new LineDataSet(dataSet, "DataSet 1");

This LineDataSet will contain sample values of the waveform captured by the microprocessor. A LineDataSet object support many methods to alter its look and feel. In order to set a color for the legend, setColor() method will be useful. This method accepts an integer as the color. This method can be accessed as follows;

lineData.setColor(Color.YELLOW);

MPAndroidChart provides different sets of colors under ColorTemplate. This class has several predefined colors with five colors in each color palette are added by the developers of the library and they can be accessed using the following line of code by simply calling the index value of the palette array list.

set1.setColor(ColorTemplate.JOYFUL_COLORS[0]);

Set of color palettes available in the ColorTemplate class are;

  1. LIBERTY_COLORS
  2. JOYFUL_COLORS
  3. PASTEL_COLORS
  4. COLORFUL_COLORS
  5. VORDIPLOM_COLORS
  6. MATERIAL_COLORS

The following demonstrates how the above activities produce a line chart with three different data sets with different colored legends.

This implementation can be used to enhance the readability of the waveforms letting user being able to differentiate between one waveform from another in PSLab Android application.

Resources:

PSLab official web site: https://pslab.fossasia.org/

Continue ReadingColoring Waveforms in PSLab Charts

Performing Diode Clipping and Clamping Experiment in PSLab Android

We can perform experiments like diode clipping and clamping using PSLab Android. A circuit which removes the peak of a waveform is known as a clipper. Diode clipper cuts off the top half or lower half or both top and lower half of the input signal. 

Different types of clipping circuits listed below

Different Clipping Experiments

A clamper circuit adds the positive dc component to the input signal to push it to the positive side. Similarly, a clamper circuit adds the negative dc component to the input signal to push it to the negative side. It basically shifts the input signal without changing the shape of the signal.

Different Clamping Experiments

Apparatus

Diode, Resistance, Capacitor (only for diode clamping), Breadboard, Wires and PSLab

Adding Diode Clipping Experiment support in PSLab Android App

To support Diode Clipping Experiment we require generating a sine wave and a dc component. This can be done using W1 and PV1 pins in PSLab device. Both input and output signals can be read using CH1 and CH2. So, when the Diode Clipping Experiment needs to be performed the following code needs to be implemented

scienceLab.setSine1(5000);
scienceLab.setPV1(//progress of the seekbar);

The signals are recorded using Oscilloscope Activity.

Adding Diode Clamping Experiment support in PSLab Android App

Diode Clamping Experiment was implemented similarly to Diode Clipping Experiment. The following are the screenshots of the experiment.     

The following is a glimpse of Diode Clamping Experiment performed using PSLab device using PSLab Android App.

Resources

  1. Read more about Clipper Circuits –
  2. Read more information about Clamping Circuits –

Continue ReadingPerforming Diode Clipping and Clamping Experiment in PSLab Android