## Sine Wave Generator

PSLab by FOSSASIA can generate sine waves with arbitrary frequencies. This is very helpful to teachers, students and electronic enthusiasts to study about different frequencies and how systems respond to them. In the device, it uses digital signal processing to derive a smooth sine wave. Except to digital implementation, there are conventional analog implementations to generate a sine wave.

The most famous method to generate a sine wave is the Wien Bridge Oscillator. It is a frequency selective bridge with a range of arbitrary frequencies. This oscillator has a good stability when it is functioning at its resonance frequency while maintaining a very low signal distortion.           Let’s take a look at this circuit. We can clearly see that there is a series combination of a resistor and a capacitor at A and a parallel combination of a resistor and a capacitor at B joining at the non-inverting pin of the OpAmp. The series combination of RC circuit is nothing but a high pass filter that allows only high frequency components to pass through. The parallel combination of RC circuit is a Low pass filter that allows only the low frequency components of a signal to pass through. Once these two are combined, a band pass filter is created allowing only a specific frequency component to pass through.

It is necessary that the resistor value and the capacitor values should be the same in order to have better performance without any distortion. Assuming that they are same, using complex algebra we can prove that the voltage at V+(3) is one third of the Voltage coming out from the pin (1) of OpAmp.

Using the resonance frequency calculation using RC values, we can determine the frequency of the output sine wave.

f=1/2RC

The combination of two resistors at the inverting pin of the Op Amp controls the gain factor. It is calculated as 1+R1/R2. Since the input to the non-inverting terminal is 1/3 of the output voltage, this gain factor should be maintained at 3. Values greater than 3 will cause a ramping behavior in the sine wave and values below 3 will show an attenuation. So the gain should be set preciously.

Equating 1+R1/R2 to 3, we can obtain a ratio for R1/R2 as 2. That implies R1 should be as twice the resistance of R2. Make sure these resistances are in the power of kilo Ohms. That is to ensure that the leakage current is minimum to the Op Amp. Let’s select R1 = 200K and R2 = 100K

This oscillator supports a range of frequencies. Let’s assume we want to generate a sine wave having 500 Hz. Using f=1/2RC, we can choose arbitrary values for R and C. Substituting values to the formula yields a value for RC = 318 x10e-6

Using practical values for R as 10k, C value can be approximated to 33nF. This oscillator is capable of generating a stable 500 Hz sinusoidal waveform. By changing the resistive and capacitive values of block A and B, we can generate a wide range of frequencies that are supported by the Op Amp because Op Amps have a limited bandwidth it can be functional inside.

It’s worth to note a few facts about generating sine waves using a digital implementation. In analog circuitry, the component values have a tolerance which makes the calculations not perfectly align with the real values. Due to this reason, the actual output will differ from the desired output. In our example to generate 500 Hz sine wave, the capacitors and resistors may have different values and they may have not matched. But with a digital implementation, we can achieve the accuracy and flexibility we require.

## Regulating Voltage in PSLab

Electronic components are highly sensitive to voltages and currents across them. Most of the devices in the current market work in the voltage levels of 3.3V, 5V, 12V and 15V. If they are provided with a different voltage than the one required by the vendor, they would not function. If the voltage supplied is higher, they might burn off. The PSLab device requires separate voltage levels such as 3.3V and 5V for its operation.

There are commercial voltage regulators available in the market designed with advanced feedback techniques and models. But we can create out own voltage regulator. In this blog post, I am going to introduce you to a few basic models capable of regulating voltage to a desired level.

Current implementation of PSLab device uses a voltage regulator derived using a zener-resistor combination. This type of regulators have a higher sensitivity to current and their operation may vary when the supplied or the drawn current is lower than the expected values. In order to have a stable voltage regulation, this combination needs to be replaced with a much stable transistor-zener combination.

Before go into much details, let’s get to know a few basic concepts and devices related to.

Zener Diode

Zener diode is a type of diode which has a different operational behavior than the general diode. General diodes allow current to flow only in one direction. If a current in the reverse is applied, they will break and become unusable after a certain voltage level known as Breakdown Voltage. But Zener diodes are specifically designed to function desirably once this break down voltage has been passed and unlike general diode, it can recover back to normal when the voltage is removed or reduced.

Transistor

This is the game changing invention of the 20th century. There are two types of Bipolar Junction Transistors (BJT) available in the market. They are known as NPN and PNP transistors. The difference is based on the polarity of diodes used.

An NPN transistor can be modeled as a combination of two diodes –[NP → PN]– and a PNP transistor can be modeled as –[PN → NP]– using two diodes.

There are three pins to take notice in BJTs. They are illustrated in the diagram shown here;

1. Base
2. Collector
3. Emitter

The amazing fact about BJTs is that the amount of current provided to the Base terminal will control the flow of current going through Collector and Emitter. Also note that always there is a voltage drop across the Base terminal and the Emitter terminal. This typically takes a value of 0.7 V

Voltage Divider

This is the most basic type of voltage regulator. It simply divides the voltage supplied by the battery with the ratio R1:R2. In the following configuration, the output voltage can be calculated using the voltage division rule;

Which is equal to 12 * 100/(100+200) = 4 V

There is a huge drawback with this design. The above calculation is valid only if there is no load impedance is present at the output terminals.

Generally there will be a load impedance and the supplied voltage cannot be easily calculated as the load impedance is unknown to the regulator.

Resistor-Zener Voltage Regulator

Due to the load dependability of the previous model with the load, an improved model can be introduced as follows. This is the current implementation of voltage regulator in PSLab device.

Unlike the previous model, this model ensures that the output voltage will be maintained constant across the output terminals within a range of supply voltage values.

Let’s assume the supply voltage is increased. Then the current flow through the zener diode will increase in order to maintain a constant voltage across the output terminals. In case if the supply voltage drops, then the zener current will decrease and a stable voltage across the output terminals will be maintained.

This design also comes with a slight draw back. This can be explained using the characteristic curve of a zener diode. (Figure is taken from : http://www.electronics-tutorials. ws/diode/diode_7.html)

For a zener diode to maintain a constant voltage level across output terminals, there should be a minimum current flowing through the diode. If this current is not flowing in the zener, there won’t be a regulation. Assume there is a very low load impedance. Then the current supplied by the source will find an easier path to flow other than through the diode. This will affect the regulatory circuit and the desired voltage will not appear across the output terminals.

To compensate the drawback, a much improved design is available using transistors.

Transistor-Zener Voltage Regulator

This is the proposed improvement to the voltage regulatory circuit in PSLab device. In this model, the zener diode is taken away from the load circuit as the current to the load is supplied from the transistor directly. This avoids current limitations to the zener diode had in the previous model and transistor acts as a bridge.

A small current through the Base terminal (1) will support a higher current flow through the output terminal via Collector (2) and Emitter (3). This amplification ratio is in the range of few hundreds for a typical BJT.

A capacitor has been added to compensate ripples from the supply source. If a higher current flow is required through the output terminals, the NPN transistor can be replaced by a Darlington pair.

Using a 5.6 V zener diode and MMBT3904/6 transistors, this model has been implemented in the newest version of PSLab device. They will be supplying a constant voltage of +/- 5V to V+ and V- pins in the device.

## Constructing and working with Polynomials in the PSLab Android App

PSLab is a device that allows the user to perform a range of science and engineering experiments. PSLab has existing communication library (PSLab Desktop) written in Python. Since we are developing an Android application to operate PSLab, the initial step was to port Python code to JAVA. In PSLab Android application we are using version 3.6.1 of Apache Maths Commons.

NumPy is the package for scientific computing with Python. Polynomials in NumPy can be created using numpy.poly1d. Since some of the files in PSLab Desktop use polynomials, it was important to find a package in JAVA that provides features equivalent to NumPy. Apache Maths Commons fulfilled our needs. It is a Mathematics Library available in JAVA, that provides the means to construct polynomials and perform a range of operations on them. A detailed documentation of the library is available here.

```import numpy

p = numpy.poly1d([1, 2, 3])

print(numpy.poly1d(p))

q = p(0.5)

print q

Output:

1 x2 + 2 x + 3

4.25```

Poly1d() function converts a list into polynomials. The first element of the list is the coefficient of the highest degree of the polynomial while the last element is the coefficient of lowest degree of the polynomial. While p(0.5) evaluates polynomial at x = 0.5.

Now let’s construct polynomials in JAVA using Apache Maths Commons

```public class poly {

public static void main(String[] args){

PolynomialFunction p = new PolynomialFunction(new double[]{3, 2, 1});

System.out.println(p);

System.out.println(p.value(0.5));

}
}

Output:

3 + 2 x + x^2

4.25```

Polynomial Function converts the double array into polynomials. The first element of the array is the coefficient of the lowest degree of the polynomial while the last element is the coefficient of the highest degree of the polynomial. p.value (0.5) evaluates polynomial at x = 0.5.

Other things we can do

• ###### Find the degree of the polynomial.

Continuing with the above example where polynomial was 3 + 2 x + x^2. p.degree() gives 2 as output which is the degree of the given polynomial.

• ###### Get the coefficients of the polynomial

p.getCoefficients() returns a double array of the coefficients of the given polynomial. In the above case [3.0, 2.0, 1.0] will be returned.

• ###### Find derivatives of the polynomial

p.derivative() returns 2 + 2 x which is derivative of polynomial 3 + 2 x + x^2.

• ###### Add, subtract and multiply two polynomials.

We can add, subtract and multiply 2 polynomials. For example p.multiply(new  Polynomial Function(new double[]{1,2})) returns 3 + 8 x + 5 x^2 + 2 x^3 which is  the product of 3 + 2 x + x^2 and 1 + 2 x

#### Where are they are used in PSLab?

Polynomials are used in AnalogInputSource.java  to convert raw ADC codes (0=0V , 1023=3.3V ) to voltage values.

• `calPoly10 = new PolynomialFunction(new double[]{0., 3.3 / 1023, 0.});`
• `calPoly12 = new PolynomialFunction(new double[]{0., 3.3 / 4095, 0.});`

Polynomials are also used in DACChannel.java to convert DAC codes to voltage values and vice versa.

• `VToCode = new PolynomialFunction(new double[]{-4095. * intercept / slope, 4095. / slope});                                                    `
• `CodeToV = new PolynomialFunction(new double[]{intercept, slope / 4095.});`

## Temporally accurate data acquisition via digital communication pathways in PSLab

This blog post deals with the importance of using a real-time processor for acquiring time dependent data sets. The PSLab already features an oscilloscope, an instrument capable of high speed voltage measurements with accurate timestamps, and it can be used for monitoring various physical parameters such as acceleration and angular velocity as long as there exists a device that can generate a voltage output corresponding to the parameter being measured.  Such devices are called sensors, and a whole variety of these are available commercially.

However, not all sensors provide an analog output that can be input to a regular oscilloscope. Many of the modern sensors use digitally encoded data which has the advantage of data integrity being preserved over long transmission pathways. A commonly used pathway is the I2C data bus, and this blog post will elaborate the challenges faced during continuous data acquisition from a PC, and will explore how a workaround can be managed by moving the complete digital acquisition process to the PSLab hardware in order create a digital equivalent of the analog oscilloscope.

Precise timestamps are essential for extracting waveform parameters such as frequency and phase shifts, which can then be used for calculating physics constants such as the value of acceleration due to gravity, precession, and other resonant phenomena. As mentioned before, oscilloscopes are capable of reliably measuring such data as long as the input signal is an analog voltage, and if a digital signal needs to be recorded, a separate implementation similar to the oscilloscope must be designed for digital communication pathways.

#### A question for the reader :

Consider a voltmeter capable of making measurements at a maximum rate of one per microsecond.

We would like to set it up to take a thousand readings (n=1000) with a fixed time delay(e.g. 2uS) between each successive sample in order to make it digitize an unknown input waveform. In other words, make ourselves a crude oscilloscope.

Which equipment would you choose to connect this voltmeter to in order to acquire a dataset?

1. A 3GHz i3 processor powering your favourite operating system, and executing a simple C program that takes n readings in a for loop with a delay_us(2) function call placed inside the loop.
2. A 10MHz microcontroller , also running a minimal C program that acquires readings in fixed intervals.

To the uninitiated, faster is better, ergo, the GHz range processor trumps the measly microcontroller.

But, we’ve missed a crucial detail here. A regular desktop operating system multitasks between several hundred tasks at a time. Therefore, your little C program might be paused midway in order to respond to a mouse click, or a window resize on any odd chores that the cpu scheduler might feel is more important. The time after which it returns to your program and resumes acquisition is unpredictable, and is most likely of the order of a few milliseconds.

The microcontroller on the other hand, is doing one thing, and one thing only. A delay_us(2) means a 2uS delay with an error margin corresponding to the accuracy of the reference clock used. Simple crystal oscillators usually offer accuracies as good as 30ppm/C, and very low jitter.

Armed with this DIY oscilloscope, we can now proceed to digitize a KHz range since wave or a sound signal from a microphone with good temporal accuracy.

### Sample results from the PSLab’s analog oscilloscope

If the same were taken via a script that shares CPU time with other processes, the waveform would compress at random intervals due to CPU time unavailability. Starting a new CPU intensive process usually has the effect of the entire waveform appearing compressed because actual time intervals between each sample are greater than the expected time intervals

##### Implementing the oscilloscope for data buses such as I2C

With regards to the PSLab which already has a reasonably accurate oscilloscope built-in, what happens if one wants to acquire time critical information from sensors connected to the data bus , and not the analog inputs ?

In order acquire such data , the PSLab firmware houses the read routine from I2C in an interrupt function that is invoked at precise intervals by a preconfigured timer’s timeout event. Each sample is stored to an array via a self incrementing pointer.

The I2C address to be accessed, and the bytes to be written before one can start reading data are all pre-configured before the acquisition process starts.

This process then runs at top priority until a preset number of samples have been acquired.Once the host software knows that acquisition should have completed, it fetches the data buffer containing the acquired information.

The plots that overlap accurately with a simulated damped sinusoidal waveform are not possible in the absence of a real-time acquisition system

The sensor in question is the MPU6050 from invensense, used primarily in drones, and other self-stabilising robots.

Its default I2C address is 0x68 ( 104 ) , and 14 registers starting from 0x3B contain data for acceleration along orthogonal axes, temperature, and angular velocity along orthogonal axes. Each of these values is an integer, and is therefore represented by two successive registers. E.g. , 0x3B and 0x3C together make up a 16-bit value for acceleration along the X-axis.

### The Final App

As a developer, the importance of testing code is well known. Testing source code helps to prevent bugs and syntax errors by cross-checking it with an expected output.
As stated on their official website: “Code coverage provides a visual measurement of what source code is being executed by a test suite”. This information indicates to the software developer where they should write new tests in the effort to achieve higher coverage, and consequently a lower chance of being buggy. Hence nearly every public repository on git uses codecov, a tool to measure the coverage of their source code.

In this blog, we shall see how to link codecov, with a public repository on Github when the code has been written in Angular2(Typescript). We shall assume that the repository uses Travis CI for integration.

STEP 1:

It will now give you the option to chose a repository to add for coverage. Select your repository.

STEP 2:
Navigate to Settings Tab, you should see something like this:

STEP 3:
We now come to one of the most important parts of Codecov integration. Writing the files in our repo to enable this.
We will need three main files:
Travis.yml- which will ensure continuous integration services on your git hosted project
Codecov.yml- to personalise your settings and override the default settings in codecov.”The Codecov Yaml file is the single point of configuration, providing the developers with a transparent and version controlled file to adjust all Codecov settings.” as mentioned in the official website
Package.json- to inform npm of the new dependencies related to codecov, in addition to providing all the metadata to the user.

In .travis.yml, Add the following line:
after_success:

` - bash <(curl -s https://codecov.io/bash)`

```Source: https://github.com/codecov/support/wiki/Codecov-Yaml#
codecov:
url: "string" # [enterprise] your self-hosted Codecov endpoint
# ex. https://codecov.company.com
slug: "owner/repo" # [enterprise] the project's name when using the global upload tokens
branch: master # the branch to show by default, inherited from your git repository settings
# ex. master, stable or release
# default: the default branch in git/mercurial
# must have previously logged into Codecov
ci: # [advanced] a list of custom CI domains
- "ci.custom.com"
after_n_builds: 5 # how many build to wait for before submitting notifications
# therefore skipping status checks
countdown: 50 # number of seconds to wait before checking CI status
delay: 100 # number of seconds between each CI status check

coverage:
precision: 2 # how many decimal places to display in the UI: 0 <= value <= 4 round: down # how coverage is rounded: down/up/nearest range: 50...100 # custom range of coverage colors from red -> yellow -> green

notify:
irc:
default: # -> see "sections" below
server: "chat.freenode.net" #*S the domain of the irc server
branches: null # -> see "branch patterns" below
threshold: null # -> see "threshold" below
message: "template string" # [advanced] -> see "customized message" below

gitter:
default: # -> see "sections" below
url: "https://webhooks.gitter.im/..." #*S unique Gitter notifications url
branches: null # -> see "branch patterns" below
threshold: null # -> see "threshold" below
message: "template string" # [advanced] -> see "customized message" below

status:
project: # measuring the overall project coverage
default: # context, you can create multiple ones with custom titles
enabled: yes # must be yes|true to enable this status
target: auto # specify the target coverage for each commit status
# option: "auto" (must increase from parent commit or pull request base)
# option: "X%" a static target percentage to hit
branches: # -> see "branch patterns" below
threshold: null # allowed to drop X% and still result in a "success" commit status
if_no_uploads: error # will post commit status of "error" if no coverage reports we uploaded
# options: success, error, failure
if_not_found: success # if parent is not found report status as success, error, or failure
if_ci_failed: error # if ci fails report status as success, error, or failure

patch: # pull requests only: this commit status will measure the
# entire pull requests Coverage Diff. Checking if the lines
# adjusted are covered at least X%.
default:
enabled: yes # must be yes|true to enable this status
target: 80% # specify the target "X%" coverage to hit
branches: null # -> see "branch patterns" below
threshold: null # allowed to drop X% and still result in a "success" commit status
if_no_uploads: error # will post commit status of "error" if no coverage reports we uploaded
# options: success, error, failure
if_not_found: success
if_ci_failed: error

changes: # if there are any unexpected changes in coverage
default:
enabled: yes # must be yes|true to enable this status
branches: null # -> see "branch patterns" below
if_not_found: success
if_ci_failed: error

ignore: # files and folders that will be removed during processing
- "tests/*"
- "demo/*.rb"

fixes: # [advanced] in rare cases the report tree is invalid, specify adjustments here
- "old_path::new_path"

# comment: false # to disable comments
comment:
layout: "header, diff, changes, sunburst, suggestions, tree"
branches: null # -> see "branch patterns" below
behavior: default # option: "default" posts once then update, posts new if delete
# option: "once" post once then updates, if deleted do not post new
# option: "new" delete old, post new
# option: "spammy" post new

```

Your package.json should look like this:

```{
"name": "example-typescript",
"version": "1.0.0",
"description": "Codecov Example Typescript",
"main": "index.js",
"devDependencies": {
"chai": "^3.5.0",
"codecov": "^1.0.1",
"mocha": "^2.5.3",
"nyc": "^6.4.4",
"tsd": "^0.6.5",
"typescript": "^1.8.10"
},
"scripts": {
"postinstall": "tsd install",
"pretest": "tsc test/*.ts --module commonjs --sourcemap",
"test": "nyc mocha",
"posttest": "nyc report --reporter=json && codecov -f coverage/*.json"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Myname/example-typescript.git"
},
/*Optional*/
"author": "Myname",
"bugs": {
"url": "https://github.com/example-typescript-path"
},
}```

Most of the code in package.json is metadata.
Two major parts of the code above are the devDependencies and the scripts.
In devDependencies, make sure to include the latest versions of all the packages your repository is using.
In scripts:

• Postinstall – indicates the actions to be performed, once installation is complete.
• Pretest – is for just before running ng test.
• Test – indicates what is used while testing.
• Posttest – is what is run just after testing is complete.

Check this repository for the sample files to generate the reports to be uploaded for Codecov: https://github.com/codecov/example-typescript

Check https://docs.codecov.io/v4.3.6/docs/codecov-yaml for detailed step by step instructions on writing codecov.yaml and https://docs.codecov.io/v4.3.6/docs for any general information

## Porting PSLab Libraries – Python to Java

PSLab has existing communication libraries and sensor files in Python which were created during the development of Python Desktop Application.

The initial task and challenge was porting this existing code to Java to be used by the Android App. Since, the python libraries also utilized the object oriented model of programming, porting from Python to Java had the similar code structure and organization.

Common problems faced while porting from Python to Java

• The most common problem is explicitly assigning data types to variables in Java since Python manages data types on its own. However, most of the time the data types are quite evident from the context of their use and understanding the purpose of the code can make the task much simpler.
• Another task was migrating the Python data structures to their corresponding Java counterparts like a List in Python represents an ArrayList in Java, similarly a Dictionary corresponds to a HashMap and so on.
• Some of the sections of the code uses highly efficient libraries like Numpy and Scipy for some mathematical functions. Finding their corresponding Java counterparts in libraries was a challenge. This was partly solved by using Apache Common Math which is a library dedicated for mathematical functions. Some of the functions were directly implemented using this library and for rest of the portions, the code was written after understanding the structure and function of Numpy methods.

While porting the code from Python to Java, some of the steps which we followed:

• Matching corresponding data-structures

The Dictionary in python…

`Gain_scaling = OrderedDict ([('GAIN_TWOTHIRDS', 0.1875), ('GAIN_ONE', 0.125), ('GAIN_TWO', 0.0625), ('GAIN_FOUR', 0.03125), ('GAIN_EIGHT', 0.015625), ('GAIN_SIXTEEN', 0.0078125)])`

…was mapped to corresponding Java HashMap in the manner given below. A point to be noted here is for adding elements to a HashMap can be done only from a method and not at the time of declaration of HashMap.

```private HashMap <String,Double> gainScaling = new HashMap <String,Double>();

gainScaling.put("GAIN_TWOTHIRDS",0.1875);
gainScaling.put("GAIN_ONE",0.125);
gainScaling.put("GAIN_TWO",0.0625);
gainScaling.put("GAIN_FOUR",0.03125);
gainScaling.put("GAIN_EIGHT",0.015625);
gainScaling.put("GAIN_SIXTEEN",0.0078125);
```

Similarly, the List in Python can be  be converted to the corresponding ArrayList in Java.

• Assigning data types and access modifiers to corresponding variables in Java
```POWER_ON = 0x01
gain_choices = [RES_500mLx, RES_1000mLx, RES_4000mLx]
ain_literal_choices = ['500mLx', '1000mLx', '4000mLx']
scaling = [2, 1, .25]```
```private int POWER_ON = 0x01;
public int[] gainChoices = {RES_500mLx,RES_1000mLx,RES_4000mLx};
public String[] gainLiteralChoices = {"500mLx", "1000mLx", "4000mLx"};
public double[] scaling = {2,1,0.25};```

Assigning data types and the corresponding access modifiers can get tricky sometimes. So, understanding the code is essential to know whether a variable in limited to the class or needs to be accessed outside the class, whether a variable is int, short, float or double etc.

• Porting Numpy & Scipy functions to Java using Apache Common Math

For example, this piece of code gives the pitch of acceleration. It uses mathematical functions like arc-tan.

```pitchAcc = np.arctan2(accData[1], accData[2]) * 180 / np.pi
```

The corresponding version of arc-tan in Apache Common Math is used in Java.

`double pitchAcc = Math.atan2(accelerometerData[1], accelerometerData[2]) * 180 / pi;`
• Porting by writing the code for Numpy and Scipy functions explicitly

In the code below, rfftfreq is used to calculate the Discrete Fourier Transform(DFT) sample frequencies.

```freqs = self.fftpack.rfftfreq(N, d=(xReal[1] - xReal[0]) / (2 * np.pi))
```

Since, hardly any library in Java supports DFT, the corresponding code for rfftfreq was self-written.

```double[] rfftFrequency(int n, double space){
double[] returnArray = new double[n + 1];
for(int i = 0; i < n + 1; i++){
returnArray[i] =  Math.floor(i / 2) / (n * space);
}
return Arrays.copyOfRange(returnArray, 1, returnArray.length);
}```

After porting of all communication libraries and sensor files are done, the testing of features can also be initiated. Currently, the ongoing development includes porting of the some of the remaining files and working on the the best possible User Interface.

## Integrating Travis CI and Codacy in PSLab Repositories

Continuous Integration Testing and Automated Code Review tools are really useful for developing better software, improving code and overall quality of the project. Continuous integration can help catch bugs by running tests automatically and to merge your code with confidence.

While working on my GsoC-16 project, my mentors guided and helped me to integrate Travis CI and Codacy in PSLab github repositories. This blog post is all about integrating these tools in my github repos, problems faced, errors occurred and the test results.

Travis CI is a hosted continuous integration and deployment system. It is used to build and test software projects hosted on github. There are two versions of it, travis-ci.com for private repositories, and travis-ci.org for public repositories.

Travis is configured with the “.travis.yml” file in your repository to tell Travis CI what to build. Following is the code from ‘.travis.yml‘ file in our This repo contains python communication library for PSLab.

```language: python
python:
- "2.6"
- "2.7"
- "3.2"
- "3.3"
- "3.4"
# - "3.5"
# command to install dependencies
# install: "pip install -r requirements.txt"
# command to run tests
script: nosetests```

With this code everything worked out of the box (except few initial builds which errored because of missing ‘requirements.txt‘ file) and build passed successfuly 🙂 🙂

Later Mario Behling added integration to

Travis CI supports notifying  Slack channels about build results. On Slack, set up a new Travis CI integration. Select a channel, and you’ll find the details to paste into your ‘.travis.yml’. Just copy and paste the settings, which already include the proper token and you’re done.

The simplest configuration requires your account name and the token.

``````notifications:
slack: '<account>:<token>'
``````
```notifications:
slack: fossasia:***tokenishidden****```

Import errors in Travis builds of PSLab-apps Repository

PSLab-apps repository contains PyQt bases apps for various experiments. The ‘.travis.yml‘ file mentioned above gave several module import errors.

```\$ python --version
Python 3.2.5
\$ pip --version
pip 6.0.7 from /home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages (python 3.2)
Could not locate requirements.txt. Override the install: key in your .travis.yml to install dependencies.
0.33s\$ nosetests
E
======================================================================
ERROR: Failure: ImportError (No module named sip)```

The repo is installable and PSLab was working fine on popular linux distributions without any errors. I was not able to find the reason for build errors. Even after adding proper ‘requirements.txt‘ file,  travis builds errored.

On exploring the documentation I could figure out the problem.

Travis CI Environment uses separate virtualenv instances for each Python version. System Python is not used and should not be relied on. If you need to install Python packages, do it via pip and not apt. If you decide to use apt anyway, note that Python system packages only include Python 2.7 libraries (default python version). This means that the packages installed from the repositories are not available in other virtualenvs even if you use the –system-site-packages option. Therefore I was getting Import module errors.

This problem was solved by making following changes in the ‘.travis.yml‘ file

```language: python

python:
#- "2.6"
- "2.7"
#- "2.7_with_system_site_packages"
- "3.2"
#- "3.2_with_system_site_packages"
- "3.3"
- "3.4"
before_install:
# Builds
- sudo mkdir -p /builds
- sudo chmod a+rw /builds

install:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- sudo apt-get install -y libqt4-dev
- sudo apt-get install -y mesa-common-dev libgl1-mesa-dev libglu1-mesa-dev
#    - sudo apt-get install -y python3-sip python3-sip-dev python3-pyqt4 cmake
# Qt4
- pushd /builds
# SIP
- pushd sip-4.16.5
- python configure.py
- make
- sudo make install
- popd
# PyQt4
- pushd PyQt-x11-gpl-4.11.3
- python configure.py -c --confirm-license --no-designer-plugin -e QtCore -e QtGui -e QtTest
- make
- sudo make install
- popd
# - "3.5"
# command to install dependencies
#install: "pip install -r requirements.txt"
# command to run tests
script: nosetests

slack: fossasia:*****tokenishidden*******

```

Codacy is an automated code analysis and review tool that helps developers ship better software, faster. With Codacy integration one can get static analysis, code complexity, code duplication and code coverage changes in every commit and pull request.

Codacy integration has really helped me to understand and enforce code quality standard. Codacy gives you impact of every pull request in terms of quality and errors directly into GitHub.

Codacy also grades your project in different categories like Code Complexity, Compatibility, security, code style, error prone etc. to help you better understand the overall project quality and what are the areas you should improve.

Here is a screen-shot of Codacy review for PSLab-apps repository.

I am extremely happy to share that my learning adventure has got  Project Certification at ‘A’ grade. Project quality analysis shows that more than 90% of the work has A grade 🙂 🙂

Travis CI and Codacy Badges for my GSoC Repositories:

PSLab-apps : Qt based GUI applications for PSLab

Pocket Science Lab : ExpEYES Programs, Sensor Plugins

That’s all for now. Have a happy coding, testing and learning 🙂 🙂

## Design Your Own Experiments With PSLab

PSLab, with its simple and open architecture allows programmers, hobbyists to use the tool for various measurements and to develop new experiments with simple python code.

One of the main target group, the PSLab is aimed at, is high-school science teachers and students, who may or may-not be familiar with the computer programming. For such users it is difficult to design or develop new experiments on their own. They may also find it difficult to fetch the data and plot required graphs, if a ready-made GUI is not available for that particular experiment.

To enable such users to quickly design a simple experiment for studying various phenomena, we have developed a simple Experiment Designer GUI. This incorporates few controls, read-back elements and easy functions to select parameters and plot graphs.

The screen shot of the ‘Design Your Own Experiment’ GUI along with the App-window is here..

Experiment Designer allows the user to define the control and read-back sequences of parameters and execute them.

#### Features of “Design Your Own Experiment” GUI

• Configure Experiment : Here user can select the required channels ( manual / sweep / read-back). One can also add a derived channel for measuring some physical quantity, for example ‘current’.
• Make Measurements : Selected channels are displayed. User can make measurements individually for each step or  can sweep in auto mode.
• Plot and View Plots: Enables user to plot selected parameters. Acquired plots can be selectively displayed or deleted.
• Save Plots: Data acquired can be save in a spreadsheet.
• Save Profile : Experiment profile can be saved for repeating the experiment in future. Saved profiles can be loaded from “Load Profile” tab.

Example : Diode IV Characteristics Experiment

For this experiment one needs the following…

• A variable voltage source : Needs to be swept from Voltage A to  B (say from 0V to 5V)
• Current Monitoring : Needs to be read for every value of Voltage
• Plotting and analytics :  Tools to plot the parameters and save data

Schematic Circuit diagram:

CH3 monitors the voltage drop across the diode. PV1 is varied in steps, and for each step the current is calculated from the difference between voltages at PV1 and CH3, and the known value of the resistor. For example for 1K resistor, current through the diode is given by

`I = (PV1-CH3)/1K`

Procedure :

Step 1. Connect Fossasia PSLab to the pc. Connect the components –  Diode from CH3 to Ground and  1k resistor from PV1 to CH3

Step 2. From the terminal Run

`Experiments`

The App-window will pop-up. Click on ‘Design your own Experiment’ button to get the experiment designer GUI.

Step 3: Select channels

Sweep Channel PV1 – Sweep from 0.00V -5.00V in 200 steps

Read-back Channel CH3 – for monitoring voltage across the diode

Derived Channel – To measure Current. Type the equation to calculate the current,   (PV1()-CH3())/1000

Step 4. Click on Prepare Experiment‘ to get measurements screen. Click on ‘Evaluate All Rows‘ to make the measurements.

Step 5. Select the required columns and click on Plot Selected Columns‘, a message window will pop-up, here user can select the Axes for plotting the graph. On clicking  ‘Plot‘, view plots screen will be displayed.

One can repeat the experiment and plot multiple curves and save them in a spreadsheet. Acquired plots can be selectively displayed or deleted.

Step 6. The entire design ( Experiment Profile)  of the experiment can be saved for repeating the experiment in future. Saved profiles can be loaded from “Load Profile” tab.

This is a very important value add to PSLab Apps. It has enabled PSLab to reach out and help users, who do not have any background in programming. Now ‘designing your own experiments’ has become super easy 🙂 🙂 🙂

## PSLab Communication Function Calls

Interfacing with the hardware of PSLab, fetching the data and plotting it is very simple and straight forward. Various sensors can be connected to PSLab and data can be fetched with a simple python code as shown in the following example…

```>>> from PSL import sciencelab
>>> I = sciencelab.connect()     # Initializing: Returns None if device isn't found. The initialization process connects to tty device and loads calibration values.```
```# An example function that measures voltage present at the specified analog input
>>> print I.get_average_voltage('CH1')```
```# An example to capture and plot data
>>> I.set_gain('CH1', 3) # set input CH1 to +/-4V range
>>> I.set_sine1(1000) # generate 1kHz sine wave on output W1
>>> x,y = I.capture1('CH1', 1000, 10) # digitize CH1 1000 times, with 10 usec interval
>>> plot(x,y)
>>> show()
```
```# An example function to get data from magnetometer sensor connected to PSLab
>>> from PSL.SENSORS import HMC5883L #A 3-axis magnetometer >>> M = HMC5883L.connect() >>> Gx,Gy,Gz = M.getRaw() ```

The module sciencelab.py contains all the functions required for communicating with PSLab hardware. It also contains some utility functions. The class ScienceLab() contains methods that can be used to interact with the PSLab.

After initiating this class, all the features built into the device can be accessed  using various function calls.

Capture1 : for capturing one trace

`capture1(ch, ns, tg)`

Arguments

• ch  : Channel to select as input. [‘CH1′..’CH3′,’SEN’]
• ns  :  Number of samples to fetch. Maximum 10000
• tg   :  Time gap between samples in microseconds
`#Example >>> x,y = I.capture1('CH1', 1000, 10) # digitize CH1 1000 times, with 10 usec interval`

Returns : Arrays X(timestamps),Y(Corresponding Voltage values)

Capture2 : for capturing two traces

`capture2(ns, tg, TraceOneRemap='CH1')`

Arguments

• ns :  Number of samples to fetch. Maximum 5000
• tg  :  Time gap between samples in microseconds
• TraceOneRemap :   Choose the analogue input for channel 1 (Like MIC OR SEN). It is connected to CH1 by default. Channel 2 always reads CH2.
```#Example
>>> x,y1,y2 = I.capture2(1600,1.75,'CH1') # digitize CH1 and CH2, 1600 times, with 1.75 usec interval```

Returns: Arrays X(timestamps),Y1(Voltage at CH1),Y2(Voltage at CH2)

Capture4 : for capturing four taces

`capture4(ns, tg, TraceOneRemap='CH1')`

Arguments

• ns:   Number of samples to fetch. Maximum 2500
• tg :   Time gap between samples in microseconds. Minimum 1.75uS
• TraceOneRemap :   Choose the analogue input for channel 1 (Like MIC OR SEN). It is connected to CH1 by default. Channel 2 always reads CH2, channel 3 always reads CH3 and MIC is channel 4 (CH4)
```#Example
>>> x,y1,y2,y3,y4 = I.capture4(800,1.75) # digitize CH1-CH4, 800 times, with 1.75 usec interval```

Returns: Arrays X(timestamps),Y1(Voltage at CH1),Y2(Voltage at CH2),Y3(Voltage at CH3),Y4(Voltage at CH4)

Capture_multiple : for capturing multiple traces

`capture_multiple(samples, tg, *args)`

Arguments

• samples:   Number of samples to fetch. Maximum 10000/(total specified channels)
• tg :   Time gap between samples in microseconds.
• *args :   channel names
```# Example
>>> from pylab import *
>>> I=interface.Interface()
>>> x,y1,y2,y3,y4 = I.capture_multiple(800,1.75,'CH1','CH2','MIC','SEN')
>>> plot(x,y1)
>>> plot(x,y2)
>>> plot(x,y3)
>>> plot(x,y4)
>>> show()```

Returns: Arrays X(timestamps),Y1,Y2 …

Capture_fullspeed : fetches oscilloscope traces from a single oscilloscope channel at a maximum speed of 2MSPS

`capture_fullspeed(chan, amples, tg, *args)`

Arguments

• chan:   channel name ‘CH1’ / ‘CH2’ … ‘SEN’
• tg :   Time gap between samples in microseconds. minimum 0.5uS
• *args :   specify if SQR1 must be toggled right before capturing. ‘SET_LOW’ will set it to 0V, ‘SET_HIGH’ will set it to 5V. if no arguments are specified, a regular capture will be executed.
```# Example
>>> from pylab import *
>>> I=interface.Interface()
>>> x,y = I.capture_fullspeed('CH1',2000,1)
>>> plot(x,y)
>>> show()```

Returns: timestamp array ,voltage_value array

Set_gain : Set the gain of selected PGA

`set_gain(channel, gain)`

Arguments

• channel:   ‘CH1’ , ‘CH2’
• gain :   (0-7) -> (1x,2x,4x,5x,8x,10x,16x,32x)

Note: The gain value applied to a channel will result in better resolution for small amplitude signals.

```# Example
>>> I.set_gain('CH1',7)  #gain set to 32x on CH1
```

Get_average_voltage : Return the voltage on the selected channel
`get_average_voltage(channel_name, **kwargs)`
Arguments

• channel_name:    ‘CH1’,’CH2’,’CH3’, ‘MIC’,’IN1’,’SEN’
• **kwargs :   Samples to average can be specified. eg. samples=100 will average a hundred readings
```# Example
>>> print I.get_average_voltage('CH4')
1.002```

Get_freq : Frequency measurement on IDx. Measures time taken for 16 rising edges of input signal. returns the frequency in Hertz

`get_average_voltage(channel='Fin', timeout=0.1)`
Arguments

• channel :    The input to measure frequency from. ‘ID1’ , ‘ID2’, ‘ID3’, ‘ID4’, ‘Fin’
• timeout :   This is a blocking call which will wait for one full wavelength before returning the calculated frequency. Use the timeout option if you’re unsure of the input signal. returns 0 if timed out
```# Example
>>> I.sqr1(4000,25)
>>> print I.get_freq('ID1')
4000.0```

Return float: frequency

Get_states : Gets the state of the digital inputs. returns dictionary with keys ‘ID1’,’ID2’,’ID3’,’ID4’
`get_states()`
```#Example
>>> print get_states()
{'ID1': True, 'ID2': True, 'ID3': True, 'ID4': False}
```

Get_state : Returns the logic level on the specified input (ID1,ID2,ID3, or ID4)
`get_state(input_id)`
Arguments

• input_id :    The input channel ‘ID1’ -> state of ID1 ‘ID4’ -> state of ID4
```#Example
>>> print I.get_state(I.ID1)
False
```

Set_state : Set the logic level on digital outputs SQR1,SQR2,SQR3,SQR4
`set_state(**kwargs)`
Arguments

• **kwargs :    SQR1,SQR2,SQR3,SQR4 states(0 or 1)
```#Example
>>> I.set_state(SQR1=1, SQR2=0) #sets SQR1 HIGH, SQR2 LOw, but leave SQR3,SQR4 untouched.
```

## Communicating with Pocket Science Lab via USB and capturing and plotting sine waves

Design of PSLab combines the flexibility of Python programming language and the real-time measurement capability of micro-controllers.

PSLab, with its simple and open architecture allows users to use the tool for various measurements and to develop new experiments with simple functions written in python.

PSLab is interfaced and powered by USB port of the computer. For connecting external signals it has several input/output terminals as shown in the figure.

#### Interfacing with the real world

Connecting to PSLab is as simple and straight forward as this…

```>>> from PSL import sciencelab
>>> I = sciencelab.connect()     #Returns None if device isn't found
# An example function that measures voltage present at the specified analog input
>>> print I.get_average_voltage('CH1')```

Various sensors can be connected to PSLab and data can be fetched with a simple python code as shown below…

```>>> from PSL.SENSORS import HMC5883L #A 3-axis magnetometer
>>> M = HMC5883L.connect()
>>> Gx,Gy,Gz = M.getRaw()
```

The module sciencelab.py contains all the functions required for communicating with PSLab hardware. It also contains some utility functions. The class ScienceLab() contains methods that can be used to interact with the PSLab. The connect() function returns an object of this class if PSLab hardware is detected.

The initialization process does the following

* connects to tty device

```>>> from PSL import sciencelab
>>> I = sciencelab.connect()
>>> print I
<PSL.sciencelab.ScienceLab instance at 0x7fe9a7bf0e18>```

After initiating this class, its various function calls will allow access to all the features built into the device. Some examples showing the use of few function calls are given below…

#### Example 1: Capturing and plotting a sine wave

The function call used,

`capture1(self,ch,ns,tg,*args,**kwargs)`

Arguments

• ch  : Channel to select as input. [‘CH1′..’CH3′,’SEN’]
• ns  :  Number of samples to fetch. Maximum 10000
• tg   :  Time gap between samples in microseconds

Example Program

Connect WG1 to CH1 and run the following code.

```>>> from pylab import *
>>> from PSL import sciencelab
>>> I=sciencelab.connect()
>>> I.set_gain('CH1', 3) # set input CH1 to +/-4V range
>>> I.set_sine1(1000) # generate 1kHz sine wave on output W1
>>> x,y = I.capture1('CH1', 1000, 10) # digitize CH1 1000 times, with 10 usec interval
>>> plot(x,y)
>>> show()```

For running the script in IDE, one should define source code encoding, add this to the top of your script:

``# -*- coding: utf-8 -*-``

The output of the program is here…

#### Example 2 : Capturing two sine waves and plotting

The function call used,

`capture2(self,ns,tg,TraceOneRemap='CH1')`

Arguments

• ns :  Number of samples to fetch. Maximum 5000
• tg  :  Time gap between samples in microseconds
• TraceOneRemap :   Choose the analogue input for channel 1 (Like MIC OR SEN). It is connected to CH1 by default. Channel 2 always reads CH2.

Example Program

Connect WG1 to CH1, WG2 to CH2 and run the following code.

```# -*- coding: utf-8 -*-

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

x,y1,y2 = I.capture2(1600,1.75,'CH1')
show()```

The output of the program is here…

#### Example 3 : Capturing four traces and plotting

The function call used,

`capture4(self,ns,tg,TraceOneRemap='CH1')`

Arguments

• ns:   Number of samples to fetch. Maximum 2500
• tg :   Time gap between samples in microseconds. Minimum 1.75uS
• TraceOneRemap :   Choose the analogue input for channel 1 (Like MIC OR SEN). It is connected to CH1 by default. Channel 2 always reads CH2.

Example Program

Connect WG1 to CH1, WG2 to CH2, SQR1 to CH3 and transducer mic to MIC (CH4) and run the following code.

```# -*- coding: utf-8 -*-

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
I.sqr1(2000,duty_cycle=50) # generate 1kHz square wave on output SQR1

x,y1,y2,y3,y4 = I.capture4(800,1.75)